2828use Pimcore \Model \DataObject \Fieldcollection \Data \AbstractData ;
2929use Pimcore \Model \DataObject \Localizedfield ;
3030use Pimcore \Model \DataObject \Objectbrick \Definition ;
31+ use Pimcore \Model \Factory ;
3132
3233class 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