vendor/pimcore/pimcore/models/DataObject/Objectbrick/Definition.php line 76

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Model\DataObject\Objectbrick;
  15. use Pimcore\Cache;
  16. use Pimcore\Cache\Runtime;
  17. use Pimcore\File;
  18. use Pimcore\Logger;
  19. use Pimcore\Model;
  20. use Pimcore\Model\DataObject;
  21. use Pimcore\Model\DataObject\ClassDefinition\Data\FieldDefinitionEnrichmentInterface;
  22. use Pimcore\Tool;
  23. /**
  24.  * @method \Pimcore\Model\DataObject\Objectbrick\Definition\Dao getDao()
  25.  * @method string getTableName(DataObject\ClassDefinition $class, $query)
  26.  * @method void createUpdateTable(DataObject\ClassDefinition $class)
  27.  * @method string getLocalizedTableName(DataObject\ClassDefinition $class, $query)
  28.  */
  29. class Definition extends Model\DataObject\Fieldcollection\Definition
  30. {
  31.     use Model\DataObject\ClassDefinition\Helper\VarExport;
  32.     use DataObject\Traits\LocateFileTrait;
  33.     use DataObject\Traits\FieldcollectionObjectbrickDefinitionTrait;
  34.     /**
  35.      * @var array
  36.      */
  37.     public $classDefinitions = [];
  38.     /**
  39.      * @var array
  40.      */
  41.     private $oldClassDefinitions = [];
  42.     /**
  43.      * @param array $classDefinitions
  44.      *
  45.      * @return $this
  46.      */
  47.     public function setClassDefinitions($classDefinitions)
  48.     {
  49.         $this->classDefinitions $classDefinitions;
  50.         return $this;
  51.     }
  52.     /**
  53.      * @return array
  54.      */
  55.     public function getClassDefinitions()
  56.     {
  57.         return $this->classDefinitions;
  58.     }
  59.     /**
  60.      * @static
  61.      *
  62.      * @param string $key
  63.      *
  64.      * @return self|null
  65.      */
  66.     public static function getByKey($key)
  67.     {
  68.         $brick null;
  69.         $cacheKey 'objectbrick_' $key;
  70.         try {
  71.             $brick \Pimcore\Cache\Runtime::get($cacheKey);
  72.             if (!$brick) {
  73.                 throw new \Exception('ObjectBrick in Registry is not valid');
  74.             }
  75.         } catch (\Exception $e) {
  76.             $def = new Definition();
  77.             $def->setKey($key);
  78.             $fieldFile $def->getDefinitionFile();
  79.             if (is_file($fieldFile)) {
  80.                 $brick = include $fieldFile;
  81.                 \Pimcore\Cache\Runtime::set($cacheKey$brick);
  82.             }
  83.         }
  84.         if ($brick) {
  85.             return $brick;
  86.         }
  87.         return null;
  88.     }
  89.     /**
  90.      * @throws \Exception
  91.      */
  92.     private function checkTablenames()
  93.     {
  94.         $tables = [];
  95.         $key $this->getKey();
  96.         if (!$this->getFieldDefinitions()) {
  97.             return;
  98.         }
  99.         $isLocalized $this->getFieldDefinition('localizedfields') ? true false;
  100.         $classDefinitions $this->getClassDefinitions();
  101.         $validLanguages Tool::getValidLanguages();
  102.         foreach ($classDefinitions as $classDef) {
  103.             $classname $classDef['classname'];
  104.             $class DataObject\ClassDefinition::getByName($classname);
  105.             if (!$class) {
  106.                 Logger::error('class ' $classname " doesn't exist anymore");
  107.                 continue;
  108.             }
  109.             $tables[] = 'object_brick_query_' $key .  '_' $class->getId();
  110.             $tables[] = 'object_brick_store_' $key .  '_' $class->getId();
  111.             if ($isLocalized) {
  112.                 foreach ($validLanguages as $validLanguage) {
  113.                     $tables[] = 'object_brick_localized_query_' $key '_' $class->getId() . '_' $validLanguage;
  114.                     $tables[] = 'object_brick_localized_' $key '_' $class->getId();
  115.                 }
  116.             }
  117.         }
  118.         array_multisort(array_map('strlen'$tables), $tables);
  119.         $longestTablename end($tables);
  120.         $length strlen($longestTablename);
  121.         if ($length 64) {
  122.             throw new \Exception('table name ' $longestTablename ' would be too long. Max length is 64. Current length would be ' .  $length '.');
  123.         }
  124.     }
  125.     /**
  126.      * @param bool $saveDefinitionFile
  127.      *
  128.      * @throws \Exception
  129.      */
  130.     public function save($saveDefinitionFile true)
  131.     {
  132.         if (!$this->getKey()) {
  133.             throw new \Exception('A object-brick needs a key to be saved!');
  134.         }
  135.         if (!preg_match('/[a-zA-Z]+[a-zA-Z0-9]+/'$this->getKey())) {
  136.             throw new \Exception(sprintf('Invalid key for object-brick: %s'$this->getKey()));
  137.         }
  138.         if ($this->getParentClass() && !preg_match('/^[a-zA-Z_\x7f-\xff\\\][a-zA-Z0-9_\x7f-\xff\\\]*$/'$this->getParentClass())) {
  139.             throw new \Exception(sprintf('Invalid parentClass value for class definition: %s',
  140.                 $this->getParentClass()));
  141.         }
  142.         $this->checkTablenames();
  143.         $this->checkContainerRestrictions();
  144.         $fieldDefinitions $this->getFieldDefinitions();
  145.         foreach ($fieldDefinitions as $fd) {
  146.             if ($fd->isForbiddenName()) {
  147.                 throw new \Exception(sprintf('Forbidden name used for field definition: %s'$fd->getName()));
  148.             }
  149.             if ($fd instanceof DataObject\ClassDefinition\Data\DataContainerAwareInterface) {
  150.                 $fd->preSave($this);
  151.             }
  152.         }
  153.         $newClassDefinitions = [];
  154.         $classDefinitionsToDelete = [];
  155.         foreach ($this->classDefinitions as $cl) {
  156.             if (!isset($cl['deleted']) || !$cl['deleted']) {
  157.                 $newClassDefinitions[] = $cl;
  158.             } else {
  159.                 $classDefinitionsToDelete[] = $cl;
  160.             }
  161.         }
  162.         $this->classDefinitions $newClassDefinitions;
  163.         $this->generateClassFiles($saveDefinitionFile);
  164.         $cacheKey 'objectbrick_' $this->getKey();
  165.         // for localized fields getting a fresh copy
  166.         Runtime::set($cacheKey$this);
  167.         $this->createContainerClasses();
  168.         $this->updateDatabase();
  169.         foreach ($fieldDefinitions as $fd) {
  170.             if ($fd instanceof DataObject\ClassDefinition\Data\DataContainerAwareInterface) {
  171.                 $fd->postSave($this);
  172.             }
  173.         }
  174.     }
  175.     private function enforceBlockRules($fds$found = [])
  176.     {
  177.         if (($found['block'] ?? false) && ($found['localizedfield'] ?? false)) {
  178.             throw new \Exception('A localizedfield cannot be nested inside a block and vice versa');
  179.         }
  180.         /** @var DataObject\ClassDefinition\Data $fd */
  181.         foreach ($fds as $fd) {
  182.             $childParams $found;
  183.             if ($fd instanceof DataObject\ClassDefinition\Data\Block) {
  184.                 $childParams['block'] = true;
  185.             } elseif ($fd instanceof DataObject\ClassDefinition\Data\Localizedfields) {
  186.                 $childParams['localizedfield'] = true;
  187.             }
  188.             if (method_exists($fd'getFieldDefinitions')) {
  189.                 $this->enforceBlockRules($fd->getFieldDefinitions(), $childParams);
  190.             }
  191.         }
  192.     }
  193.     private function checkContainerRestrictions()
  194.     {
  195.         $fds $this->getFieldDefinitions();
  196.         $this->enforceBlockRules($fds);
  197.     }
  198.     /**
  199.      * {@inheritdoc}
  200.      */
  201.     protected function generateClassFiles($generateDefinitionFile true)
  202.     {
  203.         if ($generateDefinitionFile && !$this->isWritable()) {
  204.             throw new \Exception(sprintf('Definitions in %s folder cannot be overwritten'PIMCORE_CUSTOM_CONFIGURATION_DIRECTORY));
  205.         }
  206.         $definitionFile $this->getDefinitionFile();
  207.         $infoDocBlock $this->getInfoDocBlock();
  208.         if ($generateDefinitionFile) {
  209.             $this->cleanupOldFiles($definitionFile);
  210.             /** @var self $clone */
  211.             $clone DataObject\Service::cloneDefinition($this);
  212.             $clone->setDao(null);
  213.             unset($clone->oldClassDefinitions);
  214.             unset($clone->fieldDefinitions);
  215.             DataObject\ClassDefinition::cleanupForExport($clone->layoutDefinitions);
  216.             $exportedClass var_export($clonetrue);
  217.             $data '<?php';
  218.             $data .= "\n\n";
  219.             $data .= $infoDocBlock;
  220.             $data .= "\n\n";
  221.             $data .= "\nreturn " $exportedClass ";\n";
  222.             \Pimcore\File::put($definitionFile$data);
  223.         }
  224.         $extendClass 'DataObject\\Objectbrick\\Data\\AbstractData';
  225.         if ($this->getParentClass()) {
  226.             $extendClass $this->getParentClass();
  227.             $extendClass '\\' ltrim($extendClass'\\');
  228.         }
  229.         // create class
  230.         $cd '<?php';
  231.         $cd .= "\n\n";
  232.         $cd .= $infoDocBlock;
  233.         $cd .= "\n\n";
  234.         $cd .= 'namespace Pimcore\\Model\\DataObject\\Objectbrick\\Data;';
  235.         $cd .= "\n\n";
  236.         $useParts = [
  237.             'Pimcore\Model\DataObject',
  238.             'Pimcore\Model\DataObject\Exception\InheritanceParentNotFoundException',
  239.             'Pimcore\Model\DataObject\PreGetValueHookInterface',
  240.         ];
  241.         $cd .= DataObject\ClassDefinition\Service::buildUseCode($useParts);
  242.         $cd .= "\n";
  243.         $implementsParts = [];
  244.         $implements DataObject\ClassDefinition\Service::buildImplementsInterfacesCode($implementsParts$this->getImplementsInterfaces());
  245.         $cd .= 'class ' ucfirst($this->getKey()) . ' extends ' $extendClass $implements "\n";
  246.         $cd .= '{' "\n";
  247.         $cd .= 'protected $type = "' $this->getKey() . "\";\n";
  248.         if (is_array($this->getFieldDefinitions()) && count($this->getFieldDefinitions())) {
  249.             foreach ($this->getFieldDefinitions() as $key => $def) {
  250.                 $cd .= 'protected $' $key ";\n";
  251.             }
  252.         }
  253.         $cd .= "\n\n";
  254.         $cd .= '/**' ."\n";
  255.         $cd .= '* ' ucfirst($this->getKey()) . ' constructor.' "\n";
  256.         $cd .= '* @param DataObject\Concrete $object' "\n";
  257.         $cd .= '*/' "\n";
  258.         $cd .= 'public function __construct(DataObject\Concrete $object)' "\n";
  259.         $cd .= '{' "\n";
  260.         $cd .= "\t" 'parent::__construct($object);' "\n";
  261.         $cd .= "\t" .'$this->markFieldDirty("_self");' "\n";
  262.         $cd .= '}' "\n";
  263.         $cd .= "\n\n";
  264.         if (is_array($this->getFieldDefinitions()) && count($this->getFieldDefinitions())) {
  265.             foreach ($this->getFieldDefinitions() as $key => $def) {
  266.                 $cd .= $def->getGetterCodeObjectbrick($this);
  267.                 if ($def instanceof DataObject\ClassDefinition\Data\Localizedfields) {
  268.                     $cd .= $def->getGetterCode($this);
  269.                 }
  270.                 $cd .= $def->getSetterCodeObjectbrick($this);
  271.                 if ($def instanceof DataObject\ClassDefinition\Data\Localizedfields) {
  272.                     $cd .= $def->getSetterCode($this);
  273.                 }
  274.             }
  275.         }
  276.         $cd .= "}\n";
  277.         $cd .= "\n";
  278.         File::putPhpFile($this->getPhpClassFile(), $cd);
  279.     }
  280.     /**
  281.      * @param array $definitions
  282.      *
  283.      * @return array
  284.      */
  285.     private function buildClassList($definitions)
  286.     {
  287.         $result = [];
  288.         foreach ($definitions as $definition) {
  289.             $result[] = $definition['classname'] . '-' $definition['fieldname'];
  290.         }
  291.         return $result;
  292.     }
  293.     /**
  294.      * Returns a list of classes which need to be "rebuild" because they are affected of changes.
  295.      *
  296.      * @param self $oldObject
  297.      *
  298.      * @return array
  299.      */
  300.     private function getClassesToCleanup($oldObject)
  301.     {
  302.         $oldDefinitions $oldObject->getClassDefinitions() ? $oldObject->getClassDefinitions() : [];
  303.         $newDefinitions $this->getClassDefinitions() ? $this->getClassDefinitions() : [];
  304.         $old $this->buildClassList($oldDefinitions);
  305.         $new $this->buildClassList($newDefinitions);
  306.         $diff1 array_diff($old$new);
  307.         $diff2 array_diff($new$old);
  308.         $diff array_merge($diff1$diff2);
  309.         $result = [];
  310.         foreach ($diff as $item) {
  311.             $parts explode('-'$item);
  312.             $result[] = ['classname' => $parts[0], 'fieldname' => $parts[1]];
  313.         }
  314.         return $result;
  315.     }
  316.     /**
  317.      * @param string $serializedFilename
  318.      */
  319.     private function cleanupOldFiles($serializedFilename)
  320.     {
  321.         $oldObject null;
  322.         $this->oldClassDefinitions = [];
  323.         if (file_exists($serializedFilename)) {
  324.             $oldObject = include $serializedFilename;
  325.         }
  326.         if ($oldObject && !empty($oldObject->classDefinitions)) {
  327.             $classlist $this->getClassesToCleanup($oldObject);
  328.             foreach ($classlist as $cl) {
  329.                 $this->oldClassDefinitions[$cl['classname']] = $cl['classname'];
  330.                 $class DataObject\ClassDefinition::getByName($cl['classname']);
  331.                 if ($class) {
  332.                     $path $this->getContainerClassFolder($class->getName());
  333.                     @unlink($path '/' ucfirst($cl['fieldname'] . '.php'));
  334.                     foreach ($class->getFieldDefinitions() as $fieldDef) {
  335.                         if ($fieldDef instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  336.                             $allowedTypes $fieldDef->getAllowedTypes();
  337.                             $idx array_search($this->getKey(), $allowedTypes);
  338.                             if ($idx !== false) {
  339.                                 array_splice($allowedTypes$idx1);
  340.                             }
  341.                             $fieldDef->setAllowedTypes($allowedTypes);
  342.                         }
  343.                     }
  344.                     $class->save();
  345.                 }
  346.             }
  347.         }
  348.     }
  349.     /**
  350.      * Update Database according to class-definition
  351.      */
  352.     private function updateDatabase()
  353.     {
  354.         $processedClasses = [];
  355.         if (!empty($this->classDefinitions)) {
  356.             foreach ($this->classDefinitions as $cl) {
  357.                 unset($this->oldClassDefinitions[$cl['classname']]);
  358.                 if (empty($processedClasses[$cl['classname']])) {
  359.                     $class DataObject\ClassDefinition::getByName($cl['classname']);
  360.                     $this->getDao()->createUpdateTable($class);
  361.                     $processedClasses[$cl['classname']] = true;
  362.                 }
  363.             }
  364.         }
  365.         if (!empty($this->oldClassDefinitions)) {
  366.             foreach ($this->oldClassDefinitions as $cl) {
  367.                 $class DataObject\ClassDefinition::getByName($cl);
  368.                 if ($class) {
  369.                     $this->getDao()->delete($class);
  370.                     foreach ($class->getFieldDefinitions() as $fieldDef) {
  371.                         if ($fieldDef instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  372.                             $allowedTypes $fieldDef->getAllowedTypes();
  373.                             $idx array_search($this->getKey(), $allowedTypes);
  374.                             if ($idx !== false) {
  375.                                 array_splice($allowedTypes$idx1);
  376.                             }
  377.                             $fieldDef->setAllowedTypes($allowedTypes);
  378.                         }
  379.                     }
  380.                     $class->save();
  381.                 }
  382.             }
  383.         }
  384.     }
  385.     /**
  386.      * @param DataObject\ClassDefinition $class
  387.      *
  388.      * @return array
  389.      */
  390.     private function getAllowedTypesWithFieldname(DataObject\ClassDefinition $class)
  391.     {
  392.         $result = [];
  393.         $fieldDefinitions $class->getFieldDefinitions();
  394.         foreach ($fieldDefinitions as $fd) {
  395.             if (!$fd instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  396.                 continue;
  397.             }
  398.             $allowedTypes $fd->getAllowedTypes() ? $fd->getAllowedTypes() : [];
  399.             foreach ($allowedTypes as $allowedType) {
  400.                 $result[] = $fd->getName() . '-' $allowedType;
  401.             }
  402.         }
  403.         return $result;
  404.     }
  405.     /**
  406.      * @throws \Exception
  407.      */
  408.     private function createContainerClasses()
  409.     {
  410.         $containerDefinition = [];
  411.         if (!empty($this->classDefinitions)) {
  412.             foreach ($this->classDefinitions as $cl) {
  413.                 $containerDefinition[$cl['classname']][$cl['fieldname']][] = $this->key;
  414.                 $class DataObject\ClassDefinition::getByName($cl['classname']);
  415.                 if (!$class) {
  416.                     throw new \Exception('Could not load class ' $cl['classname']);
  417.                 }
  418.                 $fd $class->getFieldDefinition($cl['fieldname']);
  419.                 if (!$fd instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  420.                     throw new \Exception('Could not resolve field definition for ' $cl['fieldname']);
  421.                 }
  422.                 $old $this->getAllowedTypesWithFieldname($class);
  423.                 $allowedTypes $fd->getAllowedTypes() ? $fd->getAllowedTypes() : [];
  424.                 if (!in_array($this->key$allowedTypes)) {
  425.                     $allowedTypes[] = $this->key;
  426.                 }
  427.                 $fd->setAllowedTypes($allowedTypes);
  428.                 $new $this->getAllowedTypesWithFieldname($class);
  429.                 if (array_diff($new$old) || array_diff($old$new)) {
  430.                     $class->save();
  431.                 } else {
  432.                     // still, the brick fields definitions could have changed.
  433.                     Cache::clearTag('class_'.$class->getId());
  434.                     Logger::debug('Objectbrick ' $this->getKey() . ', no change for class ' $class->getName());
  435.                 }
  436.             }
  437.         }
  438.         $list = new DataObject\Objectbrick\Definition\Listing();
  439.         $list $list->load();
  440.         foreach ($list as $def) {
  441.             if ($this->key != $def->getKey()) {
  442.                 $classDefinitions $def->getClassDefinitions();
  443.                 if (!empty($classDefinitions)) {
  444.                     foreach ($classDefinitions as $cl) {
  445.                         $containerDefinition[$cl['classname']][$cl['fieldname']][] = $def->getKey();
  446.                     }
  447.                 }
  448.             }
  449.         }
  450.         foreach ($containerDefinition as $classId => $cd) {
  451.             $class DataObject\ClassDefinition::getByName($classId);
  452.             if (!$class) {
  453.                 continue;
  454.             }
  455.             foreach ($cd as $fieldname => $brickKeys) {
  456.                 $className $this->getContainerClassName($class->getName(), $fieldname);
  457.                 $namespace $this->getContainerNamespace($class->getName(), $fieldname);
  458.                 $cd '<?php';
  459.                 $cd .= "\n\n";
  460.                 $cd .= 'namespace ' $namespace ';';
  461.                 $cd .= "\n\n";
  462.                 $cd .= 'use Pimcore\Model\DataObject\Exception\InheritanceParentNotFoundException;';
  463.                 $cd .= "\n\n";
  464.                 $cd .= 'class ' $className ' extends \\Pimcore\\Model\\DataObject\\Objectbrick {';
  465.                 $cd .= "\n\n";
  466.                 $cd .= 'protected $brickGetters = [' "'" implode("','"$brickKeys) . "'];\n";
  467.                 $cd .= "\n\n";
  468.                 foreach ($brickKeys as $brickKey) {
  469.                     $cd .= 'protected $' $brickKey " = null;\n\n";
  470.                     $cd .= '/**' "\n";
  471.                     $cd .= '* @return \\Pimcore\\Model\\DataObject\\Objectbrick\\Data\\' ucfirst($brickKey) . "|null\n";
  472.                     $cd .= '*/' "\n";
  473.                     $cd .= 'public function get' ucfirst($brickKey) . '()' "\n";
  474.                     $cd .= '{' "\n";
  475.                     if ($class->getAllowInherit()) {
  476.                         $cd .= "\t" 'if(!$this->' $brickKey ' && \\Pimcore\\Model\\DataObject::doGetInheritedValues($this->getObject())) { ' "\n";
  477.                         $cd .= "\t\t" 'try {' "\n";
  478.                         $cd .= "\t\t\t" '$brickContainer = $this->getObject()->getValueFromParent("' $fieldname '");' "\n";
  479.                         $cd .= "\t\t\t" 'if(!empty($brickContainer)) {' "\n";
  480.                         $cd .= "\t\t\t\t" '//check if parent object has brick, and if so, create an empty brick to enable inheritance' "\n";
  481.                         $cd .= "\t\t\t\t" '$parentBrick = $this->getObject()->getValueFromParent("' $fieldname '")->get' ucfirst($brickKey) . "();\n";
  482.                         $cd .= "\t\t\t\t" 'if (!empty($parentBrick)) {' "\n";
  483.                         $cd .= "\t\t\t\t\t" '$brickType = "\\\Pimcore\\\Model\\\DataObject\\\Objectbrick\\\Data\\\" . ucfirst($parentBrick->getType());' "\n";
  484.                         $cd .= "\t\t\t\t\t" '$brick = new $brickType($this->getObject());' "\n";
  485.                         $cd .= "\t\t\t\t\t" '$brick->setFieldname("' $fieldname '");' "\n";
  486.                         $cd .= "\t\t\t\t\t" '$this->set'ucfirst($brickKey) . '($brick);' "\n";
  487.                         $cd .= "\t\t\t\t\t" 'return $brick;' "\n";
  488.                         $cd .= "\t\t\t\t" '}' "\n";
  489.                         $cd .= "\t\t\t" "}\n";
  490.                         $cd .= "\t\t" '} catch (InheritanceParentNotFoundException $e) {' "\n";
  491.                         $cd .= "\t\t\t" '// no data from parent available, continue ...' "\n";
  492.                         $cd .= "\t\t" '}' "\n";
  493.                         $cd .= "\t" "}\n";
  494.                     }
  495.                     $cd .= "\t" 'return $this->' $brickKey ";\n";
  496.                     $cd .= "}\n\n";
  497.                     $cd .= '/**' "\n";
  498.                     $cd .= '* @param \\Pimcore\\Model\\DataObject\\Objectbrick\\Data\\' ucfirst($brickKey) . ' $' $brickKey "\n";
  499.                     $cd .= '* @return \\'.$namespace.'\\'.$className."\n";
  500.                     $cd .= '*/' "\n";
  501.                     $cd .= 'public function set' ucfirst($brickKey) . '(' '$' $brickKey ')' "\n";
  502.                     $cd .= '{' "\n";
  503.                     $cd .= "\t" '$this->' $brickKey ' = ' '$' $brickKey ";\n";
  504.                     $cd .= "\t" 'return $this' ";\n";
  505.                     $cd .= "}\n\n";
  506.                 }
  507.                 $cd .= "}\n";
  508.                 $cd .= "\n";
  509.                 $folder $this->getContainerClassFolder($class->getName());
  510.                 if (!is_dir($folder)) {
  511.                     File::mkdir($folder);
  512.                 }
  513.                 $file $folder '/' ucfirst($fieldname) . '.php';
  514.                 File::put($file$cd);
  515.             }
  516.         }
  517.     }
  518.     /**
  519.      * @param string $classname
  520.      * @param string $fieldname
  521.      *
  522.      * @return string
  523.      */
  524.     private function getContainerClassName($classname$fieldname)
  525.     {
  526.         return ucfirst($fieldname);
  527.     }
  528.     /**
  529.      * @param string $classname
  530.      * @param string $fieldname
  531.      *
  532.      * @return string
  533.      */
  534.     private function getContainerNamespace($classname$fieldname)
  535.     {
  536.         return 'Pimcore\\Model\\DataObject\\' ucfirst($classname);
  537.     }
  538.     /**
  539.      * @param string $classname
  540.      *
  541.      * @return string
  542.      */
  543.     private function getContainerClassFolder($classname)
  544.     {
  545.         return PIMCORE_CLASS_DIRECTORY '/DataObject/' ucfirst($classname);
  546.     }
  547.     /**
  548.      * Delete Brick Definition
  549.      */
  550.     public function delete()
  551.     {
  552.         @unlink($this->getDefinitionFile());
  553.         @unlink($this->getPhpClassFile());
  554.         $processedClasses = [];
  555.         if (!empty($this->classDefinitions)) {
  556.             foreach ($this->classDefinitions as $cl) {
  557.                 unset($this->oldClassDefinitions[$cl['classname']]);
  558.                 if (!isset($processedClasses[$cl['classname']])) {
  559.                     $processedClasses[$cl['classname']] = true;
  560.                     $class DataObject\ClassDefinition::getByName($cl['classname']);
  561.                     if ($class instanceof DataObject\ClassDefinition) {
  562.                         $this->getDao()->delete($class);
  563.                         foreach ($class->getFieldDefinitions() as $fieldDef) {
  564.                             if ($fieldDef instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  565.                                 $allowedTypes $fieldDef->getAllowedTypes();
  566.                                 $idx array_search($this->getKey(), $allowedTypes);
  567.                                 if ($idx !== false) {
  568.                                     array_splice($allowedTypes$idx1);
  569.                                 }
  570.                                 $fieldDef->setAllowedTypes($allowedTypes);
  571.                             }
  572.                         }
  573.                         $class->save();
  574.                     }
  575.                 }
  576.             }
  577.         }
  578.         // update classes
  579.         $classList = new DataObject\ClassDefinition\Listing();
  580.         $classes $classList->load();
  581.         if (is_array($classes)) {
  582.             foreach ($classes as $class) {
  583.                 foreach ($class->getFieldDefinitions() as $fieldDef) {
  584.                     if ($fieldDef instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  585.                         if (in_array($this->getKey(), $fieldDef->getAllowedTypes())) {
  586.                             break;
  587.                         }
  588.                     }
  589.                 }
  590.             }
  591.         }
  592.     }
  593.     /**
  594.      * {@inheritdoc}
  595.      */
  596.     protected function doEnrichFieldDefinition($fieldDefinition$context = [])
  597.     {
  598.         //TODO Pimcore 11: remove method_exists BC layer
  599.         if ($fieldDefinition instanceof FieldDefinitionEnrichmentInterface || method_exists($fieldDefinition'enrichFieldDefinition')) {
  600.             if (!$fieldDefinition instanceof FieldDefinitionEnrichmentInterface) {
  601.                 trigger_deprecation('pimcore/pimcore''10.1',
  602.                     sprintf('Usage of method_exists is deprecated since version 10.1 and will be removed in Pimcore 11.' .
  603.                     'Implement the %s interface instead.'FieldDefinitionEnrichmentInterface::class));
  604.             }
  605.             $context['containerType'] = 'objectbrick';
  606.             $context['containerKey'] = $this->getKey();
  607.             $fieldDefinition $fieldDefinition->enrichFieldDefinition($context);
  608.         }
  609.         return $fieldDefinition;
  610.     }
  611.     /**
  612.      * @internal
  613.      *
  614.      * @return bool
  615.      */
  616.     public function isWritable(): bool
  617.     {
  618.         if ($_SERVER['PIMCORE_CLASS_DEFINITION_WRITABLE'] ?? false) {
  619.             return true;
  620.         }
  621.         return !str_starts_with($this->getDefinitionFile(), PIMCORE_CUSTOM_CONFIGURATION_DIRECTORY);
  622.     }
  623.     /**
  624.      * @internal
  625.      *
  626.      * @param string|null $key
  627.      *
  628.      * @return string
  629.      */
  630.     public function getDefinitionFile($key null)
  631.     {
  632.         return $this->locateFile($key ?? $this->getKey(), 'objectbricks/%s.php');
  633.     }
  634.     /**
  635.      * @internal
  636.      *
  637.      * @return string
  638.      */
  639.     protected function getPhpClassFile()
  640.     {
  641.         return $this->locateFile(ucfirst($this->getKey()), 'DataObject/Objectbrick/Data/%s.php');
  642.     }
  643. }