Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
App
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
8 / 8
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 init
n/a
0 / 0
n/a
0 / 0
0
 process
n/a
0 / 0
n/a
0 / 0
0
 fullInit
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 fullProcess
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 addMiddleware
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 runMiddlewares
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 finish
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 loadConfigs
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 handleException
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace Dynart\Micro;
4
5use Exception;
6
7/**
8 * Micro PHP Application
9 *
10 * @package Dynart\Micro
11 */
12abstract class App {
13
14    const CONFIG_BASE_URL = 'app.base_url';
15    const CONFIG_ROOT_PATH = 'app.root_path';
16    const CONFIG_ENVIRONMENT = 'app.environment';
17    const PRODUCTION_ENVIRONMENT = 'prod';
18
19    /**
20     * Stores the middleware class names in a list
21     * @var Middleware[]
22     */
23    protected $middlewares = [];
24
25    /** @var Config */
26    protected $config;
27
28    /** @var Logger */
29    protected $logger;
30
31    /** @var string[] */
32    protected $configPaths;
33
34    /** @var bool */
35    protected $exitOnFinish = true;
36
37    public function __construct(array $configPaths) {
38        $this->configPaths = $configPaths;
39        Micro::add(Config::class);
40        Micro::add(Logger::class);
41    }
42
43    /**
44     * Abstract function for initialize the application
45     * @return mixed
46     */
47    abstract public function init();
48
49    /**
50     * Abstract function for processing the application
51     * @return mixed
52     */
53    abstract public function process();
54
55    /**
56     * Fully initializes the application
57     *
58     * Creates the `Config`, loads the configs, creates the `Logger`, calls the `init()` method
59     * then runs all the middlewares. If an exception happens, handles it with the `handleException()` method.
60     */
61    public function fullInit() {
62        try {
63            $this->config = Micro::get(Config::class);
64            $this->loadConfigs();
65            $this->logger = Micro::get(Logger::class);
66            $this->init();
67            $this->runMiddlewares();
68        } catch (Exception $e) {
69            $this->handleException($e);
70        }
71    }
72
73    /**
74     * Calls the `process()` method within a try/catch, handles exception with the `handleException()` method
75     */
76    public function fullProcess() {
77        try {
78            $this->process();
79        } catch (Exception $e) {
80            $this->handleException($e);
81        }
82    }
83
84    /**
85     * Adds a middleware
86     *
87     * It adds only if not presents.
88     *
89     * @param string $interface
90     */
91    public function addMiddleware(string $interface) {
92        if (!in_array($interface, $this->middlewares)) {
93            Micro::add($interface);
94            $this->middlewares[] = $interface;
95        }
96    }
97
98    /**
99     * Runs all the added middlewares
100     */
101    protected function runMiddlewares() {
102        foreach ($this->middlewares as $m) {
103            Micro::get($m)->run();
104        }
105    }
106
107    /**
108     * Finishes the application
109     *
110     * If the `$exitOnFinish` true (default) calls the exit, otherwise just prints out the content.
111     *
112     * @param string|int $content Content for the output. If it's an int, it is the return code of the process.
113     */
114    public function finish($content = 0): void {
115        $this->exitOnFinish ? exit($content) : print($content);
116    }
117
118    /**
119     * Loads all the configs by the `$configPaths`
120     */
121    protected function loadConfigs() {
122        foreach ($this->configPaths as $path) {
123            $this->config->load($path);
124        }
125    }
126
127    /**
128     * Handles the exception
129     *
130     * Sends the type, the line, the exception message and the stacktrace to the standard error output.
131     * If the `Config` or the `Logger` wasn't initialised throws a `MicroException`.
132     *
133     * @param Exception $e The exception
134     * @throws MicroException
135     */
136    protected function handleException(Exception $e) {
137        $type = get_class($e);
138        $file = $e->getFile();
139        $line = $e->getLine();
140        $message = $e->getMessage();
141        $trace = $e->getTraceAsString();
142        $text = "`$type` in $file on line $line with message: $message\n$trace";
143        if (!$this->config) {
144            throw new MicroException("Couldn't instantiate Config::class, original exception:\n".$text);
145        }
146        if (!$this->logger) {
147            throw new MicroException("Couldn't instantiate Logger::class, original exception:\n".$text);
148        }
149        $this->logger->error($text);
150    }
151
152}