/
Configuration.php
139 lines (117 loc) · 3.88 KB
/
Configuration.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php
namespace Bart\Configuration;
use Bart\Diesel;
/**
* Configuration base. All configuration classes must extend this.
* All children are required to define a README method which can be used
* to see how each class expects its conf files to look.
*/
abstract class Configuration
{
private static $path = null;
private static $configCache = array();
/** @var array */
protected $configurations;
/**
* @return string Sample of how configuration is intended to be defined
*/
public abstract function README();
/**
* @param string $path Root path to all configuration
* @throws ConfigurationException If already configured
*/
public static function configure($path)
{
if (self::$path) {
// If this becomes innapppropriate, it can be lifted
// It feels apppropriate based on my current understanding of use cases
throw new ConfigurationException('Cannot reconfigure configuration path. Already set to ' . self::$path);
}
self::$path = $path;
}
public function __construct()
{
$this->load();
}
/**
* @param string $section
* @param string $key
* @param mixed $default If not required, the default to use
* @param bool $required If an exception should be raised when value is missing
* @return mixed Configured value or default
* @throws ConfigurationException
*/
protected function getValue($section, $key, $default = null, $required = true)
{
if (array_key_exists($section, $this->configurations)) {
$sectionValues = $this->configurations[$section];
if (array_key_exists($key, $sectionValues)) {
return $sectionValues[$key];
}
}
// Complain when the value is required and no default passed
// ...Provides path for non-required when the default is literally null
if ($default === null && $required) {
throw new ConfigurationException("No value set for required ${section}.${key}");
}
return $default;
}
/**
* http://stackoverflow.com/questions/12650802/php-equivalent-of-javascripts-parseint-function
*/
protected function getNumeric($section, $key, $default = null, $required = true)
{
$rawVal = $this->getValue($section, $key, $default, $required);
if (ctype_digit($rawVal)) {
return intval($rawVal);
}
if (is_numeric($rawVal)) {
return $rawVal;
}
throw new ConfigurationTypeConversionException("Non-numeric provided for ${section}.${key}");
}
/**
* Load the configurations from the config file for subclass
* @return array The parsed array from the configuration file
*/
private function load()
{
if (!self::$path) {
throw new ConfigurationException('Configuration root path not set! Please call configure()');
}
$subclass = get_called_class();
// Strip off namespace
$subclass = substr($subclass, strrpos($subclass, '\\') + 1);
// Strip off "Config"
$subclass = substr($subclass, 0, -1 * strlen('Config'));
// Chop any trailing underscore for non-camel cased names
$name = strtolower(chop($subclass, '_'));
$filePath = self::$path . "/$name.conf";
if (!array_key_exists($filePath, self::$configCache)) {
self::$configCache[$filePath] = $this->loadConfigurationsFromDisk($filePath, $subclass);
}
$this->configurations = self::$configCache[$filePath];
}
/**
* @return array
* @throws ConfigurationException
*/
private function loadConfigurationsFromDisk($filePath, $subclass)
{
/** @var \Bart\Shell $shell */
$shell = Diesel::create('\Bart\Shell');
if (!$shell->file_exists($filePath)) {
throw new ConfigurationException("No configuration file found for $subclass at $filePath");
}
// @NOTE we're not using the ConfigResolver to resolve environment
// ...distinctions by default. To add this ability, a new method should
// ...be added to this base to resolve and then reset @configurations
return $shell->parse_ini_file($filePath, true);
}
}
class ConfigurationException extends \Exception
{
}
class ConfigurationTypeConversionException extends \Exception
{
}