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

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