Passed
Push — master ( f7ade8...7e9287 )
by Jean-Christophe
11:26
created

Startup   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 327
Duplicated Lines 0 %

Test Coverage

Coverage 87.41%

Importance

Changes 7
Bugs 2 Features 2
Metric Value
wmc 58
eloc 133
c 7
b 2
f 2
dl 0
loc 327
ccs 125
cts 143
cp 0.8741
rs 4.5599

22 Methods

Rating   Name   Duplication   Size   Complexity  
A parseUrl() 0 5 2
A startTemplateEngine() 0 10 3
A _getControllerInstance() 0 10 4
A run() 0 3 1
A getControllerSimpleName() 0 2 1
A getFrameworkDir() 0 2 1
A getController() 0 2 1
A getViewNameFileExtension() 0 2 1
A getAction() 0 2 1
A getActionParams() 0 2 1
A getTemplateEngineInstance() 0 7 2
A getApplicationName() 0 2 1
A startDefaultTemplateEngine() 0 7 3
A onError() 0 14 3
A runAsString() 0 4 1
A runCallable() 0 10 3
A init() 0 9 3
A forward() 0 15 5
A getApplicationDir() 0 2 1
A injectDependences() 0 17 6
B runAction() 0 44 11
A setMainParams() 0 6 3

How to fix   Complexity   

Complex Class

Complex classes like Startup often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Startup, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ubiquity\controllers;
4
5
use Ubiquity\controllers\di\DiManager;
6
use Ubiquity\controllers\traits\StartupConfigTrait;
7
use Ubiquity\log\Logger;
8
use Ubiquity\utils\http\USession;
9
use Ubiquity\views\engine\TemplateEngine;
10
11
/**
12
 * Starts the framework.
13
 * This class is part of Ubiquity
14
 *
15
 * @author jcheron <[email protected]>
16
 * @version 1.2.0
17
 *
18
 */
