Completed
Branch develop (d8e67e)
by Timothy
04:10
created

Controller::__construct()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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