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

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