<?php
/*
* 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.
*
* In accordance with the provisions of the respective licences, it is only possible to
* a.) use Blackbit software under GPLv3 with the Pimcore Community Edition under GPLv3 or
* b.) combine Blackbit software under a commercial licence and Pimcore under a commercial licence.
*
* 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:
* Open source - You can view the unencrypted programme code of our software.
* Customisation - You can adapt the software to your needs and develop it further as you wish.
* 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.
*
* 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.
*
* For further information, please refer to the respective licence files or contact sales@blackbit.de
*/
namespace Blackbit\DataDirectorBundle\EventListener;
use Blackbit\DataDirectorBundle\lib\Pim\Cache\RuntimeCache;
use Blackbit\DataDirectorBundle\lib\Pim\FieldType\CalculatedValueDataQuerySelector;
use Blackbit\DataDirectorBundle\lib\Pim\Helper;
use Blackbit\DataDirectorBundle\lib\Pim\Item\ItemMoldBuilder;
use Blackbit\DataDirectorBundle\lib\Pim\LocationAwareConfigRepository;
use Blackbit\DataDirectorBundle\lib\Pim\Logger\TagLogger;
use Blackbit\DataDirectorBundle\model\Dataport;
use Blackbit\DataDirectorBundle\model\PimcoreDbRepository;
use Blackbit\DataDirectorBundle\Tools\Installer;
use Pimcore\Bundle\AdminBundle\Event\AdminEvents;
use Pimcore\Db;
use Pimcore\Event\Model\DataObject\ClassDefinitionEvent;
use Pimcore\Event\Model\DataObject\ObjectbrickDefinitionEvent;
use Pimcore\File;
use Pimcore\Model\DataObject\ClassDefinition;
use Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage;
use Pimcore\Model\DataObject\ClassDefinition\Data\Image;
use Pimcore\Model\DataObject\ClassDefinition\Data;
use Pimcore\Model\DataObject\ClassDefinition\Data\Objectbricks;
use Pimcore\Model\DataObject\ClassDefinition\Data\Relations\AbstractRelations;
use Pimcore\Model\DataObject\ClassDefinition\Listing;
use Pimcore\Model\DataObject\ClassDefinition\PathFormatterAwareInterface;
use Pimcore\Model\DataObject\Data\ImageGallery;
use Pimcore\Model\DataObject\Objectbrick\Data\AbstractData;
use Pimcore\Model\DataObject\Objectbrick\Definition;
use Pimcore\Perspective\Config;
use Pimcore\Tool;
use Blackbit\DataDirectorBundle\lib\Pim\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
class ClassChangedListener
{
/** @var ItemMoldBuilder */
private $itemMoldBuilder;
public function __construct(ItemMoldBuilder $itemMoldBuilder)
{
$this->itemMoldBuilder = $itemMoldBuilder;
}
public function removeCompiledDataQuerySelectors(ClassDefinitionEvent $e) {
try {
$dummyObject = $this->itemMoldBuilder->getItemMoldByClassname($e->getClassDefinition()->getName());
$classFqn = \get_class($dummyObject);
} catch (\Exception $classNotFoundException) {
$classFqn = 'Pimcore\\Model\\DataObject\\'.$e->getClassDefinition()->getName();
}
$directoryIterator = new \DirectoryIterator(Installer::getCachePath());
$fileNamePrefix = preg_replace('/\W+/', '_', $classFqn.' ');
$filterIterator = new \CallbackFilterIterator($directoryIterator, static function (\SplFileInfo $fileInfo) use ($fileNamePrefix) {
return strpos($fileInfo->getFilename(), $fileNamePrefix) === 0 || strpos($fileInfo->getFilename(), 'Dao_'.$fileNamePrefix) === 0 || strpos($fileInfo->getFilename(), 'Listing_'.$fileNamePrefix) === 0;
});
/** @var \SplFileInfo $compiledFileInfo */
foreach ($filterIterator as $compiledFile) {
unlink($compiledFile->getPathname());
}
}
public function removeAllCompiledDataQuerySelectors() {
/** @var \SplFileInfo $compiledFileInfo */
foreach(new \DirectoryIterator(Installer::getCachePath()) as $compiledFileInfo) {
if (!$compiledFileInfo->isDot()) {
@unlink($compiledFileInfo->getPathname());
}
}
}
public function createStoreView(ClassDefinitionEvent $e)
{
if ($e->getClassDefinition()->getAllowInherit()) {
$hasLocalizedFields = false;
foreach ($e->getClassDefinition()->getFieldDefinitions() as $fieldDefinition) {
if ($fieldDefinition instanceof Data\Localizedfields) {
$hasLocalizedFields = true;
break;
}
}
foreach (Tool::getValidLanguages() as $language) {
$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`';
$parameters = [];
if($hasLocalizedFields) {
$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=?';
$parameters[] = $language;
}
PimcoreDbRepository::getInstance()->execute($query, $parameters);
}
} else {
$this->removeStoreView($e);
}
}
public function removeStoreView(ClassDefinitionEvent $e)
{
foreach (Tool::getValidLanguages() as $language) {
PimcoreDbRepository::getInstance()->execute('DROP VIEW IF EXISTS `object_localized_store_'.$e->getClassDefinition()->getId().'_'.$language.'`');
}
}
public function addPreviewService(ClassDefinitionEvent $e)
{
$classDefinition = $e->getClassDefinition();
if (method_exists($classDefinition, 'setPreviewGeneratorReference')) {
if (!$classDefinition->getPreviewGeneratorReference() && !$classDefinition->getLinkGeneratorReference()) {
$classDefinition->setPreviewGeneratorReference('@DataDirectorPreview');
}
} elseif (method_exists($classDefinition, 'setPreviewUrl')) {
if (!$classDefinition->getPreviewUrl()) {
$classDefinition->setPreviewUrl('/admin/BlackbitDataDirector/import/object-preview?id=%o_id');
}
}
}
/**
* @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
* @return void
*/
public function setLayoutFieldNames($e)
{
if ($e instanceof ObjectbrickDefinitionEvent) {
$classDefinition = $e->getObjectbrickDefinition();
} else {
$classDefinition = $e->getClassDefinition();
}
$layout = $classDefinition->getLayoutDefinitions();
if($layout instanceof ClassDefinition\Layout) {
$this->setLayoutFieldName($layout, $classDefinition);
}
}
/**
* @param ClassDefinition\Layout|ClassDefinition\Data $layout
* @param ClassDefinition|Definition $classDefinition
* @return void
*/
private function setLayoutFieldName($layout, $classDefinition): void
{
$translator = \Pimcore::getContainer()->get('translator');
$replaceableLayoutNames = [
'',
'Layout',
$translator->trans($layout->fieldtype, [], 'admin_ext', Tool::getDefaultLanguage()),
$translator->trans($layout->fieldtype, [], 'admin_ext', Helper::getUser()->getLanguage())
];
if($layout instanceof ClassDefinition\Layout && property_exists($layout, 'fieldtype') && in_array($layout->name, $replaceableLayoutNames, true)) {
if($layout->title) {
$name = trim(preg_replace('/[^a-z0-9_]+/i', '', Helper::toASCII($layout->title, Tool::getDefaultLanguage())));
if(!$classDefinition->getFieldDefinition($name) instanceof ClassDefinition\Data) {
$layout->setName($name);
}
} elseif (property_exists($layout, 'text') && $layout->text) {
$name = trim(preg_replace('/[^a-z0-9_]+/i', '', Helper::toASCII($layout->text, Tool::getDefaultLanguage())));
if (!$classDefinition->getFieldDefinition($name) instanceof ClassDefinition\Data) {
$layout->setName($name);
}
}
}
if (method_exists($layout, 'getChildren')) {
$children = $layout->getChildren();
if (is_array($children)) {
foreach ($children as $child) {
$this->setLayoutFieldName($child, $classDefinition);
}
}
}
}
/**
* @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
* @return void
*/
public function addPathFormatterService($e)
{
if($e instanceof ObjectbrickDefinitionEvent) {
$classDefinition = $e->getObjectbrickDefinition();
} else {
$classDefinition = $e->getClassDefinition();
}
foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
if ($fieldDefinition instanceof PathFormatterAwareInterface && !$fieldDefinition->getPathFormatterClass() && method_exists($fieldDefinition, 'setPathFormatterClass')) {
$fieldDefinition->setPathFormatterClass('@DataDirectorSearchViewPathFormatter');
} elseif ($fieldDefinition instanceof Localizedfields) {
foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
if ($localizedFieldDefinition instanceof PathFormatterAwareInterface && !$localizedFieldDefinition->getPathFormatterClass() && method_exists($localizedFieldDefinition, 'setPathFormatterClass')) {
$localizedFieldDefinition->setPathFormatterClass('@DataDirectorSearchViewPathFormatter');
}
}
}
}
}
/**
* @param ClassDefinitionEvent|ObjectbrickDefinitionEvent $e
* @return void
*/
public function clearCalculatedValueFieldCache($e)
{
if ($e instanceof ObjectbrickDefinitionEvent) {
$classDefinition = $e->getObjectbrickDefinition();
} else {
$classDefinition = $e->getClassDefinition();
}
foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
if ($fieldDefinition instanceof CalculatedValueDataQuerySelector) {
PimcoreDbRepository::getInstance()->execute('UPDATE object_query_'.$classDefinition->getId().' SET '.Db::get()->quoteIdentifier($fieldDefinition->getName()).'=NULL');
} elseif ($fieldDefinition instanceof Localizedfields) {
foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
if ($localizedFieldDefinition instanceof CalculatedValueDataQuerySelector) {
foreach (Tool::getValidLanguages() as $language) {
PimcoreDbRepository::getInstance()->execute('UPDATE object_localized_query_'.$classDefinition->getId().'_'.$language.' SET '.Db::get()->quoteIdentifier($localizedFieldDefinition->getName()).'=NULL');
}
}
}
}
}
}
public function setClassIcon(ClassDefinitionEvent $e)
{
$classDefinition = $e->getClassDefinition();
if(!$classDefinition->getIcon()) {
$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'];
$classDefinition->setIcon('/bundles/pimcoreadmin/img/object-icons/'.$icons[crc32($classDefinition->getName()) % count($icons)]);
}
}
public static function createPerspective()
{
if(RuntimeCache::isRegistered(__CLASS__.__METHOD__)) {
return;
}
$existingPerspectives = Config::get();
if(!$existingPerspectives) {
return;
}
if($existingPerspectives instanceof \Pimcore\Config\Config) {
$existingPerspectives = $existingPerspectives->toArray();
}
foreach($existingPerspectives as $perspectiveName => $existingPerspective) {
if(strpos($perspectiveName, 'pim.perspective') !== 0 && $perspectiveName !== 'default') {
return;
}
}
$dependencies = [];
$customViews = [];
foreach ((new Listing())->load() as $classDefinition) {
$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()]);
$customViewId = 'dd_'.File::getValidFilename($classDefinition->getGroup() ?? '');
if($groupExistsAsFolder) {
$rootFolder = '/'.$groupExistsAsFolder.'/';
} else {
$firstFolder = PimcoreDbRepository::getInstance()->findOneInSql('SELECT '.Helper::prefixObjectSystemColumn('path').' FROM objects WHERE '.Helper::prefixObjectSystemColumn('classId').'=? ORDER BY '.Helper::prefixObjectSystemColumn('path').' LIMIT 1', [$classDefinition->getId()]
) ?: '/';
$lastFolder = PimcoreDbRepository::getInstance()->findOneInSql('SELECT '.Helper::prefixObjectSystemColumn('path').' FROM objects WHERE '.Helper::prefixObjectSystemColumn('classId').'=? ORDER BY '.Helper::prefixObjectSystemColumn('path').' DESC LIMIT 1', [$classDefinition->getId()]
) ?: '/';
$len = min(mb_strlen($firstFolder), mb_strlen($lastFolder));
for ($i = 0; $i < $len; $i++) {
if (mb_substr($firstFolder, $i, 1) !== mb_substr($lastFolder, $i, 1)) {
break;
}
}
$commonPrefix = substr($firstFolder, 0, $i);
$rootFolder = $commonPrefix ?: '/';
if (substr($commonPrefix, -1) !== '/') {
$rootFolder = dirname($commonPrefix).'/';
}
}
if (!isset($dependencies[$customViewId])) {
$dependencies[$customViewId] = [];
}
if (!isset($customViews[$customViewId])) {
$customViews[$customViewId] = [
'id' => $customViewId,
'name' => $classDefinition->getGroup() ?: 'data_objects',
'treetype' => 'object',
'position' => 'left',
'rootfolder' => $rootFolder,
'classes' => $classDefinition->getId(),
'showroot' => true,
'sort' => 0,
'treeContextMenu' => [
'object' => [
'items' => [
'add' => true,
'addFolder' => true,
'importCsv' => true,
'cut' => true,
'copy' => true,
'paste' => true,
'delete' => true,
'rename' => true,
'reload' => true,
'publish' => true,
'unpublish' => true,
'searchAndMove' => true,
'lock' => true,
'unlock' => true,
'lockAndPropagate' => true,
'unlockAndPropagate' => true,
'changeChildrenSortBy' => true
]
]
],
'icon' => $classDefinition->getIcon() ?: '/bundles/pimcoreadmin/img/flat-white-icons/pimcore-main-icon-object.svg'
];
} else {
$customViews[$customViewId]['classes'] .= ','.$classDefinition->getId();
if (!$groupExistsAsFolder && $firstFolder !== '/') {
$firstFolder = (mb_strlen($customViews[$customViewId]['rootfolder']) <= mb_strlen($commonPrefix) ? $customViews[$customViewId]['rootfolder'] : $commonPrefix);
$lastFolder = (mb_strlen($customViews[$customViewId]['rootfolder']) > mb_strlen($commonPrefix) ? $customViews[$customViewId]['rootfolder'] : $commonPrefix);
$len = min(mb_strlen($firstFolder), mb_strlen($lastFolder));
for ($i = 0; $i < $len; $i++) {
if (mb_substr($firstFolder, $i, 1) !== mb_substr($lastFolder, $i, 1)) {
break;
}
}
$rootFolder = substr($firstFolder, 0, $i);
if (substr($commonPrefix, -1) !== '/') {
$rootFolder = dirname($commonPrefix).'/';
} else {
$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'].'%']);
if($countObjectsOutsidePreviousRootfolder < 5) {
$rootFolder = $customViews[$customViewId]['rootfolder'];
}
}
$customViews[$customViewId]['rootfolder'] = $rootFolder;
}
}
foreach ($classDefinition->getFieldDefinitions() as $fieldDefinition) {
if ($fieldDefinition instanceof AbstractRelations && method_exists($fieldDefinition, 'getDocumentsAllowed') && $fieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif($fieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($fieldDefinition, 'getObjectsAllowed') && $fieldDefinition->getObjectsAllowed()) {
foreach ((array)$fieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup() ?? '');
}
}
} elseif ($fieldDefinition instanceof Localizedfields) {
foreach ($fieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition, 'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif ($localizedFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($localizedFieldDefinition, 'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if ($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
}
}
}
}
} elseif ($fieldDefinition instanceof Objectbricks) {
foreach ($fieldDefinition->getAllowedTypes() as $brickName) {
$brickDefinition = Definition::getByKey($brickName);
if(!$brickDefinition instanceof Definition) {
continue;
}
foreach ($brickDefinition->getFieldDefinitions() as $brickFieldDefinition) {
if ($brickFieldDefinition instanceof Localizedfields) {
foreach ($brickFieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition, 'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif ($localizedFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($localizedFieldDefinition, 'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if ($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
}
}
}
}
} elseif ($brickFieldDefinition instanceof AbstractRelations && method_exists($brickFieldDefinition, 'getDocumentsAllowed') && $brickFieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif ($brickFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($brickFieldDefinition, 'getObjectsAllowed') && $brickFieldDefinition->getObjectsAllowed()) {
foreach ((array)$brickFieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if ($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
}
}
}
}
}
} elseif ($fieldDefinition instanceof ClassDefinition\Data\Fieldcollections) {
foreach ($fieldDefinition->getAllowedTypes() as $brickName) {
$brickDefinition = \Pimcore\Model\DataObject\Fieldcollection\Definition::getByKey($brickName);
foreach ($brickDefinition->getFieldDefinitions() as $brickFieldDefinition) {
if ($brickFieldDefinition instanceof Localizedfields) {
foreach ($brickFieldDefinition->getFieldDefinitions() as $localizedFieldDefinition) {
if ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition, 'getDocumentsAllowed') && $localizedFieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif ($localizedFieldDefinition instanceof AbstractRelations && method_exists($localizedFieldDefinition, 'getObjectsAllowed') && $localizedFieldDefinition->getObjectsAllowed()) {
foreach ((array)$localizedFieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if ($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
}
}
}
}
} elseif ($brickFieldDefinition instanceof AbstractRelations && method_exists($brickFieldDefinition, 'getDocumentsAllowed') && $brickFieldDefinition->getDocumentsAllowed()) {
$dependencies[$customViewId][] = 'document';
} elseif ($brickFieldDefinition instanceof AbstractRelations && !$fieldDefinition instanceof ClassDefinition\Data\ReverseManyToManyObjectRelation && !$fieldDefinition instanceof ClassDefinition\Data\ReverseObjectRelation && method_exists($brickFieldDefinition, 'getObjectsAllowed') && $brickFieldDefinition->getObjectsAllowed()) {
foreach ((array)$brickFieldDefinition->getClasses() as $allowedClass) {
$allowedClass = ClassDefinition::getByName($allowedClass['classes']);
if ($allowedClass instanceof ClassDefinition) {
$dependencies[$customViewId][] = 'dd_'.File::getValidFilename($allowedClass->getGroup());
}
}
}
}
}
}
}
}
$perspectives = [
'pim.perspective.default' => [
'elementTree' => [
[
'type' => 'documents',
'position' => 'left',
'expanded' => false,
'hidden' => false,
'sort' => 0
],
[
'type' => 'assets',
'position' => 'left',
'expanded' => false,
'hidden' => false,
'sort' => 1
],
[
'type' => 'objects',
'position' => 'left',
'expanded' => false,
'hidden' => false,
'sort' => 2
]
],
'iconCls' => 'pimcore_nav_icon_perspective',
'icon' => null,
'dashboards' => [
'predefined' => [
'welcome' => [
'positions' => [
[
[
'id' => 1,
'type' => 'pimcore.layout.portlets.modificationStatistic',
'config' => null
],
[
'id' => 2,
'type' => 'pimcore.layout.portlets.modifiedAssets',
'config' => null
]
],
[
[
'id' => 3,
'type' => 'pimcore.layout.portlets.modifiedObjects',
'config' => null
],
[
'id' => 4,
'type' => 'pimcore.layout.portlets.modifiedDocuments',
'config' => null
]
]
]
]
]
]
]
];
if (count($customViews) > 0) {
self::saveCustomView($customViews);
uksort($customViews, static function ($customViewId1, $customViewId2) use ($customViews, $dependencies) {
$order = count($dependencies[$customViewId2]) <=> count($dependencies[$customViewId1]);
if ($order !== 0) {
return $order;
}
$order = substr_count($customViews[$customViewId2]['classes'], ',') <=> substr_count($customViews[$customViewId1]['classes'], ',');
if ($order !== 0) {
return $order;
}
if ($customViews[$customViewId1]['name'] === 'data_objects' && $customViews[$customViewId2]['name'] !== 'data_objects') {
return 1;
}
if ($customViews[$customViewId1]['name'] !== 'data_objects' && $customViews[$customViewId2]['name'] === 'data_objects') {
return -1;
}
return strcasecmp($customViews[$customViewId1]['name'], $customViews[$customViewId2]['name']);
});
$elementTree = [[
'type' => 'assets',
'position' => 'right',
'expanded' => false,
'hidden' => false,
'sort' => 9000
]];
foreach ($customViews as $customViewId => $customView) {
if (in_array('document', $dependencies[$customViewId], true)) {
$elementTree[] = [
'type' => 'documents',
'position' => 'left',
'expanded' => false,
'hidden' => false,
'sort' => 9001
];
}
}
$index = 0;
foreach ($customViews as $customViewId => $customView) {
$position = 'left';
foreach ($elementTree as $perspectiveView) {
if ($perspectiveView['type'] === 'customview' && in_array($customViewId, $dependencies[$perspectiveView['id']] ?? [])) {
$position = 'right';
break;
}
}
$elementTree[] = [
'type' => 'customview',
'position' => $position,
'expanded' => false,
'hidden' => false,
'sort' => $customViewId === 'dd_' ? 8000 : ($index++),
'id' => $customViewId
];
}
$perspectives['pim.perspective.PIM'] = [
'iconCls' => 'pimcore_icon_object',
'elementTree' => $elementTree,
'dashboards' => [
'predefined' => [
'welcome' => [
'positions' => [
[
[
'id' => 1,
'type' => 'pimcore.layout.portlets.DataDirector_ErrorMonitor',
'config' => null
],
[
'id' => 2,
'type' => 'pimcore.layout.portlets.DataDirector_TaggedElements',
'config' => json_encode([
'title' => 'Objects with import errors',
'tags' => [TagLogger::getOrCreateTag('Data Director')->getId()]
])
]
],
[
[
'id' => 3,
'type' => 'pimcore.layout.portlets.DataDirector_QueueMonitor',
'config' => null
]
]
]
]
]
]
];
}
self::savePerspective($perspectives);
RuntimeCache::save(true, __CLASS__.__METHOD__);
}
private static function savePerspective(array $data) {
$containerConfig = \Pimcore::getContainer()->getParameter('pimcore.config');
$config = $containerConfig['perspectives']['definitions'];
if (method_exists(\Pimcore\Config\LocationAwareConfigRepository::class, 'getStorageConfigurationCompatibilityLayer')) {
$storageConfig = \Pimcore\Config\LocationAwareConfigRepository::getStorageConfigurationCompatibilityLayer(
$containerConfig,
'perspectives',
'PIMCORE_CONFIG_STORAGE_DIR_PERSPECTIVES',
'PIMCORE_WRITE_TARGET_PERSPECTIVES'
);
} else {
$storageConfig = $containerConfig['config_location']['perspectives'] ?? null;
}
if (empty($storageConfig['write_target']['options']['directory'])) {
$storageConfig['write_target']['options']['directory'] = PIMCORE_CONFIGURATION_DIRECTORY.'/perspectives';
}
try {
$repository = new LocationAwareConfigRepository(
$config,
'pimcore_perspectives',
$storageConfig
);
} catch (\Throwable $e) {
$repository = new LocationAwareConfigRepository(
$config,
'pimcore_perspectives',
$storageConfig['write_target']['options']['directory'],
null
);
}
foreach ($data as $key => $value) {
list($configKey, $dataSource) = $repository->loadConfigByKey($key);
if ($repository->isWriteable($key, $dataSource) === true) {
unset($value['writeable']);
$repository->saveConfig($key, $value, function ($key, $data) {
return [
'pimcore' => [
'perspectives' => [
'definitions' => [
$key => $data,
],
],
],
];
});
}
}
}
private static function saveCustomView(array $data)
{
$containerConfig = \Pimcore::getContainer()->getParameter('pimcore.config');
$config = $containerConfig['custom_views']['definitions'];
if (method_exists(\Pimcore\Config\LocationAwareConfigRepository::class, 'getStorageConfigurationCompatibilityLayer')) {
$storageConfig = \Pimcore\Config\LocationAwareConfigRepository::getStorageConfigurationCompatibilityLayer(
$containerConfig,
'custom_views',
'PIMCORE_CONFIG_STORAGE_DIR_CUSTOM_VIEWS',
'PIMCORE_WRITE_TARGET_CUSTOM_VIEWS'
);
} else {
$storageConfig = $containerConfig['config_location']['custom_views'] ?? null;
}
if(empty($storageConfig['write_target']['options']['directory'])) {
$storageConfig['write_target']['options']['directory'] = PIMCORE_CONFIGURATION_DIRECTORY.'/custom-views';
}
try {
$repository = new LocationAwareConfigRepository(
$config,
'pimcore_custom_views',
$storageConfig
);
} catch(\Throwable $e) {
$repository = new LocationAwareConfigRepository(
$config,
'pimcore_custom_views',
$storageConfig['write_target']['options']['directory'],
null
);
}
foreach ($data as $key => $value) {
$key = (string)$key;
list($configKey, $dataSource) = $repository->loadConfigByKey($key);
if ($repository->isWriteable($key, $dataSource)) {
unset($value['writeable']);
$repository->saveConfig($key, $value, function ($key, $data) {
return [
'pimcore' => [
'custom_views' => [
'definitions' => [
$key => $data,
],
],
],
];
});
}
}
}
public function updatePerspective(ClassDefinitionEvent $e)
{
self::createPerspective();
}
}