19
class Startup {
20
	use StartupConfigTrait;
21
	public static $urlParts;
22
	public static $templateEngine;
23
	protected static $controller;
24
	protected static $action;
25
	protected static $actionParams;
26
27 64
	protected static function parseUrl(&$url): array {
28 64
		if (! $url) {
29 4
			return self::$urlParts =[$url = '_default'];
30
		}
31 63
		return self::$urlParts = \explode ( '/', \rtrim ( $url, '/' ) );
32
	}
33
34 63
	protected static function _getControllerInstance($controllerName): ?object {
35 63
		if (\class_exists ( $controllerName, true )) {
36 62
			$controller = new $controllerName ();
37
			// Dependency injection
38 62
			if (isset ( self::$config ['di'] ) && \is_array ( self::$config ['di'] )) {
39 62
				self::injectDependences ( $controller );
40
			}
41 62
			return $controller;
42
		}
43 6
		return null;
44
	}
45
46 62
	protected static function startTemplateEngine(&$config): void {
47
		try {
48 62
			$templateEngine = $config ['templateEngine'];
49 62
			$engineOptions = $config ['templateEngineOptions'] ?? [ 'cache' => false ];
50 62
			$engine = new $templateEngine ( $engineOptions );
51 62
			if ($engine instanceof TemplateEngine) {
52 62
				self::$templateEngine = $engine;
53
			}
54
		} catch ( \Exception $e ) {
55
			echo $e->getTraceAsString ();
56
		}
57 62
	}
58
59 1
	protected static function setMainParams($controller,$mainParams){
60 1
		foreach ($mainParams as $k=>$v){
61 1
			if(\method_exists($controller,$k)){
62
				$controller->$k($v);
63
			}else {
64 1
				$controller->$k = $v;
65
			}
66
		}
67 1
	}
68
69
	/**
70
	 * Handles the request
71
	 *
72
	 * @param array $config The loaded config array
73
	 */
74 62
	public static function run(array &$config): void {
75 62
		self::init ( $config );
76 62
		self::forward ( $_GET ['c'] );
77 62
	}
78
79
	/**
80
	 * Initialize the app with $config array
81
	 *
82
	 * @param array $config
83
	 */
84 62
	public static function init(array &$config): void {
85 62
		self::$config = $config;
86 62
		if (isset ( $config ['templateEngine'] )) {
87 62
			self::startTemplateEngine ( $config );
88
		}
89 62
		if (isset ( $config ['sessionName'] )) {
90 62
			USession::start ( $config ['sessionName'] );
91
		}
92 62
		self::$ctrlNS = self::getNS ();
93 62
	}
94
95
	/**
96
	 * Forwards to url
97
	 *
98
	 * @param string $url The url to forward to
99
	 * @param boolean $initialize If true, the **initialize** method of the controller is called
100
	 * @param boolean $finalize If true, the **finalize** method of the controller is called
101
	 */
102 63
	public static function forward($url, $initialize = true, $finalize = true): void {
103 63
		$u = self::parseUrl ( $url );
104 63
		if (\is_array ( Router::getRoutes () ) && ($ru = Router::getRoute ( $url, true, self::$config ['debug'] ?? false)) !== false) {
105 28
			if (\is_array ( $ru )) {
106 28
				if (isset ( $ru ['controller'] )) {
107 27
					static::runAction ( $ru, $initialize, $finalize );
108
				} else {
109 28
					self::runCallable ( $ru );
110
				}
111
			} else {
112 28
				echo $ru; // Displays route response from cache
113
			}
114
		} else {
115 44
			$ru =['controller'=>self::$ctrlNS . $u [0],'action'=> $u [1]??'index','params'=> \array_slice ( $u, 2 )];
116 44
			static::runAction ( $ru, $initialize, $finalize );
117
		}
118 63
	}
119
120
	/**
121
	 * Returns the template engine instance
122
	 *
123
	 * @return TemplateEngine
124
	 */
125 3
	public static function getTemplateEngineInstance(): ?TemplateEngine {
126 3
		$config = self::$config;
127 3
		if (isset ( $config ['templateEngine'] )) {
128 3
			$templateEngine = $config ['templateEngine'];
129 3
			return new $templateEngine ( [ ] );
130
		}
131
		return null;
132
	}
133
	
134
	/**
135
	 * Starts the default Template engine (Twig for Webtools).
136
	 * 
137
	 * @return TemplateEngine
138
	 */
139 16
	public static function startDefaultTemplateEngine():TemplateEngine{
140 16
		if(self::$templateEngine===null || !self::$templateEngine instanceof \Ubiquity\views\engine\Twig){
141
			$config=self::$config;
142
			$config['templateEngine']=\Ubiquity\views\engine\Twig::class;
143
			self::startTemplateEngine($config);
144
		}
145 16
		return self::$templateEngine;
146
	}
147
148
	/**
149
	 * Runs an action on a controller
150
	 *
151
	 * @param array $u An array containing controller, action and parameters
152
	 * @param boolean $initialize If true, the **initialize** method of the controller is called
153
	 * @param boolean $finalize If true, the **finalize** method of the controller is called
154
	 */
155 63
	public static function runAction(array &$u, $initialize = true, $finalize = true): void {
156 63
		self::$controller = $ctrl = $u ['controller'];
157 63
		self::$action = $action = $u ['action'] ?? 'index';
158 63
		self::$actionParams = $u['params']??[];
159
160
		try {
161 63
			if (null !== $controller = self::_getControllerInstance ( $ctrl )) {
162 62
				if($mainParams=$u['mainParams']??false){
163 1
					static::setMainParams($controller,$mainParams);
164
				}
165 62
				if (! $controller->isValid ( $action )) {
166 6
					$controller->onInvalidControl ();
167
				} else {
168 62
					if ($initialize) {
169 62
						$controller->initialize ();
170
					}
171
					try {
172 62
						$controller->$action ( ...(self::$actionParams) );
173 2
					} catch ( \Error $e ) {
174 1
						if (! \method_exists ( $controller, $action )) {
175 1
							static::onError ( 404, "This action does not exist on the controller " . $ctrl, $controller );
176
						} else {
177
							Logger::warn ( 'Startup', $e->getTraceAsString (), 'runAction' );
178
							if (self::$config ['debug']) {
179
								throw $e;
180
							} else {
181
								static::onError ( 500, $e->getMessage (), $controller );
182
							}
183
						}
184
					}
185 62
					if ($finalize) {
186 62
						$controller->finalize ();
187
					}
188
				}
189
			} else {
190 6
				Logger::warn ( 'Startup', "The controller `$ctrl` doesn't exist! <br/>", 'runAction' );
191 63
				static::onError ( 404 ,"The controller `$ctrl` doesn't exist! <br/>");
192
			}
193 2
		} catch ( \Error $eC ) {
194
			Logger::warn ( 'Startup', $eC->getTraceAsString (), 'runAction' );
195
			if (self::$config ['debug']) {
196
				throw $eC;
197
			} else {
198
				static::onError ( 500, $eC->getMessage () );
199
			}
200
		}
201 63
	}
202
203
	/**
204
	 * Runs a callback
205
	 *
206
	 * @param array $u An array containing a callback, and some parameters
207
	 */
208 1
	public static function runCallable(array &$u): void {
209 1
		self::$actionParams = $u['params']??[];
210 1
		if (isset ( self::$config ['di'] )) {
211 1
			$di = self::$config ['di'];
212 1
			if (\is_array ( $di )) {
213 1
				self::$actionParams += \array_values ( $di );
214
			}
215
		}
216 1
		$func = $u ['callback'];
217 1
		$func ( ...(self::$actionParams) );
218 1
	}
219
220
	/**
221
	 * Injects the dependencies from the **di** config key in a controller
222
	 *
223
	 * @param Controller $controller The controller
224
	 */
225 65
	public static function injectDependences($controller): void {
226 65
		$di = DiManager::fetch ( $controller );
227 65
		if ($di !== false) {
228 51
			foreach ( $di as $k => $v ) {
229 51
				$setter = 'set' . \ucfirst ( $k );
230 51
				if (\method_exists ( $controller, $setter )) {
231 4
					$controller->$setter ( $v ( $controller ) );
232
				} else {
233 51
					$controller->$k = $v ( $controller );
234
				}
235
			}
236
		}
237
238 65
		$di = self::$config ['di'] ?? [ ];
239 65
		if (isset ( $di ['@exec'] )) {
240 62
			foreach ( $di ['@exec'] as $k => $v ) {
241 62
				$controller->$k = $v ( $controller );
242
			}
243
		}
244 65
	}
245
246
	/**
247
	 * Runs an action on a controller and returns a string
248
	 *
249
	 * @param array $u
250
	 * @param boolean $initialize If true, the **initialize** method of the controller is called
251
	 * @param boolean $finalize If true, the **finalize** method of the controller is called
252
	 * @return string
253
	 */
254 1
	public static function runAsString(array &$u, $initialize = true, $finalize = true): string {
255 1
		\ob_start ();
256 1
		self::runAction ( $u, $initialize, $finalize );
257 1
		return \ob_get_clean ();
258
	}
259
260 7
	public static function onError(int $code, ?string $message = null, $controllerInstance = null) {
261
		$onError = self::$config ['onError'] ?? (function ($code, $message = null, $controllerInstance = null) {
262
			switch ($code) {
263 7
				case 404 :
264 7
					self::getHttpInstance ()->header ( 'HTTP/1.0 404 Not Found', '', true, 404 );
265 7
					echo ($message ?? "The page you are looking for doesn't exist!");
266 7
					break;
267
268
				case 500 :
269
					echo ($message ?? "A server error occurred!");
270
					break;
271
			}
272 7
		});
273 7
		$onError ( $code, $message, $controllerInstance );
274 7
	}
275
276
	/**
277
	 * Returns the active controller name
278
	 *
279
	 * @return ?string
280
	 */
281 17
	public static function getController(): ?string {
282 17
		return self::$controller;
283
	}
284
285
	/**
286
	 * Returns the class simple name of the active controller
287
	 *
288
	 * @return string
289
	 */
290 6
	public static function getControllerSimpleName(): string {
291 6
		return (new \ReflectionClass ( self::$controller ))->getShortName ();
292
	}
293
294
	/**
295
	 * Returns the extension for view files
296
	 *
297
	 * @return string
298
	 */
299 5
	public static function getViewNameFileExtension(): string {
300 5
		return self::$config ['templateEngineOptions']['fileExt']??'html';
301
	}
302
303
	/**
304
	 * Returns tha active action
305
	 *
306
	 * @return string
307
	 */
308 28
	public static function getAction(): string {
309 28
		return self::$action;
310
	}
311
312
	/**
313
	 * Returns the active parameters
314
	 *
315
	 * @return array
316
	 */
317 6
	public static function getActionParams(): array {
318 6
		return self::$actionParams;
319
	}
320
321
	/**
322
	 * Returns the framework directory
323
	 *
324
	 * @return string
325
	 */
326 64
	public static function getFrameworkDir(): string {
327 64
		return \dirname ( __FILE__ );
328
	}
329
330
	/**
331
	 * Returns the application directory (app directory)
332
	 *
333
	 * @return string
334
	 */
335 3
	public static function getApplicationDir(): string {
336 3
		return \dirname ( \ROOT );
337
	}
338
339
	/**
340
	 * Returns the application name
341
	 *
342
	 * @return string
343
	 */
344 1
	public static function getApplicationName(): string {
345 1
		return \basename ( \dirname ( \ROOT ) );
346
	}
347
}
348