RemoveTopic::_verifyDeletePermissions()   C
last analyzed

Complexity

Conditions 13
Paths 7

Size

Total Lines 33
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 0
Metric Value
cc 13
eloc 16
nc 7
nop 0
dl 0
loc 33
ccs 0
cts 15
cp 0
crap 182
rs 6.6166
c 0
b 0
f 0

How to fix   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
 * The contents of this file handle the deletion of topics, posts, and related
5
 * paraphernalia.
6
 *
7
 * @package   ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
10
 *
11
 * This file contains code covered by:
12
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
13
 *
14
 * @version 2.0 dev
15
 *
16
 */
17
18
namespace ElkArte\Controller;
19
20
use ElkArte\AbstractController;
21
use ElkArte\Exceptions\Exception;
22
use ElkArte\MessagesDelete;
23
24
/**
25
 * Handles the deletion of topics, posts
26
 */
27
class RemoveTopic extends AbstractController
28
{
29
	/** @var array Hold topic information for supplied message */
30
	private $_topic_info;
31
32
	/**
33
	 * Pre Dispatch, called before other methods.
34
	 */
35
	public function pre_dispatch()
36
	{
37
		// This has some handy functions for topics
38
		require_once(SUBSDIR . '/Topic.subs.php');
39
	}
40
41
	/**
42
	 * Intended entry point for this class.
43
	 *
44
	 * All actions are directly called from other points, so there
45
	 * is currently nothing to action in this method.
46
	 *
47
	 * @see AbstractController::action_index
48
	 */
49
	public function action_index()
50
	{
51
		// call the right method
52
	}
53
54
	/**
55
	 * Completely remove an entire topic.
56
	 *
57
	 * What it does:
58
	 *
59
	 * - Redirects to the board when completed.
60
	 * - Accessed by ?action=removetopic2
61
	 * - Removes a topic if it has not already been removed.
62
	 */
63
	public function action_removetopic2()
64
	{
65
		global $topic, $board, $modSettings;
66
67
		// Make sure they aren't being lead around by someone. (:@)
68
		checkSession('get');
69
70
		// Trying to fool us around, are we?
71
		if (empty($topic))
72
		{
73
			redirectexit();
74
		}
75
76
		// This file needs to be included for sendNotifications().
77
		require_once(SUBSDIR . '/Notification.subs.php');
78
79
		// Check if its been recycled
80
		removeDeleteConcurrence();
81
82
		$this->_topic_info = getTopicInfo($topic, 'message');
83
84
		// Can you remove your own or any topic
85
		if ($this->_topic_info['id_member_started'] == $this->user->id && !allowedTo('remove_any'))
86
		{
87
			isAllowedTo('remove_own');
88
		}
89
		else
90
		{
91
			isAllowedTo('remove_any');
92
		}
93
94
		// Can they see the topic to remove it?
95
		$this->_checkApproval();
96
97
		// Notify people that this topic has been removed.
98
		sendNotifications($topic, 'remove');
99
100
		// Remove the topic
101
		removeTopics($topic);
102
103
		// Note, only log topic ID in native form if it's not gone forever.
104
		if (allowedTo('remove_any') || (allowedTo('remove_own') && $this->_topic_info['id_member_started'] == $this->user->id))
105
		{
106
			logAction('remove', array(
107
					(empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $board ? 'topic' : 'old_topic_id') => $topic,
108
					'subject' => $this->_topic_info['subject'],
109
					'member' => $this->_topic_info['id_member_started'],
110
					'board' => $board)
111
			);
112
		}
113
114
		// Back to the board where the topic was removed from
115
		redirectexit('board=' . $board . '.0');
116
	}
117
118
	/**
119
	 * Verifies the user has permissions to remove an unapproved message/topic
120
	 */
121
	private function _checkApproval()
122
	{
123
		global $modSettings;
124
125
		// Verify they can see this!
126
		if ($modSettings['postmod_active']
127
			&& !$this->_topic_info['approved']
128
			&& !empty($this->_topic_info['id_member'])
129
			&& $this->_topic_info['id_member'] != $this->user->id)
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
130
		{
131
			isAllowedTo('approve_posts');
132
		}
133
	}
134
135
	/**
136
	 * Remove just a single post.
137
	 *
138
	 * What it does:
139
	 *  - On completion redirect to the topic or to the board.
140
	 *  - Accessed by ?action=deletemsg
141
	 *  - Verifies the message exists and that they can see the message
142
	 */
143
	public function action_deletemsg()
144
	{
145
		global $topic, $modSettings;
146
147
		checkSession('get');
148
149
		// This has some handy functions for topics
150
		require_once(SUBSDIR . '/Messages.subs.php');
151
152
		// Need a message to remove
153
		$_msg = $this->_req->getQuery('msg', 'intval', null);
154
155
		// Is $topic set?
156
		if (empty($topic) && isset($this->_req->query->topic))
157
		{
158
			$topic = (int) $this->_req->query->topic;
159
		}
160
161
		// Trying to mess around are we?
162
		if (empty($_msg))
163
		{
164
			redirectexit();
165
		}
166
167
		// Permanently removing from the recycle bin?
168
		removeDeleteConcurrence();
169
170
		// Load the message details
171
		$this->_topic_info = loadMessageDetails(
172
			array('t.id_member_started'),
173
			array('LEFT JOIN {db_prefix}topics AS t ON (m.id_topic = t.id_topic)'),
174
			array('message_list' => $_msg)
175
		);
176
177
		// Can they see the message to remove it?
178
		$this->_checkApproval();
179
180
		// Ensure they can do this
181
		$this->_verifyDeletePermissions();
182
183
		// Do the removal, track if we removed the entire topic, so we redirect back to the board.
184
		$remover = new MessagesDelete($modSettings['recycle_enable'], $modSettings['recycle_board']);
185
		$full_topic = $remover->removeMessage($_msg);
186
187
		$this->_redirectBack($full_topic);
188
	}
189
190
	/**
191
	 * Verifies the user has the permissions needed to remove a message
192
	 *
193
	 * - @uses isAllowedTo() which will end processing if user lacks proper permissions.
194
	 */
195
	private function _verifyDeletePermissions()
196
	{
197
		global $modSettings;
198
199
		if ($this->_topic_info['id_member'] == $this->user->id)
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
200
		{
201
			// Are you allowed to delete it
202
			if (!allowedTo('delete_own'))
203
			{
204
				if ($this->_topic_info['id_member_started'] == $this->user->id && !allowedTo('delete_any'))
205
				{
206
					isAllowedTo('delete_replies');
207
				}
208
				elseif (!allowedTo('delete_any'))
209
				{
210
					isAllowedTo('delete_own');
211
				}
212
			}
213
			elseif (!allowedTo('delete_any')
214
				&& ($this->_topic_info['id_member_started'] != $this->user->id || !allowedTo('delete_replies'))
215
				&& !empty($modSettings['edit_disable_time'])
216
				&& $this->_topic_info['poster_time'] + $modSettings['edit_disable_time'] * 60 < time())
217
			{
218
				throw new Exception('modify_post_time_passed', false);
219
			}
220
		}
221
		elseif ($this->_topic_info['id_member_started'] == $this->user->id && !allowedTo('delete_any'))
222
		{
223
			isAllowedTo('delete_replies');
224
		}
225
		else
226
		{
227
			isAllowedTo('delete_any');
228
		}
229
	}
230
231
	/**
232
	 * After deleting a message(s) returns the user to the best possible location
233
	 *
234
	 * @param bool $full_topic if the entire topic was removed
235
	 */
236
	private function _redirectBack($full_topic)
237
	{
238
		global $topic, $board;
239
240
		// We want to redirect back to recent action.
241
		if (isset($this->_req->query->recent))
242
		{
243
			redirectexit('action=recent');
244
		}
245
		// Back to profile
246
		elseif (isset($this->_req->query->profile, $this->_req->query->start, $this->_req->query->u))
247
		{
248
			redirectexit('action=profile;u=' . $this->_req->query->u . ';area=showposts;start=' . $this->_req->query->start);
249
		}
250
		// Back to the board if the topic was removed
251
		elseif ($full_topic)
252
		{
253
			redirectexit('board=' . $board . '.0');
254
		}
255
		// Back to the topic where the message was removed
256
		else
257
		{
258
			redirectexit('topic=' . $topic . '.' . $this->_req->query->start);
259
		}
260
	}
261
262
	/**
263
	 * Move back a topic or post from the recycle board to its original board.
264
	 *
265
	 * What it does:
266
	 *
267
	 * - Merges back the posts to the original as necessary.
268
	 * - Accessed by ?action=restoretopic
269
	 */
270
	public function action_restoretopic()
271
	{
272
		global $modSettings;
273
274
		// Check session.
275
		checkSession('get');
276
277
		// Is recycled board enabled?
278
		if (empty($modSettings['recycle_enable']))
279
		{
280
			throw new Exception('restored_disabled', 'critical');
281
		}
282
283
		// Can we be in here?
284
		isAllowedTo('move_any', $modSettings['recycle_board']);
285
286
		$restorer = new MessagesDelete($modSettings['recycle_enable'], $modSettings['recycle_board']);
287
288
		// Restoring messages?
289
		if (!empty($this->_req->query->msgs))
290
		{
291
			$actioned_messages = $restorer->restoreMessages(array_map('intval', explode(',', $this->_req->query->msgs)));
292
		}
293
294
		// Now any topics?
295
		if (!empty($this->_req->query->topics))
296
		{
297
			$topics_to_restore = array_map('intval', explode(',', $this->_req->query->topics));
298
			$restorer->restoreTopics($topics_to_restore);
299
		}
300
301
		$restorer->doRestore();
302
303
		// Didn't find some things?
304
		if ($restorer->unfoundRestoreMessages())
305
		{
306
			throw new Exception('restore_not_found', false, array('<ul><li>' . implode('</li><li>', $restorer->unfoundRestoreMessages(true)) . '</li></ul>'));
307
		}
308
309
		// Lets send them back somewhere that may make sense
310
		if (isset($actioned_messages) && count($actioned_messages) === 1 && empty($topics_to_restore))
311
		{
312
			redirectexit('topic=' . array_key_first($actioned_messages));
313
		}
314
		elseif (count($topics_to_restore) === 1)
315
		{
316
			redirectexit('topic=' . $topics_to_restore[0]);
317
		}
318
		else
319
		{
320
			redirectexit();
321
		}
322
	}
323
}
324