1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* DronePHP (http://www.dronephp.com) |
4
|
|
|
* |
5
|
|
|
* @link http://github.com/Pleets/DronePHP |
6
|
|
|
* @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org) |
7
|
|
|
* @license http://www.dronephp.com/license |
8
|
|
|
* @author Darío Rivera <[email protected]> |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Drone\Mvc; |
12
|
|
|
|
13
|
|
|
use Drone\FileSystem\Shell; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Application class |
17
|
|
|
* |
18
|
|
|
* This is the main class for mvc pattern |
19
|
|
|
*/ |
20
|
|
|
class Application |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* Module path |
24
|
|
|
* |
25
|
|
|
* @var array |
26
|
|
|
*/ |
27
|
|
|
protected $modulePath; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* List of modules available |
31
|
|
|
* |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
private $modules; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* The router instance |
38
|
|
|
* |
39
|
|
|
* @var Router |
40
|
|
|
*/ |
41
|
|
|
private $router; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Development or production mode |
45
|
|
|
* |
46
|
|
|
* @var boolean |
47
|
|
|
*/ |
48
|
|
|
private $devMode; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Returns the router instance |
52
|
|
|
* |
53
|
|
|
* @return Router |
54
|
|
|
*/ |
55
|
|
|
public function getRouter() |
56
|
|
|
{ |
57
|
|
|
return $this->router; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Constructor |
62
|
|
|
* |
63
|
|
|
* @param array $init_parameters |
64
|
|
|
* |
65
|
|
|
* @throws \InvalidArgumentException |
66
|
|
|
* @throws \RuntimeException |
67
|
|
|
*/ |
68
|
|
|
public function __construct(Array $init_parameters) |
69
|
|
|
{ |
70
|
|
|
# start sessions |
71
|
|
|
if (!isset($_SESSION)) |
72
|
|
|
session_start(); |
73
|
|
|
|
74
|
|
|
if (!array_key_exists('environment', $init_parameters)) |
75
|
|
|
throw new \InvalidArgumentException("The 'environment' key was not defined"); |
76
|
|
|
|
77
|
|
|
if (!array_key_exists('dev_mode', $init_parameters['environment'])) |
78
|
|
|
throw new \InvalidArgumentException("The 'dev_mode' key was not defined"); |
79
|
|
|
|
80
|
|
|
$this->devMode = $init_parameters["environment"]["dev_mode"]; |
81
|
|
|
|
82
|
|
|
if (!array_key_exists('modules', $init_parameters)) |
83
|
|
|
throw new \InvalidArgumentException("The 'modules' key was not defined"); |
84
|
|
|
|
85
|
|
|
$this->modules = $init_parameters["modules"]; |
86
|
|
|
|
87
|
|
|
# setting module path |
88
|
|
|
$this->modulePath = (!array_key_exists('module_path', $init_parameters['environment'])) |
|
|
|
|
89
|
|
|
? 'module' |
90
|
|
|
: $init_parameters['environment']['module_path']; |
91
|
|
|
|
92
|
|
|
# setting development or production environment |
93
|
|
|
if ($this->devMode) |
94
|
|
|
{ |
95
|
|
|
ini_set('display_errors', 1); |
96
|
|
|
error_reporting(-1); |
97
|
|
|
} |
98
|
|
|
else |
99
|
|
|
{ |
100
|
|
|
ini_set('display_errors', 0); |
101
|
|
|
error_reporting(0); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
$this->loadModules($this->modules); |
105
|
|
|
|
106
|
|
|
if (!array_key_exists('router', $init_parameters)) |
107
|
|
|
throw new \InvalidArgumentException("The 'router' key was not defined"); |
108
|
|
|
|
109
|
|
|
if (!array_key_exists('routes', $init_parameters["router"])) |
110
|
|
|
throw new \InvalidArgumentException("The 'routes' key was not defined"); |
111
|
|
|
|
112
|
|
|
$this->router = new Router($init_parameters["router"]["routes"]); |
113
|
|
|
|
114
|
|
|
if (!array_key_exists('base_path', $init_parameters['environment'])) |
115
|
|
|
throw new \InvalidArgumentException("The 'base_path' key was not defined"); |
116
|
|
|
|
117
|
|
|
$this->router->setBasePath($init_parameters["environment"]["base_path"]); |
118
|
|
|
|
119
|
|
|
# load routes from init_parameters |
120
|
|
|
foreach ($init_parameters["router"]["routes"] as $name => $route) |
121
|
|
|
{ |
122
|
|
|
if ($route instanceof \Zend\Router\Http\RouteInterface) |
123
|
|
|
$this->getRouter()->addZendRoute($name, $route); |
124
|
|
|
else |
125
|
|
|
$this->getRouter()->addRoute($route); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
# load routes from each module |
129
|
|
|
foreach ($this->modules as $module) |
130
|
|
|
{ |
131
|
|
|
if (file_exists($this->modulePath . "/$module/config/module.config.php")) |
132
|
|
|
{ |
133
|
|
|
$module_config_file = require($this->modulePath . "/$module/config/module.config.php"); |
134
|
|
|
|
135
|
|
|
if (!array_key_exists('router', $module_config_file)) |
136
|
|
|
throw new \RuntimeException("The 'router' key was not defined in the config file for module '$module'"); |
137
|
|
|
|
138
|
|
|
if (!array_key_exists('routes', $module_config_file["router"])) |
139
|
|
|
throw new \RuntimeException("The 'routes' key was not defined in the config file for module '$module'"); |
140
|
|
|
|
141
|
|
|
$this->getRouter()->addRoute($module_config_file["router"]["routes"]); |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Loads module classes and autoloading functions |
148
|
|
|
* |
149
|
|
|
* @param array $modules |
150
|
|
|
* |
151
|
|
|
* @throws RuntimeException |
152
|
|
|
* |
153
|
|
|
* @return null |
154
|
|
|
*/ |
155
|
|
|
private function loadModules($modules) |
156
|
|
|
{ |
157
|
|
|
if (count($modules)) |
158
|
|
|
{ |
159
|
|
|
foreach ($modules as $module) |
160
|
|
|
{ |
161
|
|
|
/* |
162
|
|
|
* This instruction includes each module declared. |
163
|
|
|
* Each module has an autoloader to load its classes (controllers and models) |
164
|
|
|
*/ |
165
|
|
|
if (file_exists($this->modulePath ."/". $module."/Module.php")) |
|
|
|
|
166
|
|
|
include($this->modulePath ."/". $module."/Module.php"); |
167
|
|
|
|
168
|
|
|
spl_autoload_register($module . "\Module::loader"); |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
else |
172
|
|
|
throw new \RuntimeException("The application must have at least one module"); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Runs the application |
177
|
|
|
* |
178
|
|
|
* @return null |
179
|
|
|
*/ |
180
|
|
|
public function run() |
181
|
|
|
{ |
182
|
|
|
$module = isset($_GET["module"]) ? $_GET["module"] : null; |
183
|
|
|
$controller = isset($_GET["controller"]) ? $_GET["controller"] : null; |
184
|
|
|
$view = isset($_GET["view"]) ? $_GET["view"] : null; |
185
|
|
|
|
186
|
|
|
$request = new \Zend\Http\Request(); |
187
|
|
|
|
188
|
|
|
# build URI |
189
|
|
|
$uri = ''; |
190
|
|
|
$uri .= !empty($module) ? '/' . $module : ""; |
191
|
|
|
$uri .= !empty($controller) ? '/' . $controller : ""; |
192
|
|
|
$uri .= !empty($view) ? '/' . $view : ""; |
193
|
|
|
|
194
|
|
|
if (empty($uri)) |
195
|
|
|
$uri = "/"; |
196
|
|
|
|
197
|
|
|
$request->setUri($uri); |
198
|
|
|
|
199
|
|
|
$match = $this->router->getZendRouter()->match($request); |
200
|
|
|
|
201
|
|
|
if (!is_null($match)) |
202
|
|
|
{ |
203
|
|
|
$params = $match->getParams(); |
204
|
|
|
$parts = explode("\\", $params["controller"]); |
205
|
|
|
|
206
|
|
|
$module = $parts[0]; |
207
|
|
|
$controller = $parts[2]; |
208
|
|
|
$view = $params["action"]; |
209
|
|
|
|
210
|
|
|
$this->router->setIdentifiers($module, $controller, $view); |
211
|
|
|
} |
212
|
|
|
else |
213
|
|
|
$this->router->setIdentifiers($module, $controller, $view); |
214
|
|
|
|
215
|
|
|
$this->router->run(); |
216
|
|
|
} |
217
|
|
|
} |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.