Last active
August 30, 2017 11:46
-
-
Save sgrossberndt/a4a0b365c3b51f4c2de76d2530dc8ed0 to your computer and use it in GitHub Desktop.
A JsonView extending ExtbaseJsonView to circumvent some of the performance problems
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace MyVendor\MyExtension\View; | |
use TYPO3\CMS\Extbase\Mvc\View\JsonView as ExtbaseJsonView; | |
use TYPO3\CMS\Extbase\Persistence\ObjectStorage; | |
use TYPO3\CMS\Extbase\Reflection\ObjectAccess; | |
class JsonView extends ExtbaseJsonView { | |
/** | |
* Always transform ObjectStorage to Array | |
* | |
* @param mixed $value | |
* @param array $configuration | |
* @return array | |
* @see https://usetypo3.com/json-view.html | |
*/ | |
protected function transformValue($value, array $configuration) { | |
if ($value instanceof ObjectStorage) { | |
$value = $value->toArray(); | |
} | |
return parent::transformValue($value, $configuration); | |
} | |
private $propertyNames = []; | |
/** | |
* Traverses the given object structure in order to transform it into an | |
* array structure. | |
* | |
* @param object $object Object to traverse | |
* @param array $configuration Configuration for transforming the given object or NULL | |
* @return array Object structure as an array | |
*/ | |
protected function transformObject($object, array $configuration) { | |
$class = get_class($object); | |
// for objects from MyExtension | |
if (strpos($class, 'MyVendor\\MyExtension\\Domain\\Model\\') === 0) { | |
// fetch available properties only once per class instead of for each object, as all objects in our extension have the same properties available | |
if (!isset($this->propertyNames[$class])) { | |
$this->propertyNames[$class] = ObjectAccess::getGettablePropertyNames($object); | |
} | |
$propertiesToRender = []; | |
foreach ($this->propertyNames[$class] as $propertyName) { | |
if (isset($configuration['_only']) && is_array($configuration['_only']) && !in_array($propertyName, $configuration['_only'])) { | |
continue; | |
} | |
if (isset($configuration['_exclude']) && is_array($configuration['_exclude']) && in_array($propertyName, $configuration['_exclude'])) { | |
continue; | |
} | |
// do not fetch getters by reflection for each object, but call them directly, as all are available as 'get' . ucfirst($propertyName) | |
$propertyValue = $object->{'get' . ucfirst($propertyName)}(); | |
if (!is_array($propertyValue) && !is_object($propertyValue)) { | |
$propertiesToRender[$propertyName] = $propertyValue; | |
} elseif (!isset($configuration['_descend']) || !array_key_exists($propertyName, $configuration['_descend'])) { | |
throw new \Exception('The following property was fetched but not used at all! ' . $class . '->get' . ucfirst($propertyName)); | |
} elseif (isset($configuration['_descend']) && array_key_exists($propertyName, $configuration['_descend'])) { | |
$propertiesToRender[$propertyName] = $this->transformValue($propertyValue, $configuration['_descend'][$propertyName]); | |
} | |
} | |
} else { | |
$propertiesToRender = parent::transformObject($object, $configuration); | |
} | |
return $propertiesToRender; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment