config = $config !== null ? $config : new ConfigObject(); } /** * Return this config's file path * * @return string */ public function getConfigFile() { return $this->configFile; } /** * Set this config's file path * * @param string $filepath The path to the ini file * * @return $this */ public function setConfigFile($filepath) { $this->configFile = $filepath; return $this; } /** * Return the internal ConfigObject * * @return ConfigObject */ public function getConfigObject() { return $this->config; } /** * Provide a query for the internal config object * * @return SimpleQuery */ public function select() { return $this->config->select(); } /** * Return the count of available sections * * @return int */ public function count() { return $this->select()->count(); } /** * Reset the current position of the internal config object * * @return ConfigObject */ public function rewind() { return $this->config->rewind(); } /** * Return the section of the current iteration * * @return ConfigObject */ public function current() { return $this->config->current(); } /** * Return whether the position of the current iteration is valid * * @return bool */ public function valid() { return $this->config->valid(); } /** * Return the section's name of the current iteration * * @return string */ public function key() { return $this->config->key(); } /** * Advance the position of the current iteration and return the new section * * @return ConfigObject */ public function next() { return $this->config->next(); } /** * Return whether this config has any sections * * @return bool */ public function isEmpty() { return $this->config->isEmpty(); } /** * Return this config's section names * * @return array */ public function keys() { return $this->config->keys(); } /** * Return this config's data as associative array * * @return array */ public function toArray() { return $this->config->toArray(); } /** * Return the value from a section's property * * @param string $section The section where the given property can be found * @param string $key The section's property to fetch the value from * @param mixed $default The value to return in case the section or the property is missing * * @return mixed * * @throws UnexpectedValueException In case the given section does not hold any configuration */ public function get($section, $key, $default = null) { $value = $this->config->$section; if ($value instanceof ConfigObject) { $value = $value->$key; } elseif ($value !== null) { throw new UnexpectedValueException( sprintf('Value "%s" is not of type "%s" or a sub-type of it', $value, get_class($this->config)) ); } if ($value === null && $default !== null) { $value = $default; } return $value; } /** * Return the given section * * @param string $name The section's name * * @return ConfigObject */ public function getSection($name) { $section = $this->config->get($name); return $section !== null ? $section : new ConfigObject(); } /** * Set or replace a section * * @param string $name * @param array|ConfigObject $config * * @return $this */ public function setSection($name, $config = null) { if ($config === null) { $config = new ConfigObject(); } elseif (! $config instanceof ConfigObject) { $config = new ConfigObject($config); } $this->config->$name = $config; return $this; } /** * Remove a section * * @param string $name * * @return $this */ public function removeSection($name) { unset($this->config->$name); return $this; } /** * Return whether the given section exists * * @param string $name * * @return bool */ public function hasSection($name) { return isset($this->config->$name); } /** * Initialize a new config using the given array * * The returned config has no file associated to it. * * @param array $array The array to initialize the config with * * @return Config */ public static function fromArray(array $array) { return new static(new ConfigObject($array)); } /** * Load configuration from the given INI file * * @param string $file The file to parse * * @throws NotReadableError When the file cannot be read */ public static function fromIni($file) { $emptyConfig = new static(); $filepath = realpath($file); if ($filepath === false) { $emptyConfig->setConfigFile($file); } elseif (is_readable($filepath)) { return IniParser::parseIniFile($filepath); } elseif (@file_exists($filepath)) { throw new NotReadableError(t('Cannot read config file "%s". Permission denied'), $filepath); } return $emptyConfig; } /** * Save configuration to the given INI file * * @param string|null $filePath The path to the INI file or null in case this config's path should be used * @param int $fileMode The file mode to store the file with * * @throws LogicException In case this config has no path and none is passed in either * @throws NotWritableError In case the INI file cannot be written * * @todo create basepath and throw NotWritableError in case its not possible */ public function saveIni($filePath = null, $fileMode = 0660) { if ($filePath === null && $this->configFile) { $filePath = $this->configFile; } elseif ($filePath === null) { throw new LogicException('You need to pass $filePath or set a path using Config::setConfigFile()'); } if (! file_exists($filePath)) { File::create($filePath, $fileMode); } $this->getIniWriter($filePath, $fileMode)->write(); } /** * Return a IniWriter for this config * * @param string|null $filePath * @param int $fileMode * * @return IniWriter */ protected function getIniWriter($filePath = null, $fileMode = null) { return new IniWriter($this, $filePath, $fileMode); } /** * Prepend configuration base dir to the given relative path * * @param string $path A relative path * * @return string */ public static function resolvePath($path) { return self::$configDir . DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR); } /** * Retrieve a application config * * @param string $configname The configuration name (without ini suffix) to read and return * @param bool $fromDisk When set true, the configuration will be read from disk, even * if it already has been read * * @return Config The requested configuration */ public static function app($configname = 'config', $fromDisk = false) { if (! isset(self::$app[$configname]) || $fromDisk) { self::$app[$configname] = static::fromIni(static::resolvePath($configname . '.ini')); } return self::$app[$configname]; } /** * Retrieve a module config * * @param string $modulename The name of the module where to look for the requested configuration * @param string $configname The configuration name (without ini suffix) to read and return * @param string $fromDisk When set true, the configuration will be read from disk, even * if it already has been read * * @return Config The requested configuration */ public static function module($modulename, $configname = 'config', $fromDisk = false) { if (! isset(self::$modules[$modulename])) { self::$modules[$modulename] = array(); } if (! isset(self::$modules[$modulename][$configname]) || $fromDisk) { self::$modules[$modulename][$configname] = static::fromIni( static::resolvePath('modules/' . $modulename . '/' . $configname . '.ini') ); } return self::$modules[$modulename][$configname]; } /** * Retrieve a navigation config * * @param string $type The type identifier of the navigation item for which to return its config * @param string $username A user's name or null if the shared config is desired * @param bool $fromDisk If true, the configuration will be read from disk * * @return Config The requested configuration */ public static function navigation($type, $username = null, $fromDisk = false) { if (! isset(self::$navigation[$type])) { self::$navigation[$type] = array(); } $branch = $username ?: 'shared'; $typeConfigs = self::$navigation[$type]; if (! isset($typeConfigs[$branch]) || $fromDisk) { $typeConfigs[$branch] = static::fromIni(static::getNavigationConfigPath($type, $username)); } return $typeConfigs[$branch]; } /** * Return the path to the configuration file for the given navigation item type and user * * @param string $type * @param string $username * * @return string * * @throws IcingaException In case the given type is unknown */ protected static function getNavigationConfigPath($type, $username = null) { $itemTypeConfig = Navigation::getItemTypeConfiguration(); if (! isset($itemTypeConfig[$type])) { throw new IcingaException('Invalid navigation item type %s provided', $type); } if (isset($itemTypeConfig[$type]['config'])) { $filename = $itemTypeConfig[$type]['config'] . '.ini'; } else { $filename = $type . 's.ini'; } if ($username) { $path = static::resolvePath(implode(DIRECTORY_SEPARATOR, array('preferences', $username, $filename))); if (realpath($path) === false) { $path = static::resolvePath(implode( DIRECTORY_SEPARATOR, array('preferences', strtolower($username), $filename) )); } } else { $path = static::resolvePath('navigation' . DIRECTORY_SEPARATOR . $filename); } return $path; } /** * Return this config rendered as a INI structured string * * @return string */ public function __toString() { return $this->getIniWriter()->render(); } }