Completed
Pull Request — master (#43)
by Jakub
32:53
created

admin_controller::prepare_end_date()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 10
cts 10
cp 1
rs 9.4285
cc 3
eloc 6
nc 3
nop 1
crap 3
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\ads\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
	const DEFAULT_PRIORITY = 5;
21
22
	/** @var \phpbb\template\template */
23
	protected $template;
24
25
	/** @var \phpbb\user */
26
	protected $user;
27
28
	/** @var \phpbb\request\request */
29
	protected $request;
30
31
	/** @var \phpbb\ads\ad\manager */
32
	protected $manager;
33
34
	/** @var \phpbb\ads\location\manager */
35
	protected $location_manager;
36
37
	/** @var \phpbb\log\log */
38
	protected $log;
39
40
	/** @var \phpbb\config\db_text */
41
	protected $config_text;
42
43
	/** @var \phpbb\config\config */
44
	protected $config;
45
46
	/** @var string php_ext */
47
	protected $php_ext;
48
49
	/** @var string ext_path */
50
	protected $ext_path;
51
52
	/** @var string Custom form action */
53
	protected $u_action;
54
55
	/** @var array Form validation errors */
56
	protected $errors = array();
57
58
	/**
59
	* Constructor
60
	*
61
	* @param \phpbb\template\template				$template			Template object
62
	* @param \phpbb\user							$user				User object
63
	* @param \phpbb\request\request					$request			Request object
64
	* @param \phpbb\ads\ad\manager					$manager			Advertisement manager object
65
	* @param \phpbb\ads\location\manager			$location_manager	Template location manager object
66
	* @param \phpbb\log\log							$log				The phpBB log system
67
	* @param \phpbb\config\db_text					$config_text		Config text object
68
	* @param \phpbb\config\config					$config				Config object
69
	* @param string									$php_ext			PHP extension
70
	* @param string									$ext_path			Path to this extension
71
	*/
72 38
	public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\request\request $request, \phpbb\ads\ad\manager $manager, \phpbb\ads\location\manager $location_manager, \phpbb\log\log $log, \phpbb\config\db_text $config_text, \phpbb\config\config $config, $php_ext, $ext_path)
73
	{
74 38
		$this->template = $template;
75 38
		$this->user = $user;
76 38
		$this->request = $request;
77 38
		$this->manager = $manager;
78 38
		$this->location_manager = $location_manager;
79 38
		$this->log = $log;
80 38
		$this->config_text = $config_text;
81 38
		$this->config = $config;
82 38
		$this->php_ext = $php_ext;
83 38
		$this->ext_path = $ext_path;
84 38
	}
85
86
	/**
87
	* Process user request for manage mode
88
	*
89
	* @return void
90
	*/
91 6
	public function mode_manage()
92
	{
93 6
		$this->setup();
94
95
		// Trigger specific action
96 6
		$action = $this->request->variable('action', '');
97 6
		if (in_array($action, array('add', 'edit', 'enable', 'disable', 'delete')))
98 6
		{
99 5
			$this->{'action_' . $action}();
100 5
		}
101
102
		// Otherwise default to this
103 6
		$this->list_ads();
104 6
	}
105
106
	/**
107
	* Process user request for settings mode
108
	*
109
	* @return void
110
	*/
111 3
	public function mode_settings()
112
	{
113 3
		$this->setup();
114
115 3
		add_form_key('phpbb/ads/settings');
116 3
		if ($this->request->is_set_post('submit'))
117 3
		{
118
			// Validate form key
119 2
			if (!check_form_key('phpbb/ads/settings'))
120 2
			{
121 1
				$this->errors[] = $this->user->lang('FORM_INVALID');
122 1
			}
123
124 2
			if (empty($this->errors))
125 2
			{
126 1
				$this->config->set('phpbb_ads_adblocker_message', $this->request->variable('adblocker_message', 0));
127 1
				$this->config_text->set('phpbb_ads_hide_groups', json_encode($this->request->variable('hide_groups', array(0))));
128
129 1
				$this->success('ACP_AD_SETTINGS_SAVED');
130
			}
131
132 1
			$this->template->assign_vars(array(
133 1
				'S_ERROR'		=> (bool) count($this->errors),
134 1
				'ERROR_MSG'		=> count($this->errors) ? implode('<br />', $this->errors) : '',
135 1
			));
136 1
		}
137
138 2
		$hide_groups = json_decode($this->config_text->get('phpbb_ads_hide_groups'), true);
139 2
		$groups = $this->manager->load_groups();
140 2
		foreach ($groups as $group)
141
		{
142 2
			$group_name = ($group['group_type'] == GROUP_SPECIAL) ? $this->user->lang('G_' . $group['group_name']) : $group['group_name'];
143
144 2
			$this->template->assign_block_vars('groups', array(
145 2
				'ID'			=> $group['group_id'],
146 2
				'NAME'			=> $group_name,
147 2
				'S_SELECTED'	=> in_array($group['group_id'], $hide_groups),
148 2
			));
149 2
		}
150
151 2
		$this->template->assign_vars(array(
152 2
			'U_ACTION'			=> $this->u_action,
153 2
			'ADBLOCKER_MESSAGE'	=> $this->config['phpbb_ads_adblocker_message'],
154 2
		));
155 2
	}
