Completed
Pull Request — master (#48)
by Jakub
08:27
created

admin_controller::ad_preview()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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