Completed
Push — master ( bb1be4...cd866c )
by Matt
17s
created

admin_controller::setup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 *
4
 * Advertisement management. An extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2017 phpBB Limited <https://www.phpbb.com>
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace phpbb\admanagement\controller;
12
13
/**
14
* Admin controller
15
*/
16
class admin_controller
17
{
18
	const MAX_NAME_LENGTH = 255;
19
	const DATE_FORMAT = 'Y-m-d';
20
21
	/** @var \phpbb\template\template */
22
	protected $template;
23
24
	/** @var \phpbb\user */
25
	protected $user;
26
27
	/** @var \phpbb\request\request */
28
	protected $request;
29
30
	/** @var \phpbb\admanagement\ad\manager */
31
	protected $manager;
32
33
	/** @var \phpbb\admanagement\location\manager */
34
	protected $location_manager;
35
36
	/** @var \phpbb\log\log */
37
	protected $log;
38
39
	/** @var \phpbb\config\db_text */
40
	protected $config_text;
41
42
	/** @var string php_ext */
43
	protected $php_ext;
44
45
	/** @var string ext_path */
46
	protected $ext_path;
47
48
	/** @var string Custom form action */
49
	protected $u_action;
50
51
	/** @var array Form validation errors */
52
	protected $errors = array();
53
54
	/**
55
	* Constructor
56
	*
57
	* @param \phpbb\template\template				$template			Template object
58
	* @param \phpbb\user							$user				User object
59
	* @param \phpbb\request\request					$request			Request object
60
	* @param \phpbb\admanagement\ad\manager			$manager			Advertisement manager object
61
	* @param \phpbb\admanagement\location\manager	$location_manager	Template location manager object
62
	* @param \phpbb\log\log							$log				The phpBB log system
63
	* @param \phpbb\config\db_text					$config_text		Config text object
64
	* @param string									$php_ext			PHP extension
65
	* @param string									$ext_path			Path to this extension
66
	*/
67 34
	public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\request\request $request, \phpbb\admanagement\ad\manager $manager, \phpbb\admanagement\location\manager $location_manager, \phpbb\log\log $log, \phpbb\config\db_text $config_text, $php_ext, $ext_path)
68
	{
69 34
		$this->template = $template;
70 34
		$this->user = $user;
71 34
		$this->request = $request;
72 34
		$this->manager = $manager;
73 34
		$this->location_manager = $location_manager;
74 34
		$this->log = $log;
75 34
		$this->config_text = $config_text;
76 34
		$this->php_ext = $php_ext;
77 34
		$this->ext_path = $ext_path;
78 34
	}
79
80
	/**
81
	* Process user request for manage mode
82
	*
83
	* @return void
84
	*/
85 6
	public function mode_manage()
86
	{
87 6
		$this->setup();
88
89
		// Trigger specific action
90 6
		$action = $this->request->variable('action', '');
91 6
		if (in_array($action, array('add', 'edit', 'enable', 'disable', 'delete')))
92 6
		{
93 5
			$this->{'action_' . $action}();
94 5
		}
95
96
		// Otherwise default to this
97 6
		$this->list_ads();
98 6
	}
99
100
	/**
101
	* Process user request for settings mode
102
	*
103
	* @return void
104
	*/
105 3
	public function mode_settings()
