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

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