Completed
Push — master ( 579af5...b29473 )
by Oleg
07:53
created

micro/Micro.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 &copy; 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 string $appDir Application directory */
38
    protected $appDir;
39
    /** @var string $microDir Micro directory */
40
    protected $microDir;
41
    /** @var string $webDir Document root */
42
    protected $webDir;
43
    /** @var bool $debug Debug-mode flag */
44
    protected $debug = true;
45
    /** @var float $startTime Time of start framework */
46
    protected $startTime;
47
    /** @var bool $loaded Micro loaded flag */
48
    protected $loaded;
49
    /** @var IContainer $container Container is a container for components and options */
50
    protected $container;
51
52
53
    /**
54
     * Initialize framework
55
     *
56
     * @access public
57
     *
58
     * @param string $appDir Application directory
59
     * @param string $microDir Micro directory
60
     * @param string $environment Application environment: devel , prod , test
61
     * @param bool $debug Debug-mode flag
62
     * @param bool $registerLoader Register default autoloader
63
     *
64
     * @result void
65
     */
66
    public function __construct($appDir, $microDir, $environment = 'devel', $debug = true, $registerLoader = true)
67
    {
68
        $this->appDir = realpath($appDir);
69
        $this->microDir = realpath($microDir);
70
        $this->webDir = getenv('DOCUMENT_ROOT');
71
        $this->environment = $environment;
72
        $this->debug = (bool)$debug;
73
        $this->loaded = false;
74
75
        if ($this->debug) {
76
            $this->startTime = microtime(true);
77
        }
78
79
        if (!$registerLoader) {
80
            return;
81
        }
82
83
        $this->registerAutoload([
84
            'filename' => $this->getMicroDir() . '/base/Autoload.php',
85
            'callable' => ['\Micro\base\Autoload', 'loader']
86
        ]);
87
88
        Autoload::setAlias('Micro', $this->getMicroDir());
89
        Autoload::setAlias('App', $this->getAppDir());
90
    }
91
92
    /**
93
     * Register autoload from config array
94
     *
95
     * Config format ['filename'=>'' , 'callable'=>'' , 'throw'=>'' , 'prepend'=>''];
96
     *
97
     * @access public
98
     *
99
     * @param array $config Config array
100
     *
101
     * @return bool
102
     */
103
    public function registerAutoload(array $config)
104
    {
105
        if (empty($config['filename']) || !file_exists($config['filename'])) {
106
            return false;
107
        }
108
109
        $config = array_merge([
110
            'filename' => '/autoload.php',
111
            'callable' => '',
112
            'throw' => true,
113
            'prepend' => false
114
        ], $config);
115
116
        if (empty($config['callable']) || !file_exists($config['filename'])) {
117
            return false;
118
        }
119
120
        /** @noinspection PhpIncludeInspection */
121
        require $config['filename'];
122
        spl_autoload_register($config['callable'], (bool)$config['throw'], (bool)$config['prepend']);
123
124
        return true;
125
    }
126
127
    /**
128
     * Git Micro dir
129
     *
130
     * @access public
131
     *
132
     * @return string
133
     */
134
    public function getMicroDir()
135
    {
136
        return $this->microDir;
137
    }
138
139
    /**
140
     * Get application dir
141
     *
142
     * @access public
143
     *
144
     * @return string
145
     */
146
    public function getAppDir()
147
    {
148
        return $this->appDir;
149
    }
150
151
    /**
152
     * Clone application
153
     *
154
     * @access public
155
     *
156
     * @return void
157
     */
158
    public function __clone()
159
    {
160
        if ($this->debug) {
161
            $this->startTime = microtime(true);
162
        }
163
164
        $this->loaded = false;
165
        $this->container = null;
166
    }
167
168
    /**
169
     * Running application
170
     *
171
     * @access public
172
     *
173
     * @param IRequest $request Request object
174
     * @param string $configPath Path to config file
175
     *
176
     * @return Response
177
     * @throws \Exception
178
     */
179
    public function run(IRequest $request, $configPath = '/configs/index.php')
180
    {
181
        if (!$this->loaded) {
182
            $this->loader($configPath);
183
        }
184
        $this->container->request = $request;
185
186
        try {
187
            return $this->doRun();
188
        } catch (\Exception $e) {
189
            if ($this->debug) {
190
                $this->container->dispatcher->signal('kernel.stopped', ['exception' => $e]);
191
                throw $e;
192
            }
193
194
            return $this->doException($e);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doException($e); of type Micro\cli\DefaultConsoleCommand|Micro\web\Response adds the type Micro\cli\DefaultConsoleCommand to the return on line 194 which is incompatible with the return type documented by Micro\Micro::run of type Micro\web\Response.
Loading history...
195
        }
196
    }
197
198
    /**
199
     * Boot Loader
200
     *
201
     * @access public
202
     *
203
     * @param string $configPath Path to configure Container
204
     *
205
     * @return void
206
     */
207
    public function loader($configPath = '/configs/index.php')
208
    {
209
        if (true === $this->loaded) {
210
            return;
211
        }
212
213
        $this->initContainer($configPath);
214
215
        $this->loaded = true;
216
    }
217
218
    /**
219
     * Initialize container
220
     *
221
     * @access public
222
     *
223
     * @param string $configPath Path to configure Container
224
     *
225
     * @return void
226
     */
227
    public function initContainer($configPath)
