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

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