1
|
|
|
<?php /** Micro */ |
2
|
|
|
|
3
|
|
|
namespace Micro; |
4
|
|
|
|
5
|
|
|
use Micro\base\Autoload; |
6
|
|
|
use Micro\base\Container; |
7
|
|
|
use Micro\base\Dispatcher; |
8
|
|
|
use Micro\base\IContainer; |
9
|
|
|
use Micro\cli\DefaultConsoleCommand; |
10
|
|
|
use Micro\resolver\ConsoleResolver; |
11
|
|
|
use Micro\resolver\HMVCResolver; |
12
|
|
|
use Micro\web\IOutput; |
13
|
|
|
use Micro\web\IRequest; |
14
|
|
|
use Micro\web\Response; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Micro class file. |
18
|
|
|
* |
19
|
|
|
* Base class for initialize MicroPHP, used as bootstrap framework. |
20
|
|
|
* |
21
|
|
|
* @author Oleg Lunegov <[email protected]> |
22
|
|
|
* @link https://github.com/lugnsk/micro |
23
|
|
|
* @copyright Copyright © 2013 Oleg Lunegov |
24
|
|
|
* @license /LICENSE |
25
|
|
|
* @package micro |
26
|
|
|
* @version 1.0 |
27
|
|
|
* @since 1.0 |
28
|
|
|
*/ |
29
|
|
|
class Micro |
30
|
|
|
{ |
31
|
|
|
/** @const string VERSION Version framework */ |
32
|
|
|
const VERSION = '1.1'; |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
/** @var string $environment Application environment */ |
36
|
|
|
protected $environment = 'devel'; |
37
|
|
|
/** @var bool $debug Debug-mode flag */ |
38
|
|
|
protected $debug = true; |
39
|
|
|
/** @var float $startTime Time of start framework */ |
40
|
|
|
protected $startTime; |
41
|
|
|
/** @var bool $loaded Micro loaded flag */ |
42
|
|
|
protected $loaded; |
43
|
|
|
/** @var IContainer $container Container is a container for components and options */ |
44
|
|
|
protected $container; |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Initialize framework |
49
|
|
|
* |
50
|
|
|
* @access public |
51
|
|
|
* |
52
|
|
|
* @param string $environment Application environment: devel , prod , test |
53
|
|
|
* @param bool $debug Debug-mode flag |
54
|
|
|
* |
55
|
|
|
* @result void |
56
|
|
|
*/ |
57
|
|
View Code Duplication |
public function __construct($environment = 'devel', $debug = true) |
|
|
|
|
58
|
|
|
{ |
59
|
|
|
$this->environment = $environment; |
60
|
|
|
$this->debug = (bool)$debug; |
61
|
|
|
|
62
|
|
|
$this->loaded = false; |
63
|
|
|
|
64
|
|
|
if ($this->debug) { |
65
|
|
|
$this->startTime = microtime(true); |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Clone application |
71
|
|
|
* |
72
|
|
|
* @access public |
73
|
|
|
* |
74
|
|
|
* @return void |
75
|
|
|
*/ |
76
|
|
View Code Duplication |
public function __clone() |
|
|
|
|
77
|
|
|
{ |
78
|
|
|
if ($this->debug) { |
79
|
|
|
$this->startTime = microtime(true); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$this->loaded = false; |
83
|
|
|
$this->container = null; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Default config path |
88
|
|
|
* |
89
|
|
|
* @return string |
90
|
|
|
*/ |
91
|
|
|
protected function getConfig() |
92
|
|
|
{ |
93
|
|
|
return false; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Running application |
98
|
|
|
* |
99
|
|
|
* @access public |
100
|
|
|
* |
101
|
|
|
* @param IRequest $request Request object |
102
|
|
|
* @param string $configPath Path to config file |
|
|
|
|
103
|
|
|
* |
104
|
|
|
* @return Response |
105
|
|
|
* @throws \Exception |
106
|
|
|
*/ |
107
|
|
|
public function run(IRequest $request) |
108
|
|
|
{ |
109
|
|
|
if (!$this->loaded) { |
110
|
|
|
$this->loader(); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
$this->container->request = $request; |
|
|
|
|
114
|
|
|
|
115
|
|
|
try { |
116
|
|
|
return $this->doRun(); |
117
|
|
|
} catch (\Exception $e) { |
118
|
|
|
if ($this->debug) { |
119
|
|
|
$this->container->dispatcher->signal('kernel.stopped', ['exception' => $e]); |
|
|
|
|
120
|
|
|
throw $e; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
return $this->doException($e); |
|
|
|
|
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Boot Loader |
129
|
|
|
* |
130
|
|
|
* @access public |
131
|
|
|
* |
132
|
|
|
* @return void |
133
|
|
|
*/ |
134
|
|
|
public function loader() |
135
|
|
|
{ |
136
|
|
|
if (true === $this->loaded) { |
137
|
|
|
return; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
$this->initContainer(); |
141
|
|
|
|
142
|
|
|
$this->loaded = true; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Initialize container |
147
|
|
|
* |
148
|
|
|
* @access public |
149
|
|
|
* |
150
|
|
|
* @param string $configPath Path to configure Container |
|
|
|
|
151
|
|
|
* |
152
|
|
|
* @return void |
153
|
|
|
*/ |
154
|
|
|
public function initContainer() |
155
|
|
|
{ |
156
|
|
|
$this->container = new Container; |
157
|
|
|
$this->container->kernel = $this; |
158
|
|
|
|
159
|
|
|
$this->container->load($this->getConfig()); |
|
|
|
|
160
|
|
|
|
161
|
|
|
if (false === $this->container->dispatcher) { |
162
|
|
|
$this->container->dispatcher = new Dispatcher($this->container); |
|
|
|
|
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Starting ... |
168
|
|
|
* |
169
|
|
|
* @access public |
170
|
|
|
* |
171
|
|
|
* @return \Micro\web\IResponse |
172
|
|
|
* @throws \Micro\base\Exception |
173
|
|
|
*/ |
174
|
|
|
private function doRun() |
175
|
|
|
{ |
176
|
|
|
$resolver = $this->getResolver(); |
177
|
|
|
$this->container->dispatcher->signal('kernel.router', ['resolver' => $resolver]); |
|
|
|
|
178
|
|
|
|
179
|
|
|
$app = $resolver->getApplication(); |
180
|
|
|
$this->container->dispatcher->signal('kernel.controller', ['application' => $app]); |
|
|
|
|
181
|
|
|
|
182
|
|
|
$output = $app->action($resolver->getAction()); |
183
|
|
|
if (!$output instanceof IOutput) { |
184
|
|
|
$response = $this->container->response ?: new Response; |
|
|
|
|
185
|
|
|
$response->setBody($output); |
186
|
|
|
$output = $response; |
187
|
|
|
} |
188
|
|
|
$this->container->dispatcher->signal('kernel.response', ['output' => $output]); |
|
|
|
|
189
|
|
|
|
190
|
|
|
return $output; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Get resolver |
195
|
|
|
* |
196
|
|
|
* @access public |
197
|
|
|
* |
198
|
|
|
* @param bool|false $isCli CLI or Web |
|
|
|
|
199
|
|
|
* |
200
|
|
|
* @return ConsoleResolver|HMVCResolver |
201
|
|
|
*/ |
202
|
|
|
public function getResolver() |
203
|
|
|
{ |
204
|
|
|
if ($this->container->request->isCli()) { |
|
|
|
|
205
|
|
|
return new ConsoleResolver($this->container); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
return new HMVCResolver($this->container); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
// Methods for components |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Do exception |
215
|
|
|
* |
216
|
|
|
* @access private |
217
|
|
|
* |
218
|
|
|
* @param \Exception $e Exception |
219
|
|
|
* |
220
|
|
|
* @return IOutput |
221
|
|
|
* @throws \Micro\base\Exception |
222
|
|
|
*/ |
223
|
|
|
private function doException(\Exception $e) |
224
|
|
|
{ |
225
|
|
|
$this->container->dispatcher->signal('kernel.exception', ['exception' => $e]); |
|
|
|
|
226
|
|
|
|
227
|
|
|
$output = $this->container->request->isCli() ? new DefaultConsoleCommand([]) : new Response(); |
|
|
|
|
228
|
|
|
|
229
|
|
|
if ($this->container->request->isCli()) { |
|
|
|
|
230
|
|
|
$output->data = '"Error #' . $e->getCode() . ' - ' . $e->getMessage() . '"'; |
231
|
|
|
$output->execute(); |
|
|
|
|
232
|
|
|
|
233
|
|
|
return $output; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
if (!$this->container->errorController) { |
|
|
|
|
237
|
|
|
$output->setBody('Option `errorController` not configured'); |
238
|
|
|
|
239
|
|
|
return $output; |
240
|
|
|
} |
241
|
|
|
if (!$this->container->errorAction) { |
|
|
|
|
242
|
|
|
$output->setBody('Option `errorAction` not configured'); |
243
|
|
|
|
244
|
|
|
return $output; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
$controller = $this->container->errorController; |
|
|
|
|
248
|
|
|
$action = $this->container->errorAction; |
|
|
|
|
249
|
|
|
|
250
|
|
|
$this->container->request->setPost('error', $e); |
|
|
|
|
251
|
|
|
|
252
|
|
|
/** @var \Micro\mvc\controllers\IController $result */ |
253
|
|
|
$result = new $controller($this->container, false); |
254
|
|
|
$result = $result->action($action); |
255
|
|
|
|
256
|
|
|
if ($result instanceof IOutput) { |
257
|
|
|
return $result; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
$output->setBody($result); |
|
|
|
|
261
|
|
|
|
262
|
|
|
return $output; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Terminate application |
267
|
|
|
* |
268
|
|
|
* @access public |
269
|
|
|
* |
270
|
|
|
* @return void |
271
|
|
|
*/ |
272
|
|
|
public function terminate() |
273
|
|
|
{ |
274
|
|
|
$this->container->dispatcher->signal('kernel.terminate', []); |
|
|
|
|
275
|
|
|
|
276
|
|
|
if ($this->isDebug() && !$this->container->request->isCli()) { |
|
|
|
|
277
|
|
|
// Add timer into page |
278
|
|
|
echo '<div class=debug_timer>', (microtime(true) - $this->getStartTime()), '</div>'; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
$this->unloader(); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Get start time |
286
|
|
|
* |
287
|
|
|
* @access public |
288
|
|
|
* |
289
|
|
|
* @return float|null |
290
|
|
|
*/ |
291
|
|
|
public function getStartTime() |
292
|
|
|
{ |
293
|
|
|
return $this->isDebug() ? $this->startTime : null; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Unloader subsystem |
298
|
|
|
* |
299
|
|
|
* @access public |
300
|
|
|
* |
301
|
|
|
* @return void |
302
|
|
|
*/ |
303
|
|
|
public function unloader() |
304
|
|
|
{ |
305
|
|
|
if (false === $this->loaded) { |
306
|
|
|
return; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
$this->container = null; |
310
|
|
|
$this->loaded = false; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
// Methods helpers |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Get status of debug |
317
|
|
|
* |
318
|
|
|
* @access public |
319
|
|
|
* |
320
|
|
|
* @return bool |
321
|
|
|
*/ |
322
|
|
|
public function isDebug() |
323
|
|
|
{ |
324
|
|
|
return $this->debug; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Get character set |
329
|
|
|
* |
330
|
|
|
* @access public |
331
|
|
|
* |
332
|
|
|
* @return string |
333
|
|
|
*/ |
334
|
|
|
public function getCharset() |
335
|
|
|
{ |
336
|
|
|
return 'UTF-8'; |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* Get environment name |
341
|
|
|
* |
342
|
|
|
* @access public |
343
|
|
|
* |
344
|
|
|
* @return string |
345
|
|
|
*/ |
346
|
|
|
public function getEnvironment() |
347
|
|
|
{ |
348
|
|
|
return $this->environment; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* Get components container |
353
|
|
|
* |
354
|
|
|
* @access public |
355
|
|
|
* |
356
|
|
|
* @return IContainer |
357
|
|
|
*/ |
358
|
|
|
public function getContainer() |
359
|
|
|
{ |
360
|
|
|
return $this->container; |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
public function getAppDir() |
364
|
|
|
{ |
365
|
|
|
return Autoload::getAlias('App')[0]; |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.