MergeTopics::action_mergeExecute()   D
last analyzed

Complexity

Conditions 18
Paths 156

Size

Total Lines 124
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 342

Importance

Changes 0
Metric Value
cc 18
eloc 56
c 0
b 0
f 0
nc 156
nop 1
dl 0
loc 124
rs 4.3999
ccs 0
cts 85
cp 0
crap 342

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Handle merging of topics
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 * Original module by Mach8 - We'll never forget you.
16
 * ETA: Sorry, we did.
17
 */
18
19
namespace ElkArte\Controller;
20
21
use ElkArte\AbstractController;
22
use ElkArte\Action;
23
use ElkArte\Exceptions\Exception;
24
use ElkArte\TopicsMerge;
25
26
/**
27
 * Merges two or more topics into a single topic.
28
 */
29
class MergeTopics extends AbstractController
30
{
31
	/**
32
	 * Merges two or more topics into one topic.
33
	 *
34
	 * What it does:
35
	 *
36
	 * - delegates to the other functions (based on the URL parameter sa).
37
	 * - loads the MergeTopics template.
38
	 * - requires the merge_any permission.
39
	 * - is accessed with ?action=mergetopics.
40
	 *
41
	 * @see AbstractController::action_index
42
	 */
43
	public function action_index()
44
	{
45
		global $context;
46
47
		// Load the template....
48
		theme()->getTemplates()->load('MergeTopics');
49
50
		$subActions = array(
51
			'done' => array($this, 'action_mergeDone'),
52
			'execute' => array($this, 'action_mergeExecute'),
53
			'index' => array($this, 'action_mergeIndex'),
54
			'options' => array($this, 'action_mergeExecute')
55
		);
56
57
		// ?action=mergetopics;sa=LETSBREAKIT won't work, sorry.
58
		$action = new Action('merge_topics');
59
		$subAction = $action->initialize($subActions, 'index');
60
		$context['sub_action'] = $subAction;
61
		$action->dispatch($subAction);
62
	}
63
64
	/**
65
	 * Allows to pick a topic to merge the current topic with.
66
	 *
67
	 * What it does:
68
	 *
69
	 * - is accessed with ?action=mergetopics;sa=index
70
	 * - default sub action for ?action=mergetopics.
71
	 * - uses 'merge' sub template of the MergeTopics template.
72
	 * - allows to set a different target board.
73
	 */
74
	public function action_mergeIndex()
75
	{
76
		global $txt, $board, $context, $modSettings;
77
78
		// If we don't know where you are from we know where you go
79
		$from = $this->_req->getQuery('from', 'intval', null);
80
		if (!isset($from))
81
		{
82
			throw new Exception('no_access', false);
83
		}
84
85
		$target_board = $this->_req->getPost('targetboard', 'intval', $board);
86
		$context['target_board'] = $target_board;
87
88
		// Prepare a handy query bit for approval...
89
		if ($modSettings['postmod_active'])
90
		{
91
			$can_approve_boards = empty($this->user->mod_cache['ap']) ? boardsAllowedTo('approve_posts') : $this->user->mod_cache['ap'];
0 ignored issues
show
Bug Best Practice introduced by
The property mod_cache does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
92
			$onlyApproved = $can_approve_boards !== array(0) && !in_array($target_board, $can_approve_boards);
93
		}
94
		else
95
		{
96
			$onlyApproved = false;
97
		}
98
99
		// How many topics are on this board?  (used for paging.)
100
		require_once(SUBSDIR . '/Topic.subs.php');
101
		$topiccount = countTopicsByBoard($target_board, $onlyApproved);
102
103
		// Make the page list.
104
		$context['page_index'] = constructPageIndex('{scripturl}?action=mergetopics;from=' . $from . ';targetboard=' . $target_board . ';board=' . $board . '.%1$d', $this->_req->query->start, $topiccount, $modSettings['defaultMaxTopics'], true);
105
106
		// Get the topic's subject.
107
		$topic_info = getTopicInfo($from, 'message');
108
109
		// @todo review: double check the logic
110
		if (empty($topic_info) || ($topic_info['id_board'] != $board) || ($onlyApproved && empty($topic_info['approved'])))
111
		{
112
			throw new Exception('no_board');
113
		}
114
115
		// Tell the template a few things..
116
		$context['origin_topic'] = $from;
117
		$context['origin_subject'] = $topic_info['subject'];
118
		$context['origin_js_subject'] = addcslashes(addslashes($topic_info['subject']), '/');
119
		$context['page_title'] = $txt['merge'];
120
121
		// Check which boards you have merge permissions on.
122
		$merge_boards = boardsAllowedTo('merge_any');
123
124
		if (empty($merge_boards))
125
		{
126
			throw new Exception('cannot_merge_any', 'user');
127
		}
128
129
		// Get a list of boards they can navigate to to merge.
130
		require_once(SUBSDIR . '/Boards.subs.php');
131
		$boardListOptions = array(
132
			'not_redirection' => true
133
		);
134
135
		if (!in_array(0, $merge_boards))
136
		{
137
			$boardListOptions['included_boards'] = $merge_boards;
138
		}
139
140
		$boards_list = getBoardList($boardListOptions, true);
141
		$context['boards'] = array();
142
143
		foreach ($boards_list as $board)
144
		{
145
			$context['boards'][] = array(
146
				'id' => $board['id_board'],
147
				'name' => $board['board_name'],
148
				'category' => $board['cat_name']
149
			);
150
		}
151
152
		// Get some topics to merge it with.
153
		$context['topics'] = mergeableTopics($target_board, $from, $onlyApproved, $this->_req->query->start);
154
155
		if (empty($context['topics']) && count($context['boards']) <= 1)
156
		{
157
			throw new Exception('merge_need_more_topics');
158
		}
159
160
		$context['sub_template'] = 'merge';
161
	}
162
163
	/**
164
	 * Set merge options and do the actual merge of two or more topics.
165
	 *
166
	 * The merge options screen:
167
	 * - shows topics to be merged and allows to set some merge options.
168
	 * - is accessed by ?action=mergetopics;sa=options and can also internally be called by action_quickmod().
169
	 * - uses 'merge_extra_options' sub template of the MergeTopics template.
170
	 *
171
	 * The actual merge:
172
	 * - is accessed with ?action=mergetopics;sa=execute.
173
	 * - updates the statistics to reflect the merge.
174
	 * - logs the action in the moderation log.
175
	 * - sends a notification is sent to all users monitoring this topic.
176
	 * - redirects to ?action=mergetopics;sa=done.
177
	 *
178
	 * @param int[] $topics = array() of topic ids
179
	 *
180
	 * @return bool
181
	 * @throws Exception merge_need_more_topics
182
	 */
183
	public function action_mergeExecute($topics = array())
184
	{
185
		global $txt, $context;
186
187
		// Check the session.
188
		checkSession('request');
189
190
		require_once(SUBSDIR . '/Topic.subs.php');
191
		require_once(SUBSDIR . '/Post.subs.php');
192
193
		// Handle URLs from action_mergeIndex.
194
		if (!empty($this->_req->query->from) && !empty($this->_req->query->to))
195
		{
196
			$topics = array((int) $this->_req->query->from, (int) $this->_req->query->to);
197
		}
198
199
		// If we came from a form, the topic IDs came by post.
200
		if (!empty($this->_req->post->topics) && is_array($this->_req->post->topics))
201
		{
202
			$topics = $this->_req->post->topics;
203
		}
204
205
		// There's nothing to merge with just one topic...
206
		if (empty($topics) || !is_array($topics) || count($topics) === 1)
207
		{
208
			throw new Exception('merge_need_more_topics');
209
		}
210
211
		// Send the topics to the TopicsMerge class
212
		$merger = new TopicsMerge($topics);
213
214
		// If we didn't get any topics then they've been messing with unapproved stuff.
215
		if ($merger->hasErrors())
216
		{
217
			$error = $merger->firstError();
218
			throw new Exception($error[0], $error[1]);
219
		}
220
221
		// The parameters of action_mergeExecute were set, so this must've been an internal call.
222
		isAllowedTo('merge_any', $merger->boards);
223
		theme()->getTemplates()->load('MergeTopics');
224
225
		// Get the boards a user is allowed to merge in.
226
		$allowedto_merge_boards = boardsAllowedTo('merge_any');
227
228
		// No permissions to merge, your effort ends here
229
		if (empty($allowedto_merge_boards))
230
		{
231
			throw new Exception('cannot_merge_any', 'user');
232
		}
233
234
		// Make sure they can see all boards....
235
		$query_boards = array('boards' => $merger->boards);
236
237
		if (!in_array(0, $allowedto_merge_boards))
238
		{
239
			$query_boards['boards'] = array_merge($query_boards['boards'], $allowedto_merge_boards);
240
		}
241
242
		// Saved in a variable to (potentially) save a query later
243
		require_once(SUBSDIR . '/Boards.subs.php');
244
		$boards_info = fetchBoardsInfo($query_boards);
245
246
		$boardListOptions = array(
247
			'not_redirection' => true,
248
			'selected_board' => $merger->firstBoard,
249
		);
250
251
		if (!in_array(0, $allowedto_merge_boards))
252
		{
253
			$boardListOptions['included_boards'] = $allowedto_merge_boards;
254
		}
255
256
		$context += getBoardList($boardListOptions);
257
258
		// This is removed to avoid the board not being selectable.
259
		$context['current_board'] = null;
260
261
		// This happens when a member is moderator of a board he cannot see
262
		foreach ($merger->boards as $board)
263
		{
264
			if (!isset($boards_info[$board]))
265
			{
266
				throw new Exception('no_board');
267
			}
268
		}
269
270
		if (empty($this->_req->query->sa) || $this->_req->query->sa === 'options')
271
		{
272
			$context['polls'] = $merger->getPolls();
273
			$context['topics'] = $merger->topic_data;
274
			$context['target_board'] = $this->_req->getQuery('board', 'intval', 0);
275
276
			foreach ($merger->topic_data as $id => $topic)
277
			{
278
				$context['topics'][$id]['selected'] = $topic['id'] == $merger->firstTopic;
279
			}
280
281
			$context['page_title'] = $txt['merge'];
282
			$context['sub_template'] = 'merge_extra_options';
283
284
			return true;
285
		}
286
287
		$result = $merger->doMerge(array(
288
			'board' => $merger->boards[0],
289
			'poll' => $this->_req->getPost('poll', 'intval', 0),
290
			'subject' => $this->_req->getPost('subject', 'trim', ''),
291
			'custom_subject' => $this->_req->getPost('custom_subject', 'trim', ''),
292
			'enforce_subject' => $this->_req->getPost('enforce_subject', 'trim', ''),
293
			'notifications' => $this->_req->getPost('notifications', 'trim', ''),
294
			'accessible_boards' => array_keys($boards_info),
295
		));
296
297
		if ($merger->hasErrors())
298
		{
299
			$error = $merger->firstError();
300
			throw new Exception($error[0], $error[1]);
301
		}
302
303
		// Send them to the all done page.
304
		redirectexit('action=mergetopics;sa=done;to=' . $result[0] . ';targetboard=' . $result[1]);
305
306
		return true;
307
	}
308
309
	/**
310
	 * Shows a 'merge completed' screen.
311
	 *
312
	 * - is accessed with ?action=mergetopics;sa=done.
313
	 * - uses 'merge_done' sub template of the MergeTopics template.
314
	 */
315
	public function action_mergeDone()
316
	{
317
		global $txt, $context;
318
319
		// Make sure the template knows everything...
320
		$context['target_board'] = (int) $this->_req->query->targetboard;
321
		$context['target_topic'] = (int) $this->_req->query->to;
322
323
		$context['page_title'] = $txt['merge'];
324
		$context['sub_template'] = 'merge_done';
325
	}
326
}
327