vendor/contao/core-bundle/src/Resources/contao/library/Contao/Config.php line 172

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 Symfony\Component\Filesystem\Filesystem;
  11. use Symfony\Component\Filesystem\Path;
  12. /**
  13.  * Loads and writes the local configuration file
  14.  *
  15.  * Custom settings above or below the `### INSTALL SCRIPT ###` markers will be
  16.  * preserved.
  17.  */
  18. class Config
  19. {
  20.     /**
  21.      * Object instance (Singleton)
  22.      * @var Config
  23.      */
  24.     protected static $objInstance;
  25.     /**
  26.      * Files object
  27.      * @var Files
  28.      */
  29.     protected $Files;
  30.     /**
  31.      * Top content
  32.      * @var string
  33.      */
  34.     protected $strTop '';
  35.     /**
  36.      * Bottom content
  37.      * @var string
  38.      */
  39.     protected $strBottom '';
  40.     /**
  41.      * Modification indicator
  42.      * @var boolean
  43.      */
  44.     protected $blnIsModified false;
  45.     /**
  46.      * Local file existence
  47.      * @var boolean
  48.      */
  49.     protected static $blnHasLcf;
  50.     /**
  51.      * Data
  52.      * @var array
  53.      */
  54.     protected $arrData = array();
  55.     /**
  56.      * Cache
  57.      * @var array
  58.      */
  59.     protected $arrCache = array();
  60.     /**
  61.      * Root dir
  62.      * @var string
  63.      */
  64.     protected $strRootDir;
  65.     private static $arrDeprecatedMap = array
  66.     (
  67.         'dbHost'           => 'database_host',
  68.         'dbPort'           => 'database_port',
  69.         'dbUser'           => 'database_user',
  70.         'dbPass'           => 'database_password',
  71.         'dbDatabase'       => 'database_name',
  72.         'smtpHost'         => 'mailer_host',
  73.         'smtpUser'         => 'mailer_user',
  74.         'smtpPass'         => 'mailer_password',
  75.         'smtpPort'         => 'mailer_port',
  76.         'smtpEnc'          => 'mailer_encryption',
  77.         'addLanguageToUrl' => 'contao.prepend_locale',
  78.         'urlSuffix'        => 'contao.url_suffix',
  79.         'uploadPath'       => 'contao.upload_path',
  80.         'editableFiles'    => 'contao.editable_files',
  81.         'debugMode'        => 'kernel.debug',
  82.         'characterSet'     => 'kernel.charset',
  83.         'enableSearch'     => 'contao.search.default_indexer.enable',
  84.         'indexProtected'   => 'contao.search.index_protected',
  85.     );
  86.     private static $arrDeprecated = array
  87.     (
  88.         'validImageTypes' => 'contao.image.valid_extensions',
  89.         'jpgQuality'      => 'contao.image.imagine_options[jpeg_quality]',
  90.     );
  91.     private static $arrToBeRemoved = array
  92.     (
  93.         'os'                    => true,
  94.         'browser'               => true,
  95.         'dbCharset'             => true,
  96.         'dbCollation'           => true,
  97.         'disableRefererCheck'   => true,
  98.         'requestTokenWhitelist' => true,
  99.         'encryptionMode'        => true,
  100.         'encryptionCipher'      => true,
  101.         'sessionTimeout'        => true,
  102.         'disableInsertTags'     => true,
  103.         'rootFiles'             => true,
  104.         'exampleWebsite'        => true,
  105.         'coreOnlyMode'          => true,
  106.         'privacyAnonymizeIp'    => true,
  107.         'privacyAnonymizeGA'    => true,
  108.         'bypassCache'           => true,
  109.         'sslProxyDomain'        => true,
  110.     );
  111.     /**
  112.      * Prevent direct instantiation (Singleton)
  113.      */
  114.     protected function __construct()
  115.     {
  116.         $this->strRootDir System::getContainer()->getParameter('kernel.project_dir');
  117.     }
  118.     /**
  119.      * Automatically save the local configuration
  120.      */
  121.     public function __destruct()
  122.     {
  123.         if ($this->blnIsModified)
  124.         {
  125.             $this->save();
  126.         }
  127.     }
  128.     /**
  129.      * Prevent cloning of the object (Singleton)
  130.      */
  131.     final public function __clone()
  132.     {
  133.     }
  134.     /**
  135.      * Return the current object instance (Singleton)
  136.      *
  137.      * @return static The object instance
  138.      */
  139.     public static function getInstance()
  140.     {
  141.         if (static::$objInstance === null)
  142.         {
  143.             static::$objInstance = new static();
  144.             static::$objInstance->initialize();
  145.         }
  146.         return static::$objInstance;
  147.     }
  148.     /**
  149.      * Load all configuration files
  150.      */
  151.     protected function initialize()
  152.     {
  153.         if (static::$blnHasLcf === null)
  154.         {
  155.             static::preload();
  156.         }
  157.         $strCacheDir System::getContainer()->getParameter('kernel.cache_dir');
  158.         if (file_exists($strCacheDir '/contao/config/config.php'))
  159.         {
  160.             include $strCacheDir '/contao/config/config.php';
  161.         }
  162.         else
  163.         {
  164.             try
  165.             {
  166.                 $files System::getContainer()->get('contao.resource_locator')->locate('config/config.php'nullfalse);
  167.             }
  168.             catch (\InvalidArgumentException $e)
  169.             {
  170.                 $files = array();
  171.             }
  172.             foreach ($files as $file)
  173.             {
  174.                 include $file;
  175.             }
  176.         }
  177.         // Include the local configuration file again
  178.         if (static::$blnHasLcf)
  179.         {
  180.             include $this->strRootDir '/system/config/localconfig.php';
  181.         }
  182.         static::loadParameters();
  183.     }
  184.     /**
  185.      * Mark the object as modified
  186.      */
  187.     protected function markModified()
  188.     {
  189.         // Return if marked as modified already
  190.         if ($this->blnIsModified === true)
  191.         {
  192.             return;
  193.         }
  194.         $this->blnIsModified true;
  195.         // Reset the top and bottom content (see #344)
  196.         $this->strTop '';
  197.         $this->strBottom '';
  198.         // Import the Files object (required in the destructor)
  199.         $this->Files Files::getInstance();
  200.         // Parse the local configuration file
  201.         if (static::$blnHasLcf)
  202.         {
  203.             $strMode 'top';
  204.             $resFile fopen($this->strRootDir '/system/config/localconfig.php''r');
  205.             while (!feof($resFile))
  206.             {
  207.                 $strLine fgets($resFile);
  208.                 $strTrim trim($strLine);
  209.                 if ($strTrim == '?>')
  210.                 {
  211.                     continue;
  212.                 }
  213.                 if ($strTrim == '### INSTALL SCRIPT START ###')
  214.                 {
  215.                     $strMode 'data';
  216.                     continue;
  217.                 }
  218.                 if ($strTrim == '### INSTALL SCRIPT STOP ###')
  219.                 {
  220.                     $strMode 'bottom';
  221.                     continue;
  222.                 }
  223.                 if ($strMode == 'top')
  224.                 {
  225.                     $this->strTop .= $strLine;
  226.                 }
  227.                 elseif ($strMode == 'bottom')
  228.                 {
  229.                     $this->strBottom .= $strLine;
  230.                 }
  231.                 elseif ($strTrim)
  232.                 {
  233.                     $arrChunks array_map('trim'explode('='$strLine2));
  234.                     $this->arrData[$arrChunks[0]] = $arrChunks[1];
  235.                 }
  236.             }
  237.             fclose($resFile);
  238.         }
  239.     }
  240.     /**
  241.      * Save the local configuration file
  242.      */
  243.     public function save()
  244.     {
  245.         if (!$this->strTop)
  246.         {
  247.             $this->strTop '<?php';
  248.         }
  249.         $strFile  trim($this->strTop) . "\n\n";
  250.         $strFile .= "### INSTALL SCRIPT START ###\n";
  251.         foreach ($this->arrData as $k=>$v)
  252.         {
  253.             $strFile .= "$k = $v\n";
  254.         }
  255.         $strFile .= "### INSTALL SCRIPT STOP ###\n";
  256.         $this->strBottom trim($this->strBottom);
  257.         if ($this->strBottom)
  258.         {
  259.             $strFile .= "\n" $this->strBottom "\n";
  260.         }
  261.         $strTemp Path::join($this->strRootDir'system/tmp'md5(uniqid(mt_rand(), true)));
  262.         // Write to a temp file first
  263.         $objFile fopen($strTemp'w');
  264.         fwrite($objFile$strFile);
  265.         fclose($objFile);
  266.         // Make sure the file has been written (see #4483)
  267.         if (!filesize($strTemp))
  268.         {
  269.             System::getContainer()->get('monolog.logger.contao.error')->error('The local configuration file could not be written. Have you reached your quota limit?');
  270.             return;
  271.         }
  272.         $fs = new Filesystem();
  273.         // Adjust the file permissions (see #8178)
  274.         $fs->chmod($strTemp0666 & ~umask());
  275.         $strDestination Path::join($this->strRootDir'system/config/localconfig.php');
  276.         // Get the realpath in case it is a symlink (see #2209)
  277.         if ($realpath realpath($strDestination))
  278.         {
  279.             $strDestination $realpath;
  280.         }
  281.         // Then move the file to its final destination
  282.         $fs->rename($strTemp$strDestinationtrue);
  283.         // Reset the Zend OPcache
  284.         if (\function_exists('opcache_invalidate'))
  285.         {
  286.             opcache_invalidate($strDestinationtrue);
  287.         }
  288.         // Recompile the APC file (thanks to Trenker)
  289.         if (\function_exists('apc_compile_file') && !\ini_get('apc.stat'))
  290.         {
  291.             apc_compile_file($strDestination);
  292.         }
  293.         $this->blnIsModified false;
  294.     }
  295.     /**
  296.      * Return true if the installation is complete
  297.      *
  298.      * @return boolean True if the installation is complete
  299.      */
  300.     public static function isComplete()
  301.     {
  302.         return static::$blnHasLcf !== null && static::has('licenseAccepted');
  303.     }
  304.     /**
  305.      * Return all active modules as array
  306.      *
  307.      * @return array An array of active modules
  308.      *
  309.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  310.      *             Use the container parameter "kernel.bundles" instead.
  311.      */
  312.     public function getActiveModules()
  313.     {
  314.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\Config::getActiveModules()" has been deprecated and will no longer work in Contao 5.0. Use "kernel.bundles" instead.');
  315.         return ModuleLoader::getActive();
  316.     }
  317.     /**
  318.      * Add a configuration variable to the local configuration file
  319.      *
  320.      * @param string $strKey   The full variable name
  321.      * @param mixed  $varValue The configuration value
  322.      */
  323.     public function add($strKey$varValue)
  324.     {
  325.         $this->markModified();
  326.         $this->arrData[$strKey] = $this->escape($varValue) . ';';
  327.     }
  328.     /**
  329.      * Alias for Config::add()
  330.      *
  331.      * @param string $strKey   The full variable name
  332.      * @param mixed  $varValue The configuration value
  333.      */
  334.     public function update($strKey$varValue)
  335.     {
  336.         $this->add($strKey$varValue);
  337.     }
  338.     /**
  339.      * Remove a configuration variable
  340.      *
  341.      * @param string $strKey The full variable name
  342.      */
  343.     public function delete($strKey)
  344.     {
  345.         $this->markModified();
  346.         unset($this->arrData[$strKey]);
  347.     }
  348.     /**
  349.      * Check whether a configuration value exists
  350.      *
  351.      * @param string $strKey The short key
  352.      *
  353.      * @return boolean True if the configuration value exists
  354.      */
  355.     public static function has($strKey)
  356.     {
  357.         return \array_key_exists($strKey$GLOBALS['TL_CONFIG']);
  358.     }
  359.     /**
  360.      * Return a configuration value
  361.      *
  362.      * @param string $strKey The short key
  363.      *
  364.      * @return mixed The configuration value
  365.      */
  366.     public static function get($strKey)
  367.     {
  368.         if ($newKey self::getNewKey($strKey))
  369.         {
  370.             trigger_deprecation('contao/core-bundle''4.12''Using "%s(\'%s\')" has been deprecated. Use the "%s" parameter instead.'__METHOD__$strKey$newKey);
  371.         }
  372.         if (isset(self::$arrToBeRemoved[$strKey]))
  373.         {
  374.             trigger_deprecation('contao/core-bundle''4.13''Using "%s(\'%s\')" has been deprecated.'__METHOD__$strKeyself::$arrToBeRemoved[$strKey]);
  375.         }
  376.         return $GLOBALS['TL_CONFIG'][$strKey] ?? null;
  377.     }
  378.     /**
  379.      * Temporarily set a configuration value
  380.      *
  381.      * @param string $strKey   The short key
  382.      * @param mixed  $varValue The configuration value
  383.      */
  384.     public static function set($strKey$varValue)
  385.     {
  386.         if ($newKey self::getNewKey($strKey))
  387.         {
  388.             trigger_deprecation('contao/core-bundle''4.12''Using "%s(\'%s\', …)" has been deprecated. Use the "%s" parameter instead.'__METHOD__$strKey$newKey);
  389.         }
  390.         if (isset(self::$arrToBeRemoved[$strKey]))
  391.         {
  392.             trigger_deprecation('contao/core-bundle''4.13''Using "%s(\'%s\')" has been deprecated.'__METHOD__$strKeyself::$arrToBeRemoved[$strKey]);
  393.         }
  394.         $GLOBALS['TL_CONFIG'][$strKey] = $varValue;
  395.     }
  396.     /**
  397.      * Return the new key if the existing one is deprecated
  398.      *
  399.      * @internal
  400.      *
  401.      * @param string $strKey The short key
  402.      *
  403.      * @return string|null
  404.      */
  405.     public static function getNewKey($strKey)
  406.     {
  407.         return self::$arrDeprecated[$strKey] ?? self::$arrDeprecatedMap[$strKey] ?? null;
  408.     }
  409.     /**
  410.      * Permanently set a configuration value
  411.      *
  412.      * @param string $strKey   The short key or full variable name
  413.      * @param mixed  $varValue The configuration value
  414.      */
  415.     public static function persist($strKey$varValue)
  416.     {
  417.         $objConfig = static::getInstance();
  418.         if (strncmp($strKey'$GLOBALS'8) !== 0)
  419.         {
  420.             $strKey "\$GLOBALS['TL_CONFIG']['$strKey']";
  421.         }
  422.         $objConfig->add($strKey$varValue);
  423.     }
  424.     /**
  425.      * Permanently remove a configuration value
  426.      *
  427.      * @param string $strKey The short key or full variable name
  428.      */
  429.     public static function remove($strKey)
  430.     {
  431.         $objConfig = static::getInstance();
  432.         if (strncmp($strKey'$GLOBALS'8) !== 0)
  433.         {
  434.             $strKey "\$GLOBALS['TL_CONFIG']['$strKey']";
  435.         }
  436.         $objConfig->delete($strKey);
  437.     }
  438.     /**
  439.      * Preload the default and local configuration
  440.      */
  441.     public static function preload()
  442.     {
  443.         // Load the default files
  444.         include __DIR__ '/../../config/default.php';
  445.         include __DIR__ '/../../config/agents.php';
  446.         include __DIR__ '/../../config/mimetypes.php';
  447.         $projectDir System::getContainer()->getParameter('kernel.project_dir');
  448.         // Include the local configuration file
  449.         if (($blnHasLcf file_exists($projectDir '/system/config/localconfig.php')) === true)
  450.         {
  451.             include $projectDir '/system/config/localconfig.php';
  452.         }
  453.         static::loadParameters();
  454.         static::$blnHasLcf $blnHasLcf;
  455.     }
  456.     /**
  457.      * Override the database and SMTP parameters
  458.      */
  459.     protected static function loadParameters()
  460.     {
  461.         $container System::getContainer();
  462.         if ($container === null)
  463.         {
  464.             return;
  465.         }
  466.         if ($container->hasParameter('contao.localconfig') && \is_array($params $container->getParameter('contao.localconfig')))
  467.         {
  468.             foreach ($params as $key=>$value)
  469.             {
  470.                 $GLOBALS['TL_CONFIG'][$key] = $value;
  471.             }
  472.         }
  473.         foreach (self::$arrDeprecatedMap as $strKey=>$strParam)
  474.         {
  475.             if ($container->hasParameter($strParam))
  476.             {
  477.                 $GLOBALS['TL_CONFIG'][$strKey] = $container->getParameter($strParam);
  478.             }
  479.         }
  480.         $objRequest $container->get('request_stack')->getCurrentRequest();
  481.         /** @var PageModel $objPage */
  482.         if (null !== $objRequest && ($objPage $objRequest->attributes->get('pageModel')) instanceof PageModel)
  483.         {
  484.             $GLOBALS['TL_CONFIG']['addLanguageToUrl'] = $objPage->urlPrefix !== '';
  485.             $GLOBALS['TL_CONFIG']['urlSuffix'] = $objPage->urlSuffix;
  486.         }
  487.         if ($container->hasParameter('contao.image.valid_extensions'))
  488.         {
  489.             $GLOBALS['TL_CONFIG']['validImageTypes'] = implode(','$container->getParameter('contao.image.valid_extensions'));
  490.         }
  491.         if ($container->hasParameter('contao.image.imagine_options'))
  492.         {
  493.             $GLOBALS['TL_CONFIG']['jpgQuality'] = $container->getParameter('contao.image.imagine_options')['jpeg_quality'];
  494.         }
  495.     }
  496.     /**
  497.      * Escape a value depending on its type
  498.      *
  499.      * @param mixed $varValue The value
  500.      *
  501.      * @return mixed The escaped value
  502.      */
  503.     protected function escape($varValue)
  504.     {
  505.         if (is_numeric($varValue) && $varValue PHP_INT_MAX && !preg_match('/e|^[+-]?0[^.]/'$varValue))
  506.         {
  507.             return $varValue;
  508.         }
  509.         if (\is_bool($varValue))
  510.         {
  511.             return $varValue 'true' 'false';
  512.         }
  513.         if ($varValue == 'true')
  514.         {
  515.             return 'true';
  516.         }
  517.         if ($varValue == 'false')
  518.         {
  519.             return 'false';
  520.         }
  521.         return "'" str_replace('\\"''"'preg_replace('/[\n\r\t ]+/'' 'addslashes($varValue))) . "'";
  522.     }
  523. }
  524. class_alias(Config::class, 'Config');