* @link https://TheTempusProject.com/Core * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Bedrock\Classes; use TheTempusProject\Canary\Bin\Canary as Debug; use TheTempusProject\Bedrock\Functions\Check; use TheTempusProject\Bedrock\Functions\Input; class Config { public static $config = false; private static $location = false; private static $initialized = false; /** * Default constructor which will attempt to load the config from the location specified. * * @param {string} [$location] * @return {null|object} */ public function __construct( $location = '' ) { if ( self::$initialized !== false ) { Debug::log( 'Config already initialized.' ); return $this; } if ( empty( $location ) ) { $location = CONFIG_JSON; } self::$initialized = $this->load( $location ); if ( self::$initialized !== false ) { Debug::log( 'Config initialization succeeded.' ); return $this; } Debug::warn( 'Config initialization failed.' ); } /** * Attempts to retrieve then set the configuration from a file. * @note This function will reset the config every time it is used. * * @param {string} $location * @return {bool} */ public function load( $location ) { self::$config = $this->getConfigFile( $location ); self::$location = $location; if ( self::$config === false || empty( self::$config ) ) { Debug::warn( 'Config load failed.' ); return false; } Debug::log( 'Config load succeeded.' ); return true; } /** * Opens and decodes the config json from the location provided. * * @param {string} [$location] * @return {bool|array} */ public function getConfigFile( $location ) { if ( file_exists( $location ) ) { Debug::debug( "Config json found: $location" ); return json_decode( file_get_contents( $location ), true ); } else { Debug::warn( "Config json not found: $location" ); return false; } } /** * Add a new config option for the specified category. * * NOTE: Use a default option when using this function to * aid in fail safe execution. * * @param {string} [$category] - The primary category to add the option to. * @param {string} [$node] - The name of the new option. * @param {wild} [$value] - The desired value for the new option. * @param {bool} [$createMissing] - Whether or not to create missing options. * @param {bool} [$save] - Whether or not to save the config. * @param {bool} [$saveDefault] - Whether or not to save the default config. * @return {bool} */ public function update( $category, $node, $value, $createMissing = false, $save = false, $saveDefault = false ) { // @todo: createMissing is unused here if ( self::$config === false ) { Debug::warn( 'Config not loaded.' ); return false; } if ( !Check::simpleName( $category ) ) { Debug::warn( "Category name invalid: $categoryName" ); return false; } if ( !isset( self::$config[$category] ) ) { Debug::warn( "No such category: $category" ); return false; } if ( !Check::simpleName( $node ) ) { Debug::warn( "Node name invalid: $categoryName" ); return false; } if ( !isset( self::$config[$category][$node] ) ) { Debug::warn( 'Config not found.' ); return false; } if ( $value === 'true' ) { $value = true; } if ( $value === 'false' ) { $value = false; } self::$config[$category][$node]['value'] = $value; if ( $save ) { $this->save( $saveDefault ); } return true; } public function updateFromForm( $save = false, $saveDefault = false ) { if ( self::$config === false ) { Debug::warn( 'Config not loaded.' ); return; } foreach ( self::$config as $category => $fields ) { if ( empty( self::$config[ $category ] ) ) { Debug::warn( "Config category not found: $category" ); continue; } foreach ( self::$config[ $category ] as $field => $node ) { $name = $category . '/' . $field; if ( empty( $node ) ) { continue; } if ( !empty( $node['protected'] ) ) { continue; } $fieldname = str_ireplace( '/', '-', $name ); if ( Input::exists( $fieldname ) ) { $this->update( $category, $field, Input::post( $fieldname ) ); } } } if ( $save ) { return $this->save( $saveDefault ); } return true; } /** * Saves the current config. * * @param {bool} [$default] - Whether or not to save a default copy. * @return {bool} */ public function save( $default = false ) { if ( self::$config === false ) { Debug::warn( 'Config not loaded.' ); return false; } if ( self::$location === false ) { Debug::warn( 'Config location not set.' ); return false; } if ( $default ) { $locationArray = explode( '.', self::$location ); $locationArray[] = 'bak'; $backupLoction = implode( '.', $locationArray ); if ( !file_put_contents( $backupLoction, json_encode( self::$config ) ) ) { return false; } } if ( file_put_contents( self::$location, json_encode( self::$config ) ) ) { return true; } return false; } /** * Adds a new category to the $config array. * * @param {string} [$categoryName] * @return {bool} */ public function addCategory( $categoryName ) { if ( self::$config === false ) { self::$config = []; } if ( !Check::simpleName( $categoryName ) ) { Debug::warn( "Category name invalid: $categoryName" ); return false; } if ( isset( self::$config[$categoryName] ) ) { Debug::warn( "Category already exists: $categoryName" ); return false; } self::$config[$categoryName] = []; return true; } /** * Removes an existing category from the $config array. * * @param {string} [$categoryName] * @param {string} [$save] * @return {bool} */ public function removeCategory( $categoryName, $save = false, $saveDefault = true ) { if ( self::$config === false ) { Debug::warn( 'Config not loaded.' ); return; } if ( !isset( self::$config[$categoryName] ) ) { Debug::warn( "Config does not have category: $categoryName" ); return true; } unset( self::$config[$categoryName] ); if ( $save ) { $this->save( $saveDefault ); } return true; } /** * Add a new config node for the specified category. * * @param {string} [$category] - The primary category to add the option to. * @param {string} [$node] - The name of the new option. * @param {wild} [$value] - The desired value for the new option. * @return {bool} */ public function add( $category, $node, $details, $updateExisting = false ) { if ( self::$config === false ) { Debug::warn( 'Config not loaded.' ); return false; } if ( !Check::simpleName( $category ) ) { Debug::warn( "Category name invalid: $category" ); return false; } if ( !isset( self::$config[$category] ) ) { Debug::warn( "No such category: $category" ); return false; } if ( !Check::simpleName( $node ) ) { Debug::warn( "Category Node name invalid: $node" ); return false; } if ( isset( self::$config[$category][$node] ) ) { if ( $updateExisting ) { $details = array_replace(self::$config[$category][$node], $details ); } else { Debug::warn( "Config already exists: $node" ); return false; } } if ( !isset( $details['value'] ) ) { $details['value'] = $details['default']; } self::$config[$category][$node] = $details; return true; } public function generate( $location, $mods = [] ) { self::$location = $location; if ( !empty( $mods ) ) { foreach ( $mods as $category => $node ) { $this->addCategory( $category ); foreach ( $node as $name => $details ) { $this->add( $category, $name, $details, true ); } } } if ( $this->save( true ) ) { Debug::info( 'config file generated successfully.' ); return true; } return false; } /** * Retrieves the config option for $name. * * @param {string} [$name] - Must be in /