106
	{
107 3
		$this->setup();
108
109 3
		add_form_key('phpbb/admanagement/settings');
110 3
		if ($this->request->is_set_post('submit'))
111 3
		{
112
			// Validate form key
113 2
			if (!check_form_key('phpbb/admanagement/settings'))
114 2
			{
115 1
				$this->errors[] = $this->user->lang('FORM_INVALID');
116 1
			}
117
118 2
			if (empty($this->errors))
119 2
			{
120 1
				$this->config_text->set('phpbb_admanagement_hide_groups', json_encode($this->request->variable('hide_groups', array(0))));
121
122 1
				$this->success('ACP_AD_SETTINGS_SAVED');
123
			}
124
125 1
			$this->template->assign_vars(array(
126 1
				'S_ERROR'		=> (bool) count($this->errors),
127 1
				'ERROR_MSG'		=> count($this->errors) ? implode('<br />', $this->errors) : '',
128 1
			));
129 1
		}
130
131 2
		$hide_groups = json_decode($this->config_text->get('phpbb_admanagement_hide_groups'), true);
132 2
		$groups = $this->manager->load_groups();
133 2
		foreach ($groups as $group)
134
		{
135 2
			$group_name = ($group['group_type'] == GROUP_SPECIAL) ? $this->user->lang('G_' . $group['group_name']) : $group['group_name'];
136
137 2
			$this->template->assign_block_vars('groups', array(
138 2
				'ID'			=> $group['group_id'],
139 2
				'NAME'			=> $group_name,
140 2
				'S_SELECTED'	=> in_array($group['group_id'], $hide_groups),
141 2
			));
142 2
		}
143 2
	}
144
145
	/**
146
	* Set page url
147
	*
148
	* @param string $u_action Custom form action
149
	* @return void
150
	*/
151 28
	public function set_page_url($u_action)
152
	{
153 28
		$this->u_action = $u_action;
154 28
	}
155
156
	/**
157
	* Get ACP page title for Ads module
158
	*
159
	* @return string	Language string for Ads ACP module
160
	*/
161 1
	public function get_page_title()
162
	{
163 1
		return $this->user->lang('ACP_ADMANAGEMENT_TITLE');
164
	}
165
166
	/**
167
	* Add an advertisement
168
	*
169
	* @return void
170
	*/
171 16
	public function action_add()
172
	{
173 7
		$preview = $this->request->is_set_post('preview');
174 7
		$submit = $this->request->is_set_post('submit');
175
176 7
		add_form_key('phpbb/admanagement/add');
177 7
		if ($preview || $submit)
178 7
		{
179 6
			$data = $this->get_form_data('phpbb/admanagement/add');
180
181 View Code Duplication
			if ($preview)
182 6
			{
183 1
				$this->ad_preview($data['ad_code']);
184 1
			}
185
			else if (empty($this->errors))
186 5
			{
187 1
				$ad_id = $this->manager->insert_ad($data);
188 1
				$this->manager->insert_ad_locations($ad_id, $data['ad_locations']);
189
190 1
				$this->log('ADD', $data['ad_name']);
191
192 1
				$this->success('ACP_AD_ADD_SUCCESS');
193
			}
194
195 5
			$this->assign_locations($data);
196 16
			$this->assign_form_data($data);
197 5
		}
198
		else
199
		{
200 1
			$this->assign_locations();
201
		}
202
203
		// Set output vars for display in the template
204 6
		$this->template->assign_vars(array(
205 6
			'S_ADD_AD'				=> true,
206 6
			'U_BACK'				=> $this->u_action,
207 6
			'PICKER_DATE_FORMAT'	=> self::DATE_FORMAT,
208 6
		));
209 6
	}
210
211
	/**
212
	* Edit an advertisement
213
	*
214
	* @return void
215
	*/
216 9
	public function action_edit()
217
	{
218 9
		$ad_id = $this->request->variable('id', 0);
219 9
		$preview = $this->request->is_set_post('preview');
220 9
		$submit = $this->request->is_set_post('submit');
221
222 9
		add_form_key('phpbb/admanagement/edit/' . $ad_id);
223 9
		if ($preview || $submit)
224 9
		{
225 7
			$data = $this->get_form_data('phpbb/admanagement/edit/' . $ad_id);
226
227
			if ($preview)
228 7
			{
229 1
				$this->ad_preview($data['ad_code']);
230 1
			}
231 View Code Duplication
			else if (empty($this->errors))
232 6
			{
233 2
				$success = $this->manager->update_ad($ad_id, $data);
234
235
				if ($success)
236 2
				{
237
					// Only insert new ad locations to DB when ad exists
238 1
					$this->manager->delete_ad_locations($ad_id);
239 1
					$this->manager->insert_ad_locations($ad_id, $data['ad_locations']);
240
241 1
					$this->log('EDIT', $data['ad_name']);
242
243 1
					$this->success('ACP_AD_EDIT_SUCCESS');
244
				}
245 1
				$this->error('ACP_AD_DOES_NOT_EXIST');
246
			}
247 5
		}
248
		else
249
		{
250
			// Load ad data
251 2
			$data = $this->manager->get_ad($ad_id);
252 2
			if (empty($data))
253 2
			{
254 1
				$this->error('ACP_AD_DOES_NOT_EXIST');
255
			}
256
257
			// Load ad template locations
258 1
			$data['ad_locations'] = $this->manager->get_ad_locations($ad_id);
259
		}
260
261
		// Set output vars for display in the template
262 6
		$this->template->assign_vars(array(
263 6
			'S_EDIT_AD'				=> true,
264 6
			'EDIT_ID'				=> $ad_id,
265 6
			'U_BACK'				=> $this->u_action,
266 6
			'PICKER_DATE_FORMAT'	=> self::DATE_FORMAT,
267 6
		));
268 6
		$this->assign_locations($data);
269 6
		$this->assign_form_data($data);
270 6
	}
