pickles/src/Config.php
2014-09-30 22:24:10 -04:00

215 lines
6.6 KiB
PHP

<?php
/**
* Configuration Class File for PICKLES
*
* PHP version 5
*
* Licensed under The MIT License
* Redistribution of these files must retain the above copyright notice.
*
* @author Josh Sherman <josh@gravityblvd.com>
* @copyright Copyright 2007-2014, Josh Sherman
* @license http://www.opensource.org/licenses/mit-license.html
* @package PICKLES
* @link https://github.com/joshtronic/pickles
*/
namespace Pickles;
/**
* Config Class
*
* Handles loading the site's configuration file (if available). At the moment
* this class is a very skewed Singleton. The plan is to eventually extend this
* out to support multiple configuration files, and the ability to load in
* custom config files on the fly as well. The core of PICKLES uses the class
* as a Singleton so we're not loading the configuration multiple times per
* page load.
*/
class Config extends \ArrayObject
{
private static $_instance = false;
/**
* Constructor
*
* Calls the parent constructor and loads the passed file.
*/
public function __construct($config_filename = false)
{
try
{
ini_set('display_errors', true);
error_reporting(-1);
$filename = getcwd() . '/../../pickles.php';
$environments = false;
$environment = false;
// Why not PHP_SAPI? because I wanted it to be convenient to unit test
$cli = !isset($_SERVER['REQUEST_METHOD']);
if ($config_filename)
{
$filename = $config_filename;
}
// Only require in case you want to reload the config
require $filename;
// Checks that we have the config array
if (!isset($config))
{
throw new \Exception('Missing $config array.');
}
// Determines the environment
if (!isset($config['environments']) || !is_array($config['environments']))
{
throw new \Exception('Environments are misconfigured.');
}
$environments = $config['environments'];
// If we're on the CLI, check an environment was even passed in
if ($cli && $_SERVER['argc'] < 2)
{
throw new \Exception('You must pass an environment (e.g. php script.php <environment>)');
}
// Loops through the environments and looks for a match
foreach ($config['environments'] as $name => $hosts)
{
if (!is_array($hosts))
{
$hosts = [$hosts];
}
// Tries to determine the environment name
foreach ($hosts as $host)
{
if ($cli)
{
// Checks the first argument on the command line
if ($_SERVER['argv'][1] == $name)
{
$environment = $name;
break;
}
}
else
{
// Exact match
if ((preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $host)
&& $_SERVER['SERVER_ADDR'] == $host)
|| (isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == $host))
{
$environment = $name;
break;
}
// Fuzzy match
elseif (substr($host, 0, 1) == '/'
&& (preg_match($host, $_SERVER['SERVER_NAME'], $matches) > 0
|| preg_match($host, $_SERVER['HTTP_HOST'], $matches) > 0))
{
$environments[$name] = $matches[0];
$environment = $name;
$config['environments'][$name] = $matches[0];
break;
}
}
}
}
if (!$environment)
{
throw new \Exception('Unable to determine the environment.');
}
// Flattens the array based on the environment
$config = $this->flatten($environment, $config);
// Disables display errors in production
if ($environment == 'production')
{
ini_set('display_errors', false);
}
// Assigns the environment
$config['environment'] = $environment;
// Defaults expected Pickles variables to false
foreach (['cache', 'profiler'] as $variable)
{
if (!isset($config['pickles'][$variable]))
{
$config['pickles'][$variable] = false;
}
}
// Assigns the config variables to the object
foreach ($config as $variable => $value)
{
$this[$variable] = $value;
}
}
catch (\Exception $e)
{
throw $e;
}
}
/**
* Flatten
*
* Flattens the configuration array around the specified environment.
*
* @param string $environment selected environment
* @param array $array configuration error to flatten
* @return array flattened configuration array
*/
private function flatten($environment, $array)
{
if (is_array($array))
{
foreach ($array as $key => $value)
{
if (is_array($value))
{
if (isset($value[$environment]))
{
$value = $value[$environment];
}
else
{
$value = $this->flatten($environment, $value);
}
}
$array[$key] = $value;
}
}
return $array;
}
/**
* Get instance of the object
*
* Let's the parent class do all the work
*
* @static
* @param string $file name of config to load
* @return object self::$_instance instance of the Config class
*/
public static function getInstance($file = false)
{
if (!self::$_instance || $file)
{
self::$_instance = new Config($file);
}
return self::$_instance;
}
}