Completed
Push — master ( 9c73ab...3bd5c7 )
by Timothy
02:45
created

src/Aviat/AnimeClient/Dispatcher.php (3 issues)

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
2
/**
3
 * Hummingbird Anime Client
4
 *
5
 * An API client for Hummingbird to manage anime and manga watch lists
6
 *
7
 * @package     HummingbirdAnimeClient
8
 * @author      Timothy J. Warren
9
 * @copyright   Copyright (c) 2015 - 2016
10
 * @link        https://github.com/timw4mail/HummingBirdAnimeClient
11
 * @license     MIT
12
 */
13
namespace Aviat\AnimeClient;
14
15
use Aura\Web\Request;
16
use Aura\Web\Response;
17
18
use Aviat\Ion\Di\ContainerInterface;
19
use Aviat\AnimeClient\AnimeClient;
20
21
/**
22
 * Basic routing/ dispatch
23
 */
24
class Dispatcher extends RoutingBase {
25
26
	/**
27
	 * The route-matching object
28
	 * @var object $router
29
	 */
30
	protected $router;
31
32
	/**
33
	 * Class wrapper for input superglobals
34
	 * @var object
35
	 */
36
	protected $request;
37
38
	/**
39
	 * Routes added to router
40
	 * @var array $output_routes
41
	 */
42
	protected $output_routes;
43
44
	/**
45
	 * Constructor
46
	 *
47
	 * @param ContainerInterface $container
48
	 */
49
	public function __construct(ContainerInterface $container)
50
	{
51
		parent::__construct($container);
52
		$this->router = $container->get('aura-router');
53
		$this->request = $container->get('request');
54
55
		$this->output_routes = $this->_setup_routes();
56
	}
57
58
	/**
59
	 * Get the current route object, if one matches
60
	 *
61
	 * @return object
62
	 */
63
	public function get_route()
64
	{
65
		$error_handler = $this->container->get('error-handler');
66
67
		$raw_route = $this->request->url->get(PHP_URL_PATH);
68
		$route_path = "/" . trim($raw_route, '/');
69
70
		$error_handler->addDataTable('Route Info', [
71
			'route_path' => $route_path
72
		]);
73
74
		return $this->router->match($route_path, $_SERVER);
75
	}
76
77
	/**
78
	 * Get list of routes applied
79
	 *
80
	 * @return array
81
	 */
82
	public function get_output_routes()
83
	{
84
		return $this->output_routes;
85
	}
86
87
	/**
88
	 * Handle the current route
89
	 *
90
	 * @codeCoverageIgnore
91
	 * @param object|null $route
92
	 * @return void
93
	 */
94
	public function __invoke($route = NULL)
95
	{
96
		$error_handler = $this->container->get('error-handler');
97
		$controller_name = AnimeClient::DEFAULT_CONTROLLER;
98
		$action_method = AnimeClient::NOT_FOUND_METHOD;
0 ignored issues
show
$action_method is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
99
100
		if (is_null($route))
101
		{
102
			$route = $this->get_route();
103
			$error_handler->addDataTable('route_args', (array)$route);
104
		}
105
106
		if ( ! $route)
107
		{
108
			// If not route was matched, return an appropriate http
109
			// error message
110
			$error_route = $this->get_error_params();
111
			$params = $error_route['params'];
112
			$action_method = $error_route['action_method'];
0 ignored issues
show
$action_method is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
113
		}
114
		else
115
		{
116
			$params = (isset($route->params['params'])) ? $route->params['params'] : [];
117
118
			if (isset($route->params['controller']))
119
			{
120
				$controller_name = $route->params['controller'];
121
			}
122
123
			if (isset($route->params['action']))
124
			{
125
				$action_method = $route->params['action'];
0 ignored issues
show
$action_method is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
126
			}
127
128
			if (is_null($controller_name))
129
			{
130
				throw new \LogicException("Missing controller");
131
			}
132
133
			// Get the full namespace for a controller if a short name is given
134
			if (strpos($controller_name, '\\') === FALSE)
135
			{
136
				$map = $this->get_controller_list();
137
				$controller_name = $map[$controller_name];
138
			}
139
140
			if ( ! empty($route->tokens))
141
			{
142
				foreach ($route->tokens as $key => $v)
143
				{
144
					if (array_key_exists($key, $route->params))
145
					{
146
						$params[$key] = $route->params[$key];
147
					}
148
				}
149
			}
150
		}
151
152
		// Actually instantiate the controller
153
		$this->call($controller_name, $method, $params);
154
	}
155
156
	/**
157
	 * Get the type of route, to select the current controller
158
	 *
159
	 * @return string
160
	 */
161
	public function get_controller()
162
	{
163
		$route_type = $this->__get('default_list');
164
		$request_uri = $this->request->url->get(PHP_URL_PATH);
165
		$path = trim($request_uri, '/');
166
167
		$segments = explode('/', $path);
168
		$controller = reset($segments);
169
170
		if (empty($controller))
171
		{
172
			$controller = $route_type;
173
		}
174
175
		return $controller;
176
	}
177
178
	/**
179
	 * Get the list of controllers in the default namespace
180
	 *
181
	 * @return array
182
	 */
183
	public function get_controller_list()
184
	{
185
		$default_namespace = AnimeClient::DEFAULT_CONTROLLER_NAMESPACE;
186
		$path = str_replace('\\', '/', $default_namespace);
187
		$path = trim($path, '/');
188
		$actual_path = realpath(\_dir(AnimeClient::SRC_DIR, $path));
189
		$class_files = glob("{$actual_path}/*.php");
190
191
		$controllers = [];
192
193
		foreach ($class_files as $file)
194
		{
195
			$raw_class_name = basename(str_replace(".php", "", $file));
196
			$path = strtolower(basename($raw_class_name));
197
			$class_name = trim($default_namespace . '\\' . $raw_class_name, '\\');
198
199
			$controllers[$path] = $class_name;
200
		}
201
202
		return $controllers;
203
	}
204
205
	/**
206
	 * Create the controller object and call the appropriate
207
	 * method
208
	 *
209
	 * @param  string $controller_name - The full namespace of the controller class
210
	 * @param  string $method
211
	 * @param  array  $params
212
	 * @return void
213
	 */
214
	protected function call($controller_name, $method, array $params)
215
	{
216
		$error_handler = $this->container->get('error-handler');
217
218
		$controller = new $controller_name($this->container);
219
220
		// Run the appropriate controller method
221
		$error_handler->addDataTable('controller_args', $params);
222
		call_user_func_array([$controller, $action_method], $params);
223
	}
224
225
	/**
226
	 * Get the appropriate params for the error page
227
	 * pased on the failed route
228
	 *
229
	 * @return array|false
230
	 */
231
	protected function get_error_params()
232
	{
233
		$failure = $this->router->getFailedRoute();
234
		$error_handler = $this->container->get('error-handler');
235
		$error_handler->addDataTable('failed_route', (array)$failure);
236
		$action_method = AnimeClient::ERROR_MESSAGE_METHOD;
237
238
		$params = [];
239
240
		if ($failure->failedMethod())
241
		{
242
			$params = [
243
				'http_code' => 405,
244
				'title' => '405 Method Not Allowed',
245
				'message' => 'Invalid HTTP Verb'
246
			];
247
		}
248
		else if($failure->failedAccept())
249
		{
250
			$params = [
251
				'http_code' => 406,
252
				'title' => '406 Not Acceptable',
253
				'message' => 'Unacceptable content type'
254
			];
255
		}
256
		else
257
		{
258
			// Fall back to a 404 message
259
			$action_method = AnimeClient::NOT_FOUND_METHOD;
260
		}
261
262
		return [
263
			'params' => $params,
264
			'action_method' => $action_method
265
		];
266
	}
267
268
	/**
269
	 * Select controller based on the current url, and apply its relevent routes
270
	 *
271
	 * @return array
272
	 */
273
	protected function _setup_routes()
274
	{
275
		$route_type = $this->get_controller();
276
277
		// Add routes
278
		$routes = [];
279
		foreach ($this->routes as $name => &$route)
280
		{
281
			$path = $route['path'];
282
			unset($route['path']);
283
284
			$controller_map = $this->get_controller_list();
285
			$controller_class = (array_key_exists($route_type, $controller_map))
286
				? $controller_map[$route_type]
287
				: AnimeClient::DEFAULT_CONTROLLER;
288
289
			if (array_key_exists($route_type, $controller_map))
290
			{
291
				$controller_class = $controller_map[$route_type];
292
			}
293
294
			// Prepend the controller to the route parameters
295
			$route['controller'] = $controller_class;
296
297
			// Select the appropriate router method based on the http verb
298
			$add = (array_key_exists('verb', $route))
299
				? "add" . ucfirst(strtolower($route['verb']))
300
				: "addGet";
301
302
			// Add the route to the router object
303
			if ( ! array_key_exists('tokens', $route))
304
			{
305
				$routes[] = $this->router->$add($name, $path)->addValues($route);
306
			}
307
			else
308
			{
309
				$tokens = $route['tokens'];
310
				unset($route['tokens']);
311
312
				$routes[] = $this->router->$add($name, $path)
313
					->addValues($route)
314
					->addTokens($tokens);
315
			}
316
		}
317
318
		return $routes;
319
	}
320
}
321
// End of Dispatcher.php