Passed
Push — master ( 5b5ed9...47b84a )
by Alex
02:17
created

Application::getRequestParamsFetcher()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
namespace Mezon\Application;
3
4
/**
5
 * Class Application
6
 *
7
 * @package Mezon
8
 * @subpackage Application
9
 * @author Dodonov A.A.
10
 * @version v.1.0 (2019/08/13)
11
 * @copyright Copyright (c) 2019, aeon.org
12
 */
13
14
/**
15
 * Base class of the application
16
 */
17
class Application
18
{
19
20
    /**
21
     * Router object
22
     *
23
     * @var \Mezon\Router\Router
24
     */
25
    private $router = null;
26
27
    /**
28
     * Params fetcher
29
     *
30
     * @var \Mezon\Transport\RequestParams
31
     */
32
    private $requestParams = null;
33
34
    const DEFAULT_PHP_ROUTES_PATH = './conf/routes.php';
35
36
    const DEFAULT_JSON_ROUTES_PATH = './conf/routes.json';
37
38
    /**
39
     * Constructor
40
     */
41
    function __construct()
42
    {
43
        // getting application's actions
44
        $this->router = new \Mezon\Router\Router();
45
46
        $this->router->fetchActions($this);
47
48
        if (file_exists(CommonApplication::DEFAULT_PHP_ROUTES_PATH)) {
49
            $this->loadRoutesFromConfig(CommonApplication::DEFAULT_PHP_ROUTES_PATH);
50
        }
51
52
        if (file_exists(CommonApplication::DEFAULT_JSON_ROUTES_PATH)) {
53
            $this->loadRoutesFromConfig(CommonApplication::DEFAULT_JSON_ROUTES_PATH);
54
        }
55
    }
56
57
    /**
58
     * Method returns $this->requestParams and creates this object if necessery
59
     *
60
     * @return \Mezon\Transport\RequestParams
61
     */
62
    public function getRequestParamsFetcher(): \Mezon\Transport\RequestParams
63
    {
64
        if ($this->requestParams === null) {
65
            $this->requestParams = new \Mezon\Transport\HttpRequestParams($this->router);
66
        }
67
68
        return $this->requestParams;
69
    }
70
71
    /**
72
     * Method calls route and returns it's content
73
     */
74
    protected function callRoute()
75
    {
76
        $route = explode('/', trim(@$_GET['r'], '/'));
77
78
        if ($this->router === null) {
79
            throw (new \Exception('this->Router was not set', - 2));
80
        }
81
82
        return $this->router->callRoute($route);
83
    }
84
85
    /**
86
     * Method loads single route
87
     *
88
     * @param array $route
89
     *            Route settings
90
     */
91
    public function loadRoute(array $route): void
92
    {
93
        if (isset($route['route']) === false) {
94
            throw (new \Exception('Field "route" must be set'));
95
        }
96
        if (isset($route['callback']) === false) {
97
            throw (new \Exception('Field "callback" must be set'));
98
        }
99
100
        $callback = $route['callback'];
101
102
        if (is_array($route['callback'])) {
103
            $route['class'] = $route['callback'][0];
104
            $route['callback'] = $route['callback'][1];
105
        } else {
106
            $class = isset($route['class']) ? new $route['class']() : $this;
107
            $callback = [
108
                $class,
109
                $callback
110
            ];
111
        }
112
        $this->router->addRoute($route['route'], $callback, isset($route['method']) ? $route['method'] : 'GET');
113
    }
114
115
    /**
116
     * Method loads routes
117
     *
118
     * @param array $routes
119
     *            List of routes
120
     */
121
    public function loadRoutes(array $routes): void
122
    {
123
        foreach ($routes as $route) {
124
            $this->loadRoute($route);
125
        }
126
    }
127
128
    /**
129
     * Method loads routes from config file in *.php or *.json format
130
     *
131
     * @param string $configPath
132
     *            Path of the config for routes
133
     */
134
    public function loadRoutesFromConfig(string $configPath = CommonApplication::DEFAULT_PHP_ROUTES_PATH): void
135
    {
136
        if (file_exists($configPath)) {
137
            if (substr($configPath, - 5) === '.json') {
138
                // load config from json
139
                $routes = json_decode(file_get_contents($configPath), true);
140
            } else {
141
                // loadconfig from php
142
                $routes = (include ($configPath));
143
            }
144
            $this->loadRoutes($routes);
145
        } else {
146
            throw (new \Exception('Route ' . $configPath . ' was not found', 1));
147
        }
148
    }
149
150
    /**
151
     * Method loads list of configs
152
     *
153
     * @param array $configPaths
154
     *            paths to config files
155
     */
156
    public function loadRoutesFromConfigs(array $configPaths): void
157
    {
158
        foreach ($configPaths as $configPath) {
159
            $this->loadRoutesFromConfig($configPath);
160
        }
161
    }
162
163
    /**
164
     * Method loads routes from the directory
165
     *
166
     * @param string $directory
167
     *            path to the directory. Scanninng is recursive.
168
     */
169
    public function loadRoutesFromDirectory(string $directory): void
170
    {
171
        $paths = scandir($directory);
172
173
        foreach ($paths as $path) {
174
            if (is_file($directory . '/' . $path)) {
175
                $this->loadRoutesFromConfig($directory . '/' . $path);
176
            }
177
        }
178
    }
179
180
    /**
181
     * Method processes exception
182
     *
183
     * @param \Exception $e
184
     *            Exception object to be formatted
185
     */
186
    public function handleException(\Exception $e): void
187
    {
188
        print('<pre>' . $e);
189
    }
190
191
    /**
192
     * Running application
193
     */
194
    public function run(): void
195
    {
196
        try {
197
            print($this->callRoute());
198
        } catch (\Exception $e) {
199
            $this->handleException($e);
200
        }
201
    }
202
203
    /**
204
     * Allowing to call methods added on the fly
205
     *
206
     * @param string $method
207
     *            Method to be called
208
     * @param array $args
209
     *            Arguments
210
     * @return mixed Result of the call
211
     */
212
    public function __call(string $method, array $args)
213
    {
214
        if (isset($this->$method)) {
215
            $function = $this->$method;
216
217
            return call_user_func_array($function, $args);
218
        } else {
219
            throw (new \Exception('Method ' . $method . ' was not found in the application ' . get_class($this)));
220
        }
221
    }
222
223
    /**
224
     * Method redirects user to another page
225
     *
226
     * @param string $url
227
     *            New page
228
     */
229
    public function redirectTo($url): void
230
    {
231
        // @codeCoverageIgnoreStart
232
        header('Location: ' . $url);
233
        exit(0);
234
        // @codeCoverageIgnoreEnd
235
    }
236
237
    /**
238
     * Method validates that route exists
239
     *
240
     * @param string $route
241
     *            route
242
     * @return bool true if the route exists
243
     */
244
    public function routeExists(string $route): bool
245
    {
246
        return $this->router->routeExists($route);
247
    }
248
249
    /**
250
     * Method returns router
251
     *
252
     * @return \Mezon\Router\Router router
253
     */
254
    public function getRouter(): \Mezon\Router\Router
255
    {
256
        return $this->router;
257
    }
258
}
259