From dc102f41f84e418f6a076b4cd47b4b9f19597706 Mon Sep 17 00:00:00 2001 From: Peter Philipp Date: Fri, 16 Aug 2024 16:38:02 +0200 Subject: [PATCH] chore: Added context data handling for ElementMockupInterface. This will allow to select appropriate pre-processed data depending on execution context. --- src/GraphQL/FieldHelper/AssetFieldHelper.php | 12 ++--- .../FieldHelper/DataObjectFieldHelper.php | 12 ++--- src/GraphQL/Service.php | 44 ++++++++++++++++--- src/Model/ElementMockupInterface.php | 20 +++++++++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/GraphQL/FieldHelper/AssetFieldHelper.php b/src/GraphQL/FieldHelper/AssetFieldHelper.php index 0479b234..4b1e0fa8 100644 --- a/src/GraphQL/FieldHelper/AssetFieldHelper.php +++ b/src/GraphQL/FieldHelper/AssetFieldHelper.php @@ -17,6 +17,7 @@ use GraphQL\Language\AST\FieldNode; use GraphQL\Type\Definition\ResolveInfo; +use Pimcore\Bundle\DataHubBundle\GraphQL\Service; use Pimcore\Model\Asset; use Pimcore\Model\Asset\Image; use Pimcore\Model\Asset\Video; @@ -128,21 +129,22 @@ public function doExtractData(FieldNode $ast, &$data, $container, $args, $contex } } } else { - if ($this->getGraphQlService()::checkContainerMethodExists($container, $getter)) { + if (Service::checkContainerMethodExists($container, $getter)) { if ($languageArgument) { if ($ast->alias) { // defer it $data[$realName] = function ($source, $args, $context, ResolveInfo $info) use ( $container, - $getter + $getter, + $ast ) { - return $container->$getter($args['language'] ?? null); + return Service::callContainerGetterMethod($container, $getter, ['language' => $args['language'] ?? null], $info, $ast); }; } else { - $data[$realName] = $container->$getter($languageArgument); + $data[$realName] = Service::callContainerGetterMethod($container, $getter, ['language' => $languageArgument], $resolveInfo, $ast); } } else { - $data[$realName] = $container->$getter(); + $data[$realName] = Service::callContainerGetterMethod($container, $getter, [], $resolveInfo, $ast); } } } diff --git a/src/GraphQL/FieldHelper/DataObjectFieldHelper.php b/src/GraphQL/FieldHelper/DataObjectFieldHelper.php index 8845d887..e46dbc5f 100644 --- a/src/GraphQL/FieldHelper/DataObjectFieldHelper.php +++ b/src/GraphQL/FieldHelper/DataObjectFieldHelper.php @@ -19,6 +19,7 @@ use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use Pimcore\Bundle\DataHubBundle\GraphQL\Exception\ClientSafeException; +use Pimcore\Bundle\DataHubBundle\GraphQL\Service; use Pimcore\File; use Pimcore\Logger; use Pimcore\Model\DataObject\ClassDefinition; @@ -372,18 +373,19 @@ public function doExtractData(FieldNode $ast, &$data, $container, $args, $contex // throw new MySafeException("fieldhelper", "TBD customized error message"); $getter = 'get' . ucfirst($astName); - if ($this->getGraphQlService()::checkContainerMethodExists($container, $getter)) { - $isLocalizedField = $this->getGraphQlService()::isLocalizedField($container, $astName); + if (Service::checkContainerMethodExists($container, $getter)) { + $isLocalizedField = Service::isLocalizedField($container, $astName); if ($isLocalizedField) { // defer it $data[$astName] = function ($source, $args, $context, ResolveInfo $info) use ( $container, - $getter + $getter, + $ast ) { - return $container->$getter($args['language'] ?? null); + return Service::callContainerGetterMethod($container, $getter, ['language' => $args['language'] ?? null], $info, $ast); }; } else { - $data[$astName] = $container->$getter(); + $data[$astName] = Service::callContainerGetterMethod($container, $getter, [], $resolveInfo, $ast); } } } diff --git a/src/GraphQL/Service.php b/src/GraphQL/Service.php index 166437af..67b5fb42 100644 --- a/src/GraphQL/Service.php +++ b/src/GraphQL/Service.php @@ -44,12 +44,11 @@ use Pimcore\Cache\RuntimeCache; use Pimcore\DataObject\GridColumnConfig\ConfigElementInterface; use Pimcore\Localization\LocaleServiceInterface; -use Pimcore\Model\AbstractModel; use Pimcore\Model\DataObject\ClassDefinition; use Pimcore\Model\DataObject\ClassDefinition\Data; use Pimcore\Model\DataObject\Concrete; +use Pimcore\Model\DataObject\Fieldcollection\Definition; use Pimcore\Model\DataObject\Objectbrick\Data\AbstractData; -use Pimcore\Model\DataObject\Objectbrick\Definition; use Pimcore\Model\Element\ElementInterface; use Pimcore\Model\Factory; use Pimcore\Translation\Translator; @@ -1078,9 +1077,9 @@ public static function resolveValue(BaseDescriptor $descriptor, Data $fieldDefin } elseif (static::checkContainerMethodExists($container, $getter)) { $isLocalizedField = self::isLocalizedField($container, $fieldDefinition->getName()); if ($isLocalizedField) { - $result = $container->$getter($args['language'] ?? null); + $result = Service::callContainerGetterMethod($container, $getter, ['language' => $args['language'] ?? null]); } else { - $result = $container->$getter(); + $result = Service::callContainerGetterMethod($container, $getter); } } @@ -1286,11 +1285,10 @@ public static function checkContainerMethodExists(object $container, string $met * * @param object $container * - * @return \Pimcore\Model\AbstractModel|null + * @return \Pimcore\Model\DataObject\ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition|null * - * @throws \Exception */ - public static function getContainerClassDefinition(object $container): ?AbstractModel + public static function getContainerClassDefinition(object $container): ClassDefinition | Definition | null { // Adjust meta data for data handling on type of the data container. switch (true) { @@ -1305,4 +1303,36 @@ public static function getContainerClassDefinition(object $container): ?Abstract return null; } + + /** + * Call the getter function on a container. + * + * Passes on execution context to containers with the ElementMockupInterface. + * + * @param object $container + * @param string $getter + * @param array $getterArgs + * @param \GraphQL\Type\Definition\ResolveInfo|null $resolveInfo + * + * @return mixed + */ + public static function callContainerGetterMethod( + object $container, + string $getter, + array $getterArgs = [], + ?ResolveInfo $resolveInfo = null, + ?FieldNode $ast = null + ): mixed { + if ($container instanceof ElementMockupInterface) { + $container->setGraphQLContext($getter, $getterArgs, $resolveInfo, $ast); + } + try { + $return = call_user_func_array([$container, $getter], $getterArgs); + } finally { + if ($container instanceof ElementMockupInterface) { + $container->setGraphQLContext(null); + } + } + return $return; + } } diff --git a/src/Model/ElementMockupInterface.php b/src/Model/ElementMockupInterface.php index db2007b3..19d76c55 100644 --- a/src/Model/ElementMockupInterface.php +++ b/src/Model/ElementMockupInterface.php @@ -15,6 +15,8 @@ namespace Pimcore\Bundle\DataHubBundle\Model; +use GraphQL\Language\AST\FieldNode; +use GraphQL\Type\Definition\ResolveInfo; use Pimcore\Model\DataObject; use Pimcore\Model\DataObject\ClassDefinition; use Pimcore\Model\Element\ElementInterface; @@ -57,4 +59,22 @@ public function getId(); * @return \Pimcore\Model\Element\ElementInterface|null */ public function getOriginalObject(): ElementInterface | null; + + /** + * Set the GraphQL context. + * + * This can e.g. allow to react on operation arguments and select the + * appropriate pre-processed data from a mock object. + * + * @param string|null $getter + * @param array|null $getterArgs + * @param \GraphQL\Type\Definition\ResolveInfo|null $resolveInfo + * @param FieldNode $ast + */ + public function setGraphQLContext( + ?string $getter, + ?array $getterArgs = null, + ?ResolveInfo $resolveInfo = null, + ?FieldNode $ast = null + ): void; }