Skip to content

Instantly share code, notes, and snippets.

@cleggypdc
Last active August 23, 2016 17:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cleggypdc/a58844f9143b43d05ca3d9c149be37f7 to your computer and use it in GitHub Desktop.
Save cleggypdc/a58844f9143b43d05ca3d9c149be37f7 to your computer and use it in GitHub Desktop.
Pimcore Multi-class inheritance
<?php
namespace Website\Model\Object;
use Pimcore\Model\Object;
use Pimcore\Model\Object\AbstractObject;
class Concrete extends \Pimcore\Model\Object\Concrete
{
/**
* @var
*/
private $adminEventHook;
public $inheritableClasses = [];
/**
* An array of fields that were inherited from a parent
* Customise this per extending class
* @var array
*/
protected $inheritableFields = [];
/**
* Fields that have been inherited from parents
* @var array
*/
private $inheritedFields = [];
public function isAllowedInheritanceClass($parentClassId)
{
return $parentClassId == $this->getClassId() || in_array($parentClassId, $this->inheritableClasses);
}
public function preGetValue($key)
{
if (in_array($key, $this->getInheritableFields())) {
return $this->getObjectValueWithInheritanceCheck($key);
}
return null;
}
/**
* Based on getNextParentforInheritance but tweaked for preGetters
* @return null|static
*/
public function getInheritedValue($key)
{
if ($this->getParent() instanceof AbstractObject) {
$parent = $this->getParent();
while ($parent && $parent->getType() == "folder") {
$parent = $parent->getParent();
}
if ($parent && ($parent->getType() == "object" || $parent->getType() == "variant")) {
if ($this->isAllowedInheritanceClass($parent->getClassId())) {
$getter = 'get' . ucfirst($key);
if (method_exists($parent, $getter)) {
//set inherited fields to override in the admin panel
//as the preget value is overwritten in the concrete class for each
//object value
if (\Pimcore::inAdmin()) {
$this->initAdminEventHook();
$fieldDefinition = $this->getClass()->getFieldDefinition($key);
$this->inheritedFields[$key] = $this->getEditmodeDataForField($parent, $key, $fieldDefinition);
}
return $parent->$getter();
}
}
}
}
return null;
}
/**
* Returns the list of fields for this object that can be inherited
* @return array
*/
public function getInheritableFields()
{
return $this->inheritableFields;
}
/**
* Returns the list of fields for this object that were inherited
* @return array
*/
public function getInheritedFields()
{
return $this->inheritedFields;
}
public function getObjectValueWithInheritanceCheck($key)
{
if (in_array($key, $this->lazyLoadedFields)) {
$data = $this->getClass()->getFieldDefinition($key)->preGetData($this);
} else {
$data = $this->$key;
}
if (is_null($data) || empty($data)) {
return $this->getInheritedValue($key);
}
return $data;
}
/**
* Provides an admin panel hook that is automatically applied if inheritance is deteected
*/
private function initAdminEventHook()
{
if (!$this->adminEventHook) {
$this->adminEventHook = \Pimcore::getEventManager()
->attach("admin.object.get.preSendData", function (\Zend_EventManager_Event $e) {
$object = $e->getParam('object');
$returnValueContainer = $e->getParam('returnValueContainer');
$data = $returnValueContainer->getData();
if ($object instanceof Concrete) {
$inheritedFields = $object->getInheritedFields();
foreach($inheritedFields as $fieldName=>$editmodeData) {
if (isset($data['metaData'][$fieldName])) {
$data['metaData'][$fieldName] = $editmodeData['metaData'];
}
//add the value
$data['data'][$fieldName] = $editmodeData['data'];
}
}
$returnValueContainer->setData($data);
});
}
}
protected function getEditmodeDataForField($object, $key, $fieldDefinition)
{
$getter = "get" . ucfirst($key);
$editmodeData = [
'data' => null,
'metaData' => [
'objectid' => $object->getId()
]
];
if ((
$fieldDefinition instanceof Object\ClassDefinition\Data\Relations\AbstractRelations
&& $fieldDefinition->getLazyLoading()
&& !$fieldDefinition instanceof Object\ClassDefinition\Data\ObjectsMetadata
&& !$fieldDefinition instanceof Object\ClassDefinition\Data\MultihrefMetadata
)
|| $fieldDefinition instanceof Object\ClassDefinition\Data\Nonownerobjects
) {
$refId = null;
if ($fieldDefinition->isRemoteOwner()) {
$refKey = $fieldDefinition->getOwnerFieldName();
$refClass = Object\ClassDefinition::getByName($fieldDefinition->getOwnerClassName());
if ($refClass) {
$refId = $refClass->getId();
}
} else {
$refKey = $key;
}
$relations = $object->getRelationData($refKey, !$fieldDefinition->isRemoteOwner(), $refId);
if (!empty($relations)) {
$data = [];
if ($fieldDefinition instanceof Object\ClassDefinition\Data\Href) {
$data = $relations[0];
} else {
foreach ($relations as $rel) {
if ($fieldDefinition instanceof Object\ClassDefinition\Data\Objects) {
$data[] = [$rel["id"], $rel["path"], $rel["subtype"]];
} else {
$data[] = [$rel["id"], $rel["path"], $rel["type"], $rel["subtype"]];
}
}
}
$editmodeData['data'] = $data;
$editmodeData['metaData']['objectid'] = $object->getId();
$editmodeData['metaData']['inherited'] = true;
}
} else {
$fieldData = $object->$getter();
if ($fieldDefinition instanceof Object\ClassDefinition\Data\CalculatedValue) {
$fieldData = new Object\Data\CalculatedValue($fieldDefinition->getName());
$fieldData->setContextualData("object", null, null, null);
$value = $fieldDefinition->getDataForEditmode($fieldData, $object, true);
} else {
$value = $fieldDefinition->getDataForEditmode($fieldData, $object, true);
}
if (!$fieldDefinition->isEmpty($fieldData)) {
$editmodeData['metaData']['objectid'] = $object->getId();
$editmodeData['metaData']['inherited'] = true;
$editmodeData['data'] = $value;
}
}
return $editmodeData;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment