1: <?php
2:
3: namespace Alpha\Util\Config;
4:
5: use Alpha\Exception\IllegalArguementException;
6:
7: /**
8: * A singleton config class.
9: *
10: * @since 1.0
11: *
12: * @author John Collins <dev@alphaframework.org>
13: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
14: * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
15: * All rights reserved.
16: *
17: * <pre>
18: * Redistribution and use in source and binary forms, with or
19: * without modification, are permitted provided that the
20: * following conditions are met:
21: *
22: * * Redistributions of source code must retain the above
23: * copyright notice, this list of conditions and the
24: * following disclaimer.
25: * * Redistributions in binary form must reproduce the above
26: * copyright notice, this list of conditions and the
27: * following disclaimer in the documentation and/or other
28: * materials provided with the distribution.
29: * * Neither the name of the Alpha Framework nor the names
30: * of its contributors may be used to endorse or promote
31: * products derived from this software without specific
32: * prior written permission.
33: *
34: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
35: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
36: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
39: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47: * </pre>
48: */
49: class ConfigProvider
50: {
51: /**
52: * Array to store the config variables.
53: *
54: * @var array
55: *
56: * @since 1.0
57: */
58: private $configVars = array();
59:
60: /**
61: * The config object singleton.
62: *
63: * @var Alpha\Util\Config\ConfigProvider
64: *
65: * @since 1.0
66: */
67: private static $instance;
68:
69: /**
70: * The config environment (dev, pro, test).
71: *
72: * @var string
73: *
74: * @since 2.0
75: */
76: private $environment;
77:
78: /**
79: * Private constructor means the class cannot be instantiated from elsewhere.
80: *
81: * @since 1.0
82: */
83: private function __construct()
84: {}
85:
86: /**
87: * Get the config object instance.
88: *
89: * @return Alpha\Util\Config\ConfigProvider
90: *
91: * @since 1.0
92: */
93: public static function getInstance()
94: {
95: if (!isset(self::$instance)) {
96: self::$instance = new self();
97: self::$instance->setRootPath();
98:
99: // check to see if a child class with callbacks has been implemented
100: if (file_exists(self::$instance->get('rootPath').'config/ConfigCallbacks.inc')) {
101: require_once self::$instance->get('rootPath').'config/ConfigCallbacks.inc';
102:
103: self::$instance = new ConfigCallbacks();
104: self::$instance->setRootPath();
105: }
106:
107: // populate the config from the ini file
108: self::$instance->loadConfig();
109: }
110:
111: return self::$instance;
112: }
113:
114: /**
115: * Get config value.
116: *
117: * @param $key string
118: *
119: * @return string
120: *
121: * @throws Alpha\Exception\IllegalArguementException
122: *
123: * @since 1.0
124: */
125: public function get($key)
126: {
127: if (array_key_exists($key, $this->configVars)) {
128: return $this->configVars[$key];
129: } else {
130: throw new IllegalArguementException('The config property ['.$key.'] is not set in the .ini config file');
131: }
132: }
133:
134: /**
135: * Set config value.
136: *
137: * @param $key string
138: * @param $val string
139: *
140: * @since 1.0
141: */
142: public function set($key, $val)
143: {
144: /*
145: * If you need to alter a config option after it has been set in the .ini
146: * files, you can override this class and implement this callback method
147: */
148: if (method_exists($this, 'before_set_callback')) {
149: $val = $this->before_set_callback($key, $val, $this->configVars);
150: }
151:
152: $this->configVars[$key] = $val;
153: }
154:
155: /**
156: * Sets the root directory of the application.
157: *
158: * @since 1.0
159: */
160: private function setRootPath()
161: {
162: if (strpos(__DIR__, 'vendor/alphadevx/alpha/Alpha/Util/Config') !== false) {
163: $this->set('rootPath', str_replace('vendor/alphadevx/alpha/Alpha/Util/Config', '', __DIR__));
164: } else {
165: $this->set('rootPath', str_replace('Alpha/Util/Config', '', __DIR__));
166: }
167: }
168:
169: /**
170: * Reloads the config from the relevent .ini file, dependant upon the current
171: * environment (hostname).
172: *
173: * @since 2.0.1
174: */
175: public function reloadConfig()
176: {
177: $this->setRootPath();
178: $this->loadConfig();
179: }
180:
181: /**
182: * Loads the config from the relevent .ini file, dependant upon the current
183: * environment (hostname). Note that this method will die() on failure!
184: *
185: * @since 1.0
186: */
187: private function loadConfig()
188: {
189: $rootPath = $this->get('rootPath');
190:
191: // first we need to see if we are in dev, pro or test environment
192: if (isset($_SERVER['SERVER_NAME'])) {
193: $server = $_SERVER['SERVER_NAME'];
194: } elseif (isset($_ENV['HOSTNAME'])) {
195: // we may be running in CLI mode
196: $server = $_ENV['HOSTNAME'];
197: } elseif (php_uname('n') != '') {
198: // CLI on Linux or Windows should have this
199: $server = php_uname('n');
200: } else {
201: die('Unable to determine the server name');
202: }
203:
204: // Load the servers to see which environment the current server is set as
205: $serverIni = $rootPath.'config/servers.ini';
206:
207: if (file_exists($serverIni)) {
208: $envs = parse_ini_file($serverIni);
209: $environment = '';
210:
211: foreach ($envs as $env => $serversList) {
212: $servers = explode(',', $serversList);
213:
214: if (in_array($server, $servers)) {
215: $environment = $env;
216: }
217: }
218:
219: if ($environment == '') {
220: die('No environment configured for the server '.$server);
221: }
222: } else {
223: die('Failed to load the config file ['.$serverIni.']');
224: }
225:
226: $this->environment = $environment;
227:
228: if (mb_substr($environment, -3) == 'CLI') { // CLI mode
229: $envIni = $rootPath.'config/'.mb_substr($environment, 0, 3).'.ini';
230: } else {
231: $envIni = $rootPath.'config/'.$environment.'.ini';
232: }
233:
234: if (!file_exists($envIni)) {
235: die('Failed to load the config file ['.$envIni.']');
236: }
237:
238: $configArray = parse_ini_file($envIni);
239:
240: foreach (array_keys($configArray) as $key) {
241: $this->set($key, $configArray[$key]);
242: }
243: }
244:
245: /**
246: * Get the configuration environment for this application.
247: *
248: * @return string
249: *
250: * @since 2.0
251: */
252: public function getEnvironment()
253: {
254: return $this->environment;
255: }
256: }
257: