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

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