156
157
	/**
158
	* Set page url
159
	*
160
	* @param string $u_action Custom form action
161
	* @return void
162
	*/
163 32
	public function set_page_url($u_action)
164
	{
165 32
		$this->u_action = $u_action;
166 32
	}
167
168
	/**
169
	* Get ACP page title for Ads module
170
	*
171
	* @return string	Language string for Ads ACP module
172
	*/
173 1
	public function get_page_title()
174
	{
175 1
		return $this->user->lang('ACP_PHPBB_ADS_TITLE');
176
	}
177
178
	/**
179
	* Add an advertisement
180
	*
181
	* @return void
182
	*/
183 12
	public function action_add()
184
	{
185 9
		$preview = $this->request->is_set_post('preview');
186 9
		$submit = $this->request->is_set_post('submit');
187
188 9
		add_form_key('phpbb/ads/add');
189 9
		if ($preview || $submit)
190 9
		{
191 8
			$data = $this->get_form_data('phpbb/ads/add');
192
193 View Code Duplication
			if ($preview)
194 8
			{
195 1
				$this->ad_preview($data['ad_code']);
196 12
			}
197
			else if (empty($this->errors))
198 7
			{
199 1
				$ad_id = $this->manager->insert_ad($data);
200 1
				$this->manager->insert_ad_locations($ad_id, $data['ad_locations']);
201
202 1
				$this->log('ADD', $data['ad_name']);
203
204 1
				$this->success('ACP_AD_ADD_SUCCESS');
205
			}
206
207 7
			$this->assign_locations($data);
208 7
			$this->assign_form_data($data);
209 7
		}
210
		else
211
		{
212 1
			$this->assign_locations();
213
		}
214
215
		// Set output vars for display in the template
216 8
		$this->template->assign_vars(array(
217 8
			'S_ADD_AD'				=> true,
218 8
			'U_BACK'				=> $this->u_action,
219 8
			'U_ACTION'				=> "{$this->u_action}&amp;action=add",
220 8
			'PICKER_DATE_FORMAT'	=> self::DATE_FORMAT,
221 8
		));
222 8
	}
223
224
	/**
225
	* Edit an advertisement
226
	*
227
	* @return void
228
	*/
229 11
	public function action_edit()
230
	{
231 11
		$ad_id = $this->request->variable('id', 0);
232 11
		$preview = $this->request->is_set_post('preview');
233 11
		$submit = $this->request->is_set_post('submit');
234
235 11
		add_form_key('phpbb/ads/edit/' . $ad_id);
236 11
		if ($preview || $submit)
237 11
		{
238 9
			$data = $this->get_form_data('phpbb/ads/edit/' . $ad_id);
239
240
			if ($preview)
241 9
			{
242 1
				$this->ad_preview($data['ad_code']);
243 1
			}
244 View Code Duplication
			else if (empty($this->errors))
245 8
			{
246 2
				$success = $this->manager->update_ad($ad_id, $data);
247
248
				if ($success)
249 2
				{
250
					// Only insert new ad locations to DB when ad exists
251 1
					$this->manager->delete_ad_locations($ad_id);
252 1
					$this->manager->insert_ad_locations($ad_id, $data['ad_locations']);
253
254 1
					$this->log('EDIT', $data['ad_name']);
255
256 1
					$this->success('ACP_AD_EDIT_SUCCESS');
257
				}
258 1
				$this->error('ACP_AD_DOES_NOT_EXIST');
259
			}
260 7
		}
261
		else
262
		{
263
			// Load ad data
264 2
			$data = $this->manager->get_ad($ad_id);
265 2
			if (empty($data))
266 2
			{
267 1
				$this->error('ACP_AD_DOES_NOT_EXIST');
268
			}
269
270
			// Load ad template locations
271 1
			$data['ad_locations'] = $this->manager->get_ad_locations($ad_id);
272
		}
273
274
		// Set output vars for display in the template
275 8
		$this->template->assign_vars(array(
276 8
			'S_EDIT_AD'				=> true,
277 8
			'EDIT_ID'				=> $ad_id,
278 8
			'U_BACK'				=> $this->u_action,
279 8
			'U_ACTION'				=> "{$this->u_action}&amp;action=edit&amp;id=" . $ad_id,
280 8
			'PICKER_DATE_FORMAT'	=> self::DATE_FORMAT,
281 8
		));
282 8
		$this->assign_locations($data);
283 8
		$this->assign_form_data($data);
284 8
	}
