Completed
Branch master (1afb45)
by Timothy
04:13
created

Controller::error_page()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 8
rs 9.4285
cc 1
eloc 6
nc 1
nop 4
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 Aviat\Ion\Di\ContainerInterface;
16
use Aviat\Ion\View\HttpView;
17
use Aviat\Ion\View\HtmlView;
18
use Aviat\Ion\View\JsonView;
19
20
/**
21
 * Controller base, defines output methods
22
 *
23
 * @property Response object $response
24
 * @property Config object $config
25
 */
26
class Controller {
27
28
	use \Aviat\Ion\Di\ContainerAware;
29
30
	/**
31
	 * Cache manager
32
	 * @var \Aviat\Ion\Cache\CacheInterface
33
	 */
34
	protected $cache;
35
36
	/**
37
	 * The global configuration object
38
	 * @var object $config
39
	 */
40
	protected $config;
41
42
	/**
43
	 * Request object
44
	 * @var object $request
45
	 */
46
	protected $request;
47
48
	/**
49
	 * Response object
50
	 * @var object $response
51
	 */
52
	protected $response;
53
54
	/**
55
	 * The api model for the current controller
56
	 * @var object
57
	 */
58
	protected $model;
59
60
	/**
61
	 * Url generatation class
62
	 * @var UrlGenerator
63
	 */
64
	protected $urlGenerator;
65
66
	/**
67
	 * Session segment
68
	 * @var [type]
69
	 */
70
	protected $session;
71
72
	/**
73
	 * Common data to be sent to views
74
	 * @var array
75
	 */
76
	protected $base_data = [
77
		'url_type' => 'anime',
78
		'other_type' => 'manga',
79
		'menu_name' => ''
80
	];
81
82
	/**
83
	 * Constructor
84
	 *
85
	 * @param ContainerInterface $container
86
	 */
87
	public function __construct(ContainerInterface $container)
88
	{
89
		$this->setContainer($container);
90
		$auraUrlGenerator = $container->get('aura-router')->getGenerator();
91
		$urlGenerator = $container->get('url-generator');
92
		$this->cache =  $container->get('cache');
93
		$this->config = $container->get('config');
94
		$this->request = $container->get('request');
95
		$this->response = $container->get('response');
96
		$this->base_data['url'] = $auraUrlGenerator;
97
		$this->base_data['urlGenerator'] = $urlGenerator;
98
		$this->base_data['auth'] = $container->get('auth');
99
		$this->base_data['config'] = $this->config;
100
		$this->urlGenerator = $urlGenerator;
101
102
		$session = $container->get('session');
103
		$this->session = $session->getSegment(AnimeClient::SESSION_SEGMENT);
104
105
		// Set a 'previous' flash value for better redirects
106
		$server_params = $this->request->getServerParams();
107
		if (array_key_exists('HTTP_REFERER', $server_params))
108
		{
109
			$this->session->setFlash('previous', $server_params['HTTP_REFERER']);
110
		}
111
112
		// Set a message box if available
113
		$this->base_data['message'] = $this->session->getFlash('message');
114
	}
115
116
	/**
117
	 * Redirect to the default controller/url from an empty path
118
	 */
119
	public function redirect_to_default()
120
	{
121
		$default_type = $this->config->get(['routes', 'route_config', 'default_list']);
122
		$this->redirect($this->urlGenerator->default_url($default_type), 303);
123
	}
124
125
	/**
126
	 * Redirect to the previous page
127
	 *
128
	 * @return void
129
	 */
130
	public function redirect_to_previous()
131
	{
132
		$previous = $this->session->getFlash('previous');
133
		$this->redirect($previous, 303);
134
	}
135
136
	/**
137
	 * Set the current url in the session as the target of a future redirect
138
	 *
139
	 * @param string|null $url
140
	 * @return void
141
	 */
142
	public function set_session_redirect($url = NULL)
143
	{
144
		$server_params = $this->request->getServerParams();
145
146
		if ( ! array_key_exists('HTTP_REFERER', $server_params))
147
		{
148
			return;
149
		}
150
151
		$anime_client = $this->container->get('anime-client');
152
		$double_form_page = $server_params['HTTP_REFERER'] == $this->request->getUri();
153
154
		// Don't attempt to set the redirect url if
155
		// the page is one of the form type pages,
156
		// and the previous page is also a form type page_segments
157
		if ($double_form_page)
158
		{
159
			return;
160
		}
161
162
		if (is_null($url))
163
		{
164
			$url = ($anime_client->is_view_page())
165
				? $this->request->url->get()
166
				: $server_params['HTTP_REFERER'];
167
		}
168
169
		$this->session->set('redirect_url', $url);
170
	}
171
172
	/**
173
	 * Redirect to the url previously set in the  session
174
	 *
175
	 * @return void
176
	 */
177
	public function session_redirect()
178
	{
179
		$target = $this->session->get('redirect_url');
180
		if (empty($target))
181
		{
182
			$this->not_found();
183
		}
184
		else
185
		{
186
			$this->redirect($target, 303);
187
			$this->session->set('redirect_url', NULL);
188
		}
189
	}
190
191
	/**
192
	 * Get a class member
193
	 *
194
	 * @param string $key
195
	 * @return object
196
	 */
197
	public function __get($key)
198
	{
199
		$allowed = ['response', 'config'];
200
201
		if (in_array($key, $allowed))
202
		{
203
			return $this->$key;
204
		}
205
206
		return NULL;
207
	}
208
209
	/**
210
	 * Get the string output of a partial template
211
	 *
212
	 * @param HtmlView $view
213
	 * @param string $template
214
	 * @param array $data
215
	 * @return string
216
	 */
217
	protected function load_partial($view, $template, array $data = [])
218
	{
219
		$router = $this->container->get('dispatcher');
220
221
		if (isset($this->base_data))
222
		{
223
			$data = array_merge($this->base_data, $data);
224
		}
225
226
		$route = $router->get_route();
227
		$data['route_path'] = ($route) ? $router->get_route()->path : "";
228
229
230
		$template_path = _dir($this->config->get('view_path'), "{$template}.php");
231
232
		if ( ! is_file($template_path))
233
		{
234
			throw new \InvalidArgumentException("Invalid template : {$template}");
235
		}
236
237
		return $view->render_template($template_path, (array)$data);
238
	}
239
240
	/**
241
	 * Render a template with header and footer
242
	 *
243
	 * @param HtmlView $view
244
	 * @param string $template
245
	 * @param array $data
246
	 * @return void
247
	 */
248
	protected function render_full_page($view, $template, array $data)
249
	{
250
		$view->appendOutput($this->load_partial($view, 'header', $data));
251
252
		if (array_key_exists('message', $data) && is_array($data['message']))
253
		{
254
			$view->appendOutput($this->load_partial($view, 'message', $data['message']));
255
		}
256
257
		$view->appendOutput($this->load_partial($view, $template, $data));
258
		$view->appendOutput($this->load_partial($view, 'footer', $data));
259
	}
260
261
	/**
262
	 * Show the login form
263
	 *
264
	 * @codeCoverageIgnore
265
	 * @param string $status
266
	 * @return void
267
	 */
268
	public function login($status = "")
269
	{
270
		$message = "";
271
272
		$view = new HtmlView($this->container);
273
274
		if ($status != "")
275
		{
276
			$message = $this->show_message($view, 'error', $status);
277
		}
278
279
		// Set the redirect url
280
		$this->set_session_redirect();
281
282
		$this->outputHTML('login', [
283
			'title' => 'Api login',
284
			'message' => $message
285
		], $view);
286
	}
287
288
	/**
289
	 * Attempt login authentication
290
	 *
291
	 * @return void
292
	 */
293
	public function login_action()
294
	{
295
		$auth = $this->container->get('auth');
296
		$post = $this->request->getParsedBody();
297
		if ($auth->authenticate($post['password']))
298
		{
299
			return $this->session_redirect();
300
		}
301
302
		$this->login("Invalid username or password.");
303
	}
304
305
	/**
306
	 * Deauthorize the current user
307
	 *
308
	 * @return void
309
	 */
310
	public function logout()
311
	{
312
		$auth = $this->container->get('auth');
313
		$auth->logout();
314
315
		$this->redirect_to_default();
316
	}
317
318
	/**
319
	 * 404 action
320
	 *
321
	 * @return void
322
	 */
323
	public function not_found()
324
	{
325
		$this->outputHTML('404', [
326
			'title' => 'Sorry, page not found'
327
		], NULL, 404);
328
	}
329
330
	/**
331
	 * Display a generic error page
332
	 *
333
	 * @param int $http_code
334
	 * @param string $title
335
	 * @param string $message
336
	 * @param string $long_message
337
	 * @return void
338
	 */
339
	public function error_page($http_code, $title, $message, $long_message = "")
340
	{
341
		$this->outputHTML('error', [
342
			'title' => $title,
343
			'message' => $message,
344
			'long_message' => $long_message
345
		], NULL, $http_code);
346
	}
347
348
	/**
349
	 * Set a session flash variable to display a message on
350
	 * next page load
351
	 *
352
	 * @param string $message
353
	 * @param string $type
354
	 * @return void
355
	 */
356
	public function set_flash_message($message, $type = "info")
357
	{
358
		$this->session->setFlash('message', [
359
			'message_type' => $type,
360
			'message' => $message
361
		]);
362
	}
363
364
	/**
365
	 * Purges the API cache
366
	 *
367
	 * @return void
368
	 */
369
	public function clear_cache()
370
	{
371
		$this->cache->purge();
372
		$this->outputHTML('blank', [
373
			'title' => 'Cache cleared'
374
		], NULL, 200);
375
	}
376
377
	/**
378
	 * Add a message box to the page
379
	 *
380
	 * @codeCoverageIgnore
381
	 * @param HtmlView $view
382
	 * @param string $type
383
	 * @param string $message
384
	 * @return string
385
	 */
386
	protected function show_message($view, $type, $message)
387
	{
388
		return $this->load_partial($view, 'message', [
389
			'message_type' => $type,
390
			'message'  => $message
391
		]);
392
	}
393
394
	/**
395
	 * Output a template to HTML, using the provided data
396
	 *
397
	 * @param string $template
398
	 * @param array $data
399
	 * @param HtmlView|null $view
400
	 * @param int $code
401
	 * @return void
402
	 */
403
	protected function outputHTML($template, array $data = [], $view = NULL, $code = 200)
404
	{
405
		if (is_null($view))
406
		{
407
			$view = new HtmlView($this->container);
408
		}
409
410
		$view->setStatusCode($code);
411
		$this->render_full_page($view, $template, $data);
412
	}
413
414
	/**
415
	 * Output a JSON Response
416
	 *
417
	 * @param mixed $data
418
	 * @param int $code - the http status code
419
	 * @return void
420
	 */
421
	protected function outputJSON($data = [], $code = 200)
422
	{
423
		$view = new JsonView($this->container);
424
		$view->setStatusCode($code);
425
		$view->setOutput($data);
426
	}
427
428
	/**
429
	 * Redirect to the selected page
430
	 *
431
	 * @param string $url
432
	 * @param int $code
433
	 * @return void
434
	 */
435
	protected function redirect($url, $code)
436
	{
437
		$http = new HttpView($this->container);
438
		$http->redirect($url, $code);
439
	}
440
}
441
// End of BaseController.php