1: <?php
2: /**
3: * Wei Framework
4: *
5: * @copyright Copyright (c) 2008-2013 Twin Huang
6: * @license http://opensource.org/licenses/mit-license.php MIT License
7: */
8:
9: namespace Wei;
10:
11: /**
12: * A service to detect the environment name and load configuration by environment name
13: *
14: * The environment name detect order:
15: *
16: * user defined $name > $detector callback > $ipMap
17: *
18: * @author Twin Huang <twinhuang@qq.com>
19: */
20: class Env extends Base
21: {
22: /**
23: * The environment name
24: *
25: * @var string
26: */
27: protected $name;
28:
29: /**
30: * A callback to detect the environment name
31: *
32: * @var callable
33: */
34: protected $detector;
35:
36: /**
37: * An associative array contains server ip and environment name pairs
38: *
39: * @var array
40: */
41: protected $ipMap = array(
42: '127.0.0.1' => 'dev'
43: );
44:
45: /**
46: * The configuration file pattern
47: *
48: * @var string
49: */
50: protected $configFile = 'config/config-%env%.php';
51:
52: /**
53: * The server and execution environment parameters, equals to $_SERVER on default
54: *
55: * @var array
56: */
57: protected $server;
58:
59: /**
60: * Constructor
61: *
62: * @param array $options
63: */
64: public function __construct(array $options = array())
65: {
66: parent::__construct($options);
67:
68: if (!$this->server) {
69: $this->server = &$_SERVER;
70: }
71:
72: // Detect environment name if not set
73: if (!$this->name) {
74: $this->detectEnvName();
75: }
76:
77: // Load configuration by environment name
78: $this->loadConfigFile($this->configFile, $this->name);
79:
80: // Load CLI configuration when run in CLI mode
81: if (php_sapi_name() === 'cli') {
82: $this->loadConfigFile($this->configFile, 'cli');
83: }
84: }
85:
86: /**
87: * Returns the environment name
88: *
89: * @return string
90: */
91: public function __invoke()
92: {
93: return $this->name;
94: }
95:
96: /**
97: * Detect environment by server IP
98: */
99: public function detectEnvName()
100: {
101: // Return if env name is detected, or, or continue detecting by IP
102: if ($this->detector && $this->name = call_user_func($this->detector)) {
103: return;
104: }
105:
106: // Executes in web server, like Apache, Nginx
107: if (isset($this->server['SERVER_ADDR'])) {
108: $ip = $this->server['SERVER_ADDR'];
109: if (isset($this->ipMap[$ip])) {
110: $this->name = $this->ipMap[$ip];
111: } else {
112: $this->name = 'prod';
113: }
114: return;
115: }
116:
117: // Executes in CLI
118: if (php_sapi_name() == 'cli' && $ips = $this->getServerIps()) {
119: foreach ($ips as $ip) {
120: if (isset($this->ipMap[$ip])) {
121: $this->name = $this->ipMap[$ip];
122: return;
123: }
124: }
125: }
126:
127: $this->name = 'prod';
128: return;
129: }
130:
131: /**
132: * Check if in specified environment
133: *
134: * @param string $env
135: * @return bool
136: */
137: public function is($env)
138: {
139: return $this->name === $env;
140: }
141:
142: /**
143: * Check if in the development environment
144: *
145: * @return bool
146: */
147: public function isDev()
148: {
149: return $this->is('dev');
150: }
151:
152: /**
153: * Check if is the test environment
154: *
155: * @return bool
156: */
157: public function isTest()
158: {
159: return $this->is('test');
160: }
161:
162: /**
163: * Check if in the production environment
164: *
165: * @return bool
166: */
167: public function isProd()
168: {
169: return $this->is('prod');
170: }
171:
172: /**
173: * Returns the env string
174: *
175: * @return string
176: */
177: public function getName()
178: {
179: return $this->name;
180: }
181:
182: /**
183: * Set application environment name
184: *
185: * @param string $name
186: * @return $this
187: */
188: public function setName($name)
189: {
190: $this->name = $name;
191: return $this;
192: }
193:
194: /**
195: * Loads configs from specified file to service container
196: *
197: * @param string $file The config file path
198: * @param string $env The value to replace the %env% placeholder, default to the env name
199: * @return $this
200: */
201: public function loadConfigFile($file, $env = null)
202: {
203: $file = str_replace('%env%', $env ?: $this->name, $file);
204: if (is_file($file)) {
205: $config = (array)require $file;
206: $this->wei->setConfig($config);
207: }
208: return $this;
209: }
210:
211: /**
212: * Returns server IPs from `ifconfig` command line
213: *
214: * @return array
215: * @todo windows
216: */
217: protected function getServerIps()
218: {
219: // TODO check command result: command not found, Permission denied
220: preg_match_all('/eth(?:.+?)inet addr: ?([^ ]+)/s', `/sbin/ifconfig`, $ips);
221: return $ips[1];
222: }
223: }
224: