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