Last active
August 23, 2016 17:48
-
-
Save cleggypdc/a58844f9143b43d05ca3d9c149be37f7 to your computer and use it in GitHub Desktop.
Pimcore Multi-class inheritance
This file contains hidden or 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 | |
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