Skip to content

Commit b5f0b32

Browse files
committed
chore: Improve mock data handling
1 parent 655f123 commit b5f0b32

File tree

1 file changed

+51
-23
lines changed

1 file changed

+51
-23
lines changed

src/GraphQL/FieldHelper/DataObjectFieldHelper.php

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,18 @@
2828
use Pimcore\Model\DataObject\Fieldcollection\Data\AbstractData;
2929
use Pimcore\Model\DataObject\Localizedfield;
3030
use Pimcore\Model\DataObject\Objectbrick\Definition;
31+
use Pimcore\Model\Factory;
3132

3233
class DataObjectFieldHelper extends AbstractFieldHelper
3334
{
35+
protected Factory $modelFactory;
36+
37+
public function __construct(\Pimcore\Model\Factory $modelFactory)
38+
{
39+
parent::__construct();
40+
$this->modelFactory = $modelFactory;
41+
}
42+
3443
/**
3544
* @param array $nodeDef
3645
* @param ClassDefinition|\Pimcore\Model\DataObject\Fieldcollection\Definition $class
@@ -70,8 +79,8 @@ public function getQueryFieldConfigFromConfig($nodeDef, $class, $container = nul
7079
'key' => $key,
7180
'config' => [
7281
'name' => $key,
73-
'type' => Type::int()
74-
]
82+
'type' => Type::int(),
83+
],
7584
];
7685
case 'filename':
7786
case 'fullpath':
@@ -80,16 +89,16 @@ public function getQueryFieldConfigFromConfig($nodeDef, $class, $container = nul
8089
'key' => $key,
8190
'config' => [
8291
'name' => $key,
83-
'type' => Type::string()
84-
]
92+
'type' => Type::string(),
93+
],
8594
];
8695
case 'published':
8796
return [
8897
'key' => $key,
8998
'config' => [
9099
'name' => $key,
91100
'type' => Type::boolean(),
92-
]
101+
],
93102
];
94103
default:
95104
return null;
@@ -269,7 +278,7 @@ public function getMutationFieldConfigFromConfig($nodeDef, $class)
269278
'arg' => ['type' => Type::string()],
270279
'processor' => function ($object, $newValue, $args) {
271280
$object->setKey($newValue);
272-
}
281+
},
273282

274283
];
275284
case 'published':
@@ -278,7 +287,7 @@ public function getMutationFieldConfigFromConfig($nodeDef, $class)
278287
'arg' => ['type' => Type::boolean()],
279288
'processor' => function ($object, $newValue, $args) {
280289
$object->setPublished($newValue);
281-
}
290+
},
282291
];
283292
default:
284293
return null;
@@ -370,10 +379,39 @@ public function doExtractData(FieldNode $ast, &$data, $container, $args, $contex
370379
$isLocalizedField = false;
371380
$containerDefinition = null;
372381

373-
if ($container instanceof Concrete) {
374-
$containerDefinition = $container->getClass();
375-
} elseif ($container instanceof AbstractData || $container instanceof \Pimcore\Model\DataObject\Objectbrick\Data\AbstractData) {
376-
$containerDefinition = $container->getDefinition();
382+
// This reflection object is used to determine if the getter can be used.
383+
// $container isn't used directly in order to allow specialized handling
384+
// of mock objects and other placeholders which act transparently but
385+
// don't implement the getters themselves.
386+
$methodCheckClass = new \ReflectionClass($container);
387+
$skipMethodCallCheck = false;
388+
// Adjust meta data for data handling on type of the data container.
389+
switch (true) {
390+
case $container instanceof Concrete:
391+
$containerDefinition = $container->getClass();
392+
break;
393+
394+
case $container instanceof AbstractData:
395+
case $container instanceof \Pimcore\Model\DataObject\Objectbrick\Data\AbstractData:
396+
$containerDefinition = $container->getDefinition();
397+
break;
398+
399+
// All default indexers implement o_classId - access it directly to
400+
// load class definition and with it use the model loader to fetch
401+
// the actual implementing class for further reflection.
402+
case $container instanceof DefaultMockup:
403+
if (($mockClassId = $container->getParam('o_classId'))) {
404+
$containerDefinition = ClassDefinition::getById($mockClassId);
405+
// Unfortunately there's no API for this so we re-implement
406+
// what \Pimcore\Model\DataObject\AbstractObject::getById()
407+
// does.
408+
$baseClassName = 'Pimcore\\Model\\DataObject\\' . ucfirst($containerDefinition->getName());
409+
$className = $this->modelFactory->getClassNameFor($baseClassName);
410+
$methodCheckClass = new \ReflectionClass($className);
411+
} else {
412+
$skipMethodCallCheck = true;
413+
}
414+
break;
377415
}
378416

379417
if ($containerDefinition) {
@@ -383,7 +421,8 @@ public function doExtractData(FieldNode $ast, &$data, $container, $args, $contex
383421
$isLocalizedField = true;
384422
}
385423
}
386-
if (method_exists($container, $getter)) {
424+
425+
if (($methodCheckClass->hasMethod($getter) && $methodCheckClass->getMethod($getter)->isPublic()) || $skipMethodCallCheck) {
387426
if ($isLocalizedField) {
388427
// defer it
389428
$data[$astName] = function ($source, $args, $context, ResolveInfo $info) use (
@@ -395,17 +434,6 @@ public function doExtractData(FieldNode $ast, &$data, $container, $args, $contex
395434
} else {
396435
$data[$astName] = $container->$getter();
397436
}
398-
} else {
399-
// we could also have a Mockup objects from Elastic which not supports the "method_exists"
400-
// in this case we just try to get the data directly
401-
if ($container instanceof DefaultMockup) {
402-
try {
403-
// we don't have to take care about localization because this is already handled in elastic
404-
$data[$astName] = $container->$getter();
405-
} catch (\Exception $e) {
406-
Logger::info('Could not get data from Datahub/DataObjectFieldHelper with message: ' . $e->getMessage());
407-
}
408-
}
409437
}
410438
}
411439

0 commit comments

Comments
 (0)