vendor/pimcore/pimcore/models/DataObject/ClassDefinition.php line 290

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;
  15. use Pimcore\Cache;
  16. use Pimcore\Db;
  17. use Pimcore\Event\DataObjectClassDefinitionEvents;
  18. use Pimcore\Event\Model\DataObject\ClassDefinitionEvent;
  19. use Pimcore\File;
  20. use Pimcore\Logger;
  21. use Pimcore\Model;
  22. use Pimcore\Model\DataObject;
  23. use Pimcore\Model\DataObject\ClassDefinition\Data\FieldDefinitionEnrichmentInterface;
  24. /**
  25.  * @method \Pimcore\Model\DataObject\ClassDefinition\Dao getDao()
  26.  */
  27. final class ClassDefinition extends Model\AbstractModel
  28. {
  29.     use DataObject\ClassDefinition\Helper\VarExport;
  30.     use DataObject\Traits\LocateFileTrait;
  31.     /**
  32.      * @internal
  33.      *
  34.      * @var string|null
  35.      */
  36.     public $id;
  37.     /**
  38.      * @internal
  39.      *
  40.      * @var string|null
  41.      */
  42.     public $name;
  43.     /**
  44.      * @internal
  45.      *
  46.      * @var string
  47.      */
  48.     public $description '';
  49.     /**
  50.      * @internal
  51.      *
  52.      * @var int|null
  53.      */
  54.     public $creationDate;
  55.     /**
  56.      * @internal
  57.      *
  58.      * @var int|null
  59.      */
  60.     public $modificationDate;
  61.     /**
  62.      * @internal
  63.      *
  64.      * @var int|null
  65.      */
  66.     public $userOwner;
  67.     /**
  68.      * @internal
  69.      *
  70.      * @var int|null
  71.      */
  72.     public $userModification;
  73.     /**
  74.      * @internal
  75.      *
  76.      * @var string
  77.      */
  78.     public $parentClass '';
  79.     /**
  80.      * Comma separated list of interfaces
  81.      *
  82.      * @internal
  83.      *
  84.      * @var string|null
  85.      */
  86.     public $implementsInterfaces;
  87.     /**
  88.      * Name of the listing parent class if set
  89.      *
  90.      * @internal
  91.      *
  92.      * @var string
  93.      */
  94.     public $listingParentClass '';
  95.     /**
  96.      * @internal
  97.      *
  98.      * @var string
  99.      */
  100.     public $useTraits '';
  101.     /**
  102.      * @internal
  103.      *
  104.      * @var string
  105.      */
  106.     public $listingUseTraits '';
  107.     /**
  108.      * @internal
  109.      *
  110.      * @var bool
  111.      */
  112.     protected $encryption false;
  113.     /**
  114.      * @internal
  115.      *
  116.      * @var array
  117.      */
  118.     protected $encryptedTables = [];
  119.     /**
  120.      * @internal
  121.      *
  122.      * @var bool
  123.      */
  124.     public $allowInherit false;
  125.     /**
  126.      * @internal
  127.      *
  128.      * @var bool
  129.      */
  130.     public $allowVariants false;
  131.     /**
  132.      * @internal
  133.      *
  134.      * @var bool
  135.      */
  136.     public $showVariants false;
  137.     /**
  138.      * @internal
  139.      *
  140.      * @var DataObject\ClassDefinition\Data[]
  141.      */
  142.     public array $fieldDefinitions = [];
  143.     /**
  144.      * @internal
  145.      *
  146.      * @var DataObject\ClassDefinition\Layout|null
  147.      */
  148.     public $layoutDefinitions;
  149.     /**
  150.      * @internal
  151.      *
  152.      * @var string
  153.      */
  154.     public $icon;
  155.     /**
  156.      * @internal
  157.      *
  158.      * @var string
  159.      */
  160.     public $previewUrl;
  161.     /**
  162.      * @internal
  163.      *
  164.      * @var string
  165.      */
  166.     public $group;
  167.     /**
  168.      * @internal
  169.      *
  170.      * @var bool
  171.      */
  172.     public $showAppLoggerTab false;
  173.     /**
  174.      * @internal
  175.      *
  176.      * @var string
  177.      */
  178.     public $linkGeneratorReference;
  179.     /**
  180.      * @internal
  181.      *
  182.      * @var string|null
  183.      */
  184.     public $previewGeneratorReference;
  185.     /**
  186.      * @internal
  187.      *
  188.      * @var array
  189.      */
  190.     public $compositeIndices = [];
  191.     /**
  192.      * @internal
  193.      *
  194.      * @var bool
  195.      */
  196.     public $generateTypeDeclarations true;
  197.     /**
  198.      * @internal
  199.      *
  200.      * @var bool
  201.      */
  202.     public $showFieldLookup false;
  203.     /**
  204.      * @internal
  205.      *
  206.      * @var array
  207.      */
  208.     public $propertyVisibility = [
  209.         'grid' => [
  210.             'id' => true,
  211.             'path' => true,
  212.             'published' => true,
  213.             'modificationDate' => true,
  214.             'creationDate' => true,
  215.         ],
  216.         'search' => [
  217.             'id' => true,
  218.             'path' => true,
  219.             'published' => true,
  220.             'modificationDate' => true,
  221.             'creationDate' => true,
  222.         ],
  223.     ];
  224.     /**
  225.      * @internal
  226.      *
  227.      * @var bool
  228.      */
  229.     public $enableGridLocking false;
  230.     /**
  231.      * @param string $id
  232.      * @param bool $force
  233.      *
  234.      * @return null|ClassDefinition
  235.      *
  236.      * @throws \Exception
  237.      */
  238.     public static function getById(string $id$force false)
  239.     {
  240.         $cacheKey 'class_' $id;
  241.         try {
  242.             if ($force) {
  243.                 throw new \Exception('Forced load');
  244.             }
  245.             $class \Pimcore\Cache\Runtime::get($cacheKey);
  246.             if (!$class) {
  247.                 throw new \Exception('Class in registry is null');
  248.             }
  249.         } catch (\Exception $e) {
  250.             try {
  251.                 $class = new self();
  252.                 $name $class->getDao()->getNameById($id);
  253.                 $definitionFile $class->getDefinitionFile($name);
  254.                 $class = @include $definitionFile;
  255.                 if (!$class instanceof self) {
  256.                     throw new \Exception('Class definition with name ' $name ' or ID ' $id ' does not exist');
  257.                 }
  258.                 $class->setId($id);
  259.                 \Pimcore\Cache\Runtime::set($cacheKey$class);
  260.             } catch (\Exception $e) {
  261.                 Logger::info($e->getMessage());
  262.                 return null;
  263.             }
  264.         }
  265.         return $class;
  266.     }
  267.     /**
  268.      * @param string $name
  269.      *
  270.      * @return self|null
  271.      *
  272.      * @throws \Exception
  273.      */
  274.     public static function getByName($name)
  275.     {
  276.         try {
  277.             $class = new self();
  278.             $id $class->getDao()->getIdByName($name);
  279.             return self::getById($id);
  280.         } catch (Model\Exception\NotFoundException $e) {
  281.             return null;
  282.         }
  283.     }
  284.     /**
  285.      * @param array $values
  286.      *
  287.      * @return self
  288.      */
  289.     public static function create($values = [])
  290.     {
  291.         $class = new self();
  292.         $class->setValues($values);
  293.         return $class;
  294.     }
  295.     /**
  296.      * @internal
  297.      *
  298.      * @param string $name
  299.      */
  300.     public function rename($name)
  301.     {
  302.         $this->deletePhpClasses();
  303.         $this->getDao()->updateClassNameInObjects($name);
  304.         $this->setName($name);
  305.         $this->save();
  306.     }
  307.     /**
  308.      * @param mixed $data
  309.      *
  310.      * @internal
  311.      */
  312.     public static function cleanupForExport(&$data)
  313.     {
  314.         if (!is_object($data)) {
  315.             return;
  316.         }
  317.         if ($data instanceof DataObject\ClassDefinition\Data\VarExporterInterface) {
  318.             $blockedVars $data->resolveBlockedVars();
  319.             foreach ($blockedVars as $blockedVar) {
  320.                 if (isset($data->{$blockedVar})) {
  321.                     unset($data->{$blockedVar});
  322.                 }
  323.             }
  324.             if (isset($data->blockedVarsForExport)) {
  325.                 unset($data->blockedVarsForExport);
  326.             }
  327.         }
  328.         if (method_exists($data'getChildren')) {
  329.             $children $data->getChildren();
  330.             if (is_array($children)) {
  331.                 foreach ($children as $child) {
  332.                     self::cleanupForExport($child);
  333.                 }
  334.             }
  335.         }
  336.     }
  337.     /**
  338.      * @return bool
  339.      */
  340.     private function exists()
  341.     {
  342.         $name $this->getDao()->getNameById($this->getId());
  343.         return is_string($name);
  344.     }
  345.     /**
  346.      * @param bool $saveDefinitionFile
  347.      *
  348.      * @throws \Exception
  349.      * @throws DataObject\Exception\DefinitionWriteException
  350.      */
  351.     public function save($saveDefinitionFile true)
  352.     {
  353.         if ($saveDefinitionFile && !$this->isWritable()) {
  354.             throw new DataObject\Exception\DefinitionWriteException();
  355.         }
  356.         $fieldDefinitions $this->getFieldDefinitions();
  357.         foreach ($fieldDefinitions as $fd) {
  358.             if ($fd->isForbiddenName()) {
  359.                 throw new \Exception(sprintf('Forbidden name used for field definition: %s'$fd->getName()));
  360.             }
  361.             if ($fd instanceof DataObject\ClassDefinition\Data\DataContainerAwareInterface) {
  362.                 $fd->preSave($this);
  363.             }
  364.         }
  365.         if (!$this->getId()) {
  366.             $db Db::get();
  367.             $maxId $db->fetchOne('SELECT MAX(CAST(id AS SIGNED)) FROM classes;');
  368.             $this->setId($maxId $maxId 1);
  369.         }
  370.         if (!preg_match('/[a-zA-Z][a-zA-Z0-9_]+/'$this->getName())) {
  371.             throw new \Exception(sprintf('Invalid name for class definition: %s'$this->getName()));
  372.         }
  373.         if (!preg_match('/[a-zA-Z0-9]([a-zA-Z0-9_]+)?/'$this->getId())) {
  374.             throw new \Exception(sprintf('Invalid ID `%s` for class definition %s'$this->getId(), $this->getName()));
  375.         }
  376.         foreach (['parentClass''listingParentClass''useTraits''listingUseTraits'] as $propertyName) {
  377.             $propertyValue $this->{'get'.ucfirst($propertyName)}();
  378.             if ($propertyValue && !preg_match('/^[a-zA-Z_\x7f-\xff\\\][a-zA-Z0-9_\x7f-\xff\\\ ,]*$/'$propertyValue)) {
  379.                 throw new \Exception(sprintf('Invalid %s value for class definition: %s'$propertyName,
  380.                     $this->getParentClass()));
  381.             }
  382.         }
  383.         $isUpdate $this->exists();
  384.         if (!$isUpdate) {
  385.             \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::PRE_ADD);
  386.         } else {
  387.             \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::PRE_UPDATE);
  388.         }
  389.         $this->setModificationDate(time());
  390.         $this->getDao()->save($isUpdate);
  391.         $this->generateClassFiles($saveDefinitionFile);
  392.         // empty object cache
  393.         try {
  394.             Cache::clearTag('class_'.$this->getId());
  395.         } catch (\Exception $e) {
  396.         }
  397.         foreach ($fieldDefinitions as $fd) {
  398.             if ($fd instanceof DataObject\ClassDefinition\Data\DataContainerAwareInterface) {
  399.                 $fd->postSave($this);
  400.             }
  401.         }
  402.         if ($isUpdate) {
  403.             \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::POST_UPDATE);
  404.         } else {
  405.             \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::POST_ADD);
  406.         }
  407.     }
  408.     /**
  409.      * @param bool $generateDefinitionFile
  410.      *
  411.      * @throws \Exception
  412.      *
  413.      * @internal
  414.      */
  415.     public function generateClassFiles($generateDefinitionFile true)
  416.     {
  417.         $infoDocBlock $this->getInfoDocBlock();
  418.         // create class for object
  419.         $extendClass 'Concrete';
  420.         if ($this->getParentClass()) {
  421.             $extendClass $this->getParentClass();
  422.             $extendClass '\\'.ltrim($extendClass'\\');
  423.         }
  424.         $cd '<?php';
  425.         $cd .= "\n\n";
  426.         $cd .= $infoDocBlock;
  427.         $cd .= "\n\n";
  428.         $cd .= 'namespace Pimcore\\Model\\DataObject;';
  429.         $cd .= "\n\n";
  430.         $cd .= 'use Pimcore\Model\DataObject\Exception\InheritanceParentNotFoundException;';
  431.         $cd .= "\n";
  432.         $cd .= 'use Pimcore\Model\DataObject\PreGetValueHookInterface;';
  433.         $cd .= "\n\n";
  434.         $cd .= "/**\n";
  435.         $cd .= '* @method static \\Pimcore\\Model\\DataObject\\'.ucfirst($this->getName()).'\Listing getList(array $config = [])'."\n";
  436.         if (is_array($this->getFieldDefinitions()) && count($this->getFieldDefinitions())) {
  437.             foreach ($this->getFieldDefinitions() as $key => $def) {
  438.                 if ($def instanceof DataObject\ClassDefinition\Data\Localizedfields) {
  439.                     $cd .= '* @method static \\Pimcore\\Model\\DataObject\\'.ucfirst(
  440.                             $this->getName()
  441.                         ).'\Listing|\\Pimcore\\Model\\DataObject\\'.ucfirst(
  442.                             $this->getName()
  443.                         ).'|null getBy'.ucfirst(
  444.                             $def->getName()
  445.                         ).'($field, $value, $locale = null, $limit = 0, $offset = 0, $objectTypes = null)'."\n";
  446.                     foreach ($def->getFieldDefinitions() as $localizedFieldDefinition) {
  447.                         $cd .= '* @method static \\Pimcore\\Model\\DataObject\\'.ucfirst(
  448.                                 $this->getName()
  449.                             ).'\Listing|\\Pimcore\\Model\\DataObject\\'.ucfirst(
  450.                                 $this->getName()
  451.                             ).'|null getBy'.ucfirst(
  452.                                 $localizedFieldDefinition->getName()
  453.                             ).'($value, $locale = null, $limit = 0, $offset = 0, $objectTypes = null)'."\n";
  454.                     }
  455.                 } elseif ($def->isFilterable()) {
  456.                     $cd .= '* @method static \\Pimcore\\Model\\DataObject\\'.ucfirst(
  457.                             $this->getName()
  458.                         ).'\Listing|\\Pimcore\\Model\\DataObject\\'.ucfirst(
  459.                             $this->getName()
  460.                         ).'|null getBy'.ucfirst($def->getName()).'($value, $limit = 0, $offset = 0, $objectTypes = null)'."\n";
  461.                 }
  462.             }
  463.         }
  464.         $cd .= "*/\n\n";
  465.         $implementsParts = [];
  466.         $implements DataObject\ClassDefinition\Service::buildImplementsInterfacesCode($implementsParts$this->getImplementsInterfaces());
  467.         $cd .= 'class '.ucfirst($this->getName()).' extends '.$extendClass$implements "\n";
  468.         $cd .= '{' "\n";
  469.         $useParts = [];
  470.         $cd .= DataObject\ClassDefinition\Service::buildUseTraitsCode($useParts$this->getUseTraits());
  471.         $cd .= 'protected $o_classId = "' $this->getId(). "\";\n";
  472.         $cd .= 'protected $o_className = "'.$this->getName().'"'.";\n";
  473.         if (is_array($this->getFieldDefinitions()) && count($this->getFieldDefinitions())) {
  474.             foreach ($this->getFieldDefinitions() as $key => $def) {
  475.                 if (!$def instanceof DataObject\ClassDefinition\Data\ReverseObjectRelation && !$def instanceof DataObject\ClassDefinition\Data\CalculatedValue
  476.                 ) {
  477.                     $cd .= 'protected $'.$key.";\n";
  478.                 }
  479.             }
  480.         }
  481.         $cd .= "\n\n";
  482.         $cd .= '/**'."\n";
  483.         $cd .= '* @param array $values'."\n";
  484.         $cd .= '* @return \\Pimcore\\Model\\DataObject\\'.ucfirst($this->getName())."\n";
  485.         $cd .= '*/'."\n";
  486.         $cd .= 'public static function create($values = array()) {';
  487.         $cd .= "\n";
  488.         $cd .= "\t".'$object = new static();'."\n";
  489.         $cd .= "\t".'$object->setValues($values);'."\n";
  490.         $cd .= "\t".'return $object;'."\n";
  491.         $cd .= '}';
  492.         $cd .= "\n\n";
  493.         if (is_array($this->getFieldDefinitions()) && count($this->getFieldDefinitions())) {
  494.             foreach ($this->getFieldDefinitions() as $key => $def) {
  495.                 if ($def instanceof DataObject\ClassDefinition\Data\ReverseObjectRelation) {
  496.                     continue;
  497.                 }
  498.                 // get setter and getter code
  499.                 $cd .= $def->getGetterCode($this);
  500.                 $cd .= $def->getSetterCode($this);
  501.                 // call the method "classSaved" if exists, this is used to create additional data tables or whatever which depends on the field definition, for example for localizedfields
  502.                 //TODO Pimcore 11 remove method_exists call
  503.                 if (!$def instanceof DataObject\ClassDefinition\Data\DataContainerAwareInterface && method_exists($def'classSaved')) {
  504.                     $def->classSaved($this);
  505.                 }
  506.             }
  507.         }
  508.         $cd .= "}\n";
  509.         $cd .= "\n";
  510.         if (File::put($this->getPhpClassFile(), $cd) === false) {
  511.             throw new \Exception(sprintf('Cannot write class file in %s please check the rights on this directory'$this->getPhpClassFile()));
  512.         }
  513.         // create class for object list
  514.         $extendListingClass 'DataObject\\Listing\\Concrete';
  515.         if ($this->getListingParentClass()) {
  516.             $extendListingClass $this->getListingParentClass();
  517.             $extendListingClass '\\'.ltrim($extendListingClass'\\');
  518.         }
  519.         // create list class
  520.         $cd '<?php';
  521.         $cd .= "\n\n";
  522.         $cd .= 'namespace Pimcore\\Model\\DataObject\\'.ucfirst($this->getName()).';';
  523.         $cd .= "\n\n";
  524.         $cd .= 'use Pimcore\\Model\\DataObject;';
  525.         $cd .= "\n\n";
  526.         $cd .= "/**\n";
  527.         $cd .= ' * @method DataObject\\'.ucfirst($this->getName())."|false current()\n";
  528.         $cd .= ' * @method DataObject\\'.ucfirst($this->getName())."[] load()\n";
  529.         $cd .= ' * @method DataObject\\'.ucfirst($this->getName())."[] getData()\n";
  530.         $cd .= ' */';
  531.         $cd .= "\n\n";
  532.         $cd .= 'class Listing extends '.$extendListingClass "\n";
  533.         $cd .= '{' "\n";
  534.         $cd .= DataObject\ClassDefinition\Service::buildUseTraitsCode([], $this->getListingUseTraits());
  535.         $cd .= 'protected $classId = "'$this->getId()."\";\n";
  536.         $cd .= 'protected $className = "'.$this->getName().'"'.";\n";
  537.         $cd .= "\n\n";
  538.         if (\is_array($this->getFieldDefinitions())) {
  539.             foreach ($this->getFieldDefinitions() as $key => $def) {
  540.                 if ($def instanceof DataObject\ClassDefinition\Data\Localizedfields) {
  541.                     foreach ($def->getFieldDefinitions() as $localizedFieldDefinition) {
  542.                         $cd .= $localizedFieldDefinition->getFilterCode();
  543.                     }
  544.                 } elseif ($def->isFilterable()) {
  545.                     $cd .= $def->getFilterCode();
  546.                 }
  547.             }
  548.         }
  549.         $cd .= "\n\n";
  550.         $cd .= "}\n";
  551.         if (File::put($this->getPhpListingClassFile(), $cd) === false) {
  552.             throw new \Exception(
  553.                 sprintf('Cannot write class file in %s please check the rights on this directory'$this->getPhpListingClassFile())
  554.             );
  555.         }
  556.         if ($generateDefinitionFile) {
  557.             // save definition as a php file
  558.             $definitionFile $this->getDefinitionFile();
  559.             if (!is_writable(dirname($definitionFile)) || (is_file($definitionFile) && !is_writable($definitionFile))) {
  560.                 throw new \Exception(
  561.                     'Cannot write definition file in: '.$definitionFile.' please check write permission on this directory.'
  562.                 );
  563.             }
  564.             /** @var self $clone */
  565.             $clone DataObject\Service::cloneDefinition($this);
  566.             $clone->setDao(null);
  567.             $clone->fieldDefinitions = [];
  568.             self::cleanupForExport($clone->layoutDefinitions);
  569.             $exportedClass var_export($clonetrue);
  570.             $data '<?php';
  571.             $data .= "\n\n";
  572.             $data .= $infoDocBlock;
  573.             $data .= "\n\n";
  574.             $data .= "\nreturn ".$exportedClass.";\n";
  575.             \Pimcore\File::putPhpFile($definitionFile$data);
  576.         }
  577.     }
  578.     /**
  579.      * @return string
  580.      *
  581.      * @internal
  582.      */
  583.     protected function getInfoDocBlock()
  584.     {
  585.         $cd '/**' "\n";
  586.         $cd .= '* Inheritance: '.($this->getAllowInherit() ? 'yes' 'no')."\n";
  587.         $cd .= '* Variants: '.($this->getAllowVariants() ? 'yes' 'no')."\n";
  588.         if ($this->getDescription()) {
  589.             $description str_replace(['/**''*/''//'], ''$this->getDescription());
  590.             $description str_replace("\n""\n* "$description);
  591.             $cd .= '* '.$description."\n";
  592.         }
  593.         $cd .= "\n\n";
  594.         $cd .= "Fields Summary:\n";
  595.         $cd $this->getInfoDocBlockForFields($this$cd1);
  596.         $cd .= '*/';
  597.         return $cd;
  598.     }
  599.     /**
  600.      * @internal
  601.      *
  602.      * @param ClassDefinition|ClassDefinition\Data $definition
  603.      * @param string $text
  604.      * @param int $level
  605.      *
  606.      * @return string
  607.      */
  608.     protected function getInfoDocBlockForFields($definition$text$level)
  609.     {
  610.         foreach ($definition->getFieldDefinitions() as $fd) {
  611.             $text .= str_pad(''$level'-').' '.$fd->getName().' ['.$fd->getFieldtype()."]\n";
  612.             if (method_exists($fd'getFieldDefinitions')) {
  613.                 $text $this->getInfoDocBlockForFields($fd$text$level 1);
  614.             }
  615.         }
  616.         return $text;
  617.     }
  618.     public function delete()
  619.     {
  620.         \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::PRE_DELETE);
  621.         // delete all objects using this class
  622.         $list = new Listing();
  623.         $list->setCondition('o_classId = ?'$this->getId());
  624.         $list->load();
  625.         foreach ($list->getObjects() as $o) {
  626.             $o->delete();
  627.         }
  628.         $this->deletePhpClasses();
  629.         // empty object cache
  630.         try {
  631.             Cache::clearTag('class_'.$this->getId());
  632.         } catch (\Exception $e) {
  633.         }
  634.         // empty output cache
  635.         try {
  636.             Cache::clearTag('output');
  637.         } catch (\Exception $e) {
  638.         }
  639.         $customLayouts = new ClassDefinition\CustomLayout\Listing();
  640.         $customLayouts->setCondition('classId = ?'$this->getId());
  641.         $customLayouts $customLayouts->load();
  642.         foreach ($customLayouts as $customLayout) {
  643.             $customLayout->delete();
  644.         }
  645.         $brickListing = new DataObject\Objectbrick\Definition\Listing();
  646.         $brickListing $brickListing->load();
  647.         foreach ($brickListing as $brickDefinition) {
  648.             $modified false;
  649.             $classDefinitions $brickDefinition->getClassDefinitions();
  650.             if (is_array($classDefinitions)) {
  651.                 foreach ($classDefinitions as $key => $classDefinition) {
  652.                     if ($classDefinition['classname'] == $this->getId()) {
  653.                         unset($classDefinitions[$key]);
  654.                         $modified true;
  655.                     }
  656.                 }
  657.             }
  658.             if ($modified) {
  659.                 $brickDefinition->setClassDefinitions($classDefinitions);
  660.                 $brickDefinition->save();
  661.             }
  662.         }
  663.         $this->getDao()->delete();
  664.         \Pimcore::getEventDispatcher()->dispatch(new ClassDefinitionEvent($this), DataObjectClassDefinitionEvents::POST_DELETE);
  665.     }
  666.     private function deletePhpClasses()
  667.     {
  668.         // delete the class files
  669.         @unlink($this->getPhpClassFile());
  670.         @unlink($this->getPhpListingClassFile());
  671.         @rmdir(dirname($this->getPhpListingClassFile()));
  672.         @unlink($this->getDefinitionFile());
  673.     }
  674.     /**
  675.      * @internal
  676.      *
  677.      * @return bool
  678.      */
  679.     public function isWritable(): bool
  680.     {
  681.         if ($_SERVER['PIMCORE_CLASS_DEFINITION_WRITABLE'] ?? false) {
  682.             return true;
  683.         }
  684.         return !str_starts_with($this->getDefinitionFile(), PIMCORE_CUSTOM_CONFIGURATION_DIRECTORY);
  685.     }
  686.     /**
  687.      * @internal
  688.      *
  689.      * @param string|null $name
  690.      *
  691.      * @return string
  692.      */
  693.     public function getDefinitionFile($name null)
  694.     {
  695.         return $this->locateDefinitionFile($name ?? $this->getName(), 'definition_%s.php');
  696.     }
  697.     private function getPhpClassFile(): string
  698.     {
  699.         return $this->locateFile(ucfirst($this->getName()), 'DataObject/%s.php');
  700.     }
  701.     private function getPhpListingClassFile(): string
  702.     {
  703.         return $this->locateFile(ucfirst($this->getName()), 'DataObject/%s/Listing.php');
  704.     }
  705.     /**
  706.      * @return string|null
  707.      */
  708.     public function getId()
  709.     {
  710.         return $this->id;
  711.     }
  712.     /**
  713.      * @return string|null
  714.      */
  715.     public function getName()
  716.     {
  717.         return $this->name;
  718.     }
  719.     /**
  720.      * @return int|null
  721.      */
  722.     public function getCreationDate()
  723.     {
  724.         return $this->creationDate;
  725.     }
  726.     /**
  727.      * @return int|null
  728.      */
  729.     public function getModificationDate()
  730.     {
  731.         return $this->modificationDate;
  732.     }
  733.     /**
  734.      * @return int|null
  735.      */
  736.     public function getUserOwner()
  737.     {
  738.         return $this->userOwner;
  739.     }
  740.     /**
  741.      * @return int|null
  742.      */
  743.     public function getUserModification()
  744.     {
  745.         return $this->userModification;
  746.     }
  747.     /**
  748.      * @param string $id
  749.      *
  750.      * @return $this
  751.      */
  752.     public function setId($id)
  753.     {
  754.         $this->id $id;
  755.         return $this;
  756.     }
  757.     /**
  758.      * @param string $name
  759.      *
  760.      * @return $this
  761.      */
  762.     public function setName($name)
  763.     {
  764.         $this->name $name;
  765.         return $this;
  766.     }
  767.     /**
  768.      * @param int $creationDate
  769.      *
  770.      * @return $this
  771.      */
  772.     public function setCreationDate($creationDate)
  773.     {
  774.         $this->creationDate = (int)$creationDate;
  775.         return $this;
  776.     }
  777.     /**
  778.      * @param int $modificationDate
  779.      *
  780.      * @return $this
  781.      */
  782.     public function setModificationDate($modificationDate)
  783.     {
  784.         $this->modificationDate = (int)$modificationDate;
  785.         return $this;
  786.     }
  787.     /**
  788.      * @param int $userOwner
  789.      *
  790.      * @return $this
  791.      */
  792.     public function setUserOwner($userOwner)
  793.     {
  794.         $this->userOwner = (int)$userOwner;
  795.         return $this;
  796.     }
  797.     /**
  798.      * @param int $userModification
  799.      *
  800.      * @return $this
  801.      */
  802.     public function setUserModification($userModification)
  803.     {
  804.         $this->userModification = (int)$userModification;
  805.         return $this;
  806.     }
  807.     /**
  808.      * @param array $context
  809.      *
  810.      * @return DataObject\ClassDefinition\Data[]
  811.      */
  812.     public function getFieldDefinitions($context = [])
  813.     {
  814.         if (!\Pimcore::inAdmin() || (isset($context['suppressEnrichment']) && $context['suppressEnrichment'])) {
  815.             return $this->fieldDefinitions;
  816.         }
  817.         $enrichedFieldDefinitions = [];
  818.         foreach ($this->fieldDefinitions as $key => $fieldDefinition) {
  819.             $fieldDefinition $this->doEnrichFieldDefinition($fieldDefinition$context);
  820.             $enrichedFieldDefinitions[$key] = $fieldDefinition;
  821.         }
  822.         return $enrichedFieldDefinitions;
  823.     }
  824.     /**
  825.      * @internal
  826.      */
  827.     protected function doEnrichFieldDefinition($fieldDefinition$context = [])
  828.     {
  829.         //TODO Pimcore 11: remove method_exists BC layer
  830.         if ($fieldDefinition instanceof FieldDefinitionEnrichmentInterface || method_exists($fieldDefinition'enrichFieldDefinition')) {
  831.             if (!$fieldDefinition instanceof FieldDefinitionEnrichmentInterface) {
  832.                 trigger_deprecation('pimcore/pimcore''10.1',
  833.                     sprintf('Usage of method_exists is deprecated since version 10.1 and will be removed in Pimcore 11.' .
  834.                     'Implement the %s interface instead.'FieldDefinitionEnrichmentInterface::class));
  835.             }
  836.             $context['class'] = $this;
  837.             $fieldDefinition $fieldDefinition->enrichFieldDefinition($context);
  838.         }
  839.         return $fieldDefinition;
  840.     }
  841.     /**
  842.      * @return DataObject\ClassDefinition\Layout|null
  843.      */
  844.     public function getLayoutDefinitions()
  845.     {
  846.         return $this->layoutDefinitions;
  847.     }
  848.     /**
  849.      * @param DataObject\ClassDefinition\Data[] $fieldDefinitions
  850.      *
  851.      * @return $this
  852.      */
  853.     public function setFieldDefinitions(array $fieldDefinitions)
  854.     {
  855.         $this->fieldDefinitions $fieldDefinitions;
  856.         return $this;
  857.     }
  858.     /**
  859.      * @param string $key
  860.      * @param DataObject\ClassDefinition\Data $data
  861.      *
  862.      * @return $this
  863.      */
  864.     public function addFieldDefinition($key$data)
  865.     {
  866.         $this->fieldDefinitions[$key] = $data;
  867.         return $this;
  868.     }
  869.     /**
  870.      * @param string $key
  871.      * @param array $context
  872.      *
  873.      * @return DataObject\ClassDefinition\Data|null
  874.      */
  875.     public function getFieldDefinition($key$context = [])
  876.     {
  877.         if (array_key_exists($key$this->fieldDefinitions)) {
  878.             if (!\Pimcore::inAdmin() || (isset($context['suppressEnrichment']) && $context['suppressEnrichment'])) {
  879.                 return $this->fieldDefinitions[$key];
  880.             }
  881.             $fieldDefinition $this->doEnrichFieldDefinition($this->fieldDefinitions[$key], $context);
  882.             return $fieldDefinition;
  883.         }
  884.         return null;
  885.     }
  886.     /**
  887.      * @param DataObject\ClassDefinition\Layout|null $layoutDefinitions
  888.      *
  889.      * @return $this
  890.      */
  891.     public function setLayoutDefinitions($layoutDefinitions)
  892.     {
  893.         $this->layoutDefinitions $layoutDefinitions;
  894.         $this->fieldDefinitions = [];
  895.         $this->extractDataDefinitions($this->layoutDefinitions);
  896.         return $this;
  897.     }
  898.     /**
  899.      * @param DataObject\ClassDefinition\Layout|DataObject\ClassDefinition\Data $def
  900.      */
  901.     private function extractDataDefinitions($def)
  902.     {
  903.         if ($def instanceof DataObject\ClassDefinition\Layout) {
  904.             if ($def->hasChildren()) {
  905.                 foreach ($def->getChildren() as $child) {
  906.                     $this->extractDataDefinitions($child);
  907.                 }
  908.             }
  909.         }
  910.         if ($def instanceof DataObject\ClassDefinition\Data) {
  911.             $existing $this->getFieldDefinition($def->getName());
  912.             if (!$existing && method_exists($def'addReferencedField') && method_exists($def'setReferencedFields')) {
  913.                 $def->setReferencedFields([]);
  914.             }
  915.             if ($existing && method_exists($existing'addReferencedField')) {
  916.                 // this is especially for localized fields which get aggregated here into one field definition
  917.                 // in the case that there are more than one localized fields in the class definition
  918.                 // see also pimcore.object.edit.addToDataFields();
  919.                 $existing->addReferencedField($def);
  920.             } else {
  921.                 $this->addFieldDefinition($def->getName(), $def);
  922.             }
  923.         }
  924.     }
  925.     /**
  926.      * @return string
  927.      */
  928.     public function getParentClass()
  929.     {
  930.         return $this->parentClass;
  931.     }
  932.     /**
  933.      * @return string
  934.      */
  935.     public function getListingParentClass()
  936.     {
  937.         return $this->listingParentClass;
  938.     }
  939.     /**
  940.      * @return string
  941.      */
  942.     public function getUseTraits()
  943.     {
  944.         return $this->useTraits;
  945.     }
  946.     /**
  947.      * @param string $useTraits
  948.      *
  949.      * @return ClassDefinition
  950.      */
  951.     public function setUseTraits($useTraits)
  952.     {
  953.         $this->useTraits = (string) $useTraits;
  954.         return $this;
  955.     }
  956.     /**
  957.      * @return string
  958.      */
  959.     public function getListingUseTraits()
  960.     {
  961.         return $this->listingUseTraits;
  962.     }
  963.     /**
  964.      * @param string $listingUseTraits
  965.      *
  966.      * @return ClassDefinition
  967.      */
  968.     public function setListingUseTraits($listingUseTraits)
  969.     {
  970.         $this->listingUseTraits = (string) $listingUseTraits;
  971.         return $this;
  972.     }
  973.     /**
  974.      * @return bool
  975.      */
  976.     public function getAllowInherit()
  977.     {
  978.         return $this->allowInherit;
  979.     }
  980.     /**
  981.      * @return bool
  982.      */
  983.     public function getAllowVariants()
  984.     {
  985.         return $this->allowVariants;
  986.     }
  987.     /**
  988.      * @param string $parentClass
  989.      *
  990.      * @return $this
  991.      */
  992.     public function setParentClass($parentClass)
  993.     {
  994.         $this->parentClass $parentClass;
  995.         return $this;
  996.     }
  997.     /**
  998.      * @param string $listingParentClass
  999.      *
  1000.      * @return $this
  1001.      */
  1002.     public function setListingParentClass($listingParentClass)
  1003.     {
  1004.         $this->listingParentClass = (string) $listingParentClass;
  1005.         return $this;
  1006.     }
  1007.     /**
  1008.      * @return bool
  1009.      */
  1010.     public function getEncryption(): bool
  1011.     {
  1012.         return $this->encryption;
  1013.     }
  1014.     /**
  1015.      * @param bool $encryption
  1016.      *
  1017.      * @return $this
  1018.      */
  1019.     public function setEncryption(bool $encryption)
  1020.     {
  1021.         $this->encryption $encryption;
  1022.         return $this;
  1023.     }
  1024.     /**
  1025.      * @internal
  1026.      *
  1027.      * @param array $tables
  1028.      */
  1029.     public function addEncryptedTables(array $tables)
  1030.     {
  1031.         $this->encryptedTables array_unique(array_merge($this->encryptedTables$tables));
  1032.     }
  1033.     /**
  1034.      * @internal
  1035.      *
  1036.      * @param array $tables
  1037.      */
  1038.     public function removeEncryptedTables(array $tables)
  1039.     {
  1040.         foreach ($tables as $table) {
  1041.             if (($key array_search($table$this->encryptedTables)) !== false) {
  1042.                 unset($this->encryptedTables[$key]);
  1043.             }
  1044.         }
  1045.     }
  1046.     /**
  1047.      * @internal
  1048.      *
  1049.      * @param string $table
  1050.      *
  1051.      * @return bool
  1052.      */
  1053.     public function isEncryptedTable(string $table): bool
  1054.     {
  1055.         return (array_search($table$this->encryptedTables) === false) ? false true;
  1056.     }
  1057.     /**
  1058.      * @return bool
  1059.      */
  1060.     public function hasEncryptedTables(): bool
  1061.     {
  1062.         return (bool) count($this->encryptedTables);
  1063.     }
  1064.     /**
  1065.      * @internal
  1066.      *
  1067.      * @param array $encryptedTables
  1068.      *
  1069.      * @return $this
  1070.      */
  1071.     public function setEncryptedTables(array $encryptedTables)
  1072.     {
  1073.         $this->encryptedTables $encryptedTables;
  1074.         return $this;
  1075.     }
  1076.     /**
  1077.      * @param bool $allowInherit
  1078.      *
  1079.      * @return $this
  1080.      */
  1081.     public function setAllowInherit($allowInherit)
  1082.     {
  1083.         $this->allowInherit = (bool)$allowInherit;
  1084.         return $this;
  1085.     }
  1086.     /**
  1087.      * @param bool $allowVariants
  1088.      *
  1089.      * @return $this
  1090.      */
  1091.     public function setAllowVariants($allowVariants)
  1092.     {
  1093.         $this->allowVariants = (bool)$allowVariants;
  1094.         return $this;
  1095.     }
  1096.     /**
  1097.      * @return string
  1098.      */
  1099.     public function getIcon()
  1100.     {
  1101.         return $this->icon;
  1102.     }
  1103.     /**
  1104.      * @param string $icon
  1105.      *
  1106.      * @return $this
  1107.      */
  1108.     public function setIcon($icon)
  1109.     {
  1110.         $this->icon $icon;
  1111.         return $this;
  1112.     }
  1113.     /**
  1114.      * @return array
  1115.      */
  1116.     public function getPropertyVisibility()
  1117.     {
  1118.         return $this->propertyVisibility;
  1119.     }
  1120.     /**
  1121.      * @param array $propertyVisibility
  1122.      *
  1123.      * @return $this
  1124.      */
  1125.     public function setPropertyVisibility($propertyVisibility)
  1126.     {
  1127.         if (is_array($propertyVisibility)) {
  1128.             $this->propertyVisibility $propertyVisibility;
  1129.         }
  1130.         return $this;
  1131.     }
  1132.     /**
  1133.      * @param string $previewUrl
  1134.      *
  1135.      * @return $this
  1136.      */
  1137.     public function setPreviewUrl($previewUrl)
  1138.     {
  1139.         $this->previewUrl $previewUrl;
  1140.         return $this;
  1141.     }
  1142.     /**
  1143.      * @return string
  1144.      */
  1145.     public function getPreviewUrl()
  1146.     {
  1147.         return $this->previewUrl;
  1148.     }
  1149.     /**
  1150.      * @return string
  1151.      */
  1152.     public function getGroup()
  1153.     {
  1154.         return $this->group;
  1155.     }
  1156.     /**
  1157.      * @param string $group
  1158.      *
  1159.      * @return $this
  1160.      */
  1161.     public function setGroup($group)
  1162.     {
  1163.         $this->group $group;
  1164.         return $this;
  1165.     }
  1166.     /**
  1167.      * @param string $description
  1168.      *
  1169.      * @return $this
  1170.      */
  1171.     public function setDescription($description)
  1172.     {
  1173.         $this->description $description;
  1174.         return $this;
  1175.     }
  1176.     /**
  1177.      * @return string
  1178.      */
  1179.     public function getDescription()
  1180.     {
  1181.         return $this->description;
  1182.     }
  1183.     /**
  1184.      * @param bool $showVariants
  1185.      *
  1186.      * @return $this
  1187.      */
  1188.     public function setShowVariants($showVariants)
  1189.     {
  1190.         $this->showVariants = (bool)$showVariants;
  1191.         return $this;
  1192.     }
  1193.     /**
  1194.      * @return bool
  1195.      */
  1196.     public function getShowVariants()
  1197.     {
  1198.         return $this->showVariants;
  1199.     }
  1200.     /**
  1201.      * @return bool
  1202.      */
  1203.     public function getShowAppLoggerTab()
  1204.     {
  1205.         return $this->showAppLoggerTab;
  1206.     }
  1207.     /**
  1208.      * @param bool $showAppLoggerTab
  1209.      *
  1210.      * @return $this
  1211.      */
  1212.     public function setShowAppLoggerTab($showAppLoggerTab)
  1213.     {
  1214.         $this->showAppLoggerTab = (bool) $showAppLoggerTab;
  1215.         return $this;
  1216.     }
  1217.     /**
  1218.      * @return bool
  1219.      */
  1220.     public function getShowFieldLookup()
  1221.     {
  1222.         return $this->showFieldLookup;
  1223.     }
  1224.     /**
  1225.      * @param bool $showFieldLookup
  1226.      *
  1227.      * @return $this
  1228.      */
  1229.     public function setShowFieldLookup($showFieldLookup)
  1230.     {
  1231.         $this->showFieldLookup = (bool) $showFieldLookup;
  1232.         return $this;
  1233.     }
  1234.     /**
  1235.      * @return string
  1236.      */
  1237.     public function getLinkGeneratorReference()
  1238.     {
  1239.         return $this->linkGeneratorReference;
  1240.     }
  1241.     /**
  1242.      * @param string $linkGeneratorReference
  1243.      *
  1244.      * @return $this
  1245.      */
  1246.     public function setLinkGeneratorReference($linkGeneratorReference)
  1247.     {
  1248.         $this->linkGeneratorReference $linkGeneratorReference;
  1249.         return $this;
  1250.     }
  1251.     /**
  1252.      * @return DataObject\ClassDefinition\LinkGeneratorInterface|null
  1253.      */
  1254.     public function getLinkGenerator()
  1255.     {
  1256.         return DataObject\ClassDefinition\Helper\LinkGeneratorResolver::resolveGenerator($this->getLinkGeneratorReference());
  1257.     }
  1258.     /**
  1259.      * @return string|null
  1260.      */
  1261.     public function getPreviewGeneratorReference(): ?string
  1262.     {
  1263.         return $this->previewGeneratorReference;
  1264.     }
  1265.     /**
  1266.      * @param string|null $previewGeneratorReference
  1267.      */
  1268.     public function setPreviewGeneratorReference(?string $previewGeneratorReference): void
  1269.     {
  1270.         $this->previewGeneratorReference $previewGeneratorReference;
  1271.     }
  1272.     /**
  1273.      * @return DataObject\ClassDefinition\PreviewGeneratorInterface|null
  1274.      */
  1275.     public function getPreviewGenerator()
  1276.     {
  1277.         return DataObject\ClassDefinition\Helper\PreviewGeneratorResolver::resolveGenerator($this->getPreviewGeneratorReference());
  1278.     }
  1279.     /**
  1280.      * @return bool
  1281.      */
  1282.     public function isEnableGridLocking(): bool
  1283.     {
  1284.         return $this->enableGridLocking;
  1285.     }
  1286.     /**
  1287.      * @param bool $enableGridLocking
  1288.      */
  1289.     public function setEnableGridLocking(bool $enableGridLocking): void
  1290.     {
  1291.         $this->enableGridLocking $enableGridLocking;
  1292.     }
  1293.     /**
  1294.      * @return string|null
  1295.      */
  1296.     public function getImplementsInterfaces(): ?string
  1297.     {
  1298.         return $this->implementsInterfaces;
  1299.     }
  1300.     /**
  1301.      * @param string|null $implementsInterfaces
  1302.      *
  1303.      * @return $this
  1304.      */
  1305.     public function setImplementsInterfaces(?string $implementsInterfaces)
  1306.     {
  1307.         $this->implementsInterfaces $implementsInterfaces;
  1308.         return $this;
  1309.     }
  1310.     /**
  1311.      * @return array
  1312.      */
  1313.     public function getCompositeIndices(): array
  1314.     {
  1315.         return $this->compositeIndices;
  1316.     }
  1317.     /**
  1318.      * @param array|null $compositeIndices
  1319.      *
  1320.      * @return $this
  1321.      */
  1322.     public function setCompositeIndices($compositeIndices)
  1323.     {
  1324.         $this->compositeIndices $compositeIndices ?? [];
  1325.         return $this;
  1326.     }
  1327.     /**
  1328.      * @return bool
  1329.      */
  1330.     public function getGenerateTypeDeclarations()
  1331.     {
  1332.         return (bool) $this->generateTypeDeclarations;
  1333.     }
  1334.     /**
  1335.      * @param bool $generateTypeDeclarations
  1336.      *
  1337.      * @return $this
  1338.      */
  1339.     public function setGenerateTypeDeclarations($generateTypeDeclarations)
  1340.     {
  1341.         $this->generateTypeDeclarations = (bool) $generateTypeDeclarations;
  1342.         return $this;
  1343.     }
  1344. }