Completed
Pull Request — master (#43)
by
unknown
13:26
created

topicsolved::mark_solved()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 27
Code Lines 10

Duplication

Lines 27
Ratio 100 %

Code Coverage

Tests 3
CRAP Score 7.608

Importance

Changes 2
Bugs 0 Features 2
Metric Value
c 2
b 0
f 2
dl 27
loc 27
ccs 3
cts 15
cp 0.2
rs 8.8571
cc 3
eloc 10
nc 2
nop 2
crap 7.608
1
<?php
2
/**
3
 * This file is part of the phpBB Topic Solved extension package.
4
 *
5
 * @copyright (c) Bryan Petty
6
 * @license GNU General Public License, version 2 (GPL-2.0)
7
 *
8
 * @package tierra/topicsolved
9
 */
10
11
namespace tierra\topicsolved;
12
13
/**
14
 * Core topic solved functionality used throughout the extension.
15
 *
16
 * @package tierra/topicsolved
17
 */
18
class topicsolved
19
{
20
	/** No-one can mark topics as solved. */
21
	const TOPIC_SOLVED_NO = 0;
22
23
	/** Topic starter and moderators can mark topics as solved. */
24
	const TOPIC_SOLVED_YES = 1;
25
26
	/** Only moderators can mark topics as solved. */
27
	const TOPIC_SOLVED_MOD = 2;
28
29
	/** @var \phpbb\db\driver\driver_interface */
30
	protected $db;
31
32
	/** @var \phpbb\user */
33
	protected $user;
34
35
	/** @var \phpbb\auth\auth */
36
	protected $auth;
37
38
	/** @var \phpbb\event\dispatcher_interface */
39
	protected $dispatcher;
40
41
	/** @var string core.root_path */
42
	protected $root_path;
43
44
	/** @var string core.php_ext */
45
	protected $php_ext;
46
47
	/**
48
	 * Constructor
49
	 *
50
	 * @param \phpbb\db\driver\driver_interface $db Database object
51
	 * @param \phpbb\user $user
52
	 * @param \phpbb\auth\auth $auth
53 10
	 * @param \phpbb\event\dispatcher_interface $dispatcher
54
	 * @param string $root_path core.root_path
55
	 * @param string $php_ext core.php_ext
56
	 */
57
	public function __construct(
58
		\phpbb\db\driver\driver_interface $db,
59 10
		\phpbb\user $user,
60 10
		\phpbb\auth\auth $auth,
61 10
		\phpbb\event\dispatcher_interface $dispatcher,
62 10
		$root_path, $php_ext)
63 10
	{
64
		$this->db = $db;
65 10
		$this->user = $user;
66 10
		$this->auth = $auth;
67
		$this->dispatcher = $dispatcher;
68
		$this->root_path = $root_path;
69
		$this->php_ext = $php_ext;
70
71
		$this->user->add_lang_ext('tierra/topicsolved', 'common');
72
	}
73
74
	/**
75
	 * Determine if user is allowed to mark a post as solved or unsolved.
76
	 *
77
	 * @param string $solved Either "solved" or "unsolved".
78
	 * @param array $topic_data Topic to be solved or unsolved.
79 1
	 *
80
	 * @throws \phpbb\exception\runtime_exception
81
	 *         if an invalid solved parameter is specified.
82 1
	 *
83 1
	 * @return bool User is authorized to (un)solve topic.
84
	 */
85
	public function user_can_solve_post($solved, $topic_data)
86
	{
87
		// Disallow (un)solving topic if post is global.
88 1
		if ($topic_data['topic_type'] == POST_GLOBAL)
89 1
		{
90 1
			return false;
91
		}
92 1
93 1
		$forum_permission = array(
94
			'solved' => 'forum_allow_solve',
95
			'unsolved' => 'forum_allow_unsolve',
96
		);
97
98 1
		if (!array_key_exists($solved, $forum_permission))
99 1
		{
100 1
			throw new \phpbb\exception\runtime_exception(
101 1
				'BAD_METHOD_CALL', array('user_can_solve_post'));
102
		}
103
104 1
		if (($topic_data[$forum_permission[$solved]] == topicsolved::TOPIC_SOLVED_MOD ||
105 1
			$topic_data[$forum_permission[$solved]] == topicsolved::TOPIC_SOLVED_YES) &&
106 1
			$this->auth->acl_get('m_', $topic_data['forum_id']))
107 1
		{
108 1
			return true;
109
		}
110
		else if ($topic_data[$forum_permission[$solved]] == topicsolved::TOPIC_SOLVED_YES &&
111
			$topic_data['topic_poster'] == $this->user->data['user_id'] &&
112
			$topic_data['topic_status'] == ITEM_UNLOCKED)
113
		{
114
			return true;
115
		}
116
117
		return false;
118
	}
119
120
	/**
121 1
	 * Fetches all topic solved data related to the given post.
122
	 *
123
	 * @param int $post_id ID of post to fetch topic/forum data for.
124
	 *
125
	 * @return mixed topic data, or false if not found
126 1
	 */
127 1
	public function get_topic_data($post_id)
128
	{
129 1
		$select_sql_array = array(
130 1
			'SELECT' =>
131 1
				't.topic_id, t.topic_poster, t.topic_status, t.topic_type, t.topic_solved, ' .
132 1
				'f.forum_id, f.forum_allow_solve, f.forum_allow_unsolve, f.forum_lock_solved, ' .
133
				'p.post_id',
134 1
			'FROM' => array(
135 1
				FORUMS_TABLE => 'f',
136 1
				POSTS_TABLE => 'p',
137 1
				TOPICS_TABLE => 't',
138 1
			),
139 1
			'WHERE' =>
140 1
				'p.post_id = ' . (int) $post_id .
141
				' AND t.topic_id = p.topic_id AND f.forum_id = t.forum_id',
142 1
		);
143
		$select_sql = $this->db->sql_build_query('SELECT', $select_sql_array);
144
		$result = $this->db->sql_query($select_sql);
145
		$topic_data = $this->db->sql_fetchrow($result);
146
		$this->db->sql_freeresult($result);
147
148
		return $topic_data;
149
	}
150
151
	/**
152
	 * Update topic with the given data.
153 1
	 *
154
	 * @param int $topic_id Topic to update.
155 1
	 * @param array $data Topic data to update.
156 1
	 *
157 1
	 * @return mixed true if successful
158 1
	 */
159 1
	public function update_topic($topic_id, $data)
160 1
	{
161
		$update_sql = $this->db->sql_build_array('UPDATE', $data);
162 1
		$result = $this->db->sql_query('
163
			UPDATE ' . TOPICS_TABLE . '
164
			SET ' . $update_sql . '
165
			WHERE topic_id = ' . (int) $topic_id
166
		);
167
168
		return $result;
169
	}
170
171 1
	/**
172
	 * Marks a topic as solved.
173
	 *
174 1
	 * @param array $topic_data Topic to be marked as solved.
175
	 * @param int $post_id Post to mark as the solution.
176 1
	 */
177 View Code Duplication
	public function mark_solved($topic_data, $post_id)
178 1
	{
179
		// Database column values to set.
180
		$column_data = array('topic_solved' => $post_id);
181
182 1
		if ($topic_data['forum_lock_solved'] &&
183 1
			$this->user_can_lock_post($topic_data['forum_id']))
184
		{
185
			$column_data['topic_status'] = ITEM_LOCKED;
186
		}
187
188
		$this->update_topic($topic_data['topic_id'], $column_data);
189
190
		/**
191
		 * This event allows you to perform additional actions after a topic has been marked as solved.
192
		 *
193
		 * @event tierra.topicsolved.mark_solved_after
194
		 * @var	array	topic_data	Array with general topic data
195
		 * @var	array	column_data	Array with topic data that the database has been updated with
196
		 * @since 2.2.0
197
		 */
198
		$vars = array(
199
			'topic_data',
200
			'column_data',
201
		);
202
		extract($this->dispatcher->trigger_event('tierra.topicsolved.mark_solved_after', compact($vars)));
203
	}
204
205
	/**
206
	 * Marks a topic as unsolved.
207
	 *
208
	 * @param array $topic_data Topic to be marked as unsolved.
209
	 */
210 View Code Duplication
	public function mark_unsolved($topic_data)
211
	{
212
		// Database column values to set.
213
		$column_data = array('topic_solved' => 0);
214
215 3
		if ($topic_data['forum_lock_solved'] &&
216
			$this->auth->acl_get('m_lock', $topic_data['forum_id']))
217
		{
218 3
			$column_data['topic_status'] = ITEM_UNLOCKED;
219 3
		}
220 1
221
		$this->update_topic($topic_data['topic_id'], $column_data);
222
223
		/**
224 2
		 * This event allows you to perform additional actions after a topic has been marked as unsolved.
225 2
		 *
226 1
		 * @event tierra.topicsolved.mark_unsolved_after
227
		 * @var	array	topic_data	Array with general topic data
228
		 * @var	array	column_data	Array with topic data that the database has been updated with
229 1
		 * @since 2.2.0
230
		 */
231
		$vars = array(
232
			'topic_data',
233
			'column_data',
234
		);
235
		extract($this->dispatcher->trigger_event('tierra.topicsolved.mark_unsolved_after', compact($vars)));
236
	}
237
238
	/**
239
	 * Checks if the currently logged in user has permission to lock a post.
240
	 *
241 6
	 * Regular users won't have permission to solve any topics other than their
242
	 * own, and moderator permissions are forum based, so we only need to know
243 6
	 * the forum, not the post.
244
	 *
245 6
	 * @param int $forum_id Forum to check permissions on.
246
	 *
247 6
	 * @return bool true if user has permission to lock a post.
248 6
	 */
249 4
	public function user_can_lock_post($forum_id)
250 4
	{
251 4
		// Check if user is moderator with appropriate lock permission
252
		if ($this->auth->acl_get('m_lock', $forum_id))
253 6
		{
254 6
			return true;
255 6
		}
256 6
257 6
		// Check if user has "lock own posts" permission
258
		if ($this->auth->acl_get('f_user_lock', $forum_id))
259 6
		{
260
			return true;
261
		}
262
263
		return false;
264
	}
265
266
	/**
267
	 * Generate markup for the given solved indicator image.
268
	 *
269
	 * @param string $type One of "head", "list", or "post".
270
	 * @param string $alt Language code for title and alternative text.
271 1
	 * @param string $url Optional link to solved post.
272
	 *
273 1
	 * @return string HTML markup for image.
274 1
	 */
275
	public function image($type, $alt = '', $url = '')
276
	{
277
		$title = '';
278
279
		$markup = $this->user->img('icon_solved_' . $type, $alt);
280
281
		if (!empty($alt))
282
		{
283
			$alt = $this->user->lang($alt);
284
			$title = ' title="' . htmlspecialchars($alt, ENT_QUOTES, 'UTF-8') . '"';
285
		}
286
287
		if (!empty($url))
288
		{
289
			$markup = sprintf('<a href="%s"%s>%s</a>',
290
				htmlspecialchars($url, ENT_QUOTES, 'UTF-8'), $title, $markup);
291
		}
292
293
		return $markup;
294
	}
295
296
	/**
297
	 * Generate link to specific post (usually solution post).
298
	 *
299
	 * @param int $forum_id
300
	 * @param int $topic_id
301
	 * @param int $post_id
302
	 *
303
	 * @return string Relative URL to post
304
	 */
305
	public function get_link_to_post($forum_id, $topic_id, $post_id)
306
	{
307
		return append_sid("{$this->root_path}viewtopic.{$this->php_ext}",
308
			"f=$forum_id&t=$topic_id&p=$post_id") . '#p' . $post_id;
309
	}
310
}
311