285
286
	/**
287
	* Enable an advertisement
288
	*
289
	* @return void
290
	*/
291 3
	public function action_enable()
292
	{
293 3
		$this->ad_enable(true);
294 1
	}
295
296
	/**
297
	* Disable an advertisement
298
	*
299
	* @return void
300
	*/
301 3
	public function action_disable()
302
	{
303 3
		$this->ad_enable(false);
304 1
	}
305
306
	/**
307
	* Delete an advertisement
308
	*
309
	* @return void
310
	*/
311 3
	public function action_delete()
312
	{
313 3
		$ad_id = $this->request->variable('id', 0);
314
		if ($ad_id)
315 3
		{
316 3
			if (confirm_box(true))
317 3
			{
318
				// Get ad data so that we can log ad name
319 2
				$ad_data = $this->manager->get_ad($ad_id);
320
321
				// Delete ad and it's template locations
322 2
				$this->manager->delete_ad_locations($ad_id);
323 2
				$success = $this->manager->delete_ad($ad_id);
324
325
				// Only notify user on error or if not ajax
326 2
				if (!$success)
327 2
				{
328 1
					$this->error('ACP_AD_DELETE_ERRORED');
329
				}
330
				else
331
				{
332 1
					$this->log('DELETE', $ad_data['ad_name']);
333
334 1
					if (!$this->request->is_ajax())
335 1
					{
336 1
						$this->success('ACP_AD_DELETE_SUCCESS');
337
					}
338
				}
339
			}
340
			else
341
			{
342 1
				confirm_box(false, $this->user->lang('CONFIRM_OPERATION'), build_hidden_fields(array(
343 1
					'id'		=> $ad_id,
344 1
					'i'			=> $this->request->variable('i', ''),
345 1
					'mode'		=> $this->request->variable('mode', ''),
346
					'action'	=> 'delete'
347 1
				)));
348
			}
349 1
		}
350 1
	}
351
352
	/**
353
	* Display the ads
354
	*
355
	* @return void
356
	*/
357 1
	public function list_ads()
358
	{
359 1
		foreach ($this->manager->get_all_ads() as $row)
360
		{
361 1
			$ad_enabled = (int) $row['ad_enabled'];
362 1
			$ad_end_date = (int) $row['ad_end_date'];
363 1
			$ad_expired = $ad_end_date > 0 && $ad_end_date < time();
364 1
			if ($ad_expired && $ad_enabled)
365 1
			{
366 1
				$ad_enabled = 0;
367 1
				$this->manager->update_ad($row['ad_id'], array('ad_enabled' => 0));
368 1
			}
369
370 1
			$this->template->assign_block_vars('ads', array(
371 1
				'NAME'					=> $row['ad_name'],
372 1
				'END_DATE'				=> $ad_end_date ? $this->user->format_date($ad_end_date, self::DATE_FORMAT) : '',
373 1
				'VIEWS'					=> $row['ad_views'],
374 1
				'CLICKS'				=> $row['ad_clicks'],
375 1
				'VIEWS_LIMIT'			=> $row['ad_views_limit'],
376 1
				'CLICKS_LIMIT'			=> $row['ad_clicks_limit'],
377 1
				'S_END_DATE_EXPIRED'	=> $ad_expired,
378 1
				'S_ENABLED'				=> $ad_enabled,
379 1
				'U_ENABLE'				=> $this->u_action . '&amp;action=' . ($ad_enabled ? 'disable' : 'enable') . '&amp;id=' . $row['ad_id'],
380
				'U_EDIT'				=> $this->u_action . '&amp;action=edit&amp;id=' . $row['ad_id'],
381
				'U_DELETE'				=> $this->u_action . '&amp;action=delete&amp;id=' . $row['ad_id'],
382 1
			));
383 1
		}
384
385
		// Set output vars for display in the template
386
		$this->template->assign_var('U_ACTION_ADD', $this->u_action . '&amp;action=add');
387
	}
