Skip to content
Newer
Older
100644 341 lines (325 sloc) 13.7 KB
e7f3c31 @gwoo going lithium
gwoo authored Oct 12, 2009
1 <?php
2 /**
3 * Lithium: the most rad php framework
4 *
14de7bf @gwoo Happy 2012!
gwoo authored Jan 2, 2012
5 * @copyright Copyright 2012, Union of RAD (http://union-of-rad.org)
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
6 * @license http://opensource.org/licenses/bsd-license.php The BSD License
7 */
8
9 namespace lithium\core;
10
6fb3f64 @daschl change _use lithium_ commands and remove the prefixed slash
daschl authored Nov 16, 2010
11 use lithium\util\Set;
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
12
f4dd741 @alkemann added @package to action, core and data classes
alkemann authored Oct 30, 2009
13 /**
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
14 * The `Environment` class allows you to manage multiple configurations for your application,
15 * depending on the context within which it is running, i.e. development, test or production.
f4dd741 @alkemann added @package to action, core and data classes
alkemann authored Oct 30, 2009
16 *
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
17 * While those three environments are the most common, you can create any arbitrary environment
18 * with any set of configuration, for example:
19 *
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Jan 31, 2010
20 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(1-3)}}}
21 *
22 * You can then retrieve the configurations using the key name. The correct configuration is
23 * returned, automatically accounting for the current environment:
24 *
25 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(15-15)}}}
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
26 *
27 * `Environment` also works with subclasses of `Adaptable`, allowing you to maintain separate
28 * configurations for database servers, cache adapters, and other environment-specific classes, for
29 * example:
30 * {{{
31 * Connections::add('default', array(
32 * 'production' => array(
33 * 'type' => 'database',
34 * 'adapter' => 'MySql',
35 * 'host' => 'db1.application.local',
36 * 'login' => 'secure',
37 * 'password' => 'secret',
38 * 'database' => 'app-production'
39 * ),
40 * 'development' => array(
41 * 'type' => 'database',
42 * 'adapter' => 'MySql',
43 * 'host' => 'localhost',
44 * 'login' => 'root',
45 * 'password' => '',
46 * 'database' => 'app'
47 * )
48 * ));
49 * }}}
50 *
51 * This allows the database connection named `'default'` to be connected to a local database in
52 * development, and a production database in production. You can define environment-specific
53 * configurations for caching, logging, even session storage, i.e.:
54 * {{{
55 * Cache::config(array(
56 * 'userData' => array(
57 * 'development' => array('adapter' => 'File'),
58 * 'production' => array('adapter' => 'Memcache')
59 * )
60 * ));
61 * }}}
62 *
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
63 * When the cache configuration is accessed in the application's code, the correct configuration is
64 * automatically used:
65 * {{{
66 * $user = User::find($request->id);
67 * Cache::write('userData', "User.{$request->id}", $user->data(), '+5 days');
68 * }}}
69 *
70 * In this configuration, the above example will automatically send cache writes to the file system
71 * during local development, and to a [ memcache](http://memcached.org/) server in production.
72 *
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
73 * When writing classes that connect to other external resources, you can automatically take
74 * advantage of environment-specific configurations by extending `Adaptable` and implementing
75 * your resource-handling functionality in adapter classes.
76 *
77 * In addition to managing your environment-specific configurations, `Environment` will also help
78 * you by automatically detecting which environment your application is running in. For additional
79 * information, see the documentation for `Environment::is()`.
80 *
81 * @see lithium\core\Adaptable
f4dd741 @alkemann added @package to action, core and data classes
alkemann authored Oct 30, 2009
82 */
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
83 class Environment {
84
85 protected static $_configurations = array(
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
86 'production' => array(),
87 'development' => array(),
88 'test' => array()
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
89 );
90
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
91 /**
92 * Holds the name of the current environment under which the application is running. Set by
93 * passing a `Request` object or `$_SERVER` or `$_ENV` array into `Environment::set()` (which
94 * in turn passes this on to the _detector_ used to determine the correct environment). Can be
95 * tested or retrieved using `Environment::is()` or `Environment::get()`.
96 *
97 * @see lithium\correct\Environment::set()
98 * @see lithium\correct\Environment::is()
99 * @see lithium\correct\Environment::get()
100 * @var string
101 */
102 protected static $_current = '';
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
103
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
104 /**
105 * If `Environment::is()` is used to assign a custom closure for environment detection, a copy
106 * is kept in `$_detector`. Otherwise, `$_detector` is `null`, and the hard-coded detector is
107 * used.
108 *
109 * @see lithium\core\Environment::_detector()
110 * @see lithium\core\Environment::is()
111 * @var object
112 */
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
113 protected static $_detector = null;
114
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
115 /**
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
116 * Resets the `Environment` class to its default state, including unsetting the current
117 * environment, removing any environment-specific configurations, and removing the custom
118 * environment detector, if any has been specified.
119 *
120 * @return void
121 */
122 public static function reset() {
123 static::$_current = '';
124 static::$_detector = null;
125 static::$_configurations = array(
126 'production' => array(),
127 'development' => array(),
128 'test' => array()
129 );
130 }
131
132 /**
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
133 * A simple boolean detector that can be used to test which environment the application is
134 * running under. For example `Environment::is('development')` will return `true` if
135 * `'development'` is, in fact, the current environment.
136 *
137 * This method also handles how the environment is detected at the beginning of the request.
7b422f4 @nateabele Implementing host mapping in `\core\Environment::is()`.
nateabele authored Sep 12, 2012
138 *
139 * #### Custom Detection
140 *
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
141 * While the default detection rules are very simple (if the `'SERVER_ADDR'` variable is set to
142 * `127.0.0.1`, the environment is assumed to be `'development'`, or if the string `'test'` is
143 * found anywhere in the host name, it is assumed to be `'test'`, and in all other cases it
144 * is assumed to be `'production'`), you can define your own detection rule set easily using a
145 * closure that accepts an instance of the `Request` object, and returns the name of the correct
146 * environment, as in the following example:
7b422f4 @nateabele Implementing host mapping in `\core\Environment::is()`.
nateabele authored Sep 12, 2012
147 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testCustomDetector(1-9) }}}
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
148 *
149 * In the above example, the user-specified closure takes in a `Request` object, and using the
150 * server data which it encapsulates, returns the correct environment name as a string.
151 *
7b422f4 @nateabele Implementing host mapping in `\core\Environment::is()`.
nateabele authored Sep 12, 2012
152 * #### Host Mapping
153 *
154 * The most common use case is to set the environment depending on host name. For convenience,
155 * the `is()` method also accepts an array that matches host names to environment names, where
156 * each key is an environment, and each value is either an array of valid host names, or a
157 * regular expression used to match a valid host name.
158 *
159 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testDetectionWithArrayMap(1-5) }}}
160 *
161 * In this example, a regular expression is being used to match local domains
162 * (i.e. `localhost`), as well as the built-in `.console` domain, for console requests. Note
163 * that in the console, the environment can always be overridden by specifying the `--env`
164 * option.
165 *
166 * Then, one or more host names are matched up to `'test'` and `'staging'`, respectively. Note
167 * that no rule is present for production: this is because `'production'` is the default value
168 * if no other environment matches.
169 *
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
170 * @param mixed $detect Either the name of an environment to check against the current, i.e.
171 * `'development'` or `'production'`, or a closure which `Environment` will use
7b422f4 @nateabele Implementing host mapping in `\core\Environment::is()`.
nateabele authored Sep 12, 2012
172 * to determine the current environment name, or an array mapping environment names
173 * to host names.
4c10d97 @nateabele Adding documentation and small refactoring to `core\Environment`.
nateabele authored Jan 31, 2010
174 * @return boolean If `$detect` is a string, returns `true` if the current environment matches
175 * the value of `$detect`, or `false` if no match. If used to set a custom detector,
176 * returns `null`.
177 */
178 public static function is($detect) {
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
179 if (is_callable($detect)) {
180 static::$_detector = $detect;
181 }
7b422f4 @nateabele Implementing host mapping in `\core\Environment::is()`.
nateabele authored Sep 12, 2012
182 if (!is_array($detect)) {
183 return (static::$_current == $detect);
184 }
185 static::$_detector = function($request) use ($detect) {
186 if ($request->env || $request->command == 'test') {
187 return ($request->env) ? $request->env : 'test';
188 }
189 $host = method_exists($request, 'get') ? $request->get('http:host') : '.console';
190
191 foreach ($detect as $environment => $hosts) {
192 if (is_string($hosts) && preg_match($hosts, $host)) {
193 return $environment;
194 }
195 if (is_array($hosts) && in_array($host, $hosts)) {
196 return $environment;
197 }
198 }
199 return "production";
200 };
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
201 }
202
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
203 /**
204 * Gets the current environment name, a setting associated with the current environment, or the
205 * entire configuration array for the current environment.
206 *
207 * @param string $name The name of the environment setting to retrieve, or the name of an
208 * environment, if that environment's entire configuration is to be retrieved. If
209 * retrieving the current environment name, `$name` should not be passed.
210 * @return mixed If `$name` is unspecified, returns the name of the current environment name as
211 * a string (i.e. `'production'`). If an environment name is specified, returns that
212 * environment's entire configuration as an array.
213 */
214 public static function get($name = null) {
a90a34d @nateabele Adding semantics in `\core\Environment` for automatically using the c…
nateabele authored Apr 30, 2010
215 $cur = static::$_current;
216
217 if (!$name) {
218 return $cur;
219 }
220 if ($name === true) {
221 return isset(static::$_configurations[$cur]) ? static::$_configurations[$cur] : null;
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
222 }
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
223 if (isset(static::$_configurations[$name])) {
bed760f @Howard3 Environment: Added dot path fetching for Environment::get, this utili…
Howard3 authored Apr 25, 2011
224 return static::_processDotPath($name, static::$_configurations);
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
225 }
bed760f @Howard3 Environment: Added dot path fetching for Environment::get, this utili…
Howard3 authored Apr 26, 2011
226 if (!isset(static::$_configurations[$cur])) {
227 return static::_processDotPath($name, static::$_configurations);
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
228 }
a90a34d @nateabele Adding semantics in `\core\Environment` for automatically using the c…
nateabele authored Apr 30, 2010
229
bed760f @Howard3 Environment: Added dot path fetching for Environment::get, this utili…
Howard3 authored Apr 26, 2011
230 return static::_processDotPath($name, static::$_configurations[$cur]);
231 }
232
233 protected static function _processDotPath($path, &$arrayPointer) {
234 if (isset($arrayPointer[$path])) {
235 return $arrayPointer[$path];
236 }
237 if (strpos($path, '.') === false) {
238 return null;
239 }
240 $pathKeys = explode('.', $path);
241 foreach ($pathKeys as $pathKey) {
82e831e @davidpersson Correcting spacing and whitespace.
davidpersson authored Jun 17, 2011
242 if (!isset($arrayPointer[$pathKey])) {
bed760f @Howard3 Environment: Added dot path fetching for Environment::get, this utili…
Howard3 authored Apr 26, 2011
243 return false;
244 }
245 $arrayPointer = &$arrayPointer[$pathKey];
246 }
247 return $arrayPointer;
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
248 }
249
250 /**
e8b36b8 @nateabele Adding documentation to `core\Environment`, fixing issue in `Environm…
nateabele authored Feb 1, 2010
251 * Creates, modifies or switches to an existing environment configuration. To create a new
252 * configuration, or to update an existing configuration, pass an environment name and an array
253 * that defines its configuration:
254 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(1-1) }}}
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
255 *
e8b36b8 @nateabele Adding documentation to `core\Environment`, fixing issue in `Environm…
nateabele authored Feb 1, 2010
256 * You can then add to an existing configuration by calling the `set()` method again with the
257 * same environment name:
258 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(6-6) }}}
259 *
260 * The settings for the environment will then be the aggregate of all `set()` calls:
261 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testModifyEnvironmentConfig(7-7) }}}
262 *
263 * The `set()` method can also be called to manually set which environment to operate in:
264 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testSetAndGetCurrentEnvironment(5-5) }}}
265 *
266 * Finally, `set()` can accept a `Request` object, or the `$_SERVER` or `$_ENV` superglobals, to
267 * automatically detect the correct environment.
268 *
269 * {{{ embed:lithium\tests\cases\core\EnvironmentTest::testEnvironmentDetection(9-10) }}}
270 *
271 * For more information on defining custom rules to automatically detect your application's
272 * environment, see the documentation for `Environment::is()`.
273 *
274 * @see lithium\http\Request
275 * @see lithium\core\Environment::is()
276 * @param mixed $env The name of the environment you wish to create, update or switch to
277 * (string), or a `Request` object or `$_SERVER` / `$_ENV` array used to detect
278 * (and switch to) the application's current environment.
279 * @param array $config If creating or updating a configuration, accepts an array of settings.
280 * If the environment name specified in `$env` already exists, the values in
281 * `$config` will be recursively merged with any pre-existing settings.
282 * @return array If creating or updating a configuration, returns an array of the environment's
283 * settings. If updating an existing configuration, this will be the newly-applied
284 * configuration merged with the pre-existing values. If setting the environment
285 * itself (i.e. `$config` is unspecified), returns `null`.
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
286 */
287 public static function set($env, $config = null) {
288 if (is_null($config)) {
6e0ab9c @davidpersson QA: Updating control structures for correct spacing.
davidpersson authored Mar 23, 2011
289 switch (true) {
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
290 case is_object($env) || is_array($env):
291 static::$_current = static::_detector()->__invoke($env);
292 break;
293 case isset(static::$_configurations[$env]):
294 static::$_current = $env;
295 break;
296 }
297 return;
298 }
a90a34d @nateabele Adding semantics in `\core\Environment` for automatically using the c…
nateabele authored Apr 30, 2010
299 $env = ($env === true) ? static::$_current : $env;
e8b36b8 @nateabele Adding documentation to `core\Environment`, fixing issue in `Environm…
nateabele authored Feb 1, 2010
300 $base = isset(static::$_configurations[$env]) ? static::$_configurations[$env] : array();
301 return static::$_configurations[$env] = Set::merge($base, $config);
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
302 }
303
45d74c1 @nateabele Adding documentation to `core\Environment`, refactoring `Environment:…
nateabele authored Feb 1, 2010
304 /**
305 * Accessor method for `Environment::$_detector`. If `$_detector` is unset, returns the default
306 * detector built into the class. For more information on setting and using `$_detector`, see
307 * the documentation for `Environment::is()`. The `_detector()` method is called at the
308 * beginning of the application's life-cycle, when `Environment::set()` is passed either an
309 * instance of a `Request` object, or the `$_SERVER` or `$_ENV` array. This object (or array)
310 * is then passed onto `$_detector`, which returns the correct environment.
311 *
312 * @see lithium\core\Environment::is()
313 * @see lithium\core\Environment::set()
314 * @see lithium\core\Environment::$_detector
315 * @return object Returns a callable object (anonymous function) which detects the application's
316 * current environment.
317 */
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
318 protected static function _detector() {
319 return static::$_detector ?: function($request) {
49080ac @mackstar Removed duplication and line length offensive code
mackstar authored Jul 27, 2011
320 $isLocal = in_array($request->env('SERVER_ADDR'), array('::1', '127.0.0.1'));
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
321 switch (true) {
f12057f @gwoo changing environment check for CLI.
gwoo authored Oct 15, 2011
322 case (isset($request->env)):
323 return $request->env;
324 case ($request->command == 'test'):
427ee64 @mackstar Added environment recognition for the console
mackstar authored Aug 3, 2011
325 return 'test';
d41ee98 @davidpersson Adding `'PLATFORM'` environment variable to console request.
davidpersson authored May 8, 2012
326 case ($request->env('PLATFORM') == 'CLI'):
427ee64 @mackstar Added environment recognition for the console
mackstar authored Aug 3, 2011
327 return 'development';
49080ac @mackstar Removed duplication and line length offensive code
mackstar authored Jul 27, 2011
328 case (preg_match('/^test\//', $request->url) && $isLocal):
cd0f9dc @mackstar Added a default detector for routes beginning with /test
mackstar authored Jul 25, 2011
329 return 'test';
49080ac @mackstar Removed duplication and line length offensive code
mackstar authored Jul 27, 2011
330 case ($isLocal):
e7f3c31 @gwoo going lithium
gwoo authored Oct 13, 2009
331 return 'development';
332 case (preg_match('/^test/', $request->env('HTTP_HOST'))):
333 return 'test';
334 default:
335 return 'production';
336 }
337 };
338 }
339 }
340
341 ?>
Something went wrong with that request. Please try again.