342 lines
7.3 KiB
PHP
342 lines
7.3 KiB
PHP
<?php
|
|
/* {{{ Copyright and License Notice
|
|
*
|
|
* Copyright © 2021 RaBe Websolutions
|
|
*
|
|
* This file is part of rabe/Util-Settings.
|
|
*
|
|
* rabe/Util-Settings is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* rabe/Util-Settings is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with rabe/Util-Settings. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*///}}}
|
|
declare(strict_types=1);
|
|
namespace rabe\Util;
|
|
|
|
/**
|
|
* Settings Class to read Configuration Files
|
|
* @author Norbert.e.Wagner dev@norb.me
|
|
*/
|
|
class Settings implements \Iterator
|
|
{
|
|
private const SITE = 0x01;
|
|
|
|
private array $settings = [];
|
|
|
|
private string $appPath = './';
|
|
private string $pkgPath = './';
|
|
private string $site;
|
|
|
|
protected string $confDir = 'config/';
|
|
protected string $filePrefix = '';
|
|
protected string $filePostfix = 'conf.php';
|
|
protected array $modes = [
|
|
'prod' => 'default',
|
|
'test' => 'testing',
|
|
];
|
|
|
|
private string $mode;
|
|
|
|
// Constructor {{{
|
|
/** {{{
|
|
* Construct a new Settings Object
|
|
*
|
|
* @param array $settings an array of settings to be used directly
|
|
* @param string $mode One of the keys of $this->modes
|
|
*///}}}
|
|
public function __construct( ?array $settings=null, ?string $mode=null )
|
|
{
|
|
if (isset($settings)) $this->settings = $settings;
|
|
if (isset($mode)) $this->mode = $mode;
|
|
}// }}}
|
|
|
|
// appPath() {{{
|
|
/** {{{
|
|
* Sets the application path where the config/ dirtectory is located
|
|
* If the package path is not set it is set to the appPath
|
|
*
|
|
*///}}}
|
|
public function appPath( string $path )
|
|
{
|
|
if ($this->pkgPath === $this->appPath) $this->pkgPath = $path;
|
|
$this->appPath = $path;
|
|
return $this;
|
|
}// }}}
|
|
|
|
// pkgPath() {{{
|
|
/** {{{
|
|
* Sets the package path where the config/ dirtectory for the default and mode files is located
|
|
*
|
|
*///}}}
|
|
public function pkgPath( string $path )
|
|
{
|
|
$this->pkgPath = $path;
|
|
return $this;
|
|
}// }}}
|
|
|
|
// prefix() {{{
|
|
/** {{{
|
|
*///}}}
|
|
public function prefix( string $prefix )
|
|
{
|
|
$this->filePrefix = "$prefix.";
|
|
return $this;
|
|
}// }}}
|
|
|
|
// addModes() {{{
|
|
/** {{{
|
|
*///}}}
|
|
public function addModes( array $modes )
|
|
{
|
|
$this->modes += $modes;
|
|
return $this;
|
|
}// }}}
|
|
|
|
// site() {{{
|
|
/** {{{
|
|
*///}}}
|
|
public function site( string $site )
|
|
{
|
|
$this->site = $site;
|
|
return $this;
|
|
}// }}}
|
|
|
|
// load() method {{{
|
|
/** {{{
|
|
* Load the configuration from the files and merge them
|
|
*
|
|
* @param array $settings uses the Settings as an Array.<br>
|
|
*///}}}
|
|
public function load( ?array $settings=null )
|
|
{
|
|
if (isset($settings))
|
|
{
|
|
$this->settings = $settings;
|
|
}
|
|
else
|
|
{
|
|
|
|
$modes = $this->modes;
|
|
|
|
// load Prefix.default.conf.php
|
|
$defaultConf = $this->buildFileName( array_shift($modes) );
|
|
|
|
if ( file_exists($defaultConf) )
|
|
{
|
|
$this->settings = require( $defaultConf );
|
|
}
|
|
else
|
|
{
|
|
// echo "No settingsfile: $defaultConf";
|
|
throw new \ErrorException( "No settingsfile: $defaultConf" );
|
|
// throw new FileNotFoundException();
|
|
}
|
|
|
|
// load local config without merging - we need it here for the mode
|
|
$conf = $this->buildFileName();
|
|
$localConf = false;
|
|
if (file_exists($conf)) $localConf = require($conf);
|
|
|
|
if (! isset($this->mode))
|
|
{ // if a localConf Mode is set use it, or take the default conf mode
|
|
$this->mode = (isset($localConf['mode'])) ? $localConf['mode'] : $this->settings['mode'];
|
|
}
|
|
else
|
|
{
|
|
$this->settings['mode'] = $this->mode;
|
|
}
|
|
|
|
if ( isset($this->site) )
|
|
{
|
|
$siteConf = $this->buildFileName(self::SITE);
|
|
if (file_exists($siteConf))
|
|
{
|
|
$localConf = array_replace_recursive($this->settings, require($siteConf));
|
|
}
|
|
}
|
|
|
|
// load and merge Prefix.mode.conf.php
|
|
if ( isset( $modes[ $this->mode ] ) )
|
|
{
|
|
$modeConf = $this->buildFileName( $modes[ $this->mode ] );
|
|
|
|
if ( file_exists($modeConf) )
|
|
{
|
|
$this->settings = array_replace_recursive( $this->settings, require($modeConf) );
|
|
}
|
|
else
|
|
{
|
|
// log no mode config File
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// log invalid mode
|
|
}
|
|
|
|
// merge Prefix.conf.php (localConf)
|
|
if ($localConf !== false)
|
|
{
|
|
$this->settings = array_replace_recursive( $this->settings, $localConf );
|
|
}
|
|
}
|
|
|
|
// echo "<pre>"; print_r( $this->settings ); echo "</pre>";
|
|
return $this;
|
|
}// }}}
|
|
|
|
// mergeFile() {{{
|
|
/** {{{
|
|
*///}}}
|
|
public function mergeFile( )
|
|
{
|
|
|
|
}// }}}
|
|
|
|
// create() {{{
|
|
/** {{{
|
|
* Creates a copy of the Settingsobject without the Settings
|
|
*
|
|
*///}}}
|
|
public function create( ?array $settings=null )
|
|
{
|
|
$cfg = clone $this;
|
|
if (isset($settings)) $cfg->load($settings);
|
|
return $cfg;
|
|
}// }}}
|
|
|
|
// buildFileName() method {{{
|
|
/** {{{
|
|
* Compose the filename of the configuration File
|
|
* @param string|hex $mode The name of the mode, null for localConf and self::SITE for the site config
|
|
*///}}}
|
|
public function buildFileName( $type=null )
|
|
{
|
|
$mode = '';
|
|
$path = $this->appPath.$this->confDir;
|
|
|
|
if ($type === self::SITE) $path .= $this->site.'/';
|
|
|
|
if (is_string( $type ))
|
|
{
|
|
$mode = "$type.";
|
|
$path = $this->pkgPath.$this->confDir;
|
|
}
|
|
|
|
return $path.$this->filePrefix.$mode.$this->filePostfix;
|
|
}
|
|
// }}}
|
|
|
|
// toArray() method {{{
|
|
/**
|
|
* Return the internal settings array
|
|
*
|
|
* @return array
|
|
*/
|
|
public function toArray()
|
|
{
|
|
return $this->settings;
|
|
}// }}}
|
|
|
|
// __clone() {{{
|
|
/** {{{
|
|
*///}}}
|
|
public function __clone()
|
|
{
|
|
$this->settings = [];
|
|
}// }}}
|
|
|
|
// Iterator methods {{{
|
|
/**
|
|
* Rewind the Iterator to the first element
|
|
* @link https://www.php.net/iterator.rewind
|
|
*/
|
|
public function rewind()
|
|
{
|
|
reset( $this->settings);
|
|
}
|
|
|
|
/**
|
|
* Return the current element
|
|
* @link https://www.php.net/iterator.current
|
|
*/
|
|
public function current()
|
|
{
|
|
return current( $this->settings );
|
|
}
|
|
|
|
/**
|
|
* Return the key of the current element
|
|
* @link https://www.php.net/iterator.key
|
|
*/
|
|
public function key()
|
|
{
|
|
return key( $this->settings );
|
|
}
|
|
|
|
/**
|
|
* Move forward to next element
|
|
* @link https://www.php.net/iterator.next
|
|
*/
|
|
public function next()
|
|
{
|
|
return next( $this->settings );
|
|
}
|
|
|
|
/**
|
|
* Checks if current position is valid
|
|
* @link https://www.php.net/iterator.valid
|
|
*/
|
|
public function valid()
|
|
{
|
|
$key = key( $this->settings );
|
|
return ($key !== null && $key !== false);
|
|
}
|
|
|
|
// }}}
|
|
|
|
// Magic getter/setter methods {{{
|
|
public function __set( $name, $value )
|
|
{
|
|
// todo: throw new SettingsAreReadOnlyException();
|
|
}
|
|
|
|
public function __get( $name )
|
|
{
|
|
if ( !isset( $this->settings[$name] ) )
|
|
{
|
|
throw new \Exception("Setting '$name' not found");
|
|
// todo: throw new SettingNotFoundException();
|
|
}
|
|
|
|
return (is_array( $this->settings[$name] ))
|
|
? $this->create( $this->settings[$name] )
|
|
: $this->settings[$name];
|
|
}
|
|
|
|
public function __isset( $name )
|
|
{
|
|
return ( isset( $this->settings[$name] ) );
|
|
}
|
|
|
|
public function __unset( $name )
|
|
{
|
|
unset( $this->settings[$name] );
|
|
}
|
|
// }}}
|
|
|
|
|
|
}
|
|
|
|
/* jEdit buffer local properties {{{
|
|
* :folding=explicit:collapseFolds=1:
|
|
}}}*/ |