vendor/blackbit/data-director/EventListener/ClassChangedListener.php line 257

Open in your IDE?
  1. <?php
  2. /*
  3.  * The software is distributed under the enclosed dual licence agreement. Accordingly, it is the responsibility of the licensee to use the software under the terms of the GPLv3 or, if purchased, under the terms of the commercial licence. Simultaneous use of the software under both licence forms for the same licensed object or a subsequent ‘change’ of licence forms by the same licensee is not permitted.
  4.  *
  5.  * In accordance with the provisions of the respective licences, it is only possible to
  6.  * a.) use Blackbit software under GPLv3 with the Pimcore Community Edition under GPLv3 or
  7.  * b.) combine Blackbit software under a commercial licence and Pimcore under a commercial licence.
  8.  *
  9.  * You can use the software under the terms of the GNU General Public Licence, Version 3 (GPLv3). This brings with it many rights of use and freedoms:
  10.  * Open source - You can view the unencrypted programme code of our software.
  11.  * Customisation - You can adapt the software to your needs and develop it further as you wish.
  12.  * Distribution - You can copy, distribute and even sell the software or further developments of the software as long as you comply with the GNU GPL v3 licence. Because you become the owner of the code when you purchase the bundle, there is no warranty and no free service.
  13.  *
  14.  * Alternatively, you can use the software under the Blackbit Commercial Licence. This means that the software remains the property of Blackbit and may be used in one instance per licence. Blackbit grants the user a limited right of use and eliminates defects and errors and provides updates free of charge during the contract period. Optionally, separate service and support contracts can be concluded for Blackbit software.
  15.  *
  16.  * For further information, please refer to the respective licence files or contact sales@blackbit.de
  17.  */
  18. namespace Blackbit\DataDirectorBundle\EventListener;
  19. use Blackbit\DataDirectorBundle\lib\Pim\Cache\RuntimeCache;
  20. use Blackbit\DataDirectorBundle\lib\Pim\FieldType\CalculatedValueDataQuerySelector;
  21. use Blackbit\DataDirectorBundle\lib\Pim\Helper;
  22. use Blackbit\DataDirectorBundle\lib\Pim\Item\ItemMoldBuilder;
  23. use Blackbit\DataDirectorBundle\lib\Pim\LocationAwareConfigRepository;
  24. use Blackbit\DataDirectorBundle\lib\Pim\Logger\TagLogger;
  25. use Blackbit\DataDirectorBundle\model\Dataport;
  26. use Blackbit\DataDirectorBundle\model\PimcoreDbRepository;
  27. use Blackbit\DataDirectorBundle\Tools\Installer;
  28. use Pimcore\Bundle\AdminBundle\Event\AdminEvents;
  29. use Pimcore\Db;
  30. use Pimcore\Event\Model\DataObject\ClassDefinitionEvent;
  31. use Pimcore\Event\Model\DataObject\ObjectbrickDefinitionEvent;
  32. use Pimcore\File;
  33. use Pimcore\Model\DataObject\ClassDefinition;
  34. use Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage;
  35. use Pimcore\Model\DataObject\ClassDefinition\Data\Image;
  36. use Pimcore\Model\DataObject\ClassDefinition\Data;
  37. use Pimcore\Model\DataObject\ClassDefinition\Data\Objectbricks;
  38. use Pimcore\Model\DataObject\ClassDefinition\Data\Relations\AbstractRelations;
  39. use Pimcore\Model\DataObject\ClassDefinition\Listing;
  40. use Pimcore\Model\DataObject\ClassDefinition\PathFormatterAwareInterface;
  41. use Pimcore\Model\DataObject\Data\ImageGallery;
  42. use Pimcore\Model\DataObject\Objectbrick\Data\AbstractData;
  43. use Pimcore\Model\DataObject\Objectbrick\Definition;
  44. use Pimcore\Perspective\Config;
  45. use Pimcore\Tool;
  46. use Blackbit\DataDirectorBundle\lib\Pim\EventDispatcher;
  47. use Symfony\Component\EventDispatcher\GenericEvent;
  48. class ClassChangedListener
  49. {
  50.     /** @var ItemMoldBuilder */
  51.     private $itemMoldBuilder;
  52.     public function __construct(ItemMoldBuilder $itemMoldBuilder)
  53.     {
  54.         $this->itemMoldBuilder $itemMoldBuilder;
  55.     }
  56.     public function removeCompiledDataQuerySelectors(ClassDefinitionEvent $e) {
  57.         try {
  58.             $dummyObject $this->itemMoldBuilder->getItemMoldByClassname($e->getClassDefinition()->getName());
  59.             $classFqn \get_class($dummyObject);
  60.         } catch (\Exception $classNotFoundException) {
  61.             $classFqn 'Pimcore\\Model\\DataObject\\'.$e->getClassDefinition()->getName();
  62.         }
  63.         $directoryIterator = new \DirectoryIterator(Installer::getCachePath());
  64.         $fileNamePrefix preg_replace('/\W+/''_'$classFqn.' ');
  65.         $filterIterator = new \CallbackFilterIterator($directoryIterator, static function (\SplFileInfo $fileInfo) use ($fileNamePrefix) {
  66.             return strpos($fileInfo->getFilename(), $fileNamePrefix) === || strpos($fileInfo->getFilename(), 'Dao_'.$fileNamePrefix) === || strpos($fileInfo->getFilename(), 'Listing_'.$fileNamePrefix) === 0;
  67.         });
  68.         /** @var \SplFileInfo $compiledFileInfo */
  69.         foreach ($filterIterator as $compiledFile) {
  70.             unlink($compiledFile->getPathname());
  71.         }
  72.     }
  73.     public function removeAllCompiledDataQuerySelectors() {
  74.         /** @var \SplFileInfo $compiledFileInfo */
  75.         foreach(new \DirectoryIterator(Installer::getCachePath()) as $compiledFileInfo) {
  76.             if (!$compiledFileInfo->isDot()) {
  77.                 @unlink($compiledFileInfo->getPathname());
  78.             }
  79.         }
  80.     }
  81.     public function createStoreView(ClassDefinitionEvent $e)
  82.     {
  83.         if ($e->getClassDefinition()->getAllowInherit()) {
  84.             $hasLocalizedFields false;
  85.             foreach ($e->getClassDefinition()->getFieldDefinitions() as $fieldDefinition) {
  86.                 if ($fieldDefinition instanceof Data\Localizedfields) {
  87.                     $hasLocalizedFields true;
  88.                     break;
  89.                 }
  90.             }
  91.             foreach (Tool::getValidLanguages() as $language) {
  92.                 $query 'CREATE OR REPLACE VIEW `object_localized_store_'.$e->getClassDefinition()->getId().'_'.$language.'` AS SELECT * FROM `object_store_'.$e->getClassDefinition()->getId().'` JOIN `objects` ON `objects`.`'.Helper::prefixObjectSystemColumn('id').'` = `object_store_'.$e->getClassDefinition()->getId().'`.`oo_id`';
  93.                 $parameters = [];
  94.                 if($hasLocalizedFields) {
  95.                     $query .= ' JOIN `object_localized_data_'.$e->getClassDefinition()->getId().'` ON `object_store_'.$e->getClassDefinition()->getId().'`.oo_id=`object_localized_data_'.$e->getClassDefinition()->getId().'`.ooo_id AND language=?';
  96.                     $parameters[] = $language;
  97.                 }
  98.                 PimcoreDbRepository::getInstance()->execute($query$parameters);
  99.             }
  100.         } else {
  101.             $this->removeStoreView($e);
  102.         }
  103.     }
  104.     public function removeStoreView(ClassDefinitionEvent $e)
  105.     {
  106.         foreach (Tool::getValidLanguages() as $language) {
  107.             PimcoreDbRepository::getInstance()->execute('DROP VIEW IF EXISTS `object_localized_store_'.$e->getClassDefinition()->getId().'_'.$language.'`');
  108.         }
  109.     }
  110.     public function addPreviewService(ClassDefinitionEvent $e)
  111.     {
  112.         $classDefinition $e->getClassDefinition();
  113.         if (method_exists($classDefinition'setPreviewGeneratorReference')) {
  114.             if (!$classDefinition->getPreviewGeneratorReference() && !$classDefinition->getLinkGeneratorReference()) {
  115.                 $classDefinition->setPreviewGeneratorReference('@DataDirectorPreview');
  116.             }
  117.         } elseif (method_exists($classDefinition'setPreviewUrl')) {
  118.             if (!$classDefinition->getPreviewUrl()) {
  119.                 $classDefinition->setPreviewUrl('/admin/BlackbitDataDirector/import/object-preview?id=%o_id');
  120.             }
  121.         }
  122.     }
  123.     /**
  124.      * @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
  125.      * @return void
  126.      */
  127.     public function setLayoutFieldNames($e)
  128.     {
  129.         if ($e instanceof ObjectbrickDefinitionEvent) {
  130.             $classDefinition $e->getObjectbrickDefinition();
  131.         } else {
  132.             $classDefinition $e->getClassDefinition();
  133.         }
  134.         $layout $classDefinition->getLayoutDefinitions();
  135.         if($layout instanceof ClassDefinition\Layout) {
  136.             $this->setLayoutFieldName($layout$classDefinition);
  137.         }
  138.     }
  139.     /**
  140.      * @param ClassDefinition\Layout|ClassDefinition\Data $layout
  141.      * @param ClassDefinition|Definition $classDefinition
  142.      * @return void
  143.      */
  144.     private function setLayoutFieldName($layout$classDefinition): void
  145.     {
  146.         $translator \Pimcore::getContainer()->get('translator');
  147.         $replaceableLayoutNames = [
  148.             '',
  149.             'Layout',
  150.             $translator->trans($layout->fieldtype, [], 'admin_ext'Tool::getDefaultLanguage()),
  151.             $translator->trans($layout->fieldtype, [], 'admin_ext'Helper::getUser()->getLanguage())
  152.         ];
  153.         if($layout instanceof ClassDefinition\Layout && property_exists($layout'fieldtype') && in_array($layout->name$replaceableLayoutNamestrue)) {
  154.             if($layout->title) {
  155.                 $name trim(preg_replace('/[^a-z0-9_]+/i'''Helper::toASCII($layout->titleTool::getDefaultLanguage())));
  156.                 if(!$classDefinition->getFieldDefinition($name) instanceof ClassDefinition\Data) {
  157.                     $layout->setName($name);
  158.                 }
  159.             } elseif (property_exists($layout'text') && $layout->text) {
  160.                 $name trim(preg_replace('/[^a-z0-9_]+/i'''Helper::toASCII($layout->textTool::getDefaultLanguage())));
  161.                 if (!$classDefinition->getFieldDefinition($name) instanceof ClassDefinition\Data) {
  162.                     $layout->setName($name);
  163.                 }
  164.             }
  165.         }
  166.         if (method_exists($layout'getChildren')) {
  167.             $children $layout->getChildren();
  168.             if (is_array($children)) {
  169.                 foreach ($children as $child) {
  170.                     $this->setLayoutFieldName($child$classDefinition);
  171.                 }
  172.             }
  173.         }
  174.     }
  175.     /**
  176.      * @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
  177.      * @return void
  178.      */
  179.     public function addPathFormatterService($e)
  180.     {
  181.         if($e instanceof ObjectbrickDefinitionEvent) {
  182.             $classDefinition $e->getObjectbrickDefinition();
  183.         } else {
  184.             $classDefinition $e->getClassDefinition();
  185.         }
  186.         foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
  187.             if ($fieldDefinition instanceof PathFormatterAwareInterface && !$fieldDefinition->getPathFormatterClass() && method_exists($fieldDefinition'setPathFormatterClass')) {
  188.                 $fieldDefinition->setPathFormatterClass('@DataDirectorSearchViewPathFormatter');
  189.             } elseif ($fieldDefinition instanceof Localizedfields) {
  190.                 foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
  191.                     if ($localizedFieldDefinition instanceof PathFormatterAwareInterface && !$localizedFieldDefinition->getPathFormatterClass() && method_exists($localizedFieldDefinition'setPathFormatterClass')) {
  192.                         $localizedFieldDefinition->setPathFormatterClass('@DataDirectorSearchViewPathFormatter');
  193.                     }
  194.                 }
  195.             }
  196.         }
  197.     }
  198.     /**
  199.      * @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
  200.      * @return void
  201.      */
  202.     public function clearCalculatedValueFieldCache($e)
  203.     {
  204.         if ($e instanceof ObjectbrickDefinitionEvent) {
  205.             $classDefinition $e->getObjectbrickDefinition();
  206.         } else {
  207.             $classDefinition $e->getClassDefinition();
  208.         }
  209.         foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
  210.             if ($fieldDefinition instanceof CalculatedValueDataQuerySelector) {
  211.                 PimcoreDbRepository::getInstance()->execute('UPDATE object_query_'.$classDefinition->getId().' SET '.Db::get()->quoteIdentifier($fieldDefinition->getName()).'=NULL');
  212.             } elseif ($fieldDefinition instanceof Localizedfields) {
  213.                 foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
  214.                     if ($localizedFieldDefinition instanceof CalculatedValueDataQuerySelector) {
  215.                         foreach (Tool::getValidLanguages() as $language) {
  216.                             PimcoreDbRepository::getInstance()->execute('UPDATE object_localized_query_'.$classDefinition->getId().'_'.$language.' SET '.Db::get()->quoteIdentifier($localizedFieldDefinition->getName()).'=NULL');
  217.                         }
  218.                     }
  219.                 }
  220.             }
  221.         }
  222.     }
  223.     
  224.     public function setClassIcon(ClassDefinitionEvent $e)
  225.     {
  226.         $classDefinition $e->getClassDefinition();
  227.         if(!$classDefinition->getIcon()) {
  228.             $icons = ['00_purple.svg''01_magenta.svg''02_red.svg''03_vermilion.svg''04_orange.svg''05_amber.svg''06_yellow.svg''07_chartreuse.svg','08_green.svg''09_teal.svg''10_blue.svg''11_violet.svg'];
  229.             
  230.             $classDefinition->setIcon('/bundles/pimcoreadmin/img/object-icons/'.$icons[crc32($classDefinition->getName()) % count($icons)]);
  231.         }
  232.     }
  233.     public static function createPerspective()
  234.     {
  235.         if(RuntimeCache::isRegistered(__CLASS__.__METHOD__)) {
  236.             return;
  237.         }
  238.         $existingPerspectives Config::get();
  239.         if(!$existingPerspectives) {
  240.             return;
  241.         }
  242.         if($existingPerspectives instanceof \Pimcore\Config\Config) {
  243.             $existingPerspectives $existingPerspectives->toArray();
  244.         }
  245.         foreach($existingPerspectives as $perspectiveName => $existingPerspective) {
  246.             if(strpos($perspectiveName'pim.perspective') !== && $perspectiveName !== 'default') {
  247.                 return;
  248.             }
  249.         }
  250.         $dependencies = [];
  251.         $customViews = [];
  252.         foreach ((new Listing())->load() as $classDefinition) {
  253.             $groupExistsAsFolder PimcoreDbRepository::getInstance()->findOneInSql('SELECT `'.Helper::prefixObjectSystemColumn('key').'` FROM objects WHERE '.Helper::prefixObjectSystemColumn('path').'=\'/\' AND CAST(objects.'.Helper::prefixObjectSystemColumn('key').' AS CHAR CHARACTER SET utf8) COLLATE utf8_general_ci LIKE ? LIMIT 1', [$classDefinition->getGroup()]);
  254.             $customViewId 'dd_'.File::getValidFilename($classDefinition->getGroup() ?? '');
  255.             if($groupExistsAsFolder) {
  256.                 $rootFolder '/'.$groupExistsAsFolder.'/';
  257.             } else {
  258.                 $firstFolder PimcoreDbRepository::getInstance()->findOneInSql('SELECT '.Helper::prefixObjectSystemColumn('path').' FROM objects WHERE '.Helper::prefixObjectSystemColumn('classId').'=? ORDER BY '.Helper::prefixObjectSystemColumn('path').' LIMIT 1', [$classDefinition->getId()]
  259.                 ) ?: '/';
  260.                 $lastFolder PimcoreDbRepository::getInstance()->findOneInSql('SELECT '.Helper::prefixObjectSystemColumn('path').' FROM objects WHERE '.Helper::prefixObjectSystemColumn('classId').'=? ORDER BY '.Helper::prefixObjectSystemColumn('path').' DESC LIMIT 1', [$classDefinition->getId()]
  261.                 ) ?: '/';
  262.                 $len min(mb_strlen($firstFolder), mb_strlen($lastFolder));
  263.                 for ($i 0$i $len$i++) {
  264.                     if (mb_substr($firstFolder$i1) !== mb_substr($lastFolder$i1)) {
  265.                         break;
  266.                     }
  267.                 }
  268.                 $commonPrefix substr($firstFolder0$i);
  269.                 $rootFolder $commonPrefix ?: '/';
  270.                 if (substr($commonPrefix, -1) !== '/') {
  271.                     $rootFolder dirname($commonPrefix).'/';
  272.                 }
  273.             }
  274.             if (!isset($dependencies[$customViewId])) {
  275.                 $dependencies[$customViewId] = [];
  276.             }
  277.             if (!isset($customViews[$customViewId])) {
  278.                 $customViews[$customViewId] = [
  279.                     'id' => $customViewId,
  280.                     'name' => $classDefinition->getGroup() ?: 'data_objects',
  281.                     'treetype' => 'object',
  282.                     'position' => 'left',
  283.                     'rootfolder' => $rootFolder,
  284.                     'classes' => $classDefinition->getId(),
  285.                     'showroot' => true,
  286.                     'sort' => 0,
  287.                     'treeContextMenu' => [
  288.                         'object' => [
  289.                             'items' => [
  290.                                 'add' => true,
  291.                                 'addFolder' => true,
  292.                                 'importCsv' => true,
  293.                                 'cut' => true,
  294.                                 'copy' => true,
  295.                                 'paste' => true,
  296.                                 'delete' => true,
  297.                                 'rename' => true,
  298.                                 'reload' => true,
  299.                                 'publish' => true,
  300.                                 'unpublish' => true,
  301.                                 'searchAndMove' => true,
  302.                                 'lock' => true,
  303.                                 'unlock' => true,
  304.                                 'lockAndPropagate' => true,
  305.                                 'unlockAndPropagate' => true,
  306.                                 'changeChildrenSortBy' => true
  307.                             ]
  308.                         ]
  309.                     ],
  310.                     'icon' => $classDefinition->getIcon() ?: '/bundles/pimcoreadmin/img/flat-white-icons/pimcore-main-icon-object.svg'
  311.                 ];
  312.             } else {
  313.                 $customViews[$customViewId]['classes'] .= ','.$classDefinition->getId();
  314.                 if (!$groupExistsAsFolder && $firstFolder !== '/') {
  315.                     $firstFolder = (mb_strlen($customViews[$customViewId]['rootfolder']) <= mb_strlen($commonPrefix) ? $customViews[$customViewId]['rootfolder'] : $commonPrefix);
  316.                     $lastFolder = (mb_strlen($customViews[$customViewId]['rootfolder']) > mb_strlen($commonPrefix) ? $customViews[$customViewId]['rootfolder'] : $commonPrefix);
  317.                     $len min(mb_strlen($firstFolder), mb_strlen($lastFolder));
  318.                     for ($i 0$i $len$i++) {
  319.                         if (mb_substr($firstFolder$i1) !== mb_substr($lastFolder$i1)) {
  320.                             break;
  321.                         }
  322.                     }
  323.                     $rootFolder substr($firstFolder0$i);
  324.                     if (substr($commonPrefix, -1) !== '/') {
  325.                         $rootFolder dirname($commonPrefix).'/';
  326.                     } else {
  327.                         $countObjectsOutsidePreviousRootfolder PimcoreDbRepository::getInstance()->findOneInSql('SELECT COUNT(*) FROM objects WHERE '.Helper::prefixObjectSystemColumn('classId').' IN (?) AND '.Helper::prefixObjectSystemColumn('path').' NOT LIKE ?', [explode(','$customViews[$customViewId]['classes']), $customViews[$customViewId]['rootfolder'].'%']);
  328.                         if($countObjectsOutsidePreviousRootfolder 5) {
  329.                             $rootFolder $customViews[$customViewId]['rootfolder'];
  330.                         }
  331.                     }
  332.                     $customViews[$customViewId]['rootfolder'] = $rootFolder;
  333.                 }
  334.             }
  335.             foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
  336.                 if ($fieldDefinition instanceof AbstractRelations && method_exists($fieldDefinition'getDocumentsAllowed') && $fieldDefinition->getDocumentsAllowed()) {
  337.                     $dependencies[$customViewId][] = 'document';
  338.                 } elseif($fieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($fieldDefinition'getObjectsAllowed') && $fieldDefinition->getObjectsAllowed()) {
  339.                     foreach ((array)$fieldDefinition->getClasses() as $allowedClass) {
  340.                         $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  341.                         if($allowedClass instanceof ClassDefinition) {
  342.                             $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup() ?? '');
  343.                         }
  344.                     }
  345.                 } elseif ($fieldDefinition instanceof Localizedfields) {
  346.                     foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
  347.                         if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
  348.                             $dependencies[$customViewId][] = 'document';
  349.                         } elseif ($localizedFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($localizedFieldDefinition'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
  350.                             foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
  351.                                 $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  352.                                 if ($allowedClass instanceof ClassDefinition) {
  353.                                     $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
  354.                                 }
  355.                             }
  356.                         }
  357.                     }
  358.                 } elseif ($fieldDefinition instanceof Objectbricks) {
  359.                     foreach ($fieldDefinition->getAllowedTypes() as $brickName) {
  360.                         $brickDefinition Definition::getByKey($brickName);
  361.                         if(!$brickDefinition instanceof Definition) {
  362.                             continue;
  363.                         }
  364.                         foreach ($brickDefinition->getFieldDefinitions() as $brickFieldDefinition) {
  365.                             if ($brickFieldDefinition instanceof Localizedfields) {
  366.                                 foreach ($brickFieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
  367.                                     if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
  368.                                         $dependencies[$customViewId][] = 'document';
  369.                                     } elseif ($localizedFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($localizedFieldDefinition'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
  370.                                         foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
  371.                                             $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  372.                                             if ($allowedClass instanceof ClassDefinition) {
  373.                                                 $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
  374.                                             }
  375.                                         }
  376.                                     }
  377.                                 }
  378.                             } elseif ($brickFieldDefinition instanceof AbstractRelations && method_exists($brickFieldDefinition'getDocumentsAllowed') && $brickFieldDefinition->getDocumentsAllowed()) {
  379.                                 $dependencies[$customViewId][] = 'document';
  380.                             } elseif ($brickFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($brickFieldDefinition'getObjectsAllowed') && $brickFieldDefinition->getObjectsAllowed()) {
  381.                                 foreach ((array)$brickFieldDefinition->getClasses() as $allowedClass) {
  382.                                     $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  383.                                     if ($allowedClass instanceof ClassDefinition) {
  384.                                         $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
  385.                                     }
  386.                                 }
  387.                             }
  388.                         }
  389.                     }
  390.                 } elseif ($fieldDefinition instanceof ClassDefinition\Data\Fieldcollections) {
  391.                     foreach ($fieldDefinition->getAllowedTypes() as $brickName) {
  392.                         $brickDefinition \Pimcore\Model\DataObject\Fieldcollection\Definition::getByKey($brickName);
  393.                         foreach ($brickDefinition->getFieldDefinitions() as $brickFieldDefinition) {
  394.                             if ($brickFieldDefinition instanceof Localizedfields) {
  395.                                 foreach ($brickFieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
  396.                                     if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
  397.                                         $dependencies[$customViewId][] = 'document';
  398.                                     } elseif ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
  399.                                         foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
  400.                                             $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  401.                                             if ($allowedClass instanceof ClassDefinition) {
  402.                                                 $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
  403.                                             }
  404.                                         }
  405.                                     }
  406.                                 }
  407.                             } elseif ($brickFieldDefinition instanceof AbstractRelations && method_exists($brickFieldDefinition'getDocumentsAllowed') && $brickFieldDefinition->getDocumentsAllowed()) {
  408.                                 $dependencies[$customViewId][] = 'document';
  409.                             } elseif ($brickFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($brickFieldDefinition'getObjectsAllowed') && $brickFieldDefinition->getObjectsAllowed()) {
  410.                                 foreach ((array)$brickFieldDefinition->getClasses() as $allowedClass) {
  411.                                     $allowedClass ClassDefinition::getByName($allowedClass['classes']);
  412.                                     if ($allowedClass instanceof ClassDefinition) {
  413.                                         $dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
  414.                                     }
  415.                                 }
  416.                             }
  417.                         }
  418.                     }
  419.                 }
  420.             }
  421.         }
  422.         $perspectives = [
  423.             'pim.perspective.default' => [
  424.                 'elementTree' => [
  425.                     [
  426.                         'type' => 'documents',
  427.                         'position' => 'left',
  428.                         'expanded' => false,
  429.                         'hidden' => false,
  430.                         'sort' => 0
  431.                     ],
  432.                     [
  433.                         'type' => 'assets',
  434.                         'position' => 'left',
  435.                         'expanded' => false,
  436.                         'hidden' => false,
  437.                         'sort' => 1
  438.                     ],
  439.                     [
  440.                         'type' => 'objects',
  441.                         'position' => 'left',
  442.                         'expanded' => false,
  443.                         'hidden' => false,
  444.                         'sort' => 2
  445.                     ]
  446.                 ],
  447.                 'iconCls' => 'pimcore_nav_icon_perspective',
  448.                 'icon' => null,
  449.                 'dashboards' => [
  450.                     'predefined' => [
  451.                         'welcome' => [
  452.                             'positions' => [
  453.                                 [
  454.                                     [
  455.                                         'id' => 1,
  456.                                         'type' => 'pimcore.layout.portlets.modificationStatistic',
  457.                                         'config' => null
  458.                                     ],
  459.                                     [
  460.                                         'id' => 2,
  461.                                         'type' => 'pimcore.layout.portlets.modifiedAssets',
  462.                                         'config' => null
  463.                                     ]
  464.                                 ],
  465.                                 [
  466.                                     [
  467.                                         'id' => 3,
  468.                                         'type' => 'pimcore.layout.portlets.modifiedObjects',
  469.                                         'config' => null
  470.                                     ],
  471.                                     [
  472.                                         'id' => 4,
  473.                                         'type' => 'pimcore.layout.portlets.modifiedDocuments',
  474.                                         'config' => null
  475.                                     ]
  476.                                 ]
  477.                             ]
  478.                         ]
  479.                     ]
  480.                 ]
  481.             ]
  482.         ];
  483.         if (count($customViews) > 0) {
  484.             self::saveCustomView($customViews);
  485.             uksort($customViews, static function ($customViewId1$customViewId2) use ($customViews$dependencies) {
  486.                 $order count($dependencies[$customViewId2]) <=> count($dependencies[$customViewId1]);
  487.                 if ($order !== 0) {
  488.                     return $order;
  489.                 }
  490.                 $order substr_count($customViews[$customViewId2]['classes'], ',') <=> substr_count($customViews[$customViewId1]['classes'], ',');
  491.                 if ($order !== 0) {
  492.                     return $order;
  493.                 }
  494.                 if ($customViews[$customViewId1]['name'] === 'data_objects' && $customViews[$customViewId2]['name'] !== 'data_objects') {
  495.                     return 1;
  496.                 }
  497.                 if ($customViews[$customViewId1]['name'] !== 'data_objects' && $customViews[$customViewId2]['name'] === 'data_objects') {
  498.                     return -1;
  499.                 }
  500.                 return strcasecmp($customViews[$customViewId1]['name'], $customViews[$customViewId2]['name']);
  501.             });
  502.             $elementTree = [[
  503.                 'type' => 'assets',
  504.                 'position' => 'right',
  505.                 'expanded' => false,
  506.                 'hidden' => false,
  507.                 'sort' => 9000
  508.             ]];
  509.             foreach ($customViews as $customViewId => $customView) {
  510.                 if (in_array('document'$dependencies[$customViewId], true)) {
  511.                     $elementTree[] = [
  512.                         'type' => 'documents',
  513.                         'position' => 'left',
  514.                         'expanded' => false,
  515.                         'hidden' => false,
  516.                         'sort' => 9001
  517.                     ];
  518.                 }
  519.             }
  520.             $index 0;
  521.             foreach ($customViews as $customViewId => $customView) {
  522.                 $position 'left';
  523.                 foreach ($elementTree as $perspectiveView) {
  524.                     if ($perspectiveView['type'] === 'customview' && in_array($customViewId$dependencies[$perspectiveView['id']] ?? [])) {
  525.                         $position 'right';
  526.                         break;
  527.                     }
  528.                 }
  529.                 $elementTree[] = [
  530.                     'type' => 'customview',
  531.                     'position' => $position,
  532.                     'expanded' => false,
  533.                     'hidden' => false,
  534.                     'sort' => $customViewId === 'dd_' 8000 : ($index++),
  535.                     'id' => $customViewId
  536.                 ];
  537.             }
  538.             $perspectives['pim.perspective.PIM'] = [
  539.                 'iconCls' => 'pimcore_icon_object',
  540.                 'elementTree' => $elementTree,
  541.                 'dashboards' => [
  542.                     'predefined' => [
  543.                         'welcome' => [
  544.                             'positions' => [
  545.                                 [
  546.                                     [
  547.                                         'id' => 1,
  548.                                         'type' => 'pimcore.layout.portlets.DataDirector_ErrorMonitor',
  549.                                         'config' => null
  550.                                     ],
  551.                                     [
  552.                                         'id' => 2,
  553.                                         'type' => 'pimcore.layout.portlets.DataDirector_TaggedElements',
  554.                                         'config' => json_encode([
  555.                                             'title' => 'Objects with import errors',
  556.                                             'tags' => [TagLogger::getOrCreateTag('Data Director')->getId()]
  557.                                         ])
  558.                                     ]
  559.                                 ],
  560.                                 [
  561.                                     [
  562.                                         'id' => 3,
  563.                                         'type' => 'pimcore.layout.portlets.DataDirector_QueueMonitor',
  564.                                         'config' => null
  565.                                     ]
  566.                                 ]
  567.                             ]
  568.                         ]
  569.                     ]
  570.                 ]
  571.             ];
  572.         }
  573.         self::savePerspective($perspectives);
  574.         RuntimeCache::save(true__CLASS__.__METHOD__);
  575.     }
  576.     private static function savePerspective(array $data) {
  577.         $containerConfig \Pimcore::getContainer()->getParameter('pimcore.config');
  578.         $config $containerConfig['perspectives']['definitions'];
  579.         if (method_exists(\Pimcore\Config\LocationAwareConfigRepository::class, 'getStorageConfigurationCompatibilityLayer')) {
  580.             $storageConfig \Pimcore\Config\LocationAwareConfigRepository::getStorageConfigurationCompatibilityLayer(
  581.                 $containerConfig,
  582.                 'perspectives',
  583.                 'PIMCORE_CONFIG_STORAGE_DIR_PERSPECTIVES',
  584.                 'PIMCORE_WRITE_TARGET_PERSPECTIVES'
  585.             );
  586.         } else {
  587.             $storageConfig $containerConfig['config_location']['perspectives'] ?? null;
  588.         }
  589.         if (empty($storageConfig['write_target']['options']['directory'])) {
  590.             $storageConfig['write_target']['options']['directory'] = PIMCORE_CONFIGURATION_DIRECTORY.'/perspectives';
  591.         }
  592.         try {
  593.             $repository = new LocationAwareConfigRepository(
  594.                 $config,
  595.                 'pimcore_perspectives',
  596.                 $storageConfig
  597.             );
  598.         } catch (\Throwable $e) {
  599.             $repository = new LocationAwareConfigRepository(
  600.                 $config,
  601.                 'pimcore_perspectives',
  602.                 $storageConfig['write_target']['options']['directory'],
  603.                 null
  604.             );
  605.         }
  606.         foreach ($data as $key => $value) {
  607.             list($configKey$dataSource) = $repository->loadConfigByKey($key);
  608.             if ($repository->isWriteable($key$dataSource) === true) {
  609.                 unset($value['writeable']);
  610.                 $repository->saveConfig($key$value, function ($key$data) {
  611.                     return [
  612.                         'pimcore' => [
  613.                             'perspectives' => [
  614.                                 'definitions' => [
  615.                                     $key => $data,
  616.                                 ],
  617.                             ],
  618.                         ],
  619.                     ];
  620.                 });
  621.             }
  622.         }
  623.     }
  624.     private static function saveCustomView(array $data)
  625.     {
  626.         $containerConfig \Pimcore::getContainer()->getParameter('pimcore.config');
  627.         $config $containerConfig['custom_views']['definitions'];
  628.         if (method_exists(\Pimcore\Config\LocationAwareConfigRepository::class, 'getStorageConfigurationCompatibilityLayer')) {
  629.             $storageConfig \Pimcore\Config\LocationAwareConfigRepository::getStorageConfigurationCompatibilityLayer(
  630.                 $containerConfig,
  631.                 'custom_views',
  632.                 'PIMCORE_CONFIG_STORAGE_DIR_CUSTOM_VIEWS',
  633.                 'PIMCORE_WRITE_TARGET_CUSTOM_VIEWS'
  634.             );
  635.         } else {
  636.             $storageConfig $containerConfig['config_location']['custom_views'] ?? null;
  637.         }
  638.         if(empty($storageConfig['write_target']['options']['directory'])) {
  639.             $storageConfig['write_target']['options']['directory'] = PIMCORE_CONFIGURATION_DIRECTORY.'/custom-views';
  640.         }
  641.         try {
  642.             $repository = new LocationAwareConfigRepository(
  643.                 $config,
  644.                 'pimcore_custom_views',
  645.                 $storageConfig
  646.             );
  647.         } catch(\Throwable $e) {
  648.             $repository = new LocationAwareConfigRepository(
  649.                 $config,
  650.                 'pimcore_custom_views',
  651.                 $storageConfig['write_target']['options']['directory'],
  652.                 null
  653.             );
  654.         }
  655.         foreach ($data as $key => $value) {
  656.             $key = (string)$key;
  657.             list($configKey$dataSource) = $repository->loadConfigByKey($key);
  658.             if ($repository->isWriteable($key$dataSource)) {
  659.                 unset($value['writeable']);
  660.                 $repository->saveConfig($key$value, function ($key$data) {
  661.                     return [
  662.                         'pimcore' => [
  663.                             'custom_views' => [
  664.                                 'definitions' => [
  665.                                     $key => $data,
  666.                                 ],
  667.                             ],
  668.                         ],
  669.                     ];
  670.                 });
  671.             }
  672.         }
  673.     }
  674.     public function updatePerspective(ClassDefinitionEvent $e)
  675.     {
  676.         self::createPerspective();
  677.     }
  678. }