vendor/contao/core-bundle/src/Resources/contao/library/Contao/System.php line 158

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. use Contao\CoreBundle\Config\Loader\PhpFileLoader;
  11. use Contao\CoreBundle\Config\Loader\XliffFileLoader;
  12. use Contao\CoreBundle\Monolog\ContaoContext;
  13. use Contao\CoreBundle\Util\LocaleUtil;
  14. use Contao\Database\Installer;
  15. use Contao\Database\Updater;
  16. use Psr\Log\LogLevel;
  17. use Symfony\Component\DependencyInjection\Container;
  18. use Symfony\Component\DependencyInjection\ContainerInterface;
  19. use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  20. use Symfony\Component\Finder\SplFileInfo;
  21. use Symfony\Component\HttpFoundation\Session\Session;
  22. /**
  23.  * Abstract library base class
  24.  *
  25.  * The class provides miscellaneous methods that are used all throughout the
  26.  * application. It is the base class of the Contao library which provides the
  27.  * central "import" method to load other library classes.
  28.  *
  29.  * Usage:
  30.  *
  31.  *     class MyClass extends System
  32.  *     {
  33.  *         public function __construct()
  34.  *         {
  35.  *             $this->import('Database');
  36.  *         }
  37.  *     }
  38.  *
  39.  * @property Automator                        $Automator   The automator object
  40.  * @property Config                           $Config      The config object
  41.  * @property Database                         $Database    The database object
  42.  * @property Environment                      $Environment The environment object
  43.  * @property Files                            $Files       The files object
  44.  * @property Input                            $Input       The input object
  45.  * @property Installer                        $Installer   The database installer object
  46.  * @property Updater                          $Updater     The database updater object
  47.  * @property Messages                         $Messages    The messages object
  48.  * @property Session                          $Session     The session object
  49.  * @property StyleSheets                      $StyleSheets The style sheets object
  50.  * @property BackendTemplate|FrontendTemplate $Template    The template object (TODO: remove this line in Contao 5.0)
  51.  * @property BackendUser|FrontendUser         $User        The user object
  52.  */
  53. abstract class System
  54. {
  55.     /**
  56.      * Container
  57.      * @var ContainerInterface
  58.      */
  59.     protected static $objContainer;
  60.     /**
  61.      * @var array|null
  62.      */
  63.     private static $removedServiceIds;
  64.     /**
  65.      * Cache
  66.      * @var array
  67.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  68.      */
  69.     protected $arrCache = array();
  70.     /**
  71.      * Default libraries
  72.      * @var array
  73.      */
  74.     protected $arrObjects = array();
  75.     /**
  76.      * Static objects
  77.      * @var array
  78.      */
  79.     protected static $arrStaticObjects = array();
  80.     /**
  81.      * Singletons
  82.      * @var array
  83.      */
  84.     protected static $arrSingletons = array();
  85.     /**
  86.      * Available languages
  87.      * @var array
  88.      */
  89.     protected static $arrLanguages = array();
  90.     /**
  91.      * Loaded language files
  92.      * @var array
  93.      */
  94.     protected static $arrLanguageFiles = array();
  95.     /**
  96.      * Available image sizes
  97.      * @var array
  98.      */
  99.     protected static $arrImageSizes = array();
  100.     /**
  101.      * Import the Config instance
  102.      */
  103.     protected function __construct()
  104.     {
  105.         $this->import(Config::class, 'Config');
  106.     }
  107.     /**
  108.      * Get an object property
  109.      *
  110.      * Lazy load the Input and Environment libraries (which are now static) and
  111.      * only include them as object property if an old module requires it
  112.      *
  113.      * @param string $strKey The property name
  114.      *
  115.      * @return mixed|null The property value or null
  116.      */
  117.     public function __get($strKey)
  118.     {
  119.         if (!isset($this->arrObjects[$strKey]))
  120.         {
  121.             /** @var Input|Environment|Session|string $strKey */
  122.             if ($strKey == 'Input' || $strKey == 'Environment' || $strKey == 'Session')
  123.             {
  124.                 $this->arrObjects[$strKey] = $strKey::getInstance();
  125.             }
  126.             else
  127.             {
  128.                 return null;
  129.             }
  130.         }
  131.         return $this->arrObjects[$strKey];
  132.     }
  133.     /**
  134.      * Import a library and make it accessible by its name or an optional key
  135.      *
  136.      * @param string|object $strClass The class name
  137.      * @param string|object $strKey   An optional key to store the object under
  138.      * @param boolean       $blnForce If true, existing objects will be overridden
  139.      *
  140.      * @throws ServiceNotFoundException
  141.      */
  142.     protected function import($strClass$strKey=null$blnForce=false)
  143.     {
  144.         $strKey $strKey ?: $strClass;
  145.         if (\is_object($strKey))
  146.         {
  147.             $strKey = \get_class($strClass);
  148.         }
  149.         if ($blnForce || !isset($this->arrObjects[$strKey]))
  150.         {
  151.             $container = static::getContainer();
  152.             if (null === $container)
  153.             {
  154.                 throw new \RuntimeException('The Symfony container is not available, did you initialize the Contao framework?');
  155.             }
  156.             if (\is_object($strClass))
  157.             {
  158.                 $this->arrObjects[$strKey] = $strClass;
  159.             }
  160.             elseif (isset(static::$arrSingletons[$strClass]))
  161.             {
  162.                 $this->arrObjects[$strKey] = static::$arrSingletons[$strClass];
  163.             }
  164.             elseif ($container->has($strClass) && (strpos($strClass'\\') !== false || !class_exists($strClass)))
  165.             {
  166.                 $this->arrObjects[$strKey] = $container->get($strClass);
  167.             }
  168.             elseif (($container->getParameter('kernel.debug') || !class_exists($strClass)) && self::isServiceInlined($strClass))
  169.             {
  170.                 // In debug mode, we check for inlined services before trying to create a new instance of the class
  171.                 throw new ServiceNotFoundException($strClassnullnull, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.'$strClass));
  172.             }
  173.             elseif (!class_exists($strClass))
  174.             {
  175.                 throw new \RuntimeException('System::import() failed because class "' $strClass '" is not a valid class name or does not exist.');
  176.             }
  177.             elseif (\in_array('getInstance'get_class_methods($strClass)))
  178.             {
  179.                 $this->arrObjects[$strKey] = static::$arrSingletons[$strClass] = \call_user_func(array($strClass'getInstance'));
  180.             }
  181.             else
  182.             {
  183.                 try
  184.                 {
  185.                     $this->arrObjects[$strKey] = new $strClass();
  186.                 }
  187.                 catch (\Throwable $t)
  188.                 {
  189.                     if (!$container->getParameter('kernel.debug') && self::isServiceInlined($strClass))
  190.                     {
  191.                         throw new ServiceNotFoundException($strClassnullnull, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.'$strClass));
  192.                     }
  193.                     throw $t;
  194.                 }
  195.             }
  196.         }
  197.     }
  198.     /**
  199.      * Import a library in non-object context
  200.      *
  201.      * @param string|object $strClass The class name
  202.      * @param string|object $strKey   An optional key to store the object under
  203.      * @param boolean       $blnForce If true, existing objects will be overridden
  204.      *
  205.      * @throws ServiceNotFoundException
  206.      *
  207.      * @return object The imported object
  208.      */
  209.     public static function importStatic($strClass$strKey=null$blnForce=false)
  210.     {
  211.         $strKey $strKey ?: $strClass;
  212.         if (\is_object($strKey))
  213.         {
  214.             $strKey = \get_class($strClass);
  215.         }
  216.         if ($blnForce || !isset(static::$arrStaticObjects[$strKey]))
  217.         {
  218.             $container = static::getContainer();
  219.             if (null === $container)
  220.             {
  221.                 throw new \RuntimeException('The Symfony container is not available, did you initialize the Contao framework?');
  222.             }
  223.             if (\is_object($strClass))
  224.             {
  225.                 static::$arrStaticObjects[$strKey] = $strClass;
  226.             }
  227.             elseif (isset(static::$arrSingletons[$strClass]))
  228.             {
  229.                 static::$arrStaticObjects[$strKey] = static::$arrSingletons[$strClass];
  230.             }
  231.             elseif ($container->has($strClass) && (strpos($strClass'\\') !== false || !class_exists($strClass)))
  232.             {
  233.                 static::$arrStaticObjects[$strKey] = $container->get($strClass);
  234.             }
  235.             elseif (($container->getParameter('kernel.debug') || !class_exists($strClass)) && self::isServiceInlined($strClass))
  236.             {
  237.                 // In debug mode, we check for inlined services before trying to create a new instance of the class
  238.                 throw new ServiceNotFoundException($strClassnullnull, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.'$strClass));
  239.             }
  240.             elseif (!class_exists($strClass))
  241.             {
  242.                 throw new \RuntimeException('System::importStatic() failed because class "' $strClass '" is not a valid class name or does not exist.');
  243.             }
  244.             elseif (\in_array('getInstance'get_class_methods($strClass)))
  245.             {
  246.                 static::$arrStaticObjects[$strKey] = static::$arrSingletons[$strClass] = \call_user_func(array($strClass'getInstance'));
  247.             }
  248.             else
  249.             {
  250.                 try
  251.                 {
  252.                     static::$arrStaticObjects[$strKey] = new $strClass();
  253.                 }
  254.                 catch (\Throwable $t)
  255.                 {
  256.                     if (!$container->getParameter('kernel.debug') && self::isServiceInlined($strClass))
  257.                     {
  258.                         throw new ServiceNotFoundException($strClassnullnull, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.'$strClass));
  259.                     }
  260.                     throw $t;
  261.                 }
  262.             }
  263.         }
  264.         return static::$arrStaticObjects[$strKey];
  265.     }
  266.     private static function isServiceInlined($strClass)
  267.     {
  268.         $container = static::getContainer();
  269.         if (!$container instanceof Container)
  270.         {
  271.             return false;
  272.         }
  273.         if (null === self::$removedServiceIds)
  274.         {
  275.             self::$removedServiceIds $container->getRemovedIds();
  276.         }
  277.         return isset(self::$removedServiceIds[$strClass]);
  278.     }
  279.     /**
  280.      * Return the container object
  281.      *
  282.      * @return ContainerInterface The container object
  283.      */
  284.     public static function getContainer()
  285.     {
  286.         return static::$objContainer;
  287.     }
  288.     /**
  289.      * Set the container object
  290.      *
  291.      * @param ContainerInterface $container The container object
  292.      */
  293.     public static function setContainer(ContainerInterface $container)
  294.     {
  295.         static::$objContainer $container;
  296.     }
  297.     /**
  298.      * Add a log entry to the database
  299.      *
  300.      * @param string $strText     The log message
  301.      * @param string $strFunction The function name
  302.      * @param string $strCategory The category name
  303.      *
  304.      * @deprecated Deprecated since Contao 4.2, to be removed in Contao 5.
  305.      *             Use the logger service with your context or any of the predefined monolog.logger.contao services instead.
  306.      */
  307.     public static function log($strText$strFunction$strCategory)
  308.     {
  309.         trigger_deprecation('contao/core-bundle''4.2''Using "Contao\System::log()" has been deprecated and will no longer work in Contao 5.0. Use the "logger" service or any of the predefined "monolog.logger.contao" services instead.');
  310.         $level 'ERROR' === $strCategory LogLevel::ERROR LogLevel::INFO;
  311.         $logger = static::getContainer()->get('monolog.logger.contao');
  312.         $logger->log($level$strText, array('contao' => new ContaoContext($strFunction$strCategory)));
  313.     }
  314.     /**
  315.      * Return the referer URL and optionally encode ampersands
  316.      *
  317.      * @param boolean $blnEncodeAmpersands If true, ampersands will be encoded
  318.      * @param string  $strTable            An optional table name
  319.      *
  320.      * @return string The referer URL
  321.      */
  322.     public static function getReferer($blnEncodeAmpersands=false$strTable=null)
  323.     {
  324.         $objSession = static::getContainer()->get('session');
  325.         $ref Input::get('ref');
  326.         $key Input::get('popup') ? 'popupReferer' 'referer';
  327.         $session $objSession->get($key);
  328.         $return null;
  329.         if (null !== $session)
  330.         {
  331.             // Unique referer ID
  332.             if ($ref && isset($session[$ref]))
  333.             {
  334.                 $session $session[$ref];
  335.             }
  336.             elseif (\defined('TL_MODE') && TL_MODE == 'BE' && \is_array($session))
  337.             {
  338.                 $session end($session);
  339.             }
  340.             // Use a specific referer
  341.             if ($strTable && isset($session[$strTable]) && Input::get('act') != 'select')
  342.             {
  343.                 $session['current'] = $session[$strTable];
  344.             }
  345.             // Remove parameters helper
  346.             $cleanUrl = static function ($url$params = array('rt''ref'))
  347.             {
  348.                 if (!$url || strpos($url'?') === false)
  349.                 {
  350.                     return $url;
  351.                 }
  352.                 list($path$query) = explode('?'$url2);
  353.                 parse_str($query$pairs);
  354.                 foreach ($params as $param)
  355.                 {
  356.                     unset($pairs[$param]);
  357.                 }
  358.                 if (empty($pairs))
  359.                 {
  360.                     return $path;
  361.                 }
  362.                 return $path '?' http_build_query($pairs'''&'PHP_QUERY_RFC3986);
  363.             };
  364.             // Determine current or last
  365.             $strUrl = ($cleanUrl($session['current'] ?? null) != $cleanUrl(Environment::get('request'))) ? ($session['current'] ?? null) : ($session['last'] ?? null);
  366.             // Remove the "toggle" and "toggle all" parameters
  367.             $return $cleanUrl($strUrl, array('tg''ptg'));
  368.         }
  369.         // Fallback to the generic referer in the front end
  370.         if (!$return && \defined('TL_MODE') && TL_MODE == 'FE')
  371.         {
  372.             $return Environment::get('httpReferer');
  373.         }
  374.         // Fallback to the current URL if there is no referer
  375.         if (!$return)
  376.         {
  377.             if (\defined('TL_MODE') && TL_MODE == 'BE')
  378.             {
  379.                 $return = static::getContainer()->get('router')->generate('contao_backend');
  380.             }
  381.             else
  382.             {
  383.                 $return Environment::get('url');
  384.             }
  385.         }
  386.         // Do not urldecode here!
  387.         return preg_replace('/&(amp;)?/i', ($blnEncodeAmpersands '&amp;' '&'), $return);
  388.     }
  389.     /**
  390.      * Load a set of language files
  391.      *
  392.      * @param string      $strName     The table name
  393.      * @param string|null $strLanguage An optional language code
  394.      * @param boolean     $blnNoCache  If true, the cache will be bypassed
  395.      */
  396.     public static function loadLanguageFile($strName$strLanguage=null$blnNoCache=false)
  397.     {
  398.         if ($strLanguage === null)
  399.         {
  400.             $strLanguage LocaleUtil::formatAsLocale($GLOBALS['TL_LANGUAGE'] ?? 'en');
  401.         }
  402.         // Fall back to English
  403.         if (!$strLanguage)
  404.         {
  405.             $strLanguage 'en';
  406.         }
  407.         if (!== preg_match('/^[a-z0-9_-]+$/i'$strName))
  408.         {
  409.             throw new \InvalidArgumentException(sprintf('Invalid language file name "%s"'$strName));
  410.         }
  411.         // Return if the language file has been loaded already
  412.         if (!$blnNoCache && array_key_last(static::$arrLanguageFiles[$strName] ?? array()) === $strLanguage)
  413.         {
  414.             return;
  415.         }
  416.         $strCacheKey $strLanguage;
  417.         // Make sure the language exists
  418.         if ($strLanguage != 'en' && !static::isInstalledLanguage($strLanguage))
  419.         {
  420.             $strShortLang substr($strLanguage02);
  421.             // Fall back to "de" if "de_DE" does not exist
  422.             if ($strShortLang != $strLanguage && static::isInstalledLanguage($strShortLang))
  423.             {
  424.                 $strLanguage $strShortLang;
  425.             }
  426.             // Fall back to English (see #6581)
  427.             else
  428.             {
  429.                 $strLanguage 'en';
  430.             }
  431.         }
  432.         // Unset to move the new array key to the last position
  433.         unset(static::$arrLanguageFiles[$strName][$strCacheKey]);
  434.         // Use a global cache variable to support nested calls
  435.         static::$arrLanguageFiles[$strName][$strCacheKey] = $strLanguage;
  436.         // Backwards compatibility
  437.         if ('languages' === $strName)
  438.         {
  439.             // Reset previously loaded languages without destroying references
  440.             foreach (array_keys($GLOBALS['TL_LANG']['LNG'] ?? array()) as $strLocale)
  441.             {
  442.                 $GLOBALS['TL_LANG']['LNG'][$strLocale] = null;
  443.             }
  444.             foreach (self::getContainer()->get('contao.intl.locales')->getLocales($strCacheKey) as $strLocale => $strLabel)
  445.             {
  446.                 $GLOBALS['TL_LANG']['LNG'][$strLocale] = $strLabel;
  447.             }
  448.         }
  449.         // Backwards compatibility
  450.         if ('countries' === $strName)
  451.         {
  452.             // Reset previously loaded countries without destroying references
  453.             foreach (array_keys($GLOBALS['TL_LANG']['CNT'] ?? array()) as $strLocale)
  454.             {
  455.                 $GLOBALS['TL_LANG']['CNT'][$strLocale] = null;
  456.             }
  457.             foreach (self::getContainer()->get('contao.intl.countries')->getCountries($strLanguage) as $strCountryCode => $strLabel)
  458.             {
  459.                 $GLOBALS['TL_LANG']['CNT'][strtolower($strCountryCode)] = $strLabel;
  460.             }
  461.         }
  462.         // Fall back to English
  463.         $arrCreateLangs = ($strLanguage == 'en') ? array('en') : array('en'$strLanguage);
  464.         // Prepare the XLIFF loader
  465.         $xlfLoader = new XliffFileLoader(static::getContainer()->getParameter('kernel.project_dir'), true);
  466.         $strCacheDir = static::getContainer()->getParameter('kernel.cache_dir');
  467.         // Load the language(s)
  468.         foreach ($arrCreateLangs as $strCreateLang)
  469.         {
  470.             // Try to load from cache
  471.             if (file_exists($strCacheDir '/contao/languages/' $strCreateLang '/' $strName '.php'))
  472.             {
  473.                 include $strCacheDir '/contao/languages/' $strCreateLang '/' $strName '.php';
  474.             }
  475.             else
  476.             {
  477.                 // Find the given filename either as .php or .xlf file
  478.                 $finder = static::getContainer()->get('contao.resource_finder')->findIn('languages/' $strCreateLang)->name('/^' $strName '\.(php|xlf)$/');
  479.                 /** @var SplFileInfo $file */
  480.                 foreach ($finder as $file)
  481.                 {
  482.                     switch ($file->getExtension())
  483.                     {
  484.                         case 'php':
  485.                             include $file;
  486.                             break;
  487.                         case 'xlf':
  488.                             $xlfLoader->load($file$strCreateLang);
  489.                             break;
  490.                         default:
  491.                             throw new \RuntimeException(sprintf('Invalid language file extension: %s'$file->getExtension()));
  492.                     }
  493.                 }
  494.             }
  495.         }
  496.         // Set MSC.textDirection (see #3360)
  497.         if ('default' === $strName)
  498.         {
  499.             $GLOBALS['TL_LANG']['MSC']['textDirection'] = (\ResourceBundle::create($strLanguage'ICUDATA'true)['layout']['characters'] ?? null) === 'right-to-left' 'rtl' 'ltr';
  500.         }
  501.         // HOOK: allow loading custom labels
  502.         if (isset($GLOBALS['TL_HOOKS']['loadLanguageFile']) && \is_array($GLOBALS['TL_HOOKS']['loadLanguageFile']))
  503.         {
  504.             foreach ($GLOBALS['TL_HOOKS']['loadLanguageFile'] as $callback)
  505.             {
  506.                 static::importStatic($callback[0])->{$callback[1]}($strName$strLanguage$strCacheKey);
  507.             }
  508.         }
  509.         // Handle single quotes in the deleteConfirm message
  510.         if ($strName == 'default' && isset($GLOBALS['TL_LANG']['MSC']['deleteConfirm']))
  511.         {
  512.             $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] = str_replace("'""\\'"$GLOBALS['TL_LANG']['MSC']['deleteConfirm']);
  513.         }
  514.         $projectDir self::getContainer()->getParameter('kernel.project_dir');
  515.         // Local configuration file
  516.         if (file_exists($projectDir '/system/config/langconfig.php'))
  517.         {
  518.             trigger_deprecation('contao/core-bundle''4.3''Using the "langconfig.php" file has been deprecated and will no longer work in Contao 5.0. Create custom language files in the "contao/languages" folder instead.');
  519.             include $projectDir '/system/config/langconfig.php';
  520.         }
  521.     }
  522.     /**
  523.      * Check whether a language is installed
  524.      *
  525.      * @param boolean $strLanguage The language code
  526.      *
  527.      * @return boolean True if the language is installed
  528.      */
  529.     public static function isInstalledLanguage($strLanguage)
  530.     {
  531.         if (!isset(static::$arrLanguages[$strLanguage]))
  532.         {
  533.             if (LocaleUtil::canonicalize($strLanguage) !== $strLanguage)
  534.             {
  535.                 return false;
  536.             }
  537.             $projectDir self::getContainer()->getParameter('kernel.project_dir');
  538.             if (is_dir($projectDir '/vendor/contao/core-bundle/src/Resources/contao/languages/' $strLanguage))
  539.             {
  540.                 static::$arrLanguages[$strLanguage] = true;
  541.             }
  542.             elseif (is_dir(static::getContainer()->getParameter('kernel.cache_dir') . '/contao/languages/' $strLanguage))
  543.             {
  544.                 static::$arrLanguages[$strLanguage] = true;
  545.             }
  546.             else
  547.             {
  548.                 static::$arrLanguages[$strLanguage] = static::getContainer()->get('contao.resource_finder')->findIn('languages')->depth(0)->directories()->name($strLanguage)->hasResults();
  549.             }
  550.         }
  551.         return static::$arrLanguages[$strLanguage];
  552.     }
  553.     /**
  554.      * Return the countries as array
  555.      *
  556.      * @return array An array of country names
  557.      *
  558.      * @deprecated Deprecated since Contao 4.12, to be removed in Contao 5;
  559.      *             use the Contao\CoreBundle\Intl\Countries service instead
  560.      */
  561.     public static function getCountries()
  562.     {
  563.         trigger_deprecation('contao/core-bundle''4.12''Using the %s method has been deprecated and will no longer work in Contao 5.0. Use the "contao.intl.countries" service instead.'__METHOD__);
  564.         $arrCountries self::getContainer()->get('contao.intl.countries')->getCountries();
  565.         return array_combine(array_map('strtolower'array_keys($arrCountries)), $arrCountries);
  566.     }
  567.     /**
  568.      * Return the available languages as array
  569.      *
  570.      * @param boolean $blnInstalledOnly If true, return only installed languages
  571.      *
  572.      * @return array An array of languages
  573.      *
  574.      * @deprecated Deprecated since Contao 4.12, to be removed in Contao 5;
  575.      *             use the Contao\CoreBundle\Intl\Locales service instead
  576.      */
  577.     public static function getLanguages($blnInstalledOnly=false)
  578.     {
  579.         trigger_deprecation('contao/core-bundle''4.12''Using the %s method has been deprecated and will no longer work in Contao 5.0. Use the "contao.intl.locales" service instead.'__METHOD__);
  580.         if ($blnInstalledOnly)
  581.         {
  582.             return self::getContainer()->get('contao.intl.locales')->getEnabledLocales(nulltrue);
  583.         }
  584.         return self::getContainer()->get('contao.intl.locales')->getLocales(nulltrue);
  585.     }
  586.     /**
  587.      * Return the timezones as array
  588.      *
  589.      * @return array An array of timezones
  590.      */
  591.     public static function getTimeZones()
  592.     {
  593.         trigger_deprecation('contao/core-bundle''4.13''Using the %s method has been deprecated and will no longer work in Contao 5.0. Use the DateTimeZone::listIdentifiers() instead.'__METHOD__);
  594.         $arrReturn = array();
  595.         $timezones = array();
  596.         require __DIR__ '/../../config/timezones.php';
  597.         foreach ($timezones as $strGroup=>$arrTimezones)
  598.         {
  599.             foreach ($arrTimezones as $strTimezone)
  600.             {
  601.                 $arrReturn[$strGroup][] = $strTimezone;
  602.             }
  603.         }
  604.         return $arrReturn;
  605.     }
  606.     /**
  607.      * Return all image sizes as array
  608.      *
  609.      * @return array The available image sizes
  610.      *
  611.      * @deprecated Deprecated since Contao 4.1, to be removed in Contao 5.
  612.      *             Use the contao.image.sizes service instead.
  613.      */
  614.     public static function getImageSizes()
  615.     {
  616.         trigger_deprecation('contao/core-bundle''4.1''Using "Contao\System::getImageSizes()" has been deprecated and will no longer work in Contao 5.0. Use the "contao.image.sizes" service instead.');
  617.         return static::getContainer()->get('contao.image.sizes')->getAllOptions();
  618.     }
  619.     /**
  620.      * Urlencode a file path preserving slashes
  621.      *
  622.      * @param string $strPath The file path
  623.      *
  624.      * @return string The encoded file path
  625.      */
  626.     public static function urlEncode($strPath)
  627.     {
  628.         return str_replace('%2F''/'rawurlencode($strPath));
  629.     }
  630.     /**
  631.      * Set a cookie
  632.      *
  633.      * @param string       $strName     The cookie name
  634.      * @param mixed        $varValue    The cookie value
  635.      * @param integer      $intExpires  The expiration date
  636.      * @param string|null  $strPath     An optional path
  637.      * @param string|null  $strDomain   An optional domain name
  638.      * @param boolean|null $blnSecure   If true, the secure flag will be set
  639.      * @param boolean      $blnHttpOnly If true, the http-only flag will be set
  640.      */
  641.     public static function setCookie($strName$varValue$intExpires$strPath=null$strDomain=null$blnSecure=null$blnHttpOnly=false)
  642.     {
  643.         if (!$strPath)
  644.         {
  645.             $strPath Environment::get('path') ?: '/'// see #4390
  646.         }
  647.         if ($blnSecure === null)
  648.         {
  649.             $blnSecure false;
  650.             if ($request = static::getContainer()->get('request_stack')->getCurrentRequest())
  651.             {
  652.                 $blnSecure $request->isSecure();
  653.             }
  654.         }
  655.         $objCookie = new \stdClass();
  656.         $objCookie->strName     $strName;
  657.         $objCookie->varValue    $varValue;
  658.         $objCookie->intExpires  $intExpires;
  659.         $objCookie->strPath     $strPath;
  660.         $objCookie->strDomain   $strDomain;
  661.         $objCookie->blnSecure   $blnSecure;
  662.         $objCookie->blnHttpOnly $blnHttpOnly;
  663.         // HOOK: allow adding custom logic
  664.         if (isset($GLOBALS['TL_HOOKS']['setCookie']) && \is_array($GLOBALS['TL_HOOKS']['setCookie']))
  665.         {
  666.             foreach ($GLOBALS['TL_HOOKS']['setCookie'] as $callback)
  667.             {
  668.                 $objCookie = static::importStatic($callback[0])->{$callback[1]}($objCookie);
  669.             }
  670.         }
  671.         setcookie($objCookie->strName$objCookie->varValue$objCookie->intExpires$objCookie->strPath$objCookie->strDomain$objCookie->blnSecure$objCookie->blnHttpOnly);
  672.     }
  673.     /**
  674.      * Convert a byte value into a human-readable format
  675.      *
  676.      * @param integer $intSize     The size in bytes
  677.      * @param integer $intDecimals The number of decimals to show
  678.      *
  679.      * @return string The human-readable size
  680.      */
  681.     public static function getReadableSize($intSize$intDecimals=1)
  682.     {
  683.         for ($i=0$intSize>=1024$i++)
  684.         {
  685.             $intSize /= 1024;
  686.         }
  687.         return static::getFormattedNumber($intSize$intDecimals) . ' ' $GLOBALS['TL_LANG']['UNITS'][$i];
  688.     }
  689.     /**
  690.      * Format a number
  691.      *
  692.      * @param mixed   $varNumber   An integer or float number
  693.      * @param integer $intDecimals The number of decimals to show
  694.      *
  695.      * @return mixed The formatted number
  696.      */
  697.     public static function getFormattedNumber($varNumber$intDecimals=2)
  698.     {
  699.         return number_format(round($varNumber$intDecimals), $intDecimals$GLOBALS['TL_LANG']['MSC']['decimalSeparator'], $GLOBALS['TL_LANG']['MSC']['thousandsSeparator']);
  700.     }
  701.     /**
  702.      * Return the session hash
  703.      *
  704.      * @param string $strCookie The cookie name
  705.      *
  706.      * @return string The session hash
  707.      *
  708.      * @deprecated Deprecated since Contao 4.5, to be removed in Contao 5.0.
  709.      *             Use Symfony authentication instead.
  710.      */
  711.     public static function getSessionHash($strCookie)
  712.     {
  713.         trigger_deprecation('contao/core-bundle''4.5''Using "Contao\System::getSessionHash()" has been deprecated and will no longer work in Contao 5.0. Use Symfony authentication instead.');
  714.         $session = static::getContainer()->get('session');
  715.         if (!$session->isStarted())
  716.         {
  717.             $session->start();
  718.         }
  719.         return sha1($session->getId() . $strCookie);
  720.     }
  721.     /**
  722.      * Anonymize an IP address by overriding the last chunk
  723.      *
  724.      * @param string $strIp The IP address
  725.      *
  726.      * @return string The encoded IP address
  727.      */
  728.     public static function anonymizeIp($strIp)
  729.     {
  730.         // Localhost
  731.         if ($strIp == '127.0.0.1' || $strIp == '::1')
  732.         {
  733.             return $strIp;
  734.         }
  735.         // IPv6
  736.         if (strpos($strIp':') !== false)
  737.         {
  738.             return substr_replace($strIp':0000'strrpos($strIp':'));
  739.         }
  740.         // IPv4
  741.         return substr_replace($strIp'.0'strrpos($strIp'.'));
  742.     }
  743.     /**
  744.      * Read the contents of a PHP file, stripping the opening and closing PHP tags
  745.      *
  746.      * @param string $strName The name of the PHP file
  747.      *
  748.      * @return string The PHP code without the PHP tags
  749.      *
  750.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  751.      *             Use the Contao\CoreBundle\Config\Loader\PhpFileLoader class instead.
  752.      */
  753.     protected static function readPhpFileWithoutTags($strName)
  754.     {
  755.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::readPhpFileWithoutTags()" has been deprecated and will no longer work in Contao 5.0. Use the "Contao\CoreBundle\Config\Loader\PhpFileLoader" class instead.');
  756.         $projectDir self::getContainer()->getParameter('kernel.project_dir');
  757.         // Convert to absolute path
  758.         if (strpos($strName$projectDir '/') === false)
  759.         {
  760.             $strName $projectDir '/' $strName;
  761.         }
  762.         $loader = new PhpFileLoader();
  763.         return $loader->load($strName);
  764.     }
  765.     /**
  766.      * Convert an .xlf file into a PHP language file
  767.      *
  768.      * @param string  $strName     The name of the .xlf file
  769.      * @param string  $strLanguage The language code
  770.      * @param boolean $blnLoad     Add the labels to the global language array
  771.      *
  772.      * @return string The PHP code
  773.      *
  774.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  775.      *             Use the Contao\CoreBundle\Config\Loader\XliffFileLoader class instead.
  776.      */
  777.     public static function convertXlfToPhp($strName$strLanguage$blnLoad=false)
  778.     {
  779.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::convertXlfToPhp()" has been deprecated and will no longer work in Contao 5.0. Use the "Contao\CoreBundle\Config\Loader\XliffFileLoader" class instead.');
  780.         $projectDir self::getContainer()->getParameter('kernel.project_dir');
  781.         // Convert to absolute path
  782.         if (strpos($strName$projectDir '/') === false)
  783.         {
  784.             $strName $projectDir '/' $strName;
  785.         }
  786.         $loader = new XliffFileLoader(static::getContainer()->getParameter('kernel.project_dir'), $blnLoad);
  787.         return $loader->load($strName$strLanguage);
  788.     }
  789.     /**
  790.      * Parse a date format string and translate textual representations
  791.      *
  792.      * @param string  $strFormat The date format string
  793.      * @param integer $intTstamp An optional timestamp
  794.      *
  795.      * @return string The textual representation of the date
  796.      *
  797.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  798.      *             Use Date::parse() instead.
  799.      */
  800.     public static function parseDate($strFormat$intTstamp=null)
  801.     {
  802.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::parseDate()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Date::parse()" instead.');
  803.         return Date::parse($strFormat$intTstamp);
  804.     }
  805.     /**
  806.      * Add a request string to the current URL
  807.      *
  808.      * @param string $strRequest The string to be added
  809.      *
  810.      * @return string The new URL
  811.      *
  812.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  813.      *             Use Controller::addToUrl() instead.
  814.      */
  815.     public static function addToUrl($strRequest)
  816.     {
  817.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addToUrl()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Controller::addToUrl()" instead.');
  818.         return Controller::addToUrl($strRequest);
  819.     }
  820.     /**
  821.      * Reload the current page
  822.      *
  823.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  824.      *             Use Controller::reload() instead.
  825.      */
  826.     public static function reload()
  827.     {
  828.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::reload()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Controller::reload()" instead.');
  829.         Controller::reload();
  830.     }
  831.     /**
  832.      * Redirect to another page
  833.      *
  834.      * @param string  $strLocation The target URL
  835.      * @param integer $intStatus   The HTTP status code (defaults to 303)
  836.      *
  837.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  838.      *             Use Controller::redirect() instead.
  839.      */
  840.     public static function redirect($strLocation$intStatus=303)
  841.     {
  842.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::redirect()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Controller::redirect()" instead.');
  843.         Controller::redirect($strLocation$intStatus);
  844.     }
  845.     /**
  846.      * Add an error message
  847.      *
  848.      * @param string $strMessage The error message
  849.      *
  850.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  851.      *             Use Message::addError() instead.
  852.      */
  853.     protected function addErrorMessage($strMessage)
  854.     {
  855.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addErrorMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::addError()" instead.');
  856.         Message::addError($strMessage);
  857.     }
  858.     /**
  859.      * Add a confirmation message
  860.      *
  861.      * @param string $strMessage The confirmation
  862.      *
  863.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  864.      *             Use Message::addConfirmation() instead.
  865.      */
  866.     protected function addConfirmationMessage($strMessage)
  867.     {
  868.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addConfirmationMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::addConfirmation()" instead.');
  869.         Message::addConfirmation($strMessage);
  870.     }
  871.     /**
  872.      * Add a new message
  873.      *
  874.      * @param string $strMessage The new message
  875.      *
  876.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  877.      *             Use Message::addNew() instead.
  878.      */
  879.     protected function addNewMessage($strMessage)
  880.     {
  881.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addNewMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::addNew()" instead.');
  882.         Message::addNew($strMessage);
  883.     }
  884.     /**
  885.      * Add an info message
  886.      *
  887.      * @param string $strMessage The info message
  888.      *
  889.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  890.      *             Use Message::addInfo() instead.
  891.      */
  892.     protected function addInfoMessage($strMessage)
  893.     {
  894.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addInfoMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::addInfo()" instead.');
  895.         Message::addInfo($strMessage);
  896.     }
  897.     /**
  898.      * Add an unformatted message
  899.      *
  900.      * @param string $strMessage The unformatted message
  901.      *
  902.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  903.      *             Use Message::addRaw() instead.
  904.      */
  905.     protected function addRawMessage($strMessage)
  906.     {
  907.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addRawMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::addRaw()" instead.');
  908.         Message::addRaw($strMessage);
  909.     }
  910.     /**
  911.      * Add a message
  912.      *
  913.      * @param string $strMessage The message
  914.      * @param string $strType    The message type
  915.      *
  916.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  917.      *             Use Message::add() instead.
  918.      */
  919.     protected function addMessage($strMessage$strType)
  920.     {
  921.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::addMessage()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::add()" instead.');
  922.         Message::add($strMessage$strType);
  923.     }
  924.     /**
  925.      * Return all messages as HTML
  926.      *
  927.      * @param string $strScope An optional message scope
  928.      *
  929.      * @return string The messages HTML markup
  930.      *
  931.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  932.      *             Use Message::generate() instead.
  933.      */
  934.     protected function getMessages($strScope=null)
  935.     {
  936.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::getMessages()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::generate()" instead.');
  937.         return Message::generate($strScope ?? TL_MODE);
  938.     }
  939.     /**
  940.      * Reset the message system
  941.      *
  942.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  943.      *             Use Message::reset() instead.
  944.      */
  945.     protected function resetMessages()
  946.     {
  947.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::resetMessages()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::reset()" instead.');
  948.         Message::reset();
  949.     }
  950.     /**
  951.      * Return all available message types
  952.      *
  953.      * @return array An array of message types
  954.      *
  955.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  956.      *             Use Message::getTypes() instead.
  957.      */
  958.     protected function getMessageTypes()
  959.     {
  960.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::getMessageTypes()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Message::getTypes()" instead.');
  961.         return Message::getTypes();
  962.     }
  963.     /**
  964.      * Encode an internationalized domain name
  965.      *
  966.      * @param string $strDomain The domain name
  967.      *
  968.      * @return string The encoded domain name
  969.      *
  970.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  971.      *             Use Idna::encode() instead.
  972.      */
  973.     protected function idnaEncode($strDomain)
  974.     {
  975.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::idnaEncode()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Idna::encode()" instead.');
  976.         return Idna::encode($strDomain);
  977.     }
  978.     /**
  979.      * Decode an internationalized domain name
  980.      *
  981.      * @param string $strDomain The domain name
  982.      *
  983.      * @return string The decoded domain name
  984.      *
  985.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  986.      *             Use Idna::decode() instead.
  987.      */
  988.     protected function idnaDecode($strDomain)
  989.     {
  990.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::idnaDecode()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Idna::decode()" instead.');
  991.         return Idna::decode($strDomain);
  992.     }
  993.     /**
  994.      * Encode the domain in an e-mail address
  995.      *
  996.      * @param string $strEmail The e-mail address
  997.      *
  998.      * @return string The encoded e-mail address
  999.      *
  1000.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1001.      *             Use Idna::encodeEmail() instead.
  1002.      */
  1003.     protected function idnaEncodeEmail($strEmail)
  1004.     {
  1005.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::idnaEncodeEmail()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Idna::encodeEmail()" instead.');
  1006.         return Idna::encodeEmail($strEmail);
  1007.     }
  1008.     /**
  1009.      * Encode the domain in a URL
  1010.      *
  1011.      * @param string $strUrl The URL
  1012.      *
  1013.      * @return string The encoded URL
  1014.      *
  1015.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1016.      *             Use Idna::encodeUrl() instead.
  1017.      */
  1018.     protected function idnaEncodeUrl($strUrl)
  1019.     {
  1020.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::idnaEncodeUrl()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Idna::encodeUrl()" instead.');
  1021.         return Idna::encodeUrl($strUrl);
  1022.     }
  1023.     /**
  1024.      * Validate an e-mail address
  1025.      *
  1026.      * @param string $strEmail The e-mail address
  1027.      *
  1028.      * @return boolean True if it is a valid e-mail address
  1029.      *
  1030.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1031.      *             Use Validator::isEmail() instead.
  1032.      */
  1033.     protected function isValidEmailAddress($strEmail)
  1034.     {
  1035.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::isValidEmailAddress()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Validator::isEmail()" instead.');
  1036.         return Validator::isEmail($strEmail);
  1037.     }
  1038.     /**
  1039.      * Split a friendly-name e-mail address and return name and e-mail as array
  1040.      *
  1041.      * @param string $strEmail A friendly-name e-mail address
  1042.      *
  1043.      * @return array An array with name and e-mail address
  1044.      *
  1045.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1046.      *             Use StringUtil::splitFriendlyEmail() instead.
  1047.      */
  1048.     public static function splitFriendlyName($strEmail)
  1049.     {
  1050.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::splitFriendlyName()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\StringUtil::splitFriendlyEmail()" instead.');
  1051.         return StringUtil::splitFriendlyEmail($strEmail);
  1052.     }
  1053.     /**
  1054.      * Return the request string without the script name
  1055.      *
  1056.      * @param boolean $blnAmpersand If true, ampersands will be encoded
  1057.      *
  1058.      * @return string The request string
  1059.      *
  1060.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1061.      *             Use Environment::get("indexFreeRequest") instead.
  1062.      */
  1063.     public static function getIndexFreeRequest($blnAmpersand=true)
  1064.     {
  1065.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::getIndexFreeRequest()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Environment::get(\'indexFreeRequest\')" instead.');
  1066.         return StringUtil::ampersand(Environment::get('indexFreeRequest'), $blnAmpersand);
  1067.     }
  1068.     /**
  1069.      * Compile a Model class name from a table name (e.g. tl_form_field becomes FormFieldModel)
  1070.      *
  1071.      * @param string $strTable The table name
  1072.      *
  1073.      * @return string The model class name
  1074.      *
  1075.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1076.      *             Use Model::getClassFromTable() instead.
  1077.      */
  1078.     public static function getModelClassFromTable($strTable)
  1079.     {
  1080.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::getModelClassFromTable()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Model::getClassFromTable()" instead.');
  1081.         return Model::getClassFromTable($strTable);
  1082.     }
  1083.     /**
  1084.      * Enable a back end module
  1085.      *
  1086.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1087.      *             Use Composer to add or remove modules.
  1088.      */
  1089.     public static function enableModule()
  1090.     {
  1091.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::enableModule()" has been deprecated and will no longer work in Contao 5.0. Use Composer to add or remove modules.');
  1092.     }
  1093.     /**
  1094.      * Disable a back end module
  1095.      *
  1096.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  1097.      *             Use Composer to add or remove modules.
  1098.      */
  1099.     public static function disableModule()
  1100.     {
  1101.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\System::disableModule()" has been deprecated and will no longer work in Contao 5.0. Use Composer to add or remove modules.');
  1102.     }
  1103. }
  1104. class_alias(System::class, 'System');