228
    {
229
        $this->container = new Container;
230
        $this->container->kernel = $this;
231
232
        $this->container->load($configPath);
233
234
        if (false === $this->container->dispatcher) {
235
            $this->container->dispatcher = new Dispatcher($this->container);
236
        }
237
    }
238
239
    /**
240
     * Starting ...
241
     *
242
     * @access public
243
     *
244
     * @return \Micro\web\IResponse
245
     * @throws \Micro\base\Exception
246
     */
247
    private function doRun()
248
    {
249
        $resolver = $this->getResolver($this->container->request->isCli());
250
        $this->container->dispatcher->signal('kernel.router', ['resolver' => $resolver]);
251
252
        $app = $resolver->getApplication();
253
        $this->container->dispatcher->signal('kernel.controller', ['application' => $app]);
254
255
        $output = $app->action($resolver->getAction());
256
        if (!$output instanceof IOutput) {
257
            $response = $this->container->response ?: new Response;
258
            $response->setBody($output);
259
            $output = $response;
260
        }
261
        $this->container->dispatcher->signal('kernel.response', ['output' => $output]);
262
263
        return $output;
264
    }
265
266
    /**
267
     * Get resolver
268
     *
269
     * @access public
270
     *
271
     * @param bool|false $isCli CLI or Web
272
     *
273
     * @return ConsoleResolver|HMVCResolver
274
     */
275
    public function getResolver($isCli = false)
276
    {
277
        if ($isCli) {
278
            return new ConsoleResolver($this->container);
279
        }
280
281
        return new HMVCResolver($this->container);
282
    }
283
284
    // Methods for components
285
286
    /**
287
     * Do exception
288
     *
289
     * @access private
290
     *
291
     * @param \Exception $e Exception
292
     *
293
     * @return IOutput
294
     * @throws \Micro\base\Exception
295
     */
296
    private function doException(\Exception $e)
297
    {
298
        $this->container->dispatcher->signal('kernel.exception', ['exception' => $e]);
299
300
        $output = $this->container->request->isCli() ? new DefaultConsoleCommand([]) : new Response();
301
302
        if (php_sapi_name() === 'cli') {
303
            $output->data = '"Error #' . $e->getCode() . ' - ' . $e->getMessage() . '"';
304
            $output->execute();
305
306
            return $output;
307
        }
308
309
        if (!$this->container->errorController) {
310
            $output->setBody('Option `errorController` not configured');
311
312
            return $output;
313
        }
314
        if (!$this->container->errorAction) {
315
            $output->setBody('Option `errorAction` not configured');
316
317
            return $output;
318
        }
319
320
        $controller = $this->container->errorController;
321
        $action = $this->container->errorAction;
322
323
        $this->container->request->setPost('error', $e);
324
325
        /** @var \Micro\mvc\controllers\IController $result */
326
        $result = new $controller($this->container, false);
327
        $result = $result->action($action);
328
329
        if ($result instanceof IOutput) {
330
            return $result;
331
        }
332
333
        $output->setBody($result);
334
335
        return $output;
336
    }
337
338
    /**
339
     * Terminate application
340
     *
341
     * @access public
342
     *
343
     * @return void
344
     */
345
    public function terminate()
346
    {
347
        $this->container->dispatcher->signal('kernel.terminate', []);
348
349
        if ($this->debug && !$this->container->request->isCli()) {
350
            // Add timer into page
351
            echo '<div class=debug_timer>', (microtime(true) - $this->getStartTime()), '</div>';
352
        }
353
354
        $this->unloader();
355
    }
356
357
    /**
358
     * Get start time
359
     *
360
     * @access public
361
     *
362
     * @return float|null
363
     */
364
    public function getStartTime()
365
    {
366
        return $this->debug ? $this->startTime : null;
367
    }
368
369
    /**
370
     * Unloader subsystem
371
     *
372
     * @access public
373
     *
374
     * @return void
375
     */
376
    public function unloader()
377
    {
378
        if (false === $this->loaded) {
379
            return;
380
        }
381
382
        $this->container = null;
383
        $this->loaded = false;
384
    }
385
386
    // Methods helpers
387
388
    /**
389
     * Get status of debug
390
     *
391
     * @access public
392
     *
393
     * @return bool
394
     */
395
    public function isDebug()
396
    {
397
        return $this->debug;
398
    }
399
400
    /**
401
     * Get character set
402
     *
403
     * @access public
404
     *
405
     * @return string
406
     */
407
    public function getCharset()
408
    {
409
        return 'UTF-8';
410
    }
411
412
    /**
413
     * Get environment name
414
     *
415
     * @access public
416
     *
417
     * @return string
418
     */
419
    public function getEnvironment()
420
    {
421
        return $this->environment;
422
    }
423
424
    /**
425
     * Get components container
426
     *
427
     * @access public
428
     *
429
     * @return IContainer
430
     */
431
    public function getContainer()
432
    {
433
        return $this->container;
434
    }
435
436
    /**
437
     * Get web root dir
438
     *
439
     * @access public
440
     *
441
     * @return string
442
     */
443
    public function getWebDir()
444
    {
445
        return $this->webDir;
446
    }
447
448
    /**
449
     * Get cache dir
450
     *
451
     * @access public
452
     *
453
     * @return string
454
     */
455
    public function getCacheDir()
456
    {
457
        return $this->appDir . '/cache/' . $this->environment;
458
    }
459
460
    /**
461
     * Get logs dir
462
     *
463
     * @access public
464
     *
465
     * @return string
466
     */
467
    public function getLogDir()
468
    {
469
        return $this->appDir . '/logs';
470
    }
471
}
472