vendor/pimcore/data-hub/src/GraphQL/FieldHelper/DataObjectFieldHelper.php line 357

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Bundle\DataHubBundle\GraphQL\FieldHelper;
  15. use GraphQL\Language\AST\FieldNode;
  16. use GraphQL\Type\Definition\ResolveInfo;
  17. use GraphQL\Type\Definition\Type;
  18. use Pimcore\Bundle\DataHubBundle\GraphQL\Exception\ClientSafeException;
  19. use Pimcore\File;
  20. use Pimcore\Logger;
  21. use Pimcore\Model\DataObject\ClassDefinition;
  22. use Pimcore\Model\DataObject\ClassDefinition\Data;
  23. use Pimcore\Model\DataObject\Concrete;
  24. use Pimcore\Model\DataObject\Fieldcollection\Data\AbstractData;
  25. use Pimcore\Model\DataObject\Localizedfield;
  26. use Pimcore\Model\DataObject\Objectbrick\Definition;
  27. class DataObjectFieldHelper extends AbstractFieldHelper
  28. {
  29.     /**
  30.      * @param array $nodeDef
  31.      * @param ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition $class
  32.      * @param object|null $container
  33.      *
  34.      * @return array|bool|null
  35.      */
  36.     public function getQueryFieldConfigFromConfig($nodeDef$class$container null)
  37.     {
  38.         $result false;
  39.         $attributes $nodeDef['attributes'];
  40.         if ($nodeDef['isOperator']) {
  41.             $key = isset($attributes['label']) ? $attributes['label'] : '';
  42.             $key File::getValidFilename($key);
  43.             $result = [
  44.                 'key' => $key,
  45.                 'config' => $this->getGraphQlOperatorConfig(
  46.                     'query',
  47.                     $nodeDef,
  48.                     $class,
  49.                     null,
  50.                     []
  51.                 )];
  52.         } else {
  53.             $key $attributes['attribute'];
  54.             // system columns which are not part of the common set (see PimcoreObjectType)
  55.             if ($attributes['dataType'] == 'system') {
  56.                 switch ($key) {
  57.                     case 'creationDate':
  58.                     case 'modificationDate':
  59.                         return [
  60.                             'key' => $key,
  61.                             'config' => [
  62.                                 'name' => $key,
  63.                                 'type' => Type::int()
  64.                             ]
  65.                         ];
  66.                     case 'filename':
  67.                     case 'fullpath':
  68.                     case 'key':
  69.                         return [
  70.                             'key' => $key,
  71.                             'config' => [
  72.                                 'name' => $key,
  73.                                 'type' => Type::string()
  74.                             ]
  75.                         ];
  76.                     case 'published':
  77.                         return [
  78.                             'key' => $key,
  79.                             'config' => [
  80.                                 'name' => $key,
  81.                                 'type' => Type::boolean(),
  82.                             ]
  83.                         ];
  84.                     default:
  85.                         return null;
  86.                 }
  87.             } else {
  88.                 $fieldDefinition $this->getFieldDefinitionFromKey($class$key$container);
  89.                 if (!$fieldDefinition) {
  90.                     Logger::error('could not resolve field "' $key '" in class ' $class->getName());
  91.                     return false;
  92.                 }
  93.                 if ($this->supportsGraphQL($fieldDefinition'query')) {
  94.                     $fieldName $fieldDefinition->getName();
  95.                     $result = ['key' => $fieldName,
  96.                         'config' => $this->getGraphQlQueryFieldConfig(
  97.                             $key,
  98.                             $fieldDefinition,
  99.                             $class,
  100.                             $container
  101.                         )];
  102.                 }
  103.             }
  104.         }
  105.         return $result;
  106.     }
  107.     /**
  108.      * @param string $mode
  109.      * @param array $nodeDef
  110.      * @param ClassDefinition $class
  111.      * @param object|null $container
  112.      * @param array $params
  113.      *
  114.      * @return mixed
  115.      */
  116.     public function getGraphQlOperatorConfig($mode$nodeDef$class$container$params = [])
  117.     {
  118.         $attributes $nodeDef['attributes'];
  119.         $operatorTypeName $attributes['class'];
  120.         $builder 'buildDataObject' ucfirst($mode) . 'OperatorConfig';
  121.         $typeDef $this->getGraphQlService()->$builder($operatorTypeName$nodeDef$class$container$params);
  122.         return $typeDef;
  123.     }
  124.     /**
  125.      * @param ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition $class
  126.      * @param string $key
  127.      * @param object|null $container
  128.      *
  129.      * @return Data|null
  130.      */
  131.     public function getFieldDefinitionFromKey($class$key, &$container null)
  132.     {
  133.         $fieldDefinition null;
  134.         $parts explode('~'$key);
  135.         if (substr($key01) === '~') {
  136.             // classification store ...
  137.         } elseif (count($parts) > 1) {
  138.             $brickType $parts[0];
  139.             $brickDescriptor null;
  140.             if (strpos($brickType'?') !== false) {
  141.                 $brickDescriptor substr($brickType1);
  142.                 $brickDescriptor json_decode($brickDescriptortrue);
  143.                 $brickType $brickDescriptor['containerKey'];
  144.             }
  145.             $brickKey $parts[1];
  146.             $brickDefinition Definition::getByKey($brickType);
  147.             if ($brickDescriptor) {
  148.                 $fieldDefinition $brickDefinition->getFieldDefinition($brickKey);
  149.                 if (!$fieldDefinition) {
  150.                     /** @var Data\Localizedfields $fieldDefinitionLocalizedFields */
  151.                     $fieldDefinitionLocalizedFields $brickDefinition->getFieldDefinition('localizedfields');
  152.                     $container $fieldDefinitionLocalizedFields;
  153.                     $fieldDefinition $fieldDefinitionLocalizedFields->getFieldDefinition($brickKey);
  154.                 }
  155.             } else {
  156.                 $fieldDefinition $brickDefinition->getFieldDefinition($brickKey);
  157.             }
  158.         } else {
  159.             $fieldDefinition $class->getFieldDefinition($key);
  160.         }
  161.         if (!$fieldDefinition) {
  162.             /** @var Data\Localizedfields|null $container */
  163.             $container $class->getFieldDefinition('localizedfields');
  164.             $lfDefs $container;
  165.             if ($lfDefs) {
  166.                 $fieldDefinition $lfDefs->getFieldDefinition($key);
  167.             }
  168.         }
  169.         return $fieldDefinition;
  170.     }
  171.     /**
  172.      * @param Data $fieldDefinition
  173.      * @param string $operationType
  174.      *
  175.      * @return bool
  176.      *
  177.      * @throws \Exception
  178.      */
  179.     public function supportsGraphQL(Data $fieldDefinitionstring $operationType)
  180.     {
  181.         $typeName $fieldDefinition->getFieldtype();
  182.         switch ($operationType) {
  183.             case 'query':
  184.                 return $this->getGraphQlService()->supportsDataObjectQueryDataType($typeName);
  185.             case 'mutation':
  186.                 return $this->getGraphQlService()->supportsDataObjectMutationDataType($typeName);
  187.             default:
  188.                 throw new ClientSafeException('unknown operation type ' $typeName);
  189.         }
  190.     }
  191.     /**
  192.      * @param string $attribute
  193.      * @param Data $fieldDefinition
  194.      * @param ClassDefinition $class
  195.      * @param object $container
  196.      *
  197.      * @return mixed
  198.      */
  199.     public function getGraphQlQueryFieldConfig($attribute$fieldDefinition$class$container)
  200.     {
  201.         $typeName $fieldDefinition->getFieldtype();
  202.         $typeDef $this->getGraphQlService()->buildDataObjectQueryDataConfig($attribute$typeName$fieldDefinition$class$container);
  203.         return $typeDef;
  204.     }
  205.     /**
  206.      * @param array $nodeDef
  207.      * @param ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition $class
  208.      *
  209.      * @return array|false|null
  210.      */
  211.     public function getMutationFieldConfigFromConfig($nodeDef$class)
  212.     {
  213.         $container null;
  214.         $result false;
  215.         $attributes $nodeDef['attributes'];
  216.         if ($nodeDef['isOperator'] ?? false) {
  217.             $key = isset($attributes['label']) ? $attributes['label'] : '';
  218.             $key preg_replace('/[^A-Za-z0-9\-\.~_]+/''_'$key);
  219.             $result $this->getGraphQlOperatorConfig(
  220.                 'mutation',
  221.                 $nodeDef,
  222.                 $class,
  223.                 null,
  224.                 []
  225.             );
  226.             $result['key'] = $key;
  227.         } else {
  228.             $key $attributes['attribute'];
  229.             // system columns which are not part of the common set (see PimcoreObjectType)
  230.             if ($attributes['dataType'] === 'system') {
  231.                 switch ($key) {
  232.                     case 'key':
  233.                         return [
  234.                             'key' => $key,
  235.                             'arg' => ['type' => Type::string()],
  236.                             'processor' => function ($object$newValue$args) {
  237.                                 $object->setKey($newValue);
  238.                             }
  239.                         ];
  240.                     case 'published':
  241.                         return [
  242.                             'key' => $key,
  243.                             'arg' => ['type' => Type::boolean()],
  244.                             'processor' => function ($object$newValue$args) {
  245.                                 $object->setPublished($newValue);
  246.                             }
  247.                         ];
  248.                     default:
  249.                         return null;
  250.                 }
  251.             } else {
  252.                 $fieldDefinition $this->getFieldDefinitionFromKey($class$key$container);
  253.                 if (!$fieldDefinition) {
  254.                     Logger::error('could not resolve field ' $key);
  255.                     return false;
  256.                 }
  257.                 if ($this->supportsGraphQL($fieldDefinition'mutation')) {
  258.                     $fieldName $fieldDefinition->getName();
  259.                     $result $this->getGraphQlMutationFieldConfig(
  260.                         $nodeDef,
  261.                         $class,
  262.                         $container
  263.                     );
  264.                     $result['key'] = $fieldName;
  265.                 }
  266.             }
  267.         }
  268.         return $result;
  269.     }
  270.     /**
  271.      * @param array $nodeDef
  272.      * @param ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition $class
  273.      * @param object $container
  274.      *
  275.      * @return array
  276.      */
  277.     public function getGraphQlMutationFieldConfig($nodeDef$class$container)
  278.     {
  279.         $typeDef $this->getGraphQlService()->buildDataObjectMutationDataConfig($nodeDef$class$container);
  280.         return $typeDef;
  281.     }
  282.     /**
  283.      * @param array $nodeConf
  284.      * @param ClassDefinition $class
  285.      * @param object|null $container
  286.      *
  287.      * @return mixed
  288.      */
  289.     public function getGraphQlTypeFromNodeConf($nodeConf$class$container null)
  290.     {
  291.         $attributes $nodeConf['attributes'];
  292.         if ($nodeConf['isOperator']) {
  293.             $operatorTypeName $attributes['class'];
  294.             $type $this->getGraphQlService()->buildDataObjectOperatorQueryType('mutation'$operatorTypeName$nodeConf$class$container);
  295.         } else {
  296.             $key $attributes['attribute'];
  297.             $fieldDefinition $this->getFieldDefinitionFromKey($class$key);
  298.             $type $this->getGraphQlService()->buildDataObjectDataQueryType($fieldDefinition$class$container);
  299.         }
  300.         return $type;
  301.     }
  302.     /**
  303.      * @param FieldNode $ast
  304.      * @param array $data
  305.      * @param object $container
  306.      * @param array $args
  307.      * @param array $context
  308.      * @param ResolveInfo $resolveInfo
  309.      */
  310.     public function doExtractData(FieldNode $ast, &$data$container$args$context$resolveInfo null)
  311.     {
  312.         $astName $ast->name->value;
  313.         // sometimes we just want to expand relations just to throw them away afterwards because not requested
  314.         if ($this->skipField($container$astName)) {
  315.             return;
  316.         }
  317.         // example for http://webonyx.github.io/graphql-php/error-handling/
  318. //         throw new MySafeException("fieldhelper", "TBD customized error message");
  319.         $getter 'get' ucfirst($astName);
  320.         $isLocalizedField false;
  321.         $containerDefinition null;
  322.         if ($container instanceof Concrete) {
  323.             $containerDefinition $container->getClass();
  324.         } elseif ($container instanceof AbstractData || $container instanceof \Pimcore\Model\DataObject\Objectbrick\Data\AbstractData) {
  325.             $containerDefinition $container->getDefinition();
  326.         }
  327.         if ($containerDefinition) {
  328.             /** @var Data\Localizedfields|null $lfDefs */
  329.             $lfDefs $containerDefinition->getFieldDefinition('localizedfields');
  330.             if ($lfDefs && $lfDefs->getFieldDefinition($astName)) {
  331.                 $isLocalizedField true;
  332.             }
  333.         }
  334.         if (method_exists($container$getter)) {
  335.             if ($isLocalizedField) {
  336.                 // defer it
  337.                 $data[$astName] = function ($source$args$contextResolveInfo $info) use (
  338.                     $container,
  339.                     $getter
  340.                 ) {
  341.                     return $container->$getter($args['language'] ?? null);
  342.                 };
  343.             } else {
  344.                 $data[$astName] = $container->$getter();
  345.             }
  346.         }
  347.     }
  348.     /**
  349.      * @param object $container
  350.      * @param string $astName
  351.      *
  352.      * @return bool
  353.      */
  354.     public function skipField($container$astName)
  355.     {
  356.         if ($container instanceof Concrete || $container instanceof Localizedfield) {
  357.             $fieldDefinition $container->getClass()->getFieldDefinition($astName);
  358.             if ($fieldDefinition instanceof Data\Relations\AbstractRelations) {
  359.                 // do not autoexpand relations
  360.                 return true;
  361.             }
  362.         }
  363.         return false;
  364.     }
  365. }