271
272
	/**
273
	* Enable an advertisement
274
	*
275
	* @return void
276
	*/
277 3
	public function action_enable()
278
	{
279 3
		$this->ad_enable(true);
280 1
	}
281
282
	/**
283
	* Disable an advertisement
284
	*
285
	* @return void
286
	*/
287 3
	public function action_disable()
288
	{
289 3
		$this->ad_enable(false);
290 1
	}
291
292
	/**
293
	* Delete an advertisement
294
	*
295
	* @return void
296
	*/
297 3
	public function action_delete()
298
	{
299 3
		$ad_id = $this->request->variable('id', 0);
300
		if ($ad_id)
301 3
		{
302 3
			if (confirm_box(true))
303 3
			{
304
				// Get ad data so that we can log ad name
305 2
				$ad_data = $this->manager->get_ad($ad_id);
306
307
				// Delete ad and it's template locations
308 2
				$this->manager->delete_ad_locations($ad_id);
309 2
				$success = $this->manager->delete_ad($ad_id);
310
311
				// Only notify user on error or if not ajax
312 2
				if (!$success)
313 2
				{
314 1
					$this->error('ACP_AD_DELETE_ERRORED');
315
				}
316
				else
317
				{
318 1
					$this->log('DELETE', $ad_data['ad_name']);
319
320 1
					if (!$this->request->is_ajax())
321 1
					{
322 1
						$this->success('ACP_AD_DELETE_SUCCESS');
323
					}
324
				}
325
			}
326
			else
327
			{
328 1
				confirm_box(false, $this->user->lang('CONFIRM_OPERATION'), build_hidden_fields(array(
329 1
					'id'		=> $ad_id,
330 1
					'i'			=> $this->request->variable('i', ''),
331 1
					'mode'		=> $this->request->variable('mode', ''),
332
					'action'	=> 'delete'
333 1
				)));
334
			}
335 1
		}
336 1
	}
337
338
	/**
339
	* Display the ads
340
	*
341
	* @return void
342
	*/
343 1
	public function list_ads()
344
	{
345 1
		foreach ($this->manager->get_all_ads() as $row)
346
		{
347 1
			$ad_enabled = (int) $row['ad_enabled'];
348 1
			$ad_end_date = (int) $row['ad_end_date'];
349 1
			$ad_expired = $ad_end_date > 0 && $ad_end_date < time();
350 1
			if ($ad_expired && $ad_enabled)
351 1
			{
352 1
				$ad_enabled = 0;
353 1
				$this->manager->update_ad($row['ad_id'], array('ad_enabled' => 0));
354 1
			}
355
356 1
			$this->template->assign_block_vars('ads', array(
357 1
				'NAME'					=> $row['ad_name'],
358 1
				'END_DATE'				=> $ad_end_date ? $this->user->format_date($ad_end_date, self::DATE_FORMAT) : '',
359 1
				'S_END_DATE_EXPIRED'	=> $ad_expired,
360 1
				'S_ENABLED'				=> $ad_enabled,
361 1
				'U_ENABLE'				=> $this->u_action . '&amp;action=' . ($ad_enabled ? 'disable' : 'enable') . '&amp;id=' . $row['ad_id'],
362 1
				'U_EDIT'				=> $this->u_action . '&amp;action=edit&amp;id=' . $row['ad_id'],
363 1
				'U_DELETE'				=> $this->u_action . '&amp;action=delete&amp;id=' . $row['ad_id'],
364 1
			));
365 1
		}
366
367
		// Set output vars for display in the template
368 1
		$this->template->assign_var('U_ACTION_ADD', $this->u_action . '&amp;action=add');
369 1
	}