388
389
	/**
390 9
	* Perform general tasks
391
	*
392 9
	* @return void
393
	*/
394 9
	protected function setup()
395 9
	{
396
		$this->user->add_lang_ext('phpbb/ads', 'acp');
397
398
		$this->template->assign_var('S_PHPBB_ADS', true);
399
	}
400
401
	/**
402
	* Enable/disable an advertisement
403 4
	*
404
	* @param	bool	$enable	Enable or disable the advertisement?
405 4
	* @return void
406
	*/
407 4
	protected function ad_enable($enable)
408 4
	{
409 4
		$ad_id = $this->request->variable('id', 0);
410
411
		$success = $this->manager->update_ad($ad_id, array(
412 4
			'ad_enabled'	=> (int) $enable,
413 4
		));
414
415
		// If AJAX was used, show user a result message
416
		if ($this->request->is_ajax())
417
		{
418
			$json_response = new \phpbb\json_response;
419
			$json_response->send(array(
420
				'text'	=> $this->user->lang($enable ? 'ENABLED' : 'DISABLED'),
421
				'title'	=> $this->user->lang('AD_ENABLE_TITLE', (int) $enable),
422
			));
423 4
		}
424 2
425
		// Otherwise, show traditional infobox
426
		if ($success)
427
		{
428 2
			$this->success($enable ? 'ACP_AD_ENABLE_SUCCESS' : 'ACP_AD_DISABLE_SUCCESS');
429
		}
430
		else
431
		{
432
			$this->error($enable ? 'ACP_AD_ENABLE_ERRORED' : 'ACP_AD_DISABLE_ERRORED');
433
		}
434
	}
435
436
	/**
437
	* Get admin form data.
438 17
	*
439
	* @param	string	$form_name	The form name.
440
	* @return	array	Form data
441 17
	*/
442 17
	protected function get_form_data($form_name)
443 17
	{
444 17
		$data = array(
445 17
			'ad_name'			=> $this->request->variable('ad_name', '', true),
446 17
			'ad_note'			=> $this->request->variable('ad_note', '', true),
447 17
			'ad_code'			=> $this->request->variable('ad_code', '', true),
448 17
			'ad_enabled'		=> $this->request->variable('ad_enabled', 0),
449
			'ad_locations'		=> $this->request->variable('ad_locations', array('')),
450
			'ad_end_date'		=> $this->request->variable('ad_end_date', ''),
451 17
			'ad_priority'		=> $this->request->variable('ad_priority', self::DEFAULT_PRIORITY),
452 17
			'ad_views_limit'	=> $this->request->variable('ad_views_limit', 0),
453 2
			'ad_clicks_limit'	=> $this->request->variable('ad_clicks_limit', 0),
454 2
		);
455
456
		// Validate form key
457 17
		if (!check_form_key($form_name))
458 17
		{
459 2
			$this->errors[] = $this->user->lang('FORM_INVALID');
460 2
		}
461 17
462 17
		// Validate ad name
463 2
		if ($data['ad_name'] === '')
464 2
		{
465
			$this->errors[] = $this->user->lang('AD_NAME_REQUIRED');
466
		}
467 17
		if (truncate_string($data['ad_name'], self::MAX_NAME_LENGTH) !== $data['ad_name'])
468 17
		{
469 4
			$this->errors[] = $this->user->lang('AD_NAME_TOO_LONG', self::MAX_NAME_LENGTH);
470
		}
471 4
472 4
		// Validate ad end date
473 2
		if (preg_match('#^\d{4}\-\d{2}\-\d{2}$#', $data['ad_end_date']))
474 2
		{
475 4
			$data['ad_end_date'] = (int) $this->user->get_timestamp_from_format(self::DATE_FORMAT, $data['ad_end_date']);
476 13
477 13
			if ($data['ad_end_date'] < time())
478
			{
479
				$this->errors[] = $this->user->lang('AD_END_DATE_INVALID');
480
			}
481
		}
482 13
		else if ($data['ad_end_date'] !== '')
483
		{
484
			$this->errors[] = $this->user->lang('AD_END_DATE_INVALID');
485
		}
486 17
		else
487 17
		{
488 6
			$data['ad_end_date'] = 0;
489 6
		}
490
491 17
		// Validate ad priority
492
		if ($data['ad_priority'] < 1 || $data['ad_priority'] > 10)
493
		{
494
			$this->errors[] = $this->user->lang('AD_PRIORITY_INVALID');
495
		}
496
497
		// Validate ad views limit
498
		if ($data['ad_views_limit'] < 0)
499
		{
500 15
			$this->errors[] = $this->user->lang('AD_VIEWS_LIMIT_INVALID');
501
		}
502 15
503 15
		// Validate ad clicks limit
504 15
		if ($data['ad_clicks_limit'] < 0)
505
		{
506 15
			$this->errors[] = $this->user->lang('AD_CLICKS_LIMIT_INVALID');
507 15
		}
508 15
509 15
		return $data;
510 15
	}
