Completed
Pull Request — master (#132)
by Matt
01:25
created

idea   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 428
Duplicated Lines 19.63 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 2
dl 84
loc 428
rs 9.52
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A get_idea() 11 11 1
A get_idea_by_topic_id() 11 11 1
A get_status_from_id() 0 4 1
A set_status() 0 8 1
A set_duplicate() 15 15 3
A set_rfc() 16 16 3
A set_ticket() 15 15 3
A set_implemented() 16 16 3
A set_title() 0 15 2
A get_title() 0 11 2
A submit() 0 19 2
A delete() 0 19 2
B vote() 0 81 7
A remove_vote() 0 33 3
A get_voters() 0 22 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\factory;
12
13
use phpbb\ideas\ext;
14
15
/**
16
 * Class for handling a single idea
17
 */
18
class idea extends base
19
{
20
	/**
21
	 * Returns the specified idea.
22
	 *
23
	 * @param int $id The ID of the idea to return.
24
	 *
25
	 * @return array|false The idea row set, or false if not found.
26
	 */
27 View Code Duplication
	public function get_idea($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
28
	{
29
		$sql = 'SELECT *
30
			FROM ' . $this->table_ideas . '
31
			WHERE idea_id = ' . (int) $id;
32
		$result = $this->db->sql_query_limit($sql, 1);
33
		$row = $this->db->sql_fetchrow($result);
34
		$this->db->sql_freeresult($result);
35
36
		return $row;
37
	}
38
39
	/**
40
	 * Returns an idea specified by its topic ID.
41
	 *
42
	 * @param int $id The ID of the idea to return.
43
	 *
44
	 * @return array|false The idea row set, or false if not found.
45
	 */
46 View Code Duplication
	public function get_idea_by_topic_id($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
47
	{
48
		$sql = 'SELECT idea_id
49
			FROM ' . $this->table_ideas . '
50
			WHERE topic_id = ' . (int) $id;
51
		$result = $this->db->sql_query_limit($sql, 1);
52
		$idea_id = (int) $this->db->sql_fetchfield('idea_id');
53
		$this->db->sql_freeresult($result);
54
55
		return $this->get_idea($idea_id);
56
	}
57
58
	/**
59
	 * Returns the status name from the status ID specified.
60
	 *
61
	 * @param int $id ID of the status.
62
	 *
63
	 * @return string|bool The status name if it exists, false otherwise.
64
	 */
65
	public function get_status_from_id($id)
66
	{
67
		return $this->language->lang(array_search($id, ext::$statuses));
68
	}
69
70
	/**
71
	 * Updates the status of an idea.
72
	 *
73
	 * @param int $idea_id The ID of the idea.
74
	 * @param int $status  The ID of the status.
75
	 *
76
	 * @return void
77
	 */
78
	public function set_status($idea_id, $status)
79
	{
80
		$sql_ary = array(
81
			'idea_status' => (int) $status,
82
		);
83
84
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
85
	}
86
87
	/**
88
	 * Sets the ID of the duplicate for an idea.
89
	 *
90
	 * @param int    $idea_id   ID of the idea to be updated.
91
	 * @param string $duplicate Idea ID of duplicate.
92
	 *
93
	 * @return bool True if set, false if invalid.
94
	 */
95 View Code Duplication
	public function set_duplicate($idea_id, $duplicate)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
	{
97
		if ($duplicate && !is_numeric($duplicate))
98
		{
99
			return false;
100
		}
101
102
		$sql_ary = array(
103
			'duplicate_id'	=> (int) $duplicate,
104
		);
105
106
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
107
108
		return true;
109
	}
110
111
	/**
112
	 * Sets the RFC link of an idea.
113
	 *
114
	 * @param int    $idea_id ID of the idea to be updated.
115
	 * @param string $rfc     Link to the RFC.
116
	 *
117
	 * @return bool True if set, false if invalid.
118
	 */
119 View Code Duplication
	public function set_rfc($idea_id, $rfc)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
120
	{
121
		$match = '/^https?:\/\/area51\.phpbb\.com\/phpBB\/viewtopic\.php/';
122
		if ($rfc && !preg_match($match, $rfc))
123
		{
124
			return false;
125
		}
126
127
		$sql_ary = array(
128
			'rfc_link'	=> $rfc, // string is escaped by build_array()
129
		);
130
131
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
132
133
		return true;
134
	}
135
136
	/**
137
	 * Sets the ticket ID of an idea.
138
	 *
139
	 * @param int    $idea_id ID of the idea to be updated.
140
	 * @param string $ticket  Ticket ID.
141
	 *
142
	 * @return bool True if set, false if invalid.
143
	 */
144 View Code Duplication
	public function set_ticket($idea_id, $ticket)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
	{
146
		if ($ticket && !is_numeric($ticket))
147
		{
148
			return false;
149
		}
150
151
		$sql_ary = array(
152
			'ticket_id'	=> (int) $ticket,
153
		);
154
155
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
156
157
		return true;
158
	}
159
160
	/**
161
	 * Sets the implemented version of an idea.
162
	 *
163
	 * @param int    $idea_id ID of the idea to be updated.
164
	 * @param string $version Version of phpBB the idea was implemented in.
165
	 *
166
	 * @return bool True if set, false if invalid.
167
	 */
168 View Code Duplication
	public function set_implemented($idea_id, $version)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
	{
170
		$match = '/^\d\.\d\.\d+(\-\w+)?$/';
171
		if ($version && !preg_match($match, $version))
172
		{
173
			return false;
174
		}
175
176
		$sql_ary = array(
177
			'implemented_version'	=> $version, // string is escaped by build_array()
178
		);
179
180
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
181
182
		return true;
183
	}
184
185
	/**
186
	 * Sets the title of an idea.
187
	 *
188
	 * @param int    $idea_id ID of the idea to be updated.
189
	 * @param string $title   New title.
190
	 *
191
	 * @return boolean True if updated, false if invalid length.
192
	 */
193
	public function set_title($idea_id, $title)
194
	{
195
		if (utf8_clean_string($title) === '')
196
		{
197
			return false;
198
		}
199
200
		$sql_ary = array(
201
			'idea_title' => truncate_string($title, ext::SUBJECT_LENGTH),
202
		);
203
204
		$this->update_idea_data($sql_ary, $idea_id, $this->table_ideas);
205
206
		return true;
207
	}
208
209
	/**
210
	 * Get the title of an idea.
211
	 *
212
	 * @param int $id ID of an idea
213
	 *
214
	 * @return string The idea's title, empty string if not found
215
	 */
216
	public function get_title($id)
217
	{
218
		$sql = 'SELECT idea_title
219
			FROM ' . $this->table_ideas . '
220
			WHERE idea_id = ' . (int) $id;
221
		$result = $this->db->sql_query_limit($sql, 1);
222
		$idea_title = $this->db->sql_fetchfield('idea_title');
223
		$this->db->sql_freeresult($result);
224
225
		return $idea_title ?: '';
226
	}
227
228
	/**
229
	 * Submit new idea data to the ideas table
230
	 *
231
	 * @param array $data An array of post data from a newly posted idea
232
	 *
233
	 * @return int The ID of the new idea.
234
	 */
235
	public function submit($data)
236
	{
237
		$sql_ary = [
238
			'idea_title'	=> $data['topic_title'],
239
			'idea_author'	=> $data['poster_id'],
240
			'idea_date'		=> $data['post_time'],
241
			'topic_id'		=> $data['topic_id'],
242
		];
243
244
		$idea_id = $this->insert_idea_data($sql_ary, $this->table_ideas);
245
246
		// Initial vote
247
		if (($idea = $this->get_idea($idea_id)) !== false)
248
		{
249
			$this->vote($idea, $data['poster_id'], 1);
250
		}
251
252
		return $idea_id;
253
	}
254
255
	/**
256
	 * Deletes an idea and the topic to go with it.
257
	 *
258
	 * @param int $id       The ID of the idea to be deleted.
259
	 * @param int $topic_id The ID of the idea topic. Optional, but preferred.
260
	 *
261
	 * @return boolean Whether the idea was deleted or not.
262
	 */
263
	public function delete($id, $topic_id = 0)
264
	{
265
		if (!$topic_id)
266
		{
267
			$idea = $this->get_idea($id);
268
			$topic_id = $idea['topic_id'];
269
		}
270
271
		// Delete topic
272
		delete_posts('topic_id', $topic_id);
273
274
		// Delete idea
275
		$deleted = $this->delete_idea_data($id, $this->table_ideas);
276
277
		// Delete votes
278
		$this->delete_idea_data($id, $this->table_votes);
279
280
		return $deleted;
281
	}
282
283
	/**
284
	 * Submits a vote on an idea.
285
	 *
286
	 * @param array $idea    The idea returned by get_idea().
287
	 * @param int   $user_id The ID of the user voting.
288
	 * @param int   $value   Up (1) or down (0)?
289
	 *
290
	 * @return array|string Array of information or string on error.
291
	 */
292
	public function vote(&$idea, $user_id, $value)
293
	{
294
		// Validate $vote - must be 0 or 1
295
		if ($value !== 0 && $value !== 1)
296
		{
297
			return 'INVALID_VOTE';
298
		}
299
300
		// Check whether user has already voted - update if they have
301
		$sql = 'SELECT idea_id, vote_value
302
			FROM ' . $this->table_votes . '
303
			WHERE idea_id = ' . (int) $idea['idea_id'] . '
304
				AND user_id = ' . (int) $user_id;
305
		$this->db->sql_query_limit($sql, 1);
306
		if ($row = $this->db->sql_fetchrow())
307
		{
308
			if ($row['vote_value'] != $value)
309
			{
310
				$sql = 'UPDATE ' . $this->table_votes . '
311
					SET vote_value = ' . $value . '
312
					WHERE user_id = ' . (int) $user_id . '
313
						AND idea_id = ' . (int) $idea['idea_id'];
314
				$this->db->sql_query($sql);
315
316
				if ($value == 1)
317
				{
318
					// Change to upvote
319
					$idea['idea_votes_up']++;
320
					$idea['idea_votes_down']--;
321
				}
322
				else
323
				{
324
					// Change to downvote
325
					$idea['idea_votes_up']--;
326
					$idea['idea_votes_down']++;
327
				}
328
329
				$sql_ary = array(
330
					'idea_votes_up'	    => $idea['idea_votes_up'],
331
					'idea_votes_down'	=> $idea['idea_votes_down'],
332
				);
333
334
				$this->update_idea_data($sql_ary, $idea['idea_id'], $this->table_ideas);
335
			}
336
337
			return array(
338
				'message'	    => $this->language->lang('UPDATED_VOTE'),
339
				'votes_up'	    => $idea['idea_votes_up'],
340
				'votes_down'	=> $idea['idea_votes_down'],
341
				'points'        => $this->language->lang('TOTAL_POINTS', $idea['idea_votes_up'] - $idea['idea_votes_down']),
342
				'voters'		=> $this->get_voters($idea['idea_id']),
343
			);
344
		}
345
346
		// Insert vote into votes table.
347
		$sql_ary = array(
348
			'idea_id'		=> (int) $idea['idea_id'],
349
			'user_id'		=> (int) $user_id,
350
			'vote_value'	=> (int) $value,
351
		);
352
353
		$this->insert_idea_data($sql_ary, $this->table_votes);
354
355
		// Update number of votes in ideas table
356
		$idea['idea_votes_' . ($value ? 'up' : 'down')]++;
357
358
		$sql_ary = array(
359
			'idea_votes_up'	    => $idea['idea_votes_up'],
360
			'idea_votes_down'	=> $idea['idea_votes_down'],
361
		);
362
363
		$this->update_idea_data($sql_ary, $idea['idea_id'], $this->table_ideas);
364
365
		return array(
366
			'message'	    => $this->language->lang('VOTE_SUCCESS'),
367
			'votes_up'	    => $idea['idea_votes_up'],
368
			'votes_down'	=> $idea['idea_votes_down'],
369
			'points'        => $this->language->lang('TOTAL_POINTS', $idea['idea_votes_up'] - $idea['idea_votes_down']),
370
			'voters'		=> $this->get_voters($idea['idea_id']),
371
		);
372
	}
373
374
	/**
375
	 * Remove a user's vote from an idea
376
	 *
377
	 * @param array   $idea    The idea returned by get_idea().
378
	 * @param int     $user_id The ID of the user voting.
379
	 *
380
	 * @return array Array of information.
381
	 */
382
	public function remove_vote(&$idea, $user_id)
383
	{
384
		// Only change something if user has already voted
385
		$sql = 'SELECT idea_id, vote_value
386
			FROM ' . $this->table_votes . '
387
			WHERE idea_id = ' . (int) $idea['idea_id'] . '
388
				AND user_id = ' . (int) $user_id;
389
		$this->db->sql_query_limit($sql, 1);
390
		if ($row = $this->db->sql_fetchrow())
391
		{
392
			$sql = 'DELETE FROM ' . $this->table_votes . '
393
				WHERE idea_id = ' . (int) $idea['idea_id'] . '
394
					AND user_id = ' . (int) $user_id;
395
			$this->db->sql_query($sql);
396
397
			$idea['idea_votes_' . ($row['vote_value'] == 1 ? 'up' : 'down')]--;
398
399
			$sql_ary = array(
400
				'idea_votes_up'	    => $idea['idea_votes_up'],
401
				'idea_votes_down'	=> $idea['idea_votes_down'],
402
			);
403
404
			$this->update_idea_data($sql_ary, $idea['idea_id'], $this->table_ideas);
405
		}
406
407
		return array(
408
			'message'	    => $this->language->lang('UPDATED_VOTE'),
409
			'votes_up'	    => $idea['idea_votes_up'],
410
			'votes_down'	=> $idea['idea_votes_down'],
411
			'points'        => $this->language->lang('TOTAL_POINTS', $idea['idea_votes_up'] - $idea['idea_votes_down']),
412
			'voters'		=> $this->get_voters($idea['idea_id']),
413
		);
414
	}
415
416
	/**
417
	 * Returns voter info on an idea.
418
	 *
419
	 * @param int $id ID of the idea.
420
	 *
421
	 * @return array Array of row data
422
	 */
423
	public function get_voters($id)
424
	{
425
		$sql = 'SELECT iv.user_id, iv.vote_value, u.username, u.user_colour
426
			FROM ' . $this->table_votes . ' as iv,
427
				' . USERS_TABLE . ' as u
428
			WHERE iv.idea_id = ' . (int) $id . '
429
				AND iv.user_id = u.user_id
430
			ORDER BY u.username ASC';
431
		$result = $this->db->sql_query($sql);
432
		$rows = $this->db->sql_fetchrowset($result);
433
		$this->db->sql_freeresult($result);
434
435
		// Process the username for the template now, so it is
436
		// ready to use in AJAX responses and DOM injections.
437
		$profile_url = append_sid(generate_board_url() . "/memberlist.{$this->php_ext}", array('mode' => 'viewprofile'));
438
		foreach ($rows as &$row)
439
		{
440
			$row['user'] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url);
441
		}
442
443
		return $rows;
444
	}
445
}
446