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

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