511 15
512 15
	/**
513 15
	* Assign form data to the template.
514
	*
515
	* @param	array	$data	The form data.
516
	* @return void
517
	*/
518
	protected function assign_form_data($data)
519
	{
520
		$this->template->assign_vars(array(
521 15
			'S_ERROR'		=> (bool) count($this->errors),
522
			'ERROR_MSG'		=> count($this->errors) ? implode('<br />', $this->errors) : '',
523 15
524 15
			'AD_NAME'			=> $data['ad_name'],
525 12
			'AD_NOTE'			=> $data['ad_note'],
526
			'AD_CODE'			=> $data['ad_code'],
527
			'AD_ENABLED'		=> $data['ad_enabled'],
528 3
			'AD_END_DATE'		=> $this->prepare_end_date($data['ad_end_date']),
529 3
			'AD_PRIORITY'		=> $data['ad_priority'],
530 3
			'AD_VIEWS_LIMIT'	=> $data['ad_views_limit'],
531
			'AD_CLICKS_LIMIT'	=> $data['ad_clicks_limit'],
532
		));
533
	}
534
535
	/**
536
	* Prepare end date for display
537
	*
538
	* @param	mixed	$end_date	End date.
539
	* @return	string	End date prepared for display.
540
	*/
541
	protected function prepare_end_date($end_date)
542 16
	{
543
		if (empty($end_date))
544 16
		{
545
			return '';
546 16
		}
547 16
548 16
		if (is_numeric($end_date))
549 16
		{
550 16
			return $this->user->format_date($end_date, self::DATE_FORMAT);
551 16
		}
552 16
553 16
		return (string) $end_date;
554
	}
555
556
	/**
557
	* Assign template locations data to the template.
558
	*
559
	* @param	mixed	$data	The form data or nothing.
560
	* @return	void
561 2
	*/
562
	protected function assign_locations($data = false)
563 2
	{
564 2
		foreach ($this->location_manager->get_all_locations() as $location_id => $location_data)
565
		{
566
			$this->template->assign_block_vars('ad_locations', array(
567
				'LOCATION_ID'	=> $location_id,
568
				'LOCATION_DESC'	=> $location_data['desc'],
569
				'LOCATION_NAME'	=> $location_data['name'],
570
				'S_SELECTED'	=> $data ? in_array($location_id, $data['ad_locations']) : false,
571 6
			));
572
		}
573 6
	}
574
575
	/**
576
	* Prepare advertisement preview
577
	*
578
	* @param	string	$code	Ad code to preview
579
	* @return	void
580
	*/
581 5
	protected function ad_preview($code)
582
	{
583 5
		$this->template->assign_var('PREVIEW', htmlspecialchars_decode($code));
584
	}
585
586
	/**
587
	* Print success message.
588
	*
589
	* It takes arguments in the form of a language key, followed by language substitution values.
590
	*/
591
	protected function success()
592
	{
593 3
		trigger_error(call_user_func_array(array($this->user, 'lang'), func_get_args()) . adm_back_link($this->u_action));
594
	}
595 3
596 3
	/**
597
	* Print error message.
598
	*
599
	* It takes arguments in the form of a language key, followed by language substitution values.
600
	*/
601
	protected function error()
602
	{
603
		trigger_error(call_user_func_array(array($this->user, 'lang'), func_get_args()) . adm_back_link($this->u_action), E_USER_WARNING);
604
	}
605
606
	/**
607
	* Log action
608
	*
609
	* @param	string	$action		Performed action in uppercase
610
	* @param	string	$ad_name	Advertisement name
611
	* @return	void
612
	*/
613
	protected function log($action, $ad_name)
614
	{
615
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'ACP_PHPBB_ADS_' . $action . '_LOG', time(), array($ad_name));
616
	}
617
}
618