listener   B
last analyzed

Complexity

Total Complexity 52

Size/Duplication

Total Lines 417
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
wmc 52
eloc 151
c 9
b 0
f 0
dl 0
loc 417
rs 7.44

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A submit_idea_before() 0 9 2
A global_template_vars() 0 7 3
C show_idea() 0 95 17
A getSubscribedEvents() 0 12 1
A is_post_idea() 0 13 3
A edit_idea_title() 0 12 5
A show_post_buttons() 0 11 3
A viewonline_ideas() 0 7 5
A is_ideas_forum() 0 3 1
A submit_idea_template() 0 20 3
A ideas_forum_redirect() 0 5 2
A submit_idea_after() 0 16 3
A adjust_quickmod_tools() 0 24 2
A is_first_post() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like listener often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use listener, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 *
4
 * Ideas extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace phpbb\ideas\event;
12
13
use phpbb\auth\auth;
14
use phpbb\config\config;
15
use phpbb\controller\helper;
16
use phpbb\ideas\ext;
17
use phpbb\ideas\factory\idea;
18
use phpbb\ideas\factory\linkhelper;
19
use phpbb\language\language;
20
use phpbb\template\template;
21
use phpbb\user;
22
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
24
class listener implements EventSubscriberInterface
25
{
26
	/** @var auth */
27
	protected $auth;
28
29
	/* @var config */
30
	protected $config;
31
32
	/* @var helper */
33
	protected $helper;
34
35
	/* @var idea */
36
	protected $idea;
37
38
	/** @var language */
39
	protected $language;
40
41
	/* @var linkhelper */
42
	protected $link_helper;
43
44
	/* @var template */
45
	protected $template;
46
47
	/* @var user */
48
	protected $user;
49
50
	/** @var string */
51
	protected $php_ext;
52
53
	/**
54
	 * @param auth       $auth
55
	 * @param config     $config
56
	 * @param helper     $helper
57
	 * @param idea       $idea
58
	 * @param language   $language
59
	 * @param linkhelper $link_helper
60
	 * @param template   $template
61
	 * @param user       $user
62
	 * @param string     $php_ext
63
	 */
64
	public function __construct(auth $auth, config $config, helper $helper, idea $idea, language $language, linkhelper $link_helper, template $template, user $user, $php_ext)
65
	{
66
		$this->auth = $auth;
67
		$this->config = $config;
68
		$this->helper = $helper;
69
		$this->idea = $idea;
70
		$this->language = $language;
71
		$this->link_helper = $link_helper;
72
		$this->template = $template;
73
		$this->user = $user;
74
		$this->php_ext = $php_ext;
75
76
		$this->language->add_lang('common', 'phpbb/ideas');
77
	}
78
79
	/**
80
	 * @inheritDoc
81
	 */
82
	public static function getSubscribedEvents()
83
	{
84
		return array(
85
			'core.page_header'							=> 'global_template_vars',
86
			'core.viewforum_get_topic_data'				=> 'ideas_forum_redirect',
87
			'core.viewtopic_modify_post_row'			=> 'show_post_buttons',
88
			'core.viewtopic_modify_page_title'			=> 'show_idea',
89
			'core.viewtopic_add_quickmod_option_before'	=> 'adjust_quickmod_tools',
90
			'core.viewonline_overwrite_location'		=> 'viewonline_ideas',
91
			'core.posting_modify_template_vars'			=> 'submit_idea_template',
92
			'core.posting_modify_submit_post_before'	=> 'submit_idea_before',
93
			'core.posting_modify_submit_post_after'		=> [['submit_idea_after'], ['edit_idea_title']],
94
		);
95
	}
96
97
	/**
98
	 * Assign global template variables
99
	 *
100
	 * @return void
101
	 */
102
	public function global_template_vars()
103
	{
104
		if ($this->user->data['is_registered'] && !$this->user->data['is_bot'])
105
		{
106
			$this->template->assign_var(
107
				'U_SEARCH_MY_IDEAS',
108
				$this->helper->route('phpbb_ideas_list_controller', ['sort' => ext::SORT_MYIDEAS, 'status' => '-1'])
109
			);
110
		}
111
	}
112
113
	/**
114
	 * Redirect users from the forum to the Ideas centre
115
	 *
116
	 * @param \phpbb\event\data $event The event object
117
	 * @return void
118
	 * @access public
119
	 */
120
	public function ideas_forum_redirect($event)
121
	{
122
		if ($this->is_ideas_forum($event['forum_id']))
123
		{
124
			redirect($this->helper->route('phpbb_ideas_index_controller'));
125
		}
126
	}
127
128
	/**
129
	 * Show post buttons (hide delete, quote or warn user buttons)
130
	 *
131
	 * @param \phpbb\event\data $event The event object
132
	 * @return void
133
	 * @access public
134
	 */
135
	public function show_post_buttons($event)
136
	{
137
		if (!$this->is_ideas_forum($event['row']['forum_id']))
138
		{
139
			return;
140
		}
141
142
		if ($this->is_first_post($event['topic_data']['topic_first_post_id'], $event['row']['post_id']))
143
		{
144
			$event->update_subarray('post_row', 'U_DELETE', false);
145
			$event->update_subarray('post_row', 'U_WARN', false);
146
		}
147
	}
148
149
	/**
150
	 * Show the idea related to the current topic
151
	 *
152
	 * @param \phpbb\event\data $event The event object
153
	 * @return void
154
	 * @access public
155
	 */
156
	public function show_idea($event)
157
	{
158
		if (!$this->is_ideas_forum($event['forum_id']))
159
		{
160
			return;
161
		}
162
163
		$idea = $this->idea->get_idea_by_topic_id($event['topic_data']['topic_id']);
164
165
		if (!$idea)
166
		{
167
			return;
168
		}
169
170
		$mod = $this->auth->acl_get('m_', (int) $this->config['ideas_forum_id']);
171
		$own = $idea['idea_author'] === $this->user->data['user_id'];
172
173
		if ($mod)
174
		{
175
			$this->template->assign_var('STATUS_ARY', ext::$statuses);
176
177
			// Add quick mod option for deleting an idea
178
			$this->template->alter_block_array('quickmod', array(
179
				'VALUE'		=> 'delete_topic', // delete topic is used here simply to enable ajax
180
				'TITLE'		=> $this->language->lang('DELETE_IDEA'),
181
				'LINK'		=> $this->link_helper->get_idea_link($idea['idea_id'], 'delete'),
182
			));
183
		}
184
185
		$points = $idea['idea_votes_up'] - $idea['idea_votes_down'];
186
		$can_vote = ($idea['idea_status'] != ext::$statuses['IMPLEMENTED'] &&
187
			$idea['idea_status'] != ext::$statuses['DUPLICATE'] &&
188
			$this->auth->acl_get('f_vote', (int) $this->config['ideas_forum_id']) &&
189
			$event['topic_data']['topic_status'] != ITEM_LOCKED);
190
191
		$s_voted_up = $s_voted_down = false;
192
		if ($idea['idea_votes_up'] || $idea['idea_votes_down'])
193
		{
194
			$votes = $this->idea->get_voters($idea['idea_id']);
195
196
			foreach ($votes as $vote)
197
			{
198
				$this->template->assign_block_vars('votes_' . ($vote['vote_value'] ? 'up' : 'down'), array(
199
					'USER' => $vote['user'],
200
				));
201
202
				if ($this->user->data['user_id'] == $vote['user_id'])
203
				{
204
					$s_voted_up = ((int) $vote['vote_value'] === 1);
205
					$s_voted_down = ((int) $vote['vote_value'] === 0);
206
				}
207
			}
208
		}
209
210
		$this->template->assign_vars(array(
211
			'IDEA_ID'			=> $idea['idea_id'],
212
			'IDEA_TITLE'		=> $idea['idea_title'],
213
			'IDEA_VOTES'		=> $idea['idea_votes_up'] + $idea['idea_votes_down'],
214
			'IDEA_VOTES_UP'		=> $idea['idea_votes_up'],
215
			'IDEA_VOTES_DOWN'	=> $idea['idea_votes_down'],
216
			'IDEA_POINTS'		=> $points,
217
			'IDEA_STATUS_ID'	=> $idea['idea_status'],
218
			'IDEA_STATUS_NAME'	=> $this->language->lang(ext::status_name($idea['idea_status'])),
219
220
			'IDEA_DUPLICATE'	=> $idea['duplicate_id'] ? $this->idea->get_title($idea['duplicate_id']) : '',
221
			'IDEA_RFC'			=> $idea['rfc_link'],
222
			'IDEA_TICKET'		=> $idea['ticket_id'],
223
			'IDEA_IMPLEMENTED'	=> $idea['implemented_version'],
224
225
			'S_IS_MOD'			=> $mod,
226
			'S_CAN_EDIT'		=> $mod || $own,
227
			'S_CAN_VOTE'		=> $can_vote,
228
			'S_CAN_VOTE_UP'		=> $can_vote && !$s_voted_up,
229
			'S_CAN_VOTE_DOWN'	=> $can_vote && !$s_voted_down,
230
			'S_VOTED'			=> $s_voted_up || $s_voted_down,
231
			'S_VOTED_UP'		=> $s_voted_up,
232
			'S_VOTED_DOWN'		=> $s_voted_down,
233
234
			'U_CHANGE_STATUS'	=> $this->link_helper->get_idea_link($idea['idea_id'], 'status', true),
235
			'U_EDIT_DUPLICATE'	=> $this->link_helper->get_idea_link($idea['idea_id'], 'duplicate', true),
236
			'U_EDIT_RFC'		=> $this->link_helper->get_idea_link($idea['idea_id'], 'rfc', true),
237
			'U_EDIT_IMPLEMENTED'=> $this->link_helper->get_idea_link($idea['idea_id'], 'implemented', true),
238
			'U_EDIT_TICKET'		=> $this->link_helper->get_idea_link($idea['idea_id'], 'ticket', true),
239
			'U_REMOVE_VOTE'		=> $this->link_helper->get_idea_link($idea['idea_id'], 'removevote', true),
240
			'U_IDEA_VOTE'		=> $this->link_helper->get_idea_link($idea['idea_id'], 'vote', true),
241
			'U_IDEA_DUPLICATE'	=> $this->link_helper->get_idea_link($idea['duplicate_id']),
242
			'U_IDEA_STATUS_LINK'=> $this->helper->route('phpbb_ideas_list_controller', ['status' => $idea['idea_status']]),
243
			'U_TITLE_LIVESEARCH'=> $this->helper->route('phpbb_ideas_livesearch_controller'),
244
		));
245
246
		// Use Ideas breadcrumbs
247
		$this->template->destroy_block_vars('navlinks');
248
		$this->template->assign_block_vars('navlinks', array(
249
			'U_VIEW_FORUM'		=> $this->helper->route('phpbb_ideas_index_controller'),
250
			'FORUM_NAME'		=> $this->language->lang('IDEAS'),
251
		));
252
	}
253
254
	/**
255
	 * Adjust the QuickMod tools displayed
256
	 * (hide options to delete, restore, make global, sticky or announcement)
257
	 *
258
	 * @param \phpbb\event\data $event The event object
259
	 * @return void
260
	 * @access public
261
	 */
262
	public function adjust_quickmod_tools($event)
263
	{
264
		if (!$this->is_ideas_forum($event['forum_id']))
265
		{
266
			return;
267
		}
268
269
		$quickmod_array = $event['quickmod_array'];
270
271
		//$quickmod_array['lock'][1] = false;
272
		//$quickmod_array['unlock'][1] = false;
273
		$quickmod_array['delete_topic'][1] = false;
274
		$quickmod_array['restore_topic'][1] = false;
275
		//$quickmod_array['move'][1] = false;
276
		//$quickmod_array['split'][1] = false;
277
		//$quickmod_array['merge'][1] = false;
278
		//$quickmod_array['merge_topic'][1] = false;
279
		//$quickmod_array['fork'][1] = false;
280
		$quickmod_array['make_normal'][1] = false;
281
		$quickmod_array['make_sticky'][1] = false;
282
		$quickmod_array['make_announce'][1] = false;
283
		$quickmod_array['make_global'][1] = false;
284
285
		$event['quickmod_array'] = $quickmod_array;
286
	}
287
288
	/**
289
	 * Show users as viewing Ideas on Who Is Online page
290
	 *
291
	 * @param \phpbb\event\data $event The event object
292
	 * @return void
293
	 * @access public
294
	 */
295
	public function viewonline_ideas($event)
296
	{
297
		if (($event['on_page'][1] === 'viewtopic' && $event['row']['session_forum_id'] == $this->config['ideas_forum_id']) ||
298
			($event['on_page'][1] === 'app' && strrpos($event['row']['session_page'], 'app.' . $this->php_ext . '/ideas') === 0))
299
		{
300
			$event['location'] = $this->language->lang('VIEWING_IDEAS');
301
			$event['location_url'] = $this->helper->route('phpbb_ideas_index_controller');
302
		}
303
	}
304
305
	/**
306
	 * Modify the Ideas forum's posting page
307
	 *
308
	 * @param \phpbb\event\data $event The event object
309
	 */
310
	public function submit_idea_template($event)
311
	{
312
		if (!$this->is_ideas_forum($event['forum_id']))
313
		{
314
			return;
315
		}
316
317
		// Alter some posting page template vars
318
		if ($event['mode'] === 'post')
319
		{
320
			$event['page_title'] = $this->language->lang('POST_IDEA');
321
			$event->update_subarray('page_data', 'L_POST_A', $this->language->lang('POST_IDEA'));
322
			$event->update_subarray('page_data', 'U_VIEW_FORUM', $this->helper->route('phpbb_ideas_index_controller'));
323
		}
324
325
		// Alter posting page breadcrumbs to link to the ideas controller
326
		$this->template->alter_block_array('navlinks', [
327
			'U_BREADCRUMB'		=> $this->helper->route('phpbb_ideas_index_controller'),
328
			'BREADCRUMB_NAME'	=> $this->language->lang('IDEAS'),
329
		], false, 'change');
330
	}
331
332
	/**
333
	 * Prepare post data vars before posting a new idea/topic.
334
	 *
335
	 * @param \phpbb\event\data $event The event object
336
	 */
337
	public function submit_idea_before($event)
338
	{
339
		if (!$this->is_post_idea($event['mode'], $event['data']['forum_id'], empty($event['data']['topic_id'])))
340
		{
341
			return;
342
		}
343
344
		// We need $post_time after submit_post(), but it's not available in the post $data, unless we set it now
345
		$event->update_subarray('data', 'post_time', time());
346
	}
347
348
	/**
349
	 * Submit the idea data after posting a new idea/topic.
350
	 *
351
	 * @param \phpbb\event\data $event The event object
352
	 */
353
	public function submit_idea_after($event)
354
	{
355
		if (!$this->is_post_idea($event['mode'], $event['data']['forum_id'], !empty($event['data']['topic_id'])))
356
		{
357
			return;
358
		}
359
360
		$this->idea->submit($event['data']);
361
362
		// Show users whose posts need approval a special message
363
		if (!$this->auth->acl_get('f_noapprove', $event['data']['forum_id']))
364
		{
365
			// Using refresh and trigger error because we can't throw http_exceptions from posting.php
366
			$url = $this->helper->route('phpbb_ideas_index_controller');
367
			meta_refresh(10, $url);
368
			trigger_error($this->language->lang('IDEA_STORED_MOD', $url));
369
		}
370
	}
371
372
	/**
373
	 * Update the idea's title when post title is edited.
374
	 *
375
	 * @param \phpbb\event\data $event The event object
376
	 * @return void
377
	 * @access public
378
	 */
379
	public function edit_idea_title($event)
380
	{
381
		if ($event['mode'] !== 'edit' ||
382
			!$event['update_subject'] ||
383
			!$this->is_ideas_forum($event['forum_id']) ||
384
			!$this->is_first_post($event['post_data']['topic_first_post_id'], $event['post_id']))
385
		{
386
			return;
387
		}
388
389
		$idea = $this->idea->get_idea_by_topic_id($event['topic_id']);
390
		$this->idea->set_title($idea['idea_id'], $event['post_data']['post_subject']);
391
	}
392
393
	/**
394
	 * Test if we are on the posting page for a new idea
395
	 *
396
	 * @param string $mode       Mode should be post
397
	 * @param int    $forum_id   The forum posting is being made in
398
	 * @param bool   $topic_flag Flag for the state of the topic_id
399
	 *
400
	 * @return bool True if mode is post, forum is Ideas forum, and a topic id is
401
	 *              expected to exist yet, false if any of these tests failed.
402
	 */
403
	protected function is_post_idea($mode, $forum_id, $topic_flag = true)
404
	{
405
		if ($mode !== 'post')
406
		{
407
			return false;
408
		}
409
410
		if (!$this->is_ideas_forum($forum_id))
411
		{
412
			return false;
413
		}
414
415
		return $topic_flag;
416
	}
417
418
	/**
419
	 * Check if forum id is for the ideas the forum
420
	 *
421
	 * @param int $forum_id
422
	 * @return bool
423
	 * @access public
424
	 */
425
	protected function is_ideas_forum($forum_id)
426
	{
427
		return (int) $forum_id === (int) $this->config['ideas_forum_id'];
428
	}
429
430
	/**
431
	 * Check if a post is the first post in a topic
432
	 *
433
	 * @param int|string $topic_first_post_id
434
	 * @param int|string $post_id
435
	 * @return bool
436
	 * @access protected
437
	 */
438
	protected function is_first_post($topic_first_post_id, $post_id)
439
	{
440
		return (int) $topic_first_post_id === (int) $post_id;
441
	}
442
}
443