370
371
	/**
372
	* Perform general tasks
373
	*
374
	* @return void
375
	*/
376 9
	protected function setup()
377
	{
378 9
		$this->user->add_lang_ext('phpbb/admanagement', 'acp');
379
380 9
		$this->template->assign_var('S_PHPBB_ADMANAGEMENT', true);
381 9
	}
382
383
	/**
384
	* Enable/disable an advertisement
385
	*
386
	* @param	bool	$enable	Enable or disable the advertisement?
387
	* @return void
388
	*/
389 4
	protected function ad_enable($enable)
390
	{
391 4
		$ad_id = $this->request->variable('id', 0);
392
393 4
		$success = $this->manager->update_ad($ad_id, array(
394 4
			'ad_enabled'	=> (int) $enable,
395 4
		));
396
397
		// If AJAX was used, show user a result message
398 4
		if ($this->request->is_ajax())
399 4
		{
400
			$json_response = new \phpbb\json_response;
401
			$json_response->send(array(
402
				'text'	=> $this->user->lang($enable ? 'ENABLED' : 'DISABLED'),
403
				'title'	=> $this->user->lang('AD_ENABLE_TITLE', (int) $enable),
404
			));
405
		}
406
407
		// Otherwise, show traditional infobox
408
		if ($success)
409 4
		{
410 2
			$this->success($enable ? 'ACP_AD_ENABLE_SUCCESS' : 'ACP_AD_DISABLE_SUCCESS');
411
		}
412
		else
413
		{
414 2
			$this->error($enable ? 'ACP_AD_ENABLE_ERRORED' : 'ACP_AD_DISABLE_ERRORED');
415
		}
416
	}
417
418
	/**
419
	* Get admin form data.
420
	*
421
	* @param	string	$form_name	The form name.
422
	* @return	array	Form data
423
	*/
424 13
	protected function get_form_data($form_name)
425
	{
426
		$data = array(
427 13
			'ad_name'		=> $this->request->variable('ad_name', '', true),
428 13
			'ad_note'		=> $this->request->variable('ad_note', '', true),
429 13
			'ad_code'		=> $this->request->variable('ad_code', '', true),
430 13
			'ad_enabled'	=> $this->request->variable('ad_enabled', 0),
431 13
			'ad_locations'	=> $this->request->variable('ad_locations', array('')),
432 13
			'ad_end_date'	=> $this->request->variable('ad_end_date', ''),
433 13
		);
434
435
		// Validate form key
436 13
		if (!check_form_key($form_name))
437 13
		{
438 2
			$this->errors[] = $this->user->lang('FORM_INVALID');
439 2
		}
440
441
		// Validate ad name
442 13
		if ($data['ad_name'] === '')
443 13
		{
444 2
			$this->errors[] = $this->user->lang('AD_NAME_REQUIRED');
445 2
		}
446 13
		if (truncate_string($data['ad_name'], self::MAX_NAME_LENGTH) !== $data['ad_name'])
447 13
		{
448 2
			$this->errors[] = $this->user->lang('AD_NAME_TOO_LONG', self::MAX_NAME_LENGTH);
449 2
		}
450
451
		// Validate ad end date
452 13
		if (preg_match('#^\d{4}\-\d{2}\-\d{2}$#', $data['ad_end_date']))
453 13
		{
454 4
			$data['ad_end_date'] = (int) $this->user->get_timestamp_from_format(self::DATE_FORMAT, $data['ad_end_date']);
455
456 4
			if ($data['ad_end_date'] < time())
457 4
			{
458 2
				$this->errors[] = $this->user->lang('AD_END_DATE_INVALID');
459 2
			}
460 4
		}
461 9
		else if ($data['ad_end_date'] !== '')
462 9
		{
463
			$this->errors[] = $this->user->lang('AD_END_DATE_INVALID');
464
		}
465
		else
466
		{
467 9
			$data['ad_end_date'] = 0;
468
		}
469
470 13
		return $data;
471
	}
472
473
	/**
474
	* Assign form data to the template.
475
	*
476
	* @param	array	$data	The form data.
477
	* @return void
478
	*/
479 11
	protected function assign_form_data($data)
480
	{
481 11
		$this->template->assign_vars(array(
482 11
			'S_ERROR'		=> (bool) count($this->errors),
483 11
			'ERROR_MSG'		=> count($this->errors) ? implode('<br />', $this->errors) : '',
484
485 11
			'AD_NAME'		=> $data['ad_name'],
486 11
			'AD_NOTE'		=> $data['ad_note'],
487 11
			'AD_CODE'		=> $data['ad_code'],
488 11
			'AD_ENABLED'	=> $data['ad_enabled'],
489 11
			'AD_END_DATE'	=> $this->prepare_end_date($data['ad_end_date']),
490 11
		));
491 11
	}
492
	/**
493
	* Prepare end date for display
494
	*
495
	* @param	mixed	$end_date	End date.
496
	* @return	string	End date prepared for display.
497
	*/
498 11
	protected function prepare_end_date($end_date)
499
	{
500 11
		if (empty($end_date))
501 11
		{
502 8
			return '';
503
		}
504 3
		else if (is_numeric($end_date))
505 3
		{
506 3
			return $this->user->format_date($end_date, self::DATE_FORMAT);
507
		}
508
509
		return $end_date;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $end_date; (object|string|null|array|boolean) is incompatible with the return type documented by phpbb\admanagement\contr...oller::prepare_end_date of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
510
	}
511
512
	/**
513
	* Assign template locations data to the template.
514
	*
515
	* @param	mixed	$data	The form data or nothing.
516
	* @return	void
517
	*/
518 12
	protected function assign_locations($data = false)
519
	{
520 12
		foreach ($this->location_manager->get_all_locations() as $location_id => $location_data)
521
		{
522 12
			$this->template->assign_block_vars('ad_locations', array(
523 12
				'LOCATION_ID'	=> $location_id,
524 12
				'LOCATION_DESC'	=> $location_data['desc'],
525 12
				'LOCATION_NAME'	=> $location_data['name'],
526 12
				'S_SELECTED'	=> $data ? in_array($location_id, $data['ad_locations']) : false,
527 12
			));
528 12
		}
529 12
	}
530
531
	/**
532
	* Prepare advertisement preview
533
	*
534
	* @param	string	$code	Ad code to preview
535
	* @return	void
536
	*/
537 2
	protected function ad_preview($code)
538
	{
539 2
		$this->template->assign_var('PREVIEW', htmlspecialchars_decode($code));
540 2
	}
541
542
	/**
543
	* Print success message.
544
	*
545
	* It takes arguments in the form of a language key, followed by language substitution values.
546
	*/
547 6
	protected function success()
548
	{
549 6
		trigger_error(call_user_func_array(array($this->user, 'lang'), func_get_args()) . adm_back_link($this->u_action));
550
	}
551
552
	/**
553
	* Print error message.
554
	*
555
	* It takes arguments in the form of a language key, followed by language substitution values.
556
	*/
557 5
	protected function error()
558
	{
559 5
		trigger_error(call_user_func_array(array($this->user, 'lang'), func_get_args()) . adm_back_link($this->u_action), E_USER_WARNING);
560
	}
561
562
	/**
563
	* Log action
564
	*
565
	* @param	string	$action		Performed action in uppercase
566
	* @param	string	$ad_name	Advertisement name
567
	* @return	void
568
	*/
569 3
	protected function log($action, $ad_name)
570
	{
571 3
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'ACP_ADMANAGEMENT_' . $action . '_LOG', time(), array($ad_name));
572 3
	}
573
}
574