vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/IndexController.php line 131

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;
  15. use Pimcore\Analytics\Google\Config\SiteConfigProvider;
  16. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  17. use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
  18. use Pimcore\Bundle\AdminBundle\Security\CsrfProtectionHandler;
  19. use Pimcore\Config;
  20. use Pimcore\Controller\KernelResponseEventInterface;
  21. use Pimcore\Db\ConnectionInterface;
  22. use Pimcore\Event\Admin\IndexActionSettingsEvent;
  23. use Pimcore\Event\AdminEvents;
  24. use Pimcore\Extension\Bundle\PimcoreBundleManager;
  25. use Pimcore\Maintenance\Executor;
  26. use Pimcore\Maintenance\ExecutorInterface;
  27. use Pimcore\Model\Document\DocType;
  28. use Pimcore\Model\Element\Service;
  29. use Pimcore\Model\Staticroute;
  30. use Pimcore\Model\User;
  31. use Pimcore\Tool;
  32. use Pimcore\Tool\Admin;
  33. use Pimcore\Tool\Session;
  34. use Pimcore\Version;
  35. use Symfony\Component\HttpFoundation\Request;
  36. use Symfony\Component\HttpFoundation\Response;
  37. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  38. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  39. use Symfony\Component\HttpKernel\KernelInterface;
  40. use Symfony\Component\Routing\Annotation\Route;
  41. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  42. /**
  43.  * @internal
  44.  */
  45. class IndexController extends AdminController implements KernelResponseEventInterface
  46. {
  47.     /**
  48.      * @var EventDispatcherInterface
  49.      */
  50.     private $eventDispatcher;
  51.     /**
  52.      * @param EventDispatcherInterface $eventDispatcher
  53.      */
  54.     public function __construct(EventDispatcherInterface $eventDispatcher)
  55.     {
  56.         $this->eventDispatcher $eventDispatcher;
  57.     }
  58.     /**
  59.      * @Route("/", name="pimcore_admin_index", methods={"GET"})
  60.      *
  61.      * @param Request $request
  62.      * @param SiteConfigProvider $siteConfigProvider
  63.      * @param KernelInterface $kernel
  64.      * @param Executor $maintenanceExecutor
  65.      * @param CsrfProtectionHandler $csrfProtection
  66.      * @param Config $config
  67.      *
  68.      * @return Response
  69.      *
  70.      * @throws \Exception
  71.      */
  72.     public function indexAction(
  73.         Request $request,
  74.         SiteConfigProvider $siteConfigProvider,
  75.         KernelInterface $kernel,
  76.         Executor $maintenanceExecutor,
  77.         CsrfProtectionHandler $csrfProtection,
  78.         Config $config
  79.     ) {
  80.         $user $this->getAdminUser();
  81.         $perspectiveConfig = new \Pimcore\Perspective\Config();
  82.         $templateParams = [
  83.             'config' => $config,
  84.             'perspectiveConfig' => $perspectiveConfig,
  85.         ];
  86.         $this
  87.             ->addRuntimePerspective($templateParams$user)
  88.             ->addPluginAssets($templateParams);
  89.         $this->buildPimcoreSettings($request$templateParams$user$kernel$maintenanceExecutor$csrfProtection$siteConfigProvider);
  90.         if ($user->getTwoFactorAuthentication('required') && !$user->getTwoFactorAuthentication('enabled')) {
  91.             // only one login is allowed to setup 2FA by the user himself
  92.             $user->setTwoFactorAuthentication('enabled'true);
  93.             // disable the 2FA prompt for the current session
  94.             Tool\Session::useSession(function (AttributeBagInterface $adminSession) {
  95.                 $adminSession->set('2fa_required'false);
  96.             });
  97.             $user->save();
  98.             $templateParams['settings']['twoFactorSetupRequired'] = true;
  99.         }
  100.         // allow to alter settings via an event
  101.         $settingsEvent = new IndexActionSettingsEvent($templateParams['settings'] ?? []);
  102.         $this->eventDispatcher->dispatch($settingsEventAdminEvents::INDEX_ACTION_SETTINGS);
  103.         $templateParams['settings'] = $settingsEvent->getSettings();
  104.         return $this->render('@PimcoreAdmin/Admin/Index/index.html.twig'$templateParams);
  105.     }
  106.     /**
  107.      * @Route("/index/statistics", name="pimcore_admin_index_statistics", methods={"GET"})
  108.      *
  109.      * @param Request $request
  110.      * @param ConnectionInterface $db
  111.      * @param KernelInterface $kernel
  112.      *
  113.      * @return JsonResponse
  114.      *
  115.      * @throws \Exception
  116.      */
  117.     public function statisticsAction(Request $requestConnectionInterface $dbKernelInterface $kernel)
  118.     {
  119.         // DB
  120.         try {
  121.             $tables $db->fetchAll('SELECT TABLE_NAME as name,TABLE_ROWS as `rows` from information_schema.TABLES
  122.                 WHERE TABLE_ROWS IS NOT NULL AND TABLE_SCHEMA = ?', [$db->getDatabase()]);
  123.         } catch (\Exception $e) {
  124.             $tables = [];
  125.         }
  126.         try {
  127.             $mysqlVersion $db->fetchOne('SELECT VERSION()');
  128.         } catch (\Exception $e) {
  129.             $mysqlVersion null;
  130.         }
  131.         try {
  132.             $data = [
  133.                 'instanceId' => $this->getInstanceId(),
  134.                 'pimcore_major_version' => 10,
  135.                 'pimcore_version' => Version::getVersion(),
  136.                 'pimcore_hash' => Version::getRevision(),
  137.                 'php_version' => PHP_VERSION,
  138.                 'mysql_version' => $mysqlVersion,
  139.                 'bundles' => array_keys($kernel->getBundles()),
  140.                 'tables' => $tables,
  141.             ];
  142.         } catch (\Exception $e) {
  143.             $data = [];
  144.         }
  145.         return $this->adminJson($data);
  146.     }
  147.     /**
  148.      * @param array $templateParams
  149.      * @param User $user
  150.      *
  151.      * @return $this
  152.      */
  153.     protected function addRuntimePerspective(array &$templateParamsUser $user)
  154.     {
  155.         $runtimePerspective \Pimcore\Perspective\Config::getRuntimePerspective($user);
  156.         $templateParams['runtimePerspective'] = $runtimePerspective;
  157.         return $this;
  158.     }
  159.     /**
  160.      * @param array $templateParams
  161.      *
  162.      * @return $this
  163.      */
  164.     protected function addPluginAssets(array &$templateParams)
  165.     {
  166.         $bundleManager $this->get(PimcoreBundleManager::class);
  167.         $templateParams['pluginJsPaths'] = $bundleManager->getJsPaths();
  168.         $templateParams['pluginCssPaths'] = $bundleManager->getCssPaths();
  169.         return $this;
  170.     }
  171.     /**
  172.      * @param Request $request
  173.      * @param array $templateParams
  174.      * @param User $user
  175.      * @param KernelInterface $kernel
  176.      * @param ExecutorInterface $maintenanceExecutor
  177.      * @param CsrfProtectionHandler $csrfProtection
  178.      * @param SiteConfigProvider $siteConfigProvider
  179.      *
  180.      * @return $this
  181.      */
  182.     protected function buildPimcoreSettings(Request $request, array &$templateParamsUser $userKernelInterface $kernelExecutorInterface $maintenanceExecutorCsrfProtectionHandler $csrfProtectionSiteConfigProvider $siteConfigProvider)
  183.     {
  184.         $config $templateParams['config'];
  185.         $dashboardHelper = new \Pimcore\Helper\Dashboard($user);
  186.         $settings = [
  187.             'instanceId' => $this->getInstanceId(),
  188.             'version' => Version::getVersion(),
  189.             'build' => Version::getRevision(),
  190.             'debug' => \Pimcore::inDebugMode(),
  191.             'devmode' => \Pimcore::inDevMode(),
  192.             'disableMinifyJs' => \Pimcore::disableMinifyJs(),
  193.             'environment' => $kernel->getEnvironment(),
  194.             'cached_environments' => Tool::getCachedSymfonyEnvironments(),
  195.             'sessionId' => htmlentities(Session::getSessionId(), ENT_QUOTES'UTF-8'),
  196.             // languages
  197.             'language' => $request->getLocale(),
  198.             'websiteLanguages' => Admin::reorderWebsiteLanguages(
  199.                 $this->getAdminUser(),
  200.                 $config['general']['valid_languages'],
  201.                 true
  202.             ),
  203.             // flags
  204.             'showCloseConfirmation' => true,
  205.             'debug_admin_translations' => (bool)$config['general']['debug_admin_translations'],
  206.             'document_generatepreviews' => (bool)$config['documents']['generate_preview'],
  207.             'asset_disable_tree_preview' => (bool)$config['assets']['disable_tree_preview'],
  208.             'chromium' => \Pimcore\Image\Chromium::isSupported(),
  209.             'htmltoimage' => \Pimcore\Image\HtmlToImage::isSupported(),
  210.             'videoconverter' => \Pimcore\Video::isAvailable(),
  211.             'asset_hide_edit' => (bool)$config['assets']['hide_edit_image'],
  212.             'main_domain' => $config['general']['domain'],
  213.             'timezone' => $config['general']['timezone'],
  214.             'tile_layer_url_template' => $config['maps']['tile_layer_url_template'],
  215.             'geocoding_url_template' => $config['maps']['geocoding_url_template'],
  216.             'reverse_geocoding_url_template' => $config['maps']['reverse_geocoding_url_template'],
  217.             'asset_tree_paging_limit' => $config['assets']['tree_paging_limit'],
  218.             'document_tree_paging_limit' => $config['documents']['tree_paging_limit'],
  219.             'object_tree_paging_limit' => $config['objects']['tree_paging_limit'],
  220.             'maxmind_geoip_installed' => (bool) $this->getParameter('pimcore.geoip.db_file'),
  221.             'hostname' => htmlentities(\Pimcore\Tool::getHostname(), ENT_QUOTES'UTF-8'),
  222.             'document_auto_save_interval' => $config['documents']['auto_save_interval'],
  223.             'object_auto_save_interval' => $config['objects']['auto_save_interval'],
  224.             // perspective and portlets
  225.             'perspective' => $templateParams['runtimePerspective'],
  226.             'availablePerspectives' => \Pimcore\Perspective\Config::getAvailablePerspectives($user),
  227.             'disabledPortlets' => $dashboardHelper->getDisabledPortlets(),
  228.             // google analytics
  229.             'google_analytics_enabled' => (bool) $siteConfigProvider->isSiteReportingConfigured(),
  230.             // this stuff is used to decide whether the "add" button should be grayed out or not
  231.             'image-thumbnails-writeable' => (new \Pimcore\Model\Asset\Image\Thumbnail\Config())->isWriteable(),
  232.             'video-thumbnails-writeable' => (new \Pimcore\Model\Asset\Video\Thumbnail\Config())->isWriteable(),
  233.             'custom-reports-writeable' => (new \Pimcore\Model\Tool\CustomReport\Config())->isWriteable(),
  234.             'document-types-writeable' => (new DocType())->isWriteable(),
  235.             'web2print-writeable' => \Pimcore\Web2Print\Config::isWriteable(),
  236.             'predefined-properties-writeable' => (new \Pimcore\Model\Property\Predefined())->isWriteable(),
  237.             'predefined-asset-metadata-writeable' => (new \Pimcore\Model\Metadata\Predefined())->isWriteable(),
  238.             'staticroutes-writeable' => (new Staticroute())->isWriteable(),
  239.             'perspectives-writeable' => \Pimcore\Perspective\Config::isWriteable(),
  240.             'custom-views-writeable' => \Pimcore\CustomView\Config::isWriteable(),
  241.         ];
  242.         $this
  243.             ->addSystemVarSettings($settings)
  244.             ->addMaintenanceSettings($settings$maintenanceExecutor)
  245.             ->addMailSettings($settings$config)
  246.             ->addCustomViewSettings($settings);
  247.         $settings['csrfToken'] = $csrfProtection->getCsrfToken();
  248.         $templateParams['settings'] = $settings;
  249.         return $this;
  250.     }
  251.     /**
  252.      * @return string
  253.      */
  254.     private function getInstanceId()
  255.     {
  256.         $instanceId 'not-set';
  257.         try {
  258.             $instanceId $this->getParameter('secret');
  259.             $instanceId sha1(substr($instanceId3, -3));
  260.         } catch (\Exception $e) {
  261.             // nothing to do
  262.         }
  263.         return $instanceId;
  264.     }
  265.     /**
  266.      * @param array $settings
  267.      *
  268.      * @return $this
  269.      */
  270.     protected function addSystemVarSettings(array &$settings)
  271.     {
  272.         // upload limit
  273.         $max_upload filesize2bytes(ini_get('upload_max_filesize') . 'B');
  274.         $max_post filesize2bytes(ini_get('post_max_size') . 'B');
  275.         $upload_mb min($max_upload$max_post);
  276.         $settings['upload_max_filesize'] = (int) $upload_mb;
  277.         // session lifetime (gc)
  278.         $session_gc_maxlifetime ini_get('session.gc_maxlifetime');
  279.         if (empty($session_gc_maxlifetime)) {
  280.             $session_gc_maxlifetime 120;
  281.         }
  282.         $settings['session_gc_maxlifetime'] = (int)$session_gc_maxlifetime;
  283.         return $this;
  284.     }
  285.     /**
  286.      * @param array $settings
  287.      * @param ExecutorInterface $maintenanceExecutor
  288.      *
  289.      * @return $this
  290.      */
  291.     protected function addMaintenanceSettings(array &$settingsExecutorInterface $maintenanceExecutor)
  292.     {
  293.         // check maintenance
  294.         $maintenance_active false;
  295.         if ($lastExecution $maintenanceExecutor->getLastExecution()) {
  296.             if ((time() - $lastExecution) < 3660) { // maintenance script should run at least every hour + a little tolerance
  297.                 $maintenance_active true;
  298.             }
  299.         }
  300.         $settings['maintenance_active'] = $maintenance_active;
  301.         $settings['maintenance_mode'] = Admin::isInMaintenanceMode();
  302.         return $this;
  303.     }
  304.     /**
  305.      * @param array $settings
  306.      * @param Config $config
  307.      *
  308.      * @return $this
  309.      */
  310.     protected function addMailSettings(array &$settings$config)
  311.     {
  312.         //mail settings
  313.         $mailIncomplete false;
  314.         if (isset($config['email'])) {
  315.             if (\Pimcore::inDebugMode() && empty($config['email']['debug']['email_addresses'])) {
  316.                 $mailIncomplete true;
  317.             }
  318.             if (empty($config['email']['sender']['email'])) {
  319.                 $mailIncomplete true;
  320.             }
  321.         }
  322.         $settings['mail'] = !$mailIncomplete;
  323.         $settings['mailDefaultAddress'] = $config['email']['sender']['email'] ?? null;
  324.         return $this;
  325.     }
  326.     /**
  327.      * @param array $settings
  328.      *
  329.      * @return $this
  330.      */
  331.     protected function addCustomViewSettings(array &$settings)
  332.     {
  333.         $cvData = [];
  334.         // still needed when publishing objects
  335.         $cvConfig \Pimcore\CustomView\Config::get();
  336.         if ($cvConfig) {
  337.             foreach ($cvConfig as $node) {
  338.                 $tmpData $node;
  339.                 // backwards compatibility
  340.                 $treeType $tmpData['treetype'] ? $tmpData['treetype'] : 'object';
  341.                 $rootNode Service::getElementByPath($treeType$tmpData['rootfolder']);
  342.                 if ($rootNode) {
  343.                     $tmpData['rootId'] = $rootNode->getId();
  344.                     $tmpData['allowedClasses'] = $tmpData['classes'] ?? null;
  345.                     $tmpData['showroot'] = (bool)$tmpData['showroot'];
  346.                     // Check if a user has privileges to that node
  347.                     if ($rootNode->isAllowed('list')) {
  348.                         $cvData[] = $tmpData;
  349.                     }
  350.                 }
  351.             }
  352.         }
  353.         $settings['customviews'] = $cvData;
  354.         return $this;
  355.     }
  356.     /**
  357.      * {@inheritdoc}
  358.      */
  359.     public function onKernelResponseEvent(ResponseEvent $event)
  360.     {
  361.         $event->getResponse()->headers->set('X-Frame-Options''deny'true);
  362.     }
  363. }