openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

ConfigurationLoader.class.php (4743B)


      1 <?php
      2 
      3 namespace configuration;
      4 
      5 use util\text\variables\VariableResolver;
      6 use util\YAML;
      7 
      8 
      9 /**
     10  * Configuration Loader.
     11  *
     12  * Loades the configuration values from a YAML file.
     13  *
     14  * @author Jan Dankert
     15  */
     16 class ConfigurationLoader
     17 {
     18 	public $configFile;
     19 
     20 
     21 	/**
     22 	 */
     23 	public function __construct($configFile)
     24 	{
     25 		$this->configFile = $configFile;
     26 	}
     27 
     28 
     29 	/**
     30 	 * Gets the last timestamp from the configuration file.
     31 	 *
     32 	 * @return int timestamp of last change as unix-timestamp
     33 	 */
     34 	public function lastModificationTime()
     35 	{
     36 		return filemtime($this->configFile);
     37 	}
     38 
     39 
     40 	/**
     41 	 * Loads the custom configuration file.
     42 	 *
     43 	 * @return array Configuration
     44 	 */
     45 	public function load()
     46 	{
     47 		$customConfig = ConfigurationLoader::loadCustomConfig($this->configFile);
     48 
     49 		// Den Dateinamen der Konfigurationsdatei in die Konfiguration schreiben.
     50 		$customConfig['config']['filename'] = $this->configFile;
     51 		$customConfig['config']['last_modification_time'] = filemtime($this->configFile);
     52 		$customConfig['config']['last_modification'] = date('r', filemtime($this->configFile));
     53 		$customConfig['config']['read'] = date('r');
     54 
     55 		return $customConfig;
     56 	}
     57 
     58 
     59 	/**
     60 	 * Loads the configuration file and resolves all include-commands.
     61 	 *
     62 	 * @return array Configuration
     63 	 */
     64 	private function loadCustomConfig($configFile)
     65 	{
     66 		if (!is_file($configFile) && !is_link($configFile)) {
     67 			error_log('Warning: Configuration file ' . $configFile . ' not found');
     68 			return array();
     69 		}
     70 
     71 		// Parse the YAML config to a hierarchical array
     72 		$customConfig = YAML::parse(file_get_contents($configFile));
     73 
     74 		// resolve variables
     75 		$customConfig = self::resolveVariables($customConfig);
     76 
     77 		// enrich with environment variables
     78 		$customConfig = self::enrichEnvironmentVariables($customConfig, getenv('CMS_CONFIG_PREFIX')?:'CMS');
     79 
     80 		// Does we have includes?
     81 		if (isset($customConfig['include'])) {
     82 
     83 			// 'include' must be an array
     84 			if (is_string($customConfig['include']))
     85 				$customConfig['include'] = array($customConfig['include']);
     86 
     87 			// Load include files.
     88 			foreach ($customConfig['include'] as $key => $file) {
     89 
     90 				if ($file[0] == '/') // File begins with '?'
     91 					; // File has an absolute path - do not change.
     92 				else
     93 					// Prepend file path with our config directory.
     94 					$file = __DIR__ . '/../../config/' . $file;
     95 
     96 				if (substr($file, -4) == '.yml' ||
     97 					substr($file, -5) == '.yaml' ||
     98 					substr($file, -8) == '.yml.php')
     99 					$customConfig = array_replace_recursive($customConfig, self::loadCustomConfig($file));
    100 				else
    101 					error_log('Warning: ' . $file . ' is no .yml file - not loaded');
    102 
    103 			}
    104 		}
    105 
    106 		return $customConfig;
    107 	}
    108 
    109 	/**
    110 	 * Evaluates variables in a config array.
    111 	 * Examples:
    112 	 * - config-${http:host}.yml         => config-yourdomain.yml
    113 	 * - config-${server:http-host}.yml  => config-yourdomain.yml
    114 	 * - config-${env:myvar}.yml         => config-myvalue.yml
    115 	 * - config-${env:myxyz?default}.yml => config-default.yml
    116 	 * @param $config array Configuration
    117 	 * @return array
    118 	 */
    119 	private function resolveVariables($config)
    120 	{
    121 		$resolver = new VariableResolver();
    122 		$resolver->namespaceSeparator = ':';
    123 		$resolver->defaultSeparator   = '?';
    124 
    125 		$resolver->addResolver('env',function ($var) {
    126 				return getenv(strtoupper($var));
    127 		});
    128 
    129 		// http:... is a shortcut for server:http-...
    130 		$resolver->addResolver('http', function ($var) {
    131 				return @$_SERVER['HTTP_' . strtoupper($var)];
    132 		});
    133 
    134 		$resolver->addResolver('server',function ($var) {
    135 				return @$_SERVER[strtoupper($var)];
    136 		});
    137 
    138 		return $resolver->resolveVariablesInArray($config);
    139 	}
    140 
    141 
    142 
    143 	/**
    144 	 * Walk through an array and search for pleasant environment variables.
    145 	 *
    146 	 * Example input:
    147 	 *
    148 	 *     ['fruits' =>
    149 	 *         [ 'red' => 'apple' ]
    150 	 *     ]
    151 	 *
    152 	 * would search for the environment variable "PREFIX_FRUITS_RED" and,
    153 	 * if present, replaces the value "apple".
    154 	 *
    155 	 * @param $data array data array
    156 	 * @param $prefix string|array prefix
    157 	 * @return array
    158 	 */
    159 	private function enrichEnvironmentVariables($data, $prefix)
    160 	{
    161 		foreach ($data as $key=> $value ) {
    162 
    163 			$newKey = array_merge( (array)$prefix,[$key] );
    164 
    165 			if   ( is_array($value) ) {
    166 				$value = $this->enrichEnvironmentVariables($value,$newKey ); // recursive call
    167 			} else {
    168 				$environmentKey   = strtoupper( implode('_',$newKey ) );
    169 
    170 				// replace with value from environment
    171 				// if present, otherwise leave it untouched
    172 				$value = getenv( $environmentKey ) ?: $value;
    173 
    174 				// string-based boolean flags must be converted to real booleans
    175 				if   ( in_array(strtolower($value),['true ','on' ]) )
    176 					$value = true;
    177 				if   ( in_array(strtolower($value),['false','off']) )
    178 					$value = false;
    179 			}
    180 
    181 			$data[ $key ] = $value;
    182 		}
    183 
    184 		return $data;
    185 	}
    186 
    187 }
    188