vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/DataObject/ClassController.php line 900

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\Bundle\AdminBundle\Controller\Admin\DataObject;
  15. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  16. use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
  17. use Pimcore\Controller\KernelControllerEventInterface;
  18. use Pimcore\Db;
  19. use Pimcore\Event\AdminEvents;
  20. use Pimcore\Logger;
  21. use Pimcore\Model\Asset;
  22. use Pimcore\Model\DataObject;
  23. use Pimcore\Model\Document;
  24. use Pimcore\Model\Translation;
  25. use Pimcore\Tool\Session;
  26. use Symfony\Component\EventDispatcher\GenericEvent;
  27. use Symfony\Component\HttpFoundation\Request;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  30. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  33. /**
  34.  * @Route("/class", name="pimcore_admin_dataobject_class_")
  35.  *
  36.  * @internal
  37.  */
  38. class ClassController extends AdminController implements KernelControllerEventInterface
  39. {
  40.     /**
  41.      * @Route("/get-document-types", name="getdocumenttypes", methods={"GET"})
  42.      *
  43.      * @param Request $request
  44.      *
  45.      * @return JsonResponse
  46.      */
  47.     public function getDocumentTypesAction(Request $request)
  48.     {
  49.         $documentTypes Document::getTypes();
  50.         $typeItems = [];
  51.         foreach ($documentTypes as $documentType) {
  52.             $typeItems[] = [
  53.                 'text' => $documentType,
  54.             ];
  55.         }
  56.         return $this->adminJson($typeItems);
  57.     }
  58.     /**
  59.      * @Route("/get-asset-types", name="getassettypes", methods={"GET"})
  60.      *
  61.      * @param Request $request
  62.      *
  63.      * @return JsonResponse
  64.      */
  65.     public function getAssetTypesAction(Request $request)
  66.     {
  67.         $assetTypes Asset::getTypes();
  68.         $typeItems = [];
  69.         foreach ($assetTypes as $assetType) {
  70.             $typeItems[] = [
  71.                 'text' => $assetType,
  72.             ];
  73.         }
  74.         return $this->adminJson($typeItems);
  75.     }
  76.     /**
  77.      * @Route("/get-tree", name="gettree", methods={"GET", "POST"})
  78.      *
  79.      * @param Request $request
  80.      *
  81.      * @return JsonResponse
  82.      */
  83.     public function getTreeAction(Request $request)
  84.     {
  85.         $defaultIcon '/bundles/pimcoreadmin/img/flat-color-icons/class.svg';
  86.         $classesList = new DataObject\ClassDefinition\Listing();
  87.         $classesList->setOrderKey('name');
  88.         $classesList->setOrder('asc');
  89.         $classes $classesList->load();
  90.         // filter classes
  91.         if ($request->get('createAllowed')) {
  92.             $tmpClasses = [];
  93.             foreach ($classes as $class) {
  94.                 if ($this->getAdminUser()->isAllowed($class->getId(), 'class')) {
  95.                     $tmpClasses[] = $class;
  96.                 }
  97.             }
  98.             $classes $tmpClasses;
  99.         }
  100.         $withId $request->get('withId');
  101.         $getClassConfig = function ($class) use ($defaultIcon$withId) {
  102.             $text $class->getname();
  103.             if ($withId) {
  104.                 $text .= ' (' $class->getId() . ')';
  105.             }
  106.             $hasBrickField false;
  107.             foreach ($class->getFieldDefinitions() as $fieldDefinition) {
  108.                 if ($fieldDefinition instanceof DataObject\ClassDefinition\Data\Objectbricks) {
  109.                     $hasBrickField true;
  110.                     break;
  111.                 }
  112.             }
  113.             return [
  114.                 'id' => $class->getId(),
  115.                 'text' => $text,
  116.                 'leaf' => true,
  117.                 'icon' => $class->getIcon() ? htmlspecialchars($class->getIcon()) : $defaultIcon,
  118.                 'cls' => 'pimcore_class_icon',
  119.                 'propertyVisibility' => $class->getPropertyVisibility(),
  120.                 'enableGridLocking' => $class->isEnableGridLocking(),
  121.                 'hasBrickField' => $hasBrickField,
  122.             ];
  123.         };
  124.         // build groups
  125.         $groups = [];
  126.         foreach ($classes as $class) {
  127.             $groupName null;
  128.             if ($class->getGroup()) {
  129.                 $type 'manual';
  130.                 $groupName $class->getGroup();
  131.             } else {
  132.                 $type 'auto';
  133.                 if (preg_match('@^([A-Za-z])([^A-Z]+)@'$class->getName(), $matches)) {
  134.                     $groupName $matches[0];
  135.                 }
  136.                 if (!$groupName) {
  137.                     // this is eg. the case when class name uses only capital letters
  138.                     $groupName $class->getName();
  139.                 }
  140.             }
  141.             $groupName Translation::getByKeyLocalized($groupNameTranslation::DOMAIN_ADMINtruetrue);
  142.             if (!isset($groups[$groupName])) {
  143.                 $groups[$groupName] = [
  144.                     'classes' => [],
  145.                     'type' => $type,
  146.                 ];
  147.             }
  148.             $groups[$groupName]['classes'][] = $class;
  149.         }
  150.         $treeNodes = [];
  151.         if (!empty($groups)) {
  152.             $types array_column($groups'type');
  153.             array_multisort($typesSORT_ASCarray_keys($groups), SORT_ASC$groups);
  154.         }
  155.         if (!$request->get('grouped')) {
  156.             // list output
  157.             foreach ($groups as $groupName => $groupData) {
  158.                 foreach ($groupData['classes'] as $class) {
  159.                     $node $getClassConfig($class);
  160.                     if (count($groupData['classes']) > || $groupData['type'] == 'manual') {
  161.                         $node['group'] = $groupName;
  162.                     }
  163.                     $treeNodes[] = $node;
  164.                 }
  165.             }
  166.         } else {
  167.             // create json output
  168.             foreach ($groups as $groupName => $groupData) {
  169.                 if (count($groupData['classes']) === && $groupData['type'] == 'auto') {
  170.                     // no group, only one child
  171.                     $node $getClassConfig($groupData['classes'][0]);
  172.                 } else {
  173.                     // group classes
  174.                     $node = [
  175.                         'id' => 'folder_' $groupName,
  176.                         'text' => $groupName,
  177.                         'leaf' => false,
  178.                         'expandable' => true,
  179.                         'allowChildren' => true,
  180.                         'iconCls' => 'pimcore_icon_folder',
  181.                         'children' => [],
  182.                     ];
  183.                     foreach ($groupData['classes'] as $class) {
  184.                         $node['children'][] = $getClassConfig($class);
  185.                     }
  186.                 }
  187.                 $treeNodes[] = $node;
  188.             }
  189.         }
  190.         return $this->adminJson($treeNodes);
  191.     }
  192.     /**
  193.      * @Route("/get", name="get", methods={"GET"})
  194.      *
  195.      * @param Request $request
  196.      *
  197.      * @return JsonResponse
  198.      */
  199.     public function getAction(Request $request)
  200.     {
  201.         $class DataObject\ClassDefinition::getById($request->get('id'));
  202.         if (!$class) {
  203.             throw $this->createNotFoundException();
  204.         }
  205.         $class->setFieldDefinitions([]);
  206.         $isWriteable $class->isWritable();
  207.         $class $class->getObjectVars();
  208.         $class['isWriteable'] = $isWriteable;
  209.         return $this->adminJson($class);
  210.     }
  211.     /**
  212.      * @Route("/get-custom-layout", name="getcustomlayout", methods={"GET"})
  213.      *
  214.      * @param Request $request
  215.      *
  216.      * @return JsonResponse
  217.      */
  218.     public function getCustomLayoutAction(Request $request)
  219.     {
  220.         $customLayout DataObject\ClassDefinition\CustomLayout::getById($request->get('id'));
  221.         if (!$customLayout) {
  222.             $brickLayoutSeparator strpos($request->get('id'), '.brick.');
  223.             if ($brickLayoutSeparator !== false) {
  224.                 $customLayout DataObject\ClassDefinition\CustomLayout::getById(substr($request->get('id'), 0$brickLayoutSeparator));
  225.                 if ($customLayout instanceof DataObject\ClassDefinition\CustomLayout) {
  226.                     $customLayout DataObject\ClassDefinition\CustomLayout::create(
  227.                         [
  228.                             'name' => $customLayout->getName().' '.substr($request->get('id'), $brickLayoutSeparator+strlen('.brick.')),
  229.                             'userOwner' => $this->getAdminUser()->getId(),
  230.                             'classId' => $customLayout->getClassId(),
  231.                         ]
  232.                     );
  233.                     $customLayout->setId($request->get('id'));
  234.                     $customLayout->save();
  235.                 }
  236.             }
  237.             if (!$customLayout) {
  238.                 throw $this->createNotFoundException();
  239.             }
  240.         }
  241.         $isWriteable $customLayout->isWritable();
  242.         $customLayout $customLayout->getObjectVars();
  243.         $customLayout['isWriteable'] = $isWriteable;
  244.         return $this->adminJson(['success' => true'data' => $customLayout]);
  245.     }
  246.     /**
  247.      * @Route("/add", name="add", methods={"POST"})
  248.      *
  249.      * @param Request $request
  250.      *
  251.      * @return JsonResponse
  252.      */
  253.     public function addAction(Request $request)
  254.     {
  255.         $className $request->get('className');
  256.         $className $this->correctClassname($className);
  257.         $classId $request->get('classIdentifier');
  258.         $existingClass DataObject\ClassDefinition::getById($classId);
  259.         if ($existingClass) {
  260.             throw new \Exception('Class identifier already exists');
  261.         }
  262.         $class DataObject\ClassDefinition::create(
  263.             ['name' => $className,
  264.                 'userOwner' => $this->getAdminUser()->getId(), ]
  265.         );
  266.         $class->setId($classId);
  267.         $class->save(true);
  268.         return $this->adminJson(['success' => true'id' => $class->getId()]);
  269.     }
  270.     /**
  271.      * @Route("/add-custom-layout", name="addcustomlayout", methods={"POST"})
  272.      *
  273.      * @param Request $request
  274.      *
  275.      * @return JsonResponse
  276.      */
  277.     public function addCustomLayoutAction(Request $request)
  278.     {
  279.         $layoutId $request->get('layoutIdentifier');
  280.         $existingLayout DataObject\ClassDefinition\CustomLayout::getById($layoutId);
  281.         if ($existingLayout) {
  282.             throw new \Exception('Custom Layout identifier already exists');
  283.         }
  284.         $customLayout DataObject\ClassDefinition\CustomLayout::create(
  285.             [
  286.                 'name' => $request->get('layoutName'),
  287.                 'userOwner' => $this->getAdminUser()->getId(),
  288.                 'classId' => $request->get('classId'),
  289.             ]
  290.         );
  291.         $customLayout->setId($layoutId);
  292.         $customLayout->save();
  293.         $isWriteable $customLayout->isWritable();
  294.         $data $customLayout->getObjectVars();
  295.         $data['isWriteable'] = $isWriteable;
  296.         return $this->adminJson(['success' => true'id' => $customLayout->getId(), 'name' => $customLayout->getName(),
  297.                                  'data' => $data, ]);
  298.     }
  299.     /**
  300.      * @Route("/delete", name="delete", methods={"DELETE"})
  301.      *
  302.      * @param Request $request
  303.      *
  304.      * @return Response
  305.      */
  306.     public function deleteAction(Request $request)
  307.     {
  308.         $class DataObject\ClassDefinition::getById($request->get('id'));
  309.         if ($class) {
  310.             $class->delete();
  311.         }
  312.         return new Response();
  313.     }
  314.     /**
  315.      * @Route("/delete-custom-layout", name="deletecustomlayout", methods={"DELETE"})
  316.      *
  317.      * @param Request $request
  318.      *
  319.      * @return JsonResponse
  320.      */
  321.     public function deleteCustomLayoutAction(Request $request)
  322.     {
  323.         $customLayouts = new DataObject\ClassDefinition\CustomLayout\Listing();
  324.         $id $request->get('id');
  325.         $customLayouts->setFilter(function (DataObject\ClassDefinition\CustomLayout $layout) use ($id) {
  326.             $currentLayoutId $layout->getId();
  327.             return $currentLayoutId === $id || str_starts_with($currentLayoutId$id '.brick.');
  328.         });
  329.         foreach ($customLayouts->getLayoutDefinitions() as $customLayout) {
  330.             $customLayout->delete();
  331.         }
  332.         return $this->adminJson(['success' => true]);
  333.     }
  334.     /**
  335.      * @Route("/save-custom-layout", name="savecustomlayout", methods={"PUT"})
  336.      *
  337.      * @param Request $request
  338.      *
  339.      * @return JsonResponse
  340.      */
  341.     public function saveCustomLayoutAction(Request $request)
  342.     {
  343.         $customLayout DataObject\ClassDefinition\CustomLayout::getById($request->get('id'));
  344.         if (!$customLayout) {
  345.             throw $this->createNotFoundException();
  346.         }
  347.         $configuration $this->decodeJson($request->get('configuration'));
  348.         $values $this->decodeJson($request->get('values'));
  349.         $modificationDate = (int)$values['modificationDate'];
  350.         if ($modificationDate $customLayout->getModificationDate()) {
  351.             return $this->adminJson(['success' => false'msg' => 'custom_layout_changed']);
  352.         }
  353.         $configuration['datatype'] = 'layout';
  354.         $configuration['fieldtype'] = 'panel';
  355.         $configuration['name'] = 'pimcore_root';
  356.         try {
  357.             $layout DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($configurationtrue);
  358.             $customLayout->setLayoutDefinitions($layout);
  359.             $customLayout->setName($values['name']);
  360.             $customLayout->setDescription($values['description']);
  361.             $customLayout->setDefault($values['default']);
  362.             $customLayout->save();
  363.             return $this->adminJson(['success' => true'id' => $customLayout->getId(), 'data' => $customLayout->getObjectVars()]);
  364.         } catch (\Exception $e) {
  365.             Logger::error($e->getMessage());
  366.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  367.         }
  368.     }
  369.     /**
  370.      * @Route("/save", name="save", methods={"PUT"})
  371.      *
  372.      * @param Request $request
  373.      *
  374.      * @return JsonResponse
  375.      *
  376.      * @throws \Exception
  377.      */
  378.     public function saveAction(Request $request)
  379.     {
  380.         $class DataObject\ClassDefinition::getById($request->get('id'));
  381.         if (!$class) {
  382.             throw $this->createNotFoundException();
  383.         }
  384.         $configuration $this->decodeJson($request->get('configuration'));
  385.         $values $this->decodeJson($request->get('values'));
  386.         // check if the class was changed during editing in the frontend
  387.         if ($class->getModificationDate() != $values['modificationDate']) {
  388.             throw new \Exception('The class was modified during editing, please reload the class and make your changes again');
  389.         }
  390.         if ($values['name'] != $class->getName()) {
  391.             $classByName DataObject\ClassDefinition::getByName($values['name']);
  392.             if ($classByName && $classByName->getId() != $class->getId()) {
  393.                 throw new \Exception('Class name already exists');
  394.             }
  395.             $values['name'] = $this->correctClassname($values['name']);
  396.             $class->rename($values['name']);
  397.         }
  398.         if ($values['compositeIndices']) {
  399.             foreach ($values['compositeIndices'] as $index => $compositeIndex) {
  400.                 if ($compositeIndex['index_key'] !== ($sanitizedKey preg_replace('/[^a-za-z0-9_\-+]/'''$compositeIndex['index_key']))) {
  401.                     $values['compositeIndices'][$index]['index_key'] = $sanitizedKey;
  402.                 }
  403.             }
  404.         }
  405.         unset($values['creationDate']);
  406.         unset($values['userOwner']);
  407.         unset($values['layoutDefinitions']);
  408.         unset($values['fieldDefinitions']);
  409.         $configuration['datatype'] = 'layout';
  410.         $configuration['fieldtype'] = 'panel';
  411.         $configuration['name'] = 'pimcore_root';
  412.         $class->setValues($values);
  413.         try {
  414.             $layout DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($configurationtrue);
  415.             $class->setLayoutDefinitions($layout);
  416.             $class->setUserModification($this->getAdminUser()->getId());
  417.             $class->setModificationDate(time());
  418.             $propertyVisibility = [];
  419.             foreach ($values as $key => $value) {
  420.                 if (preg_match('/propertyVisibility/i'$key)) {
  421.                     if (preg_match("/\.grid\./i"$key)) {
  422.                         $propertyVisibility['grid'][preg_replace("/propertyVisibility\.grid\./i"''$key)] = (bool) $value;
  423.                     } elseif (preg_match("/\.search\./i"$key)) {
  424.                         $propertyVisibility['search'][preg_replace("/propertyVisibility\.search\./i"''$key)] = (bool) $value;
  425.                     }
  426.                 }
  427.             }
  428.             if (!empty($propertyVisibility)) {
  429.                 $class->setPropertyVisibility($propertyVisibility);
  430.             }
  431.             $class->save();
  432.             // set the fielddefinitions to [] because we don't need them in the response
  433.             $class->setFieldDefinitions([]);
  434.             return $this->adminJson(['success' => true'class' => $class]);
  435.         } catch (\Exception $e) {
  436.             Logger::error($e->getMessage());
  437.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  438.         }
  439.     }
  440.     /**
  441.      * @param string $name
  442.      *
  443.      * @return string
  444.      */
  445.     protected function correctClassname($name)
  446.     {
  447.         $name preg_replace('/[^a-zA-Z0-9_]+/'''$name);
  448.         $name preg_replace('/^[0-9]+/'''$name);
  449.         return $name;
  450.     }
  451.     /**
  452.      * @Route("/import-class", name="importclass", methods={"POST", "PUT"})
  453.      *
  454.      * @param Request $request
  455.      *
  456.      * @return Response
  457.      */
  458.     public function importClassAction(Request $request)
  459.     {
  460.         $class DataObject\ClassDefinition::getById($request->get('id'));
  461.         if (!$class) {
  462.             throw $this->createNotFoundException();
  463.         }
  464.         $json file_get_contents($_FILES['Filedata']['tmp_name']);
  465.         $success DataObject\ClassDefinition\Service::importClassDefinitionFromJson($class$jsonfalsetrue);
  466.         $response $this->adminJson([
  467.             'success' => $success,
  468.         ]);
  469.         // set content-type to text/html, otherwise (when application/json is sent) chrome will complain in
  470.         // Ext.form.Action.Submit and mark the submission as failed
  471.         $response->headers->set('Content-Type''text/html');
  472.         return $response;
  473.     }
  474.     /**
  475.      * @Route("/import-custom-layout-definition", name="importcustomlayoutdefinition", methods={"POST", "PUT"})
  476.      *
  477.      * @param Request $request
  478.      *
  479.      * @return Response
  480.      */
  481.     public function importCustomLayoutDefinitionAction(Request $request)
  482.     {
  483.         $success false;
  484.         $responseContent = [];
  485.         $json file_get_contents($_FILES['Filedata']['tmp_name']);
  486.         $importData $this->decodeJson($json);
  487.         $existingLayout null;
  488.         if (isset($importData['name'])) {
  489.             $existingLayout DataObject\ClassDefinition\CustomLayout::getByName($importData['name']);
  490.             if ($existingLayout instanceof DataObject\ClassDefinition\CustomLayout) {
  491.                 $responseContent['nameAlreadyInUse'] = true;
  492.             }
  493.         }
  494.         if (!$existingLayout instanceof DataObject\ClassDefinition\CustomLayout) {
  495.             $customLayoutId $request->get('id');
  496.             $customLayout DataObject\ClassDefinition\CustomLayout::getById($customLayoutId);
  497.             if ($customLayout) {
  498.                 try {
  499.                     $layout DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($importData['layoutDefinitions'], true);
  500.                     $customLayout->setLayoutDefinitions($layout);
  501.                     if (isset($importData['name']) === true) {
  502.                         $customLayout->setName($importData['name']);
  503.                     }
  504.                     $customLayout->setDescription($importData['description']);
  505.                     $customLayout->save();
  506.                     $success true;
  507.                 } catch (\Exception $e) {
  508.                     Logger::error($e->getMessage());
  509.                 }
  510.             }
  511.             $responseContent['success'] = $success;
  512.         }
  513.         $response $this->adminJson($responseContent);
  514.         // set content-type to text/html, otherwise (when application/json is sent) chrome will complain in
  515.         // Ext.form.Action.Submit and mark the submission as failed
  516.         $response->headers->set('Content-Type''text/html');
  517.         return $response;
  518.     }
  519.     /**
  520.      * @Route("/get-custom-layout-definitions", name="getcustomlayoutdefinitions", methods={"GET"})
  521.      *
  522.      * @param Request $request
  523.      *
  524.      * @return JsonResponse
  525.      */
  526.     public function getCustomLayoutDefinitionsAction(Request $request)
  527.     {
  528.         $classIds explode(','$request->get('classId'));
  529.         $list = new DataObject\ClassDefinition\CustomLayout\Listing();
  530.         $list->setFilter(function (DataObject\ClassDefinition\CustomLayout $layout) use ($classIds) {
  531.             return in_array($layout->getClassId(), $classIds) && !str_contains($layout->getId(), '.brick.');
  532.         });
  533.         $list $list->load();
  534.         $result = [];
  535.         foreach ($list as $item) {
  536.             $result[] = [
  537.                 'id' => $item->getId(),
  538.                 'name' => $item->getName() . ' (ID: ' $item->getId() . ')',
  539.                 'default' => $item->getDefault() ?: 0,
  540.             ];
  541.         }
  542.         return $this->adminJson(['success' => true'data' => $result]);
  543.     }
  544.     /**
  545.      * @Route("/get-all-layouts", name="getalllayouts", methods={"GET"})
  546.      *
  547.      * @param Request $request
  548.      *
  549.      * @return JsonResponse
  550.      */
  551.     public function getAllLayoutsAction(Request $request)
  552.     {
  553.         // get all classes
  554.         $resultList = [];
  555.         $mapping = [];
  556.         $customLayouts = new DataObject\ClassDefinition\CustomLayout\Listing();
  557.         $customLayouts->setFilter(function (DataObject\ClassDefinition\CustomLayout $layout) {
  558.             return !str_contains($layout->getId(), '.brick.');
  559.         });
  560.         $customLayouts->setOrder(function (DataObject\ClassDefinition\CustomLayout $aDataObject\ClassDefinition\CustomLayout $b) {
  561.             return strcmp($a->getName(), $b->getName());
  562.         });
  563.         $customLayouts $customLayouts->load();
  564.         foreach ($customLayouts as $layout) {
  565.             $mapping[$layout->getClassId()][] = $layout;
  566.         }
  567.         $classList = new DataObject\ClassDefinition\Listing();
  568.         $classList->setOrder('ASC');
  569.         $classList->setOrderKey('name');
  570.         $classList $classList->load();
  571.         foreach ($classList as $class) {
  572.             if (isset($mapping[$class->getId()])) {
  573.                 $classMapping $mapping[$class->getId()];
  574.                 $resultList[] = [
  575.                     'type' => 'master',
  576.                     'id' => $class->getId() . '_' 0,
  577.                     'name' => $class->getName(),
  578.                 ];
  579.                 foreach ($classMapping as $layout) {
  580.                     $resultList[] = [
  581.                         'type' => 'custom',
  582.                         'id' => $class->getId() . '_' $layout->getId(),
  583.                         'name' => $class->getName() . ' - ' $layout->getName(),
  584.                     ];
  585.                 }
  586.             }
  587.         }
  588.         return $this->adminJson(['data' => $resultList]);
  589.     }
  590.     /**
  591.      * @Route("/export-class", name="exportclass", methods={"GET"})
  592.      *
  593.      * @param Request $request
  594.      *
  595.      * @return Response
  596.      */
  597.     public function exportClassAction(Request $request)
  598.     {
  599.         $id $request->get('id');
  600.         $class DataObject\ClassDefinition::getById($id);
  601.         if (!$class instanceof DataObject\ClassDefinition) {
  602.             $errorMessage ': Class with id [ ' $id ' not found. ]';
  603.             Logger::error($errorMessage);
  604.             throw $this->createNotFoundException($errorMessage);
  605.         }
  606.         $json DataObject\ClassDefinition\Service::generateClassDefinitionJson($class);
  607.         $response = new Response($json);
  608.         $response->headers->set('Content-type''application/json');
  609.         $response->headers->set('Content-Disposition''attachment; filename="class_' $class->getName() . '_export.json"');
  610.         return $response;
  611.     }
  612.     /**
  613.      * @Route("/export-custom-layout-definition", name="exportcustomlayoutdefinition", methods={"GET"})
  614.      *
  615.      * @param Request $request
  616.      *
  617.      * @return Response
  618.      */
  619.     public function exportCustomLayoutDefinitionAction(Request $request)
  620.     {
  621.         $id $request->get('id');
  622.         if ($id) {
  623.             $customLayout DataObject\ClassDefinition\CustomLayout::getById($id);
  624.             if ($customLayout) {
  625.                 $name $customLayout->getName();
  626.                 $json DataObject\ClassDefinition\Service::generateCustomLayoutJson($customLayout);
  627.                 $response = new Response($json);
  628.                 $response->headers->set('Content-type''application/json');
  629.                 $response->headers->set('Content-Disposition''attachment; filename="custom_definition_' $name '_export.json"');
  630.                 return $response;
  631.             }
  632.         }
  633.         $errorMessage ': Custom Layout with id [ ' $id ' not found. ]';
  634.         Logger::error($errorMessage);
  635.         throw $this->createNotFoundException($errorMessage);
  636.     }
  637.     /**
  638.      * FIELDCOLLECTIONS
  639.      */
  640.     /**
  641.      * @Route("/fieldcollection-get", name="fieldcollectionget", methods={"GET"})
  642.      *
  643.      * @param Request $request
  644.      *
  645.      * @return JsonResponse
  646.      */
  647.     public function fieldcollectionGetAction(Request $request)
  648.     {
  649.         $fc DataObject\Fieldcollection\Definition::getByKey($request->get('id'));
  650.         $isWriteable $fc->isWritable();
  651.         $fc $fc->getObjectVars();
  652.         $fc['isWriteable'] = $isWriteable;
  653.         return $this->adminJson($fc);
  654.     }
  655.     /**
  656.      * @Route("/fieldcollection-update", name="fieldcollectionupdate", methods={"PUT", "POST"})
  657.      *
  658.      * @param Request $request
  659.      *
  660.      * @return JsonResponse
  661.      */
  662.     public function fieldcollectionUpdateAction(Request $request)
  663.     {
  664.         try {
  665.             $key $request->get('key');
  666.             $title $request->get('title');
  667.             $group $request->get('group');
  668.             if ($request->get('task') == 'add') {
  669.                 // check for existing fieldcollection with same name with different lower/upper cases
  670.                 $list = new DataObject\Fieldcollection\Definition\Listing();
  671.                 $list $list->load();
  672.                 foreach ($list as $item) {
  673.                     if (strtolower($key) === strtolower($item->getKey())) {
  674.                         throw new \Exception('FieldCollection with the same name already exists (lower/upper cases may be different)');
  675.                     }
  676.                 }
  677.             }
  678.             $fcDef = new DataObject\Fieldcollection\Definition();
  679.             $fcDef->setKey($key);
  680.             $fcDef->setTitle($title);
  681.             $fcDef->setGroup($group);
  682.             if ($request->get('values')) {
  683.                 $values $this->decodeJson($request->get('values'));
  684.                 $fcDef->setParentClass($values['parentClass']);
  685.                 $fcDef->setImplementsInterfaces($values['implementsInterfaces']);
  686.                 $fcDef->setGenerateTypeDeclarations($values['generateTypeDeclarations']);
  687.             }
  688.             if ($request->get('configuration')) {
  689.                 $configuration $this->decodeJson($request->get('configuration'));
  690.                 $configuration['datatype'] = 'layout';
  691.                 $configuration['fieldtype'] = 'panel';
  692.                 $layout DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($configurationtrue);
  693.                 $fcDef->setLayoutDefinitions($layout);
  694.             }
  695.             $fcDef->save();
  696.             return $this->adminJson(['success' => true'id' => $fcDef->getKey()]);
  697.         } catch (\Exception $e) {
  698.             Logger::error($e->getMessage());
  699.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  700.         }
  701.     }
  702.     /**
  703.      * @Route("/import-fieldcollection", name="importfieldcollection", methods={"POST"})
  704.      *
  705.      * @param Request $request
  706.      *
  707.      * @return Response
  708.      */
  709.     public function importFieldcollectionAction(Request $request)
  710.     {
  711.         $fieldCollection DataObject\Fieldcollection\Definition::getByKey($request->get('id'));
  712.         $data file_get_contents($_FILES['Filedata']['tmp_name']);
  713.         $success DataObject\ClassDefinition\Service::importFieldCollectionFromJson($fieldCollection$data);
  714.         $response $this->adminJson([
  715.             'success' => $success,
  716.         ]);
  717.         // set content-type to text/html, otherwise (when application/json is sent) chrome will complain in
  718.         // Ext.form.Action.Submit and mark the submission as failed
  719.         $response->headers->set('Content-Type''text/html');
  720.         return $response;
  721.     }
  722.     /**
  723.      * @Route("/export-fieldcollection", name="exportfieldcollection", methods={"GET"})
  724.      *
  725.      * @param Request $request
  726.      *
  727.      * @return Response
  728.      */
  729.     public function exportFieldcollectionAction(Request $request)
  730.     {
  731.         $fieldCollection DataObject\Fieldcollection\Definition::getByKey($request->get('id'));
  732.         if (!$fieldCollection instanceof DataObject\Fieldcollection\Definition) {
  733.             $errorMessage ': Field-Collection with id [ ' $request->get('id') . ' not found. ]';
  734.             Logger::error($errorMessage);
  735.             throw $this->createNotFoundException($errorMessage);
  736.         }
  737.         $json DataObject\ClassDefinition\Service::generateFieldCollectionJson($fieldCollection);
  738.         $response = new Response($json);
  739.         $response->headers->set('Content-type''application/json');
  740.         $response->headers->set('Content-Disposition''attachment; filename="fieldcollection_' $fieldCollection->getKey() . '_export.json"');
  741.         return $response;
  742.     }
  743.     /**
  744.      * @Route("/fieldcollection-delete", name="fieldcollectiondelete", methods={"DELETE"})
  745.      *
  746.      * @param Request $request
  747.      *
  748.      * @return JsonResponse
  749.      */
  750.     public function fieldcollectionDeleteAction(Request $request)
  751.     {
  752.         $fc DataObject\Fieldcollection\Definition::getByKey($request->get('id'));
  753.         $fc->delete();
  754.         return $this->adminJson(['success' => true]);
  755.     }
  756.     /**
  757.      * @Route("/fieldcollection-tree", name="fieldcollectiontree", methods={"GET", "POST"})
  758.      *
  759.      * @param Request $request
  760.      * @param EventDispatcherInterface $eventDispatcher
  761.      *
  762.      * @return JsonResponse
  763.      */
  764.     public function fieldcollectionTreeAction(Request $requestEventDispatcherInterface $eventDispatcher)
  765.     {
  766.         $list = new DataObject\Fieldcollection\Definition\Listing();
  767.         $list $list->load();
  768.         $forObjectEditor $request->get('forObjectEditor');
  769.         $layoutDefinitions = [];
  770.         $definitions = [];
  771.         $allowedTypes null;
  772.         if ($request->query->has('allowedTypes')) {
  773.             $allowedTypes explode(','$request->get('allowedTypes'));
  774.         }
  775.         $object DataObject\Concrete::getById((int) $request->get('object_id'));
  776.         $currentLayoutId $request->get('layoutId'null);
  777.         $user \Pimcore\Tool\Admin::getCurrentUser();
  778.         $groups = [];
  779.         foreach ($list as $item) {
  780.             if ($allowedTypes && !in_array($item->getKey(), $allowedTypes)) {
  781.                 continue;
  782.             }
  783.             if ($item->getGroup()) {
  784.                 if (!isset($groups[$item->getGroup()])) {
  785.                     $groups[$item->getGroup()] = [
  786.                         'id' => 'group_' $item->getKey(),
  787.                         'text' => htmlspecialchars($item->getGroup()),
  788.                         'expandable' => true,
  789.                         'leaf' => false,
  790.                         'allowChildren' => true,
  791.                         'iconCls' => 'pimcore_icon_folder',
  792.                         'group' => $item->getGroup(),
  793.                         'children' => [],
  794.                     ];
  795.                 }
  796.                 if ($forObjectEditor) {
  797.                     $itemLayoutDefinitions $item->getLayoutDefinitions();
  798.                     DataObject\Service::enrichLayoutDefinition($itemLayoutDefinitions$object);
  799.                     if ($currentLayoutId == -&& $user->isAdmin()) {
  800.                         DataObject\Service::createSuperLayout($itemLayoutDefinitions);
  801.                     }
  802.                     $layoutDefinitions[$item->getKey()] = $itemLayoutDefinitions;
  803.                 }
  804.                 $groups[$item->getGroup()]['children'][] =
  805.                     [
  806.                         'id' => $item->getKey(),
  807.                         'text' => $item->getKey(),
  808.                         'title' => $item->getTitle(),
  809.                         'key' => $item->getKey(),
  810.                         'leaf' => true,
  811.                         'iconCls' => 'pimcore_icon_fieldcollection',
  812.                     ];
  813.             } else {
  814.                 if ($forObjectEditor) {
  815.                     $itemLayoutDefinitions $item->getLayoutDefinitions();
  816.                     DataObject\Service::enrichLayoutDefinition($itemLayoutDefinitions$object);
  817.                     if ($currentLayoutId == -&& $user->isAdmin()) {
  818.                         DataObject\Service::createSuperLayout($itemLayoutDefinitions);
  819.                     }
  820.                     $layoutDefinitions[$item->getKey()] = $itemLayoutDefinitions;
  821.                 }
  822.                 $definitions[] = [
  823.                     'id' => $item->getKey(),
  824.                     'text' => $item->getKey(),
  825.                     'title' => $item->getTitle(),
  826.                     'key' => $item->getKey(),
  827.                     'leaf' => true,
  828.                     'iconCls' => 'pimcore_icon_fieldcollection',
  829.                 ];
  830.             }
  831.         }
  832.         foreach ($groups as $group) {
  833.             $definitions[] = $group;
  834.         }
  835.         $event = new GenericEvent($this, [
  836.             'list' => $definitions,
  837.             'objectId' => $request->get('object_id'),
  838.             'layoutDefinitions' => $layoutDefinitions,
  839.         ]);
  840.         $eventDispatcher->dispatch($eventAdminEvents::CLASS_FIELDCOLLECTION_LIST_PRE_SEND_DATA);
  841.         $definitions $event->getArgument('list');
  842.         $layoutDefinitions $event->getArgument('layoutDefinitions');
  843.         if ($forObjectEditor) {
  844.             return $this->adminJson(['fieldcollections' => $definitions'layoutDefinitions' => $layoutDefinitions]);
  845.         }
  846.         return $this->adminJson($definitions);
  847.     }
  848.     /**
  849.      * @Route("/fieldcollection-list", name="fieldcollectionlist", methods={"GET"})
  850.      *
  851.      * @param Request $request
  852.      * @param EventDispatcherInterface $eventDispatcher
  853.      *
  854.      * @return JsonResponse
  855.      */
  856.     public function fieldcollectionListAction(Request $requestEventDispatcherInterface $eventDispatcher)
  857.     {
  858.         $user \Pimcore\Tool\Admin::getCurrentUser();
  859.         $currentLayoutId $request->get('layoutId');
  860.         $list = new DataObject\Fieldcollection\Definition\Listing();
  861.         $list $list->load();
  862.         if ($request->query->has('allowedTypes')) {
  863.             $filteredList = [];
  864.             $allowedTypes explode(','$request->get('allowedTypes'));
  865.             foreach ($list as $type) {
  866.                 if (in_array($type->getKey(), $allowedTypes)) {
  867.                     $filteredList[] = $type;
  868.                     // mainly for objects-meta data-type
  869.                     $layoutDefinitions $type->getLayoutDefinitions();
  870.                     $context = [
  871.                         'containerType' => 'fieldcollection',
  872.                         'containerKey' => $type->getKey(),
  873.                         'outerFieldname' => $request->get('field_name'),
  874.                     ];
  875.                     $object DataObject\Concrete::getById((int) $request->get('object_id'));
  876.                     DataObject\Service::enrichLayoutDefinition($layoutDefinitions$object$context);
  877.                     if ($currentLayoutId == -&& $user->isAdmin()) {
  878.                         DataObject\Service::createSuperLayout($layoutDefinitions);
  879.                     }
  880.                 }
  881.             }
  882.             $list $filteredList;
  883.         }
  884.         $event = new GenericEvent($this, [
  885.             'list' => $list,
  886.             'objectId' => $request->get('object_id'),
  887.         ]);
  888.         $eventDispatcher->dispatch($eventAdminEvents::CLASS_FIELDCOLLECTION_LIST_PRE_SEND_DATA);
  889.         $list $event->getArgument('list');
  890.         return $this->adminJson(['fieldcollections' => $list]);
  891.     }
  892.     /**
  893.      * @Route("/get-class-definition-for-column-config", name="getclassdefinitionforcolumnconfig", methods={"GET"})
  894.      *
  895.      * @param Request $request
  896.      *
  897.      * @return JsonResponse
  898.      */
  899.     public function getClassDefinitionForColumnConfigAction(Request $request)
  900.     {
  901.         $class DataObject\ClassDefinition::getById($request->get('id'));
  902.         if (!$class) {
  903.             throw $this->createNotFoundException();
  904.         }
  905.         $objectId = (int)$request->get('oid');
  906.         $filteredDefinitions DataObject\Service::getCustomLayoutDefinitionForGridColumnConfig($class$objectId);
  907.         /** @var DataObject\ClassDefinition\Layout $layoutDefinitions */
  908.         $layoutDefinitions = isset($filteredDefinitions['layoutDefinition']) ? $filteredDefinitions['layoutDefinition'] : false;
  909.         $filteredFieldDefinition = isset($filteredDefinitions['fieldDefinition']) ? $filteredDefinitions['fieldDefinition'] : false;
  910.         $class->setFieldDefinitions([]);
  911.         $result = [];
  912.         DataObject\Service::enrichLayoutDefinition($layoutDefinitions);
  913.         $result['objectColumns']['children'] = $layoutDefinitions->getChildren();
  914.         $result['objectColumns']['nodeLabel'] = 'object_columns';
  915.         $result['objectColumns']['nodeType'] = 'object';
  916.         // array("id", "fullpath", "published", "creationDate", "modificationDate", "filename", "classname");
  917.         $systemColumnNames DataObject\Concrete::SYSTEM_COLUMN_NAMES;
  918.         $systemColumns = [];
  919.         foreach ($systemColumnNames as $systemColumn) {
  920.             $systemColumns[] = ['title' => $systemColumn'name' => $systemColumn'datatype' => 'data''fieldtype' => 'system'];
  921.         }
  922.         $result['systemColumns']['nodeLabel'] = 'system_columns';
  923.         $result['systemColumns']['nodeType'] = 'system';
  924.         $result['systemColumns']['children'] = $systemColumns;
  925.         $list = new DataObject\Objectbrick\Definition\Listing();
  926.         $list $list->load();
  927.         foreach ($list as $brickDefinition) {
  928.             $classDefs $brickDefinition->getClassDefinitions();
  929.             if (!empty($classDefs)) {
  930.                 foreach ($classDefs as $classDef) {
  931.                     if ($classDef['classname'] == $class->getName()) {
  932.                         $fieldName $classDef['fieldname'];
  933.                         if ($filteredFieldDefinition && !$filteredFieldDefinition[$fieldName]) {
  934.                             continue;
  935.                         }
  936.                         $key $brickDefinition->getKey();
  937.                         $brickLayoutDefinitions $brickDefinition->getLayoutDefinitions();
  938.                         $context = [
  939.                             'containerType' => 'objectbrick',
  940.                             'containerKey' => $key,
  941.                             'outerFieldname' => $fieldName,
  942.                         ];
  943.                         DataObject\Service::enrichLayoutDefinition($brickLayoutDefinitionsnull$context);
  944.                         $result[$key]['nodeLabel'] = $key;
  945.                         $result[$key]['brickField'] = $fieldName;
  946.                         $result[$key]['nodeType'] = 'objectbricks';
  947.                         $result[$key]['children'] = $brickLayoutDefinitions->getChildren();
  948.                         break;
  949.                     }
  950.                 }
  951.             }
  952.         }
  953.         return $this->adminJson($result);
  954.     }
  955.     /**
  956.      * OBJECT BRICKS
  957.      */
  958.     /**
  959.      * @Route("/objectbrick-get", name="objectbrickget", methods={"GET"})
  960.      *
  961.      * @param Request $request
  962.      *
  963.      * @return JsonResponse
  964.      */
  965.     public function objectbrickGetAction(Request $request)
  966.     {
  967.         $fc DataObject\Objectbrick\Definition::getByKey($request->get('id'));
  968.         $isWriteable $fc->isWritable();
  969.         $fc $fc->getObjectVars();
  970.         $fc['isWriteable'] = $isWriteable;
  971.         return $this->adminJson($fc);
  972.     }
  973.     /**
  974.      * @Route("/objectbrick-update", name="objectbrickupdate", methods={"PUT", "POST"})
  975.      *
  976.      * @param Request $request
  977.      * @param EventDispatcherInterface $eventDispatcher
  978.      *
  979.      * @return JsonResponse
  980.      */
  981.     public function objectbrickUpdateAction(Request $requestEventDispatcherInterface $eventDispatcher)
  982.     {
  983.         try {
  984.             $key $request->get('key');
  985.             $title $request->get('title');
  986.             $group $request->get('group');
  987.             if ($request->get('task') == 'add') {
  988.                 // check for existing brick with same name with different lower/upper cases
  989.                 $list = new DataObject\Objectbrick\Definition\Listing();
  990.                 $list $list->load();
  991.                 foreach ($list as $item) {
  992.                     if (strtolower($key) === strtolower($item->getKey())) {
  993.                         throw new \Exception('Brick with the same name already exists (lower/upper cases may be different)');
  994.                     }
  995.                 }
  996.             }
  997.             // now we create a new definition
  998.             $brickDef = new DataObject\Objectbrick\Definition();
  999.             $brickDef->setKey($key);
  1000.             $brickDef->setTitle($title);
  1001.             $brickDef->setGroup($group);
  1002.             if ($request->get('values')) {
  1003.                 $values $this->decodeJson($request->get('values'));
  1004.                 $brickDef->setParentClass($values['parentClass']);
  1005.                 $brickDef->setImplementsInterfaces($values['implementsInterfaces']);
  1006.                 $brickDef->setClassDefinitions($values['classDefinitions']);
  1007.                 $brickDef->setGenerateTypeDeclarations($values['generateTypeDeclarations']);
  1008.             }
  1009.             if ($request->get('configuration')) {
  1010.                 $configuration $this->decodeJson($request->get('configuration'));
  1011.                 $configuration['datatype'] = 'layout';
  1012.                 $configuration['fieldtype'] = 'panel';
  1013.                 $layout DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($configurationtrue);
  1014.                 $brickDef->setLayoutDefinitions($layout);
  1015.             }
  1016.             $event = new GenericEvent($this, [
  1017.                 'brickDefinition' => $brickDef,
  1018.             ]);
  1019.             $eventDispatcher->dispatch($eventAdminEvents::CLASS_OBJECTBRICK_UPDATE_DEFINITION);
  1020.             $brickDef $event->getArgument('brickDefinition');
  1021.             $brickDef->save();
  1022.             return $this->adminJson(['success' => true'id' => $brickDef->getKey()]);
  1023.         } catch (\Exception $e) {
  1024.             Logger::error($e->getMessage());
  1025.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  1026.         }
  1027.     }
  1028.     /**
  1029.      * @Route("/import-objectbrick", name="importobjectbrick", methods={"POST"})
  1030.      *
  1031.      * @param Request $request
  1032.      *
  1033.      * @return JsonResponse
  1034.      */
  1035.     public function importObjectbrickAction(Request $request)
  1036.     {
  1037.         $objectBrick DataObject\Objectbrick\Definition::getByKey($request->get('id'));
  1038.         $data file_get_contents($_FILES['Filedata']['tmp_name']);
  1039.         $success DataObject\ClassDefinition\Service::importObjectBrickFromJson($objectBrick$data);
  1040.         $response $this->adminJson([
  1041.             'success' => $success,
  1042.         ]);
  1043.         // set content-type to text/html, otherwise (when application/json is sent) chrome will complain in
  1044.         // Ext.form.Action.Submit and mark the submission as failed
  1045.         $response->headers->set('Content-Type''text/html');
  1046.         return $response;
  1047.     }
  1048.     /**
  1049.      * @Route("/export-objectbrick", name="exportobjectbrick", methods={"GET"})
  1050.      *
  1051.      * @param Request $request
  1052.      *
  1053.      * @return Response
  1054.      */
  1055.     public function exportObjectbrickAction(Request $request)
  1056.     {
  1057.         $objectBrick DataObject\Objectbrick\Definition::getByKey($request->get('id'));
  1058.         if (!$objectBrick instanceof DataObject\Objectbrick\Definition) {
  1059.             $errorMessage ': Object-Brick with id [ ' $request->get('id') . ' not found. ]';
  1060.             Logger::error($errorMessage);
  1061.             throw $this->createNotFoundException($errorMessage);
  1062.         }
  1063.         $xml DataObject\ClassDefinition\Service::generateObjectBrickJson($objectBrick);
  1064.         $response = new Response($xml);
  1065.         $response->headers->set('Content-type''application/json');
  1066.         $response->headers->set('Content-Disposition''attachment; filename="objectbrick_' $objectBrick->getKey() . '_export.json"');
  1067.         return $response;
  1068.     }
  1069.     /**
  1070.      * @Route("/objectbrick-delete", name="objectbrickdelete", methods={"DELETE"})
  1071.      *
  1072.      * @param Request $request
  1073.      *
  1074.      * @return JsonResponse
  1075.      */
  1076.     public function objectbrickDeleteAction(Request $request)
  1077.     {
  1078.         $fc DataObject\Objectbrick\Definition::getByKey($request->get('id'));
  1079.         $fc->delete();
  1080.         return $this->adminJson(['success' => true]);
  1081.     }
  1082.     /**
  1083.      * @Route("/objectbrick-tree", name="objectbricktree", methods={"GET", "POST"})
  1084.      *
  1085.      * @param Request $request
  1086.      * @param EventDispatcherInterface $eventDispatcher
  1087.      *
  1088.      * @return JsonResponse
  1089.      */
  1090.     public function objectbrickTreeAction(Request $requestEventDispatcherInterface $eventDispatcher)
  1091.     {
  1092.         $list = new DataObject\Objectbrick\Definition\Listing();
  1093.         $list $list->load();
  1094.         $forObjectEditor $request->get('forObjectEditor');
  1095.         $context null;
  1096.         $layoutDefinitions = [];
  1097.         $groups = [];
  1098.         $definitions = [];
  1099.         $fieldname null;
  1100.         $className null;
  1101.         $object DataObject\Concrete::getById((int) $request->get('object_id'));
  1102.         if ($request->query->has('class_id') && $request->query->has('field_name')) {
  1103.             $classId $request->get('class_id');
  1104.             $fieldname $request->get('field_name');
  1105.             $classDefinition DataObject\ClassDefinition::getById($classId);
  1106.             $className $classDefinition->getName();
  1107.         }
  1108.         foreach ($list as $item) {
  1109.             if ($forObjectEditor) {
  1110.                 $context = [
  1111.                     'containerType' => 'objectbrick',
  1112.                     'containerKey' => $item->getKey(),
  1113.                     'outerFieldname' => $fieldname,
  1114.                 ];
  1115.             }
  1116.             if ($request->query->has('class_id') && $request->query->has('field_name')) {
  1117.                 $keep false;
  1118.                 $clsDefs $item->getClassDefinitions();
  1119.                 if (!empty($clsDefs)) {
  1120.                     foreach ($clsDefs as $cd) {
  1121.                         if ($cd['classname'] == $className && $cd['fieldname'] == $fieldname) {
  1122.                             $keep true;
  1123.                             continue;
  1124.                         }
  1125.                     }
  1126.                 }
  1127.                 if (!$keep) {
  1128.                     continue;
  1129.                 }
  1130.             }
  1131.             if ($item->getGroup()) {
  1132.                 if (!isset($groups[$item->getGroup()])) {
  1133.                     $groups[$item->getGroup()] = [
  1134.                         'id' => 'group_' $item->getKey(),
  1135.                         'text' => htmlspecialchars($item->getGroup()),
  1136.                         'expandable' => true,
  1137.                         'leaf' => false,
  1138.                         'allowChildren' => true,
  1139.                         'iconCls' => 'pimcore_icon_folder',
  1140.                         'group' => $item->getGroup(),
  1141.                         'children' => [],
  1142.                     ];
  1143.                 }
  1144.                 if ($forObjectEditor) {
  1145.                     $layoutId $request->get('layoutId');
  1146.                     $itemLayoutDefinitions null;
  1147.                     if ($layoutId) {
  1148.                         $layout DataObject\ClassDefinition\CustomLayout::getById($layoutId.'.brick.'.$item->getKey());
  1149.                         if ($layout instanceof DataObject\ClassDefinition\CustomLayout) {
  1150.                             $itemLayoutDefinitions $layout->getLayoutDefinitions();
  1151.                         }
  1152.                     }
  1153.                     if ($itemLayoutDefinitions === null) {
  1154.                         $itemLayoutDefinitions $item->getLayoutDefinitions();
  1155.                     }
  1156.                     DataObject\Service::enrichLayoutDefinition($itemLayoutDefinitions$object$context);
  1157.                     $layoutDefinitions[$item->getKey()] = $itemLayoutDefinitions;
  1158.                 }
  1159.                 $groups[$item->getGroup()]['children'][] =
  1160.                     [
  1161.                         'id' => $item->getKey(),
  1162.                         'text' => $item->getKey(),
  1163.                         'title' => $item->getTitle(),
  1164.                         'key' => $item->getKey(),
  1165.                         'leaf' => true,
  1166.                         'iconCls' => 'pimcore_icon_objectbricks',
  1167.                     ];
  1168.             } else {
  1169.                 if ($forObjectEditor) {
  1170.                     $layout $item->getLayoutDefinitions();
  1171.                     $currentLayoutId $request->get('layoutId'null);
  1172.                     $user $this->getAdminUser();
  1173.                     if ($currentLayoutId == -&& $user->isAdmin()) {
  1174.                         DataObject\Service::createSuperLayout($layout);
  1175.                     } elseif ($currentLayoutId) {
  1176.                         $customLayout DataObject\ClassDefinition\CustomLayout::getById($currentLayoutId.'.brick.'.$item->getKey());
  1177.                         if ($customLayout instanceof DataObject\ClassDefinition\CustomLayout) {
  1178.                             $layout $customLayout->getLayoutDefinitions();
  1179.                         }
  1180.                     }
  1181.                     DataObject\Service::enrichLayoutDefinition($layout$object$context);
  1182.                     $layoutDefinitions[$item->getKey()] = $layout;
  1183.                 }
  1184.                 $definitions[] = [
  1185.                     'id' => $item->getKey(),
  1186.                     'text' => $item->getKey(),
  1187.                     'title' => $item->getTitle(),
  1188.                     'key' => $item->getKey(),
  1189.                     'leaf' => true,
  1190.                     'iconCls' => 'pimcore_icon_objectbricks',
  1191.                 ];
  1192.             }
  1193.         }
  1194.         foreach ($groups as $group) {
  1195.             $definitions[] = $group;
  1196.         }
  1197.         $event = new GenericEvent($this, [
  1198.             'list' => $definitions,
  1199.             'objectId' => $request->get('object_id'),
  1200.         ]);
  1201.         $eventDispatcher->dispatch($eventAdminEvents::CLASS_OBJECTBRICK_LIST_PRE_SEND_DATA);
  1202.         $definitions $event->getArgument('list');
  1203.         if ($forObjectEditor) {
  1204.             return $this->adminJson(['objectbricks' => $definitions'layoutDefinitions' => $layoutDefinitions]);
  1205.         } else {
  1206.             return $this->adminJson($definitions);
  1207.         }
  1208.     }
  1209.     /**
  1210.      * @Route("/objectbrick-list", name="objectbricklist", methods={"GET"})
  1211.      *
  1212.      * @param Request $request
  1213.      * @param EventDispatcherInterface $eventDispatcher
  1214.      *
  1215.      * @return JsonResponse
  1216.      */
  1217.     public function objectbrickListAction(Request $requestEventDispatcherInterface $eventDispatcher)
  1218.     {
  1219.         $list = new DataObject\Objectbrick\Definition\Listing();
  1220.         $list $list->load();
  1221.         if ($request->query->has('class_id') && $request->query->has('field_name')) {
  1222.             $filteredList = [];
  1223.             $classId $request->get('class_id');
  1224.             $fieldname $request->get('field_name');
  1225.             $classDefinition DataObject\ClassDefinition::getById($classId);
  1226.             $className $classDefinition->getName();
  1227.             foreach ($list as $type) {
  1228.                 $clsDefs $type->getClassDefinitions();
  1229.                 if (!empty($clsDefs)) {
  1230.                     foreach ($clsDefs as $cd) {
  1231.                         if ($cd['classname'] == $className && $cd['fieldname'] == $fieldname) {
  1232.                             $filteredList[] = $type;
  1233.                             continue;
  1234.                         }
  1235.                     }
  1236.                 }
  1237.                 $layout $type->getLayoutDefinitions();
  1238.                 $currentLayoutId $request->get('layoutId'null);
  1239.                 $user $this->getAdminUser();
  1240.                 if ($currentLayoutId == -&& $user->isAdmin()) {
  1241.                     DataObject\Service::createSuperLayout($layout);
  1242.                     $objectData['layout'] = $layout;
  1243.                 }
  1244.                 $context = [
  1245.                     'containerType' => 'objectbrick',
  1246.                     'containerKey' => $type->getKey(),
  1247.                     'outerFieldname' => $request->get('field_name'),
  1248.                 ];
  1249.                 $object DataObject\Concrete::getById((int) $request->get('object_id'));
  1250.                 DataObject\Service::enrichLayoutDefinition($layout$object$context);
  1251.                 $type->setLayoutDefinitions($layout);
  1252.             }
  1253.             $list $filteredList;
  1254.         }
  1255.         $event = new GenericEvent($this, [
  1256.             'list' => $list,
  1257.             'objectId' => $request->get('object_id'),
  1258.         ]);
  1259.         $eventDispatcher->dispatch($eventAdminEvents::CLASS_OBJECTBRICK_LIST_PRE_SEND_DATA);
  1260.         $list $event->getArgument('list');
  1261.         return $this->adminJson(['objectbricks' => $list]);
  1262.     }
  1263.     /**
  1264.      * See http://www.pimcore.org/issues/browse/PIMCORE-2358
  1265.      * Add option to export/import all class definitions/brick definitions etc. at once
  1266.      */
  1267.     /**
  1268.      * @Route("/bulk-import", name="bulkimport", methods={"POST"})
  1269.      *
  1270.      * @param Request $request
  1271.      *
  1272.      * @return JsonResponse
  1273.      */
  1274.     public function bulkImportAction(Request $request)
  1275.     {
  1276.         $result = [];
  1277.         $tmpName $_FILES['Filedata']['tmp_name'];
  1278.         $json file_get_contents($tmpName);
  1279.         $tmpName PIMCORE_SYSTEM_TEMP_DIRECTORY '/bulk-import-' uniqid() . '.tmp';
  1280.         file_put_contents($tmpName$json);
  1281.         Session::useSession(function (AttributeBagInterface $session) use ($tmpName) {
  1282.             $session->set('class_bulk_import_file'$tmpName);
  1283.         }, 'pimcore_objects');
  1284.         $json json_decode($jsontrue);
  1285.         foreach ($json as $groupName => $group) {
  1286.             foreach ($group as $groupItem) {
  1287.                 $displayName null;
  1288.                 $icon null;
  1289.                 if ($groupName == 'class') {
  1290.                     $name $groupItem['name'];
  1291.                     $icon 'class';
  1292.                 } elseif ($groupName == 'customlayout') {
  1293.                     $className $groupItem['className'];
  1294.                     $layoutData = ['className' => $className'name' => $groupItem['name']];
  1295.                     $name base64_encode(json_encode($layoutData));
  1296.                     $displayName $className ' / ' $groupItem['name'];
  1297.                     $icon 'custom_views';
  1298.                 } else {
  1299.                     if ($groupName == 'objectbrick') {
  1300.                         $icon 'objectbricks';
  1301.                     } elseif ($groupName == 'fieldcollection') {
  1302.                         $icon 'fieldcollection';
  1303.                     }
  1304.                     $name $groupItem['key'];
  1305.                 }
  1306.                 if (!$displayName) {
  1307.                     $displayName $name;
  1308.                 }
  1309.                 $result[] = ['icon' => $icon'checked' => true'type' => $groupName'name' => $name'displayName' => $displayName];
  1310.             }
  1311.         }
  1312.         $response $this->adminJson(['success' => true'data' => $result]);
  1313.         $response->headers->set('Content-Type''text/html');
  1314.         return $response;
  1315.     }
  1316.     /**
  1317.      * See http://www.pimcore.org/issues/browse/PIMCORE-2358
  1318.      * Add option to export/import all class definitions/brick definitions etc. at once
  1319.      */
  1320.     /**
  1321.      * @Route("/bulk-commit", name="bulkcommit", methods={"POST"})
  1322.      *
  1323.      * @param Request $request
  1324.      *
  1325.      * @return JsonResponse
  1326.      *
  1327.      * @throws \Exception
  1328.      */
  1329.     public function bulkCommitAction(Request $request)
  1330.     {
  1331.         $data json_decode($request->get('data'), true);
  1332.         $session Session::get('pimcore_objects');
  1333.         $filename $session->get('class_bulk_import_file');
  1334.         $json = @file_get_contents($filename);
  1335.         $json json_decode($jsontrue);
  1336.         $type $data['type'];
  1337.         $name $data['name'];
  1338.         $list $json[$type];
  1339.         foreach ($list as $item) {
  1340.             unset($item['creationDate']);
  1341.             unset($item['modificationDate']);
  1342.             unset($item['userOwner']);
  1343.             unset($item['userModification']);
  1344.             if ($type == 'class' && $item['name'] == $name) {
  1345.                 $class DataObject\ClassDefinition::getByName($name);
  1346.                 if (!$class) {
  1347.                     $class = new DataObject\ClassDefinition();
  1348.                     $class->setName($name);
  1349.                 }
  1350.                 $success DataObject\ClassDefinition\Service::importClassDefinitionFromJson($classjson_encode($item), true);
  1351.                 return $this->adminJson(['success' => $success !== false]);
  1352.             } elseif ($type == 'objectbrick' && $item['key'] == $name) {
  1353.                 if (!$brick DataObject\Objectbrick\Definition::getByKey($name)) {
  1354.                     $brick = new DataObject\Objectbrick\Definition();
  1355.                     $brick->setKey($name);
  1356.                 }
  1357.                 $success DataObject\ClassDefinition\Service::importObjectBrickFromJson($brickjson_encode($item), true);
  1358.                 return $this->adminJson(['success' => $success !== false]);
  1359.             } elseif ($type == 'fieldcollection' && $item['key'] == $name) {
  1360.                 if (!$fieldCollection DataObject\Fieldcollection\Definition::getByKey($name)) {
  1361.                     $fieldCollection = new DataObject\Fieldcollection\Definition();
  1362.                     $fieldCollection->setKey($name);
  1363.                 }
  1364.                 $success DataObject\ClassDefinition\Service::importFieldCollectionFromJson($fieldCollectionjson_encode($item), true);
  1365.                 return $this->adminJson(['success' => $success !== false]);
  1366.             } elseif ($type == 'customlayout') {
  1367.                 $layoutData json_decode(base64_decode($data['name']), true);
  1368.                 $className $layoutData['className'];
  1369.                 $layoutName $layoutData['name'];
  1370.                 if ($item['name'] == $layoutName && $item['className'] == $className) {
  1371.                     $class DataObject\ClassDefinition::getByName($className);
  1372.                     if (!$class) {
  1373.                         throw new \Exception('Class does not exist');
  1374.                     }
  1375.                     $classId $class->getId();
  1376.                     $layoutList = new DataObject\ClassDefinition\CustomLayout\Listing();
  1377.                     $layoutList->setFilter(function (DataObject\ClassDefinition\CustomLayout $layout) use ($layoutName$classId) {
  1378.                         return $layout->getName() === $layoutName && $layout->getClassId() === $classId;
  1379.                     });
  1380.                     $layoutList $layoutList->load();
  1381.                     $layoutDefinition null;
  1382.                     if ($layoutList) {
  1383.                         $layoutDefinition $layoutList[0];
  1384.                     }
  1385.                     if (!$layoutDefinition) {
  1386.                         $layoutDefinition = new DataObject\ClassDefinition\CustomLayout();
  1387.                         $layoutDefinition->setName($layoutName);
  1388.                         $layoutDefinition->setClassId($classId);
  1389.                     }
  1390.                     try {
  1391.                         $layoutDefinition->setDescription($item['description']);
  1392.                         $layoutDef DataObject\ClassDefinition\Service::generateLayoutTreeFromArray($item['layoutDefinitions'], true);
  1393.                         $layoutDefinition->setLayoutDefinitions($layoutDef);
  1394.                         $layoutDefinition->save();
  1395.                     } catch (\Exception $e) {
  1396.                         Logger::error($e->getMessage());
  1397.                         return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  1398.                     }
  1399.                 }
  1400.             }
  1401.         }
  1402.         return $this->adminJson(['success' => true]);
  1403.     }
  1404.     /**
  1405.      * See http://www.pimcore.org/issues/browse/PIMCORE-2358
  1406.      * Add option to export/import all class definitions/brick definitions etc. at once
  1407.      */
  1408.     /**
  1409.      * @Route("/bulk-export-prepare", name="bulkexportprepare", methods={"POST"})
  1410.      *
  1411.      * @param Request $request
  1412.      *
  1413.      * @return Response
  1414.      */
  1415.     public function bulkExportPrepareAction(Request $request)
  1416.     {
  1417.         $data $request->get('data');
  1418.         Session::useSession(function (AttributeBagInterface $session) use ($data) {
  1419.             $session->set('class_bulk_export_settings'$data);
  1420.         }, 'pimcore_objects');
  1421.         return $this->adminJson(['success' => true]);
  1422.     }
  1423.     /**
  1424.      * @Route("/bulk-export", name="bulkexport", methods={"GET"})
  1425.      *
  1426.      * @param Request $request
  1427.      *
  1428.      * @return Response
  1429.      */
  1430.     public function bulkExportAction(Request $request)
  1431.     {
  1432.         $result = [];
  1433.         $fieldCollections = new DataObject\Fieldcollection\Definition\Listing();
  1434.         $fieldCollections $fieldCollections->load();
  1435.         foreach ($fieldCollections as $fieldCollection) {
  1436.             $result[] = [
  1437.                 'icon' => 'fieldcollection',
  1438.                 'checked' => true,
  1439.                 'type' => 'fieldcollection',
  1440.                 'name' => $fieldCollection->getKey(),
  1441.                 'displayName' => $fieldCollection->getKey(),
  1442.             ];
  1443.         }
  1444.         $classes = new DataObject\ClassDefinition\Listing();
  1445.         $classes->setOrder('ASC');
  1446.         $classes->setOrderKey('id');
  1447.         $classes $classes->load();
  1448.         foreach ($classes as $class) {
  1449.             $result[] = [
  1450.                 'icon' => 'class',
  1451.                 'checked' => true,
  1452.                 'type' => 'class',
  1453.                 'name' => $class->getName(),
  1454.                 'displayName' => $class->getName(),
  1455.             ];
  1456.         }
  1457.         $objectBricks = new DataObject\Objectbrick\Definition\Listing();
  1458.         $objectBricks $objectBricks->load();
  1459.         foreach ($objectBricks as $objectBrick) {
  1460.             $result[] = [
  1461.                 'icon' => 'objectbricks',
  1462.                 'checked' => true,
  1463.                 'type' => 'objectbrick',
  1464.                 'name' => $objectBrick->getKey(),
  1465.                 'displayName' => $objectBrick->getKey(),
  1466.             ];
  1467.         }
  1468.         $customLayouts = new DataObject\ClassDefinition\CustomLayout\Listing();
  1469.         $customLayouts $customLayouts->load();
  1470.         foreach ($customLayouts as $customLayout) {
  1471.             $class DataObject\ClassDefinition::getById($customLayout->getClassId());
  1472.             $displayName $class->getName() . ' / ' .  $customLayout->getName();
  1473.             $result[] = [
  1474.                 'icon' => 'custom_views',
  1475.                 'checked' => true,
  1476.                 'type' => 'customlayout',
  1477.                 'name' => $customLayout->getId(),
  1478.                 'displayName' => $displayName,
  1479.             ];
  1480.         }
  1481.         return new JsonResponse(['success' => true'data' => $result]);
  1482.     }
  1483.     /**
  1484.      * @Route("/do-bulk-export", name="dobulkexport", methods={"GET"})
  1485.      *
  1486.      * @param Request $request
  1487.      *
  1488.      * @return Response
  1489.      */
  1490.     public function doBulkExportAction(Request $request)
  1491.     {
  1492.         $session Session::get('pimcore_objects');
  1493.         $list $session->get('class_bulk_export_settings');
  1494.         $list json_decode($listtrue);
  1495.         $result = [];
  1496.         foreach ($list as $item) {
  1497.             if ($item['type'] == 'fieldcollection') {
  1498.                 if ($fieldCollection DataObject\Fieldcollection\Definition::getByKey($item['name'])) {
  1499.                     $fieldCollectionJson json_decode(DataObject\ClassDefinition\Service::generateFieldCollectionJson($fieldCollection));
  1500.                     $fieldCollectionJson->key $item['name'];
  1501.                     $result['fieldcollection'][] = $fieldCollectionJson;
  1502.                 }
  1503.             } elseif ($item['type'] == 'class') {
  1504.                 if ($class DataObject\ClassDefinition::getByName($item['name'])) {
  1505.                     $data json_decode(DataObject\ClassDefinition\Service::generateClassDefinitionJson($class));
  1506.                     $data->name $item['name'];
  1507.                     $result['class'][] = $data;
  1508.                 }
  1509.             } elseif ($item['type'] == 'objectbrick') {
  1510.                 if ($objectBrick DataObject\Objectbrick\Definition::getByKey($item['name'])) {
  1511.                     $objectBrickJson json_decode(DataObject\ClassDefinition\Service::generateObjectBrickJson($objectBrick));
  1512.                     $objectBrickJson->key $item['name'];
  1513.                     $result['objectbrick'][] = $objectBrickJson;
  1514.                 }
  1515.             } elseif ($item['type'] == 'customlayout') {
  1516.                 if ($customLayout DataObject\ClassDefinition\CustomLayout::getById($item['name'])) {
  1517.                     $classId $customLayout->getClassId();
  1518.                     $class DataObject\ClassDefinition::getById($classId);
  1519.                     $customLayoutJson json_decode(DataObject\ClassDefinition\Service::generateCustomLayoutJson($customLayout));
  1520.                     $customLayoutJson->name $customLayout->getName();
  1521.                     $customLayoutJson->className $class->getName();
  1522.                     $result['customlayout'][] = $customLayoutJson;
  1523.                 }
  1524.             }
  1525.         }
  1526.         $result json_encode($resultJSON_PRETTY_PRINT);
  1527.         $response = new Response($result);
  1528.         $response->headers->set('Content-type''application/json');
  1529.         $response->headers->set('Content-Disposition''attachment; filename="bulk_export.json"');
  1530.         return $response;
  1531.     }
  1532.     /**
  1533.      * @param ControllerEvent $event
  1534.      */
  1535.     public function onKernelControllerEvent(ControllerEvent $event)
  1536.     {
  1537.         if (!$event->isMainRequest()) {
  1538.             return;
  1539.         }
  1540.         // check permissions
  1541.         $unrestrictedActions = [
  1542.             'getTreeAction''fieldcollectionListAction''fieldcollectionTreeAction''fieldcollectionGetAction',
  1543.             'getClassDefinitionForColumnConfigAction''objectbrickListAction''objectbrickTreeAction''objectbrickGetAction',
  1544.         ];
  1545.         $this->checkActionPermission($event'classes'$unrestrictedActions);
  1546.     }
  1547.     /**
  1548.      * @Route("/get-fieldcollection-usages", name="getfieldcollectionusages", methods={"GET"})
  1549.      *
  1550.      * @param Request $request
  1551.      *
  1552.      * @return Response
  1553.      */
  1554.     public function getFieldcollectionUsagesAction(Request $request)
  1555.     {
  1556.         $key $request->get('key');
  1557.         $result = [];
  1558.         $classes = new DataObject\ClassDefinition\Listing();
  1559.         $classes $classes->load();
  1560.         foreach ($classes as $class) {
  1561.             $fieldDefs $class->getFieldDefinitions();
  1562.             foreach ($fieldDefs as $fieldDef) {
  1563.                 if ($fieldDef instanceof DataObject\ClassDefinition\Data\Fieldcollections) {
  1564.                     $allowedKeys $fieldDef->getAllowedTypes();
  1565.                     if (is_array($allowedKeys) && in_array($key$allowedKeys)) {
  1566.                         $result[] = [
  1567.                             'class' => $class->getName(),
  1568.                             'field' => $fieldDef->getName(),
  1569.                         ];
  1570.                     }
  1571.                 }
  1572.             }
  1573.         }
  1574.         return $this->adminJson($result);
  1575.     }
  1576.     /**
  1577.      * @Route("/get-bricks-usages", name="getbrickusages", methods={"GET"})
  1578.      *
  1579.      * @param Request $request
  1580.      *
  1581.      * @return Response
  1582.      */
  1583.     public function getBrickUsagesAction(Request $request)
  1584.     {
  1585.         $classId $request->get('classId');
  1586.         $myclass DataObject\ClassDefinition::getById($classId);
  1587.         $result = [];
  1588.         $brickDefinitions = new DataObject\Objectbrick\Definition\Listing();
  1589.         $brickDefinitions $brickDefinitions->load();
  1590.         foreach ($brickDefinitions as $brickDefinition) {
  1591.             $classes $brickDefinition->getClassDefinitions();
  1592.             foreach ($classes as $class) {
  1593.                 if ($myclass->getName() == $class['classname']) {
  1594.                     $result[] = [
  1595.                         'objectbrick' => $brickDefinition->getKey(),
  1596.                         'field' => $class['fieldname'],
  1597.                     ];
  1598.                 }
  1599.             }
  1600.         }
  1601.         return $this->adminJson($result);
  1602.     }
  1603.     /**
  1604.      * @Route("/get-icons", name="geticons", methods={"GET"})
  1605.      *
  1606.      * @param Request $request
  1607.      * @param EventDispatcherInterface $eventDispatcher
  1608.      *
  1609.      * @return Response
  1610.      */
  1611.     public function getIconsAction(Request $requestEventDispatcherInterface $eventDispatcher)
  1612.     {
  1613.         $classId $request->get('classId');
  1614.         $iconDir PIMCORE_WEB_ROOT '/bundles/pimcoreadmin/img';
  1615.         $classIcons rscandir($iconDir '/object-icons/');
  1616.         $colorIcons rscandir($iconDir '/flat-color-icons/');
  1617.         $twemoji rscandir($iconDir '/twemoji/');
  1618.         $icons array_merge($classIcons$colorIcons$twemoji);
  1619.         foreach ($icons as &$icon) {
  1620.             $icon str_replace(PIMCORE_WEB_ROOT''$icon);
  1621.         }
  1622.         $event = new GenericEvent($this, [
  1623.             'icons' => $icons,
  1624.             'classId' => $classId,
  1625.         ]);
  1626.         $eventDispatcher->dispatch($eventAdminEvents::CLASS_OBJECT_ICONS_PRE_SEND_DATA);
  1627.         $icons $event->getArgument('icons');
  1628.         $result = [];
  1629.         foreach ($icons as $icon) {
  1630.             $content file_get_contents(PIMCORE_WEB_ROOT $icon);
  1631.             $result[] = [
  1632.                 'text' => sprintf('<img src="data:%s;base64,%s"/>'mime_content_type(PIMCORE_WEB_ROOT $icon), base64_encode($content)),
  1633.                 'value' => $icon,
  1634.             ];
  1635.         }
  1636.         return $this->adminJson($result);
  1637.     }
  1638.     /**
  1639.      * @Route("/suggest-class-identifier", name="suggestclassidentifier")
  1640.      *
  1641.      * @return Response
  1642.      */
  1643.     public function suggestClassIdentifierAction()
  1644.     {
  1645.         $db Db::get();
  1646.         $maxId $db->fetchOne('SELECT MAX(CAST(id AS SIGNED)) FROM classes;');
  1647.         $existingIds $db->fetchFirstColumn('select LOWER(id) from classes');
  1648.         $result = [
  1649.             'suggestedIdentifier' => $maxId $maxId 1,
  1650.             'existingIds' => $existingIds,
  1651.             ];
  1652.         return $this->adminJson($result);
  1653.     }
  1654.     /**
  1655.      * @Route("/suggest-custom-layout-identifier", name="suggestcustomlayoutidentifier")
  1656.      *
  1657.      * @param Request $request
  1658.      *
  1659.      * @return Response
  1660.      */
  1661.     public function suggestCustomLayoutIdentifierAction(Request $request)
  1662.     {
  1663.         $classId $request->get('classId');
  1664.         $identifier DataObject\ClassDefinition\CustomLayout::getIdentifier($classId);
  1665.         $list = new DataObject\ClassDefinition\CustomLayout\Listing();
  1666.         $list $list->load();
  1667.         $existingIds = [];
  1668.         $existingNames = [];
  1669.         foreach ($list as $item) {
  1670.             $existingIds[] = $item->getId();
  1671.             if ($item->getClassId() == $classId) {
  1672.                 $existingNames[] = $item->getName();
  1673.             }
  1674.         }
  1675.         $result = [
  1676.             'suggestedIdentifier' => $identifier,
  1677.             'existingIds' => $existingIds,
  1678.             'existingNames' => $existingNames,
  1679.             ];
  1680.         return $this->adminJson($result);
  1681.     }
  1682.     /**
  1683.      * @Route("/text-layout-preview", name="textlayoutpreview")
  1684.      *
  1685.      * @param Request $request
  1686.      *
  1687.      * @return Response
  1688.      */
  1689.     public function textLayoutPreviewAction(Request $request)
  1690.     {
  1691.         $objPath $request->get('previewObject''');
  1692.         $className '\\Pimcore\\Model\\DataObject\\' $request->get('className');
  1693.         $obj DataObject::getByPath($objPath) ?? new $className();
  1694.         $textLayout = new DataObject\ClassDefinition\Layout\Text();
  1695.         $context = [
  1696.           'data' => $request->get('renderingData'),
  1697.         ];
  1698.         if ($renderingClass $request->get('renderingClass')) {
  1699.             $textLayout->setRenderingClass($renderingClass);
  1700.         }
  1701.         if ($staticHtml $request->get('html')) {
  1702.             $textLayout->setHtml($staticHtml);
  1703.         }
  1704.         $html $textLayout->enrichLayoutDefinition($obj$context)->getHtml();
  1705.         $content =
  1706.             "<html>\n" .
  1707.             "<head>\n" .
  1708.             '<style type="text/css">' "\n" .
  1709.             file_get_contents(PIMCORE_WEB_ROOT '/bundles/pimcoreadmin/css/admin.css') .
  1710.             "</style>\n" .
  1711.             "</head>\n\n" .
  1712.             "<body class='objectlayout_element_text'>\n" .
  1713.             $html .
  1714.             "\n\n</body>\n" .
  1715.             "</html>\n";
  1716.         $response = new Response($content);
  1717.         $response->headers->set('Content-Type''text/html');
  1718.         return $response;
  1719.     }
  1720.     /**
  1721.      * @Route("/video-supported-types", name="videosupportedTypestypes")
  1722.      *
  1723.      * @param Request $request
  1724.      *
  1725.      * @return Response
  1726.      */
  1727.     public function videoAllowedTypesAction(Request $request)
  1728.     {
  1729.         $videoDef = new DataObject\ClassDefinition\Data\Video();
  1730.         $res = [];
  1731.         foreach ($videoDef->getSupportedTypes() as $type) {
  1732.             $res[] = [
  1733.                 'key' => $type,
  1734.                 'value' => $this->trans($type),
  1735.             ];
  1736.         }
  1737.         return $this->adminJson($res);
  1738.     }
  1739. }