1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * This file contains those functions pertaining to posting, and other such |
||||
5 | * operations, including sending emails, ims, blocking spam, preparsing posts, |
||||
6 | * and the post box. |
||||
7 | * |
||||
8 | * @package ElkArte Forum |
||||
9 | * @copyright ElkArte Forum contributors |
||||
10 | * @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
||||
11 | * |
||||
12 | * This file contains code covered by: |
||||
13 | * copyright: 2011 Simple Machines (http://www.simplemachines.org) |
||||
14 | * |
||||
15 | * @version 2.0 dev |
||||
16 | * |
||||
17 | */ |
||||
18 | |||||
19 | use BBC\ParserWrapper; |
||||
20 | use BBC\PreparseCode; |
||||
21 | use ElkArte\Helper\Util; |
||||
22 | use ElkArte\Search\SearchApiWrapper; |
||||
23 | use ElkArte\User; |
||||
24 | |||||
25 | /** |
||||
26 | * Takes a message and parses it, returning the prepared message as a reference. |
||||
27 | * |
||||
28 | * - Cleans up links (javascript, etc.) and code/quote sections. |
||||
29 | * - Won't convert \n's and a few other things if previewing is true. |
||||
30 | * |
||||
31 | * @param string $message |
||||
32 | * @param bool $previewing |
||||
33 | * @package Posts |
||||
34 | */ |
||||
35 | function preparsecode(&$message, $previewing = false) |
||||
36 | { |
||||
37 | 10 | $preparse = PreparseCode::instance(User::$info->name); |
|||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
38 | 10 | $preparse->preparsecode($message, $previewing); |
|||
39 | 10 | } |
|||
40 | |||||
41 | /** |
||||
42 | * This is very simple, and just removes things done by preparsecode. |
||||
43 | * |
||||
44 | * @param string $message |
||||
45 | * |
||||
46 | * @return null|string|string[] |
||||
47 | * @package Posts |
||||
48 | * |
||||
49 | */ |
||||
50 | function un_preparsecode($message) |
||||
51 | { |
||||
52 | $un_preparse = PreparseCode::instance(User::$info->name); |
||||
0 ignored issues
–
show
The property
name does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
53 | |||||
54 | return $un_preparse->un_preparsecode($message); |
||||
55 | } |
||||
56 | |||||
57 | /** |
||||
58 | * Create a post, either as new topic (id_topic = 0) or in an existing one. |
||||
59 | * |
||||
60 | * The input parameters of this function assume: |
||||
61 | * - Strings have been escaped. |
||||
62 | * - Integers have been cast to integer. |
||||
63 | * - Mandatory parameters are set. |
||||
64 | * |
||||
65 | * @param mixed[] $msgOptions |
||||
66 | * @param mixed[] $topicOptions |
||||
67 | * @param mixed[] $posterOptions |
||||
68 | * |
||||
69 | * @return bool |
||||
70 | * @package Posts |
||||
71 | * |
||||
72 | */ |
||||
73 | function createPost(&$msgOptions, &$topicOptions, &$posterOptions) |
||||
74 | { |
||||
75 | global $txt, $modSettings; |
||||
76 | 26 | ||||
77 | $db = database(); |
||||
78 | 26 | ||||
79 | // Set optional parameters to the default value. |
||||
80 | $msgOptions['icon'] = empty($msgOptions['icon']) ? 'xx' : $msgOptions['icon']; |
||||
81 | 26 | $msgOptions['smileys_enabled'] = !empty($msgOptions['smileys_enabled']); |
|||
82 | 26 | // @todo 2015/03/02 - The following line should probably be moved to a module |
|||
83 | $msgOptions['attachments'] = empty($msgOptions['attachments']) ? array() : $msgOptions['attachments']; |
||||
84 | 26 | $msgOptions['approved'] = isset($msgOptions['approved']) ? (int) $msgOptions['approved'] : 1; |
|||
85 | 26 | $topicOptions['id'] = empty($topicOptions['id']) ? 0 : (int) $topicOptions['id']; |
|||
86 | 26 | $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; |
|||
87 | 26 | $topicOptions['lock_mode'] = $topicOptions['lock_mode'] ?? null; |
|||
88 | 26 | $topicOptions['sticky_mode'] = $topicOptions['sticky_mode'] ?? null; |
|||
89 | 26 | $topicOptions['redirect_expires'] = $topicOptions['redirect_expires'] ?? null; |
|||
90 | 26 | $topicOptions['redirect_topic'] = $topicOptions['redirect_topic'] ?? null; |
|||
91 | 26 | $posterOptions['id'] = empty($posterOptions['id']) ? 0 : (int) $posterOptions['id']; |
|||
92 | 26 | $posterOptions['ip'] = empty($posterOptions['ip']) ? User::$info->ip : $posterOptions['ip']; |
|||
0 ignored issues
–
show
The property
ip does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
93 | 26 | ||||
94 | // We need to know if the topic is approved. If we're told that's great - if not find out. |
||||
95 | if (!$modSettings['postmod_active']) |
||||
96 | 26 | { |
|||
97 | $topicOptions['is_approved'] = true; |
||||
98 | 26 | } |
|||
99 | elseif (!empty($topicOptions['id']) && !isset($topicOptions['is_approved'])) |
||||
100 | { |
||||
101 | require_once(SUBSDIR . '/Topic.subs.php'); |
||||
102 | $is_approved = topicAttribute($topicOptions['id'], array('approved')); |
||||
103 | $topicOptions['is_approved'] = !empty($is_approved['approved']); |
||||
104 | } |
||||
105 | |||||
106 | // If nothing was filled in as name/email address, try the member table. |
||||
107 | if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || (empty($posterOptions['email']) && !empty($posterOptions['id']))) |
||||
108 | 26 | { |
|||
109 | if (empty($posterOptions['id'])) |
||||
110 | { |
||||
111 | $posterOptions['id'] = 0; |
||||
112 | $posterOptions['name'] = $txt['guest_title']; |
||||
113 | $posterOptions['email'] = ''; |
||||
114 | } |
||||
115 | elseif ($posterOptions['id'] != User::$info->id) |
||||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
116 | { |
||||
117 | require_once(SUBSDIR . '/Members.subs.php'); |
||||
118 | $result = getBasicMemberData($posterOptions['id']); |
||||
119 | // Couldn't find the current poster? |
||||
120 | if (empty($result)) |
||||
121 | { |
||||
122 | trigger_error('createPost(): Invalid member id ' . $posterOptions['id'], E_USER_NOTICE); |
||||
123 | $posterOptions['id'] = 0; |
||||
124 | $posterOptions['name'] = $txt['guest_title']; |
||||
125 | $posterOptions['email'] = ''; |
||||
126 | } |
||||
127 | else |
||||
128 | { |
||||
129 | $posterOptions['name'] = $result['member_name']; |
||||
130 | $posterOptions['email'] = $result['email_address']; |
||||
131 | } |
||||
132 | } |
||||
133 | else |
||||
134 | { |
||||
135 | $posterOptions['name'] = User::$info->name; |
||||
0 ignored issues
–
show
The property
name does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
136 | $posterOptions['email'] = User::$info->email; |
||||
0 ignored issues
–
show
The property
email does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
137 | } |
||||
138 | } |
||||
139 | |||||
140 | // It's do or die time: forget any user aborts! |
||||
141 | $previous_ignore_user_abort = ignore_user_abort(true); |
||||
142 | 26 | ||||
143 | $new_topic = empty($topicOptions['id']); |
||||
144 | 26 | ||||
145 | $message_columns = array( |
||||
146 | 'id_board' => 'int', |
||||
147 | 26 | 'id_topic' => 'int', |
|||
148 | 26 | 'id_member' => 'int', |
|||
149 | 26 | 'subject' => 'string-255', |
|||
150 | 26 | 'body' => (!empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? 'string-' . $modSettings['max_messageLength'] : (empty($modSettings['max_messageLength']) ? 'string' : 'string-65534')), |
|||
151 | 26 | 'poster_name' => 'string-255', |
|||
152 | 26 | 'poster_email' => 'string-255', |
|||
153 | 26 | 'poster_time' => 'int', |
|||
154 | 26 | 'poster_ip' => 'string-255', |
|||
155 | 26 | 'smileys_enabled' => 'int', |
|||
156 | 26 | 'modified_name' => 'string', |
|||
157 | 26 | 'icon' => 'string-16', |
|||
158 | 26 | 'approved' => 'int', |
|||
159 | 26 | ); |
|||
160 | |||||
161 | $message_parameters = array( |
||||
162 | 'id_board' => $topicOptions['board'], |
||||
163 | 26 | 'id_topic' => $topicOptions['id'], |
|||
164 | 26 | 'id_member' => $posterOptions['id'], |
|||
165 | 26 | 'subject' => $msgOptions['subject'], |
|||
166 | 26 | 'body' => $msgOptions['body'], |
|||
167 | 26 | 'poster_name' => $posterOptions['name'], |
|||
168 | 26 | 'poster_email' => $posterOptions['email'], |
|||
169 | 26 | 'poster_time' => empty($posterOptions['time']) ? time() : $posterOptions['time'], |
|||
170 | 26 | 'poster_ip' => $posterOptions['ip'], |
|||
171 | 26 | 'smileys_enabled' => $msgOptions['smileys_enabled'] ? 1 : 0, |
|||
172 | 26 | 'modified_name' => '', |
|||
173 | 26 | 'icon' => $msgOptions['icon'], |
|||
174 | 26 | 'approved' => $msgOptions['approved'], |
|||
175 | 26 | ); |
|||
176 | |||||
177 | // What if we want to do anything with posts? |
||||
178 | call_integration_hook('integrate_before_create_post', array(&$msgOptions, &$topicOptions, &$posterOptions, &$message_columns, &$message_parameters)); |
||||
179 | 26 | ||||
180 | // Insert the post. |
||||
181 | $db->insert('', |
||||
182 | 26 | '{db_prefix}messages', |
|||
183 | 26 | $message_columns, |
|||
184 | 13 | $message_parameters, |
|||
185 | 13 | array('id_msg') |
|||
186 | 26 | ); |
|||
187 | $msgOptions['id'] = $db->insert_id('{db_prefix}messages'); |
||||
188 | 26 | ||||
189 | // Something went wrong creating the message... |
||||
190 | if (empty($msgOptions['id'])) |
||||
191 | 26 | { |
|||
192 | return false; |
||||
193 | } |
||||
194 | |||||
195 | // What if we want to export new posts out to a CMS? |
||||
196 | call_integration_hook('integrate_create_post', array($msgOptions, $topicOptions, $posterOptions, $message_columns, $message_parameters)); |
||||
197 | 26 | ||||
198 | // Insert a new topic (if the topicID was left empty.) |
||||
199 | if ($new_topic) |
||||
200 | 26 | { |
|||
201 | $topic_columns = array( |
||||
202 | 'id_board' => 'int', 'id_member_started' => 'int', |
||||
203 | 24 | 'id_member_updated' => 'int', 'id_first_msg' => 'int', |
|||
204 | 'id_last_msg' => 'int', 'locked' => 'int', |
||||
205 | 'is_sticky' => 'int', 'num_views' => 'int', |
||||
206 | 'id_poll' => 'int', |
||||
207 | 'unapproved_posts' => 'int', 'approved' => 'int', |
||||
208 | 'redirect_expires' => 'int', |
||||
209 | 'id_redirect_topic' => 'int', |
||||
210 | ); |
||||
211 | $topic_parameters = array( |
||||
212 | 'id_board' => $topicOptions['board'], |
||||
213 | 24 | 'id_member_started' => $posterOptions['id'], |
|||
214 | 24 | 'id_member_updated' => $posterOptions['id'], |
|||
215 | 24 | 'id_first_msg' => $msgOptions['id'], |
|||
216 | 24 | 'id_last_msg' => $msgOptions['id'], |
|||
217 | 24 | 'locked' => $topicOptions['lock_mode'] ?? 0, |
|||
218 | 24 | 'is_sticky' => $topicOptions['sticky_mode'] ?? 0, |
|||
219 | 24 | 'num_views' => 0, |
|||
220 | 24 | 'id_poll' => $topicOptions['poll'] ?? 0, |
|||
221 | 24 | 'unapproved_posts' => $msgOptions['approved'] ? 0 : 1, |
|||
222 | 24 | 'approved' => $msgOptions['approved'], |
|||
223 | 24 | 'redirect_expires' => $topicOptions['redirect_expires'] ?? 0, |
|||
224 | 24 | 'id_redirect_topic' => $topicOptions['redirect_topic'] ?? 0, |
|||
225 | 24 | ); |
|||
226 | |||||
227 | call_integration_hook('integrate_before_create_topic', array(&$msgOptions, &$topicOptions, &$posterOptions, &$topic_columns, &$topic_parameters)); |
||||
228 | 24 | ||||
229 | $db->insert('', |
||||
230 | 24 | '{db_prefix}topics', |
|||
231 | 24 | $topic_columns, |
|||
232 | 12 | $topic_parameters, |
|||
233 | 12 | array('id_topic') |
|||
234 | 24 | ); |
|||
235 | $topicOptions['id'] = $db->insert_id('{db_prefix}topics'); |
||||
236 | 24 | ||||
237 | // The topic couldn't be created for some reason. |
||||
238 | if (empty($topicOptions['id'])) |
||||
239 | 24 | { |
|||
240 | // We should delete the post that did work, though... |
||||
241 | $db->query('', ' |
||||
242 | DELETE FROM {db_prefix}messages |
||||
243 | WHERE id_msg = {int:id_msg}', |
||||
244 | array( |
||||
245 | 'id_msg' => $msgOptions['id'], |
||||
246 | ) |
||||
247 | ); |
||||
248 | |||||
249 | return false; |
||||
250 | } |
||||
251 | |||||
252 | // Fix the message with the topic. |
||||
253 | $db->query('', ' |
||||
254 | 24 | UPDATE {db_prefix}messages |
|||
255 | SET id_topic = {int:id_topic} |
||||
256 | WHERE id_msg = {int:id_msg}', |
||||
257 | array( |
||||
258 | 'id_topic' => $topicOptions['id'], |
||||
259 | 24 | 'id_msg' => $msgOptions['id'], |
|||
260 | 24 | ) |
|||
261 | ); |
||||
262 | |||||
263 | // There's been a new topic AND a new post today. |
||||
264 | trackStats(array('topics' => '+', 'posts' => '+')); |
||||
265 | 24 | ||||
266 | require_once(SUBSDIR . '/Topic.subs.php'); |
||||
267 | 24 | updateTopicStats(true); |
|||
268 | 24 | require_once(SUBSDIR . '/Messages.subs.php'); |
|||
269 | 24 | updateSubjectStats($topicOptions['id'], $msgOptions['subject']); |
|||
270 | 24 | ||||
271 | // What if we want to export new topics out to a CMS? |
||||
272 | call_integration_hook('integrate_create_topic', array($msgOptions, $topicOptions, $posterOptions)); |
||||
273 | 24 | } |
|||
274 | // The topic already exists, it only needs a little updating. |
||||
275 | else |
||||
276 | { |
||||
277 | $update_parameters = array( |
||||
278 | 'poster_id' => $posterOptions['id'], |
||||
279 | 2 | 'id_msg' => $msgOptions['id'], |
|||
280 | 2 | 'locked' => $topicOptions['lock_mode'], |
|||
281 | 2 | 'is_sticky' => $topicOptions['sticky_mode'], |
|||
282 | 2 | 'id_topic' => $topicOptions['id'], |
|||
283 | 2 | 'counter_increment' => 1, |
|||
284 | 2 | ); |
|||
285 | |||||
286 | if ($msgOptions['approved']) |
||||
287 | 2 | { |
|||
288 | $topics_columns = array( |
||||
289 | 'id_member_updated = {int:poster_id}', |
||||
290 | 2 | 'id_last_msg = {int:id_msg}', |
|||
291 | 'num_replies = num_replies + {int:counter_increment}', |
||||
292 | ); |
||||
293 | } |
||||
294 | else |
||||
295 | { |
||||
296 | $topics_columns = array( |
||||
297 | 'unapproved_posts = unapproved_posts + {int:counter_increment}', |
||||
298 | ); |
||||
299 | } |
||||
300 | |||||
301 | if ($topicOptions['lock_mode'] !== null) |
||||
302 | 2 | { |
|||
303 | $topics_columns[] = 'locked = {int:locked}'; |
||||
304 | } |
||||
305 | |||||
306 | if ($topicOptions['sticky_mode'] !== null) |
||||
307 | 2 | { |
|||
308 | $topics_columns[] = 'is_sticky = {int:is_sticky}'; |
||||
309 | } |
||||
310 | |||||
311 | call_integration_hook('integrate_before_modify_topic', array(&$topics_columns, &$update_parameters, &$msgOptions, &$topicOptions, &$posterOptions)); |
||||
312 | 2 | ||||
313 | // Update the number of replies and the lock/sticky status. |
||||
314 | $db->query('', ' |
||||
315 | 2 | UPDATE {db_prefix}topics |
|||
316 | SET |
||||
317 | ' . implode(', ', $topics_columns) . ' |
||||
318 | 2 | WHERE id_topic = {int:id_topic}', |
|||
319 | $update_parameters |
||||
320 | 1 | ); |
|||
321 | |||||
322 | // One new post has been added today. |
||||
323 | trackStats(array('posts' => '+')); |
||||
324 | 2 | } |
|||
325 | |||||
326 | // Creating is modifying...in a way. |
||||
327 | // @todo id_msg_modified needs to be set when you create a post, now this query is |
||||
328 | // the only place it does get set for post creation. Why not set it on the insert? |
||||
329 | $db->query('', ' |
||||
330 | 26 | UPDATE {db_prefix}messages |
|||
331 | SET id_msg_modified = {int:id_msg} |
||||
332 | WHERE id_msg = {int:id_msg}', |
||||
333 | array( |
||||
334 | 'id_msg' => $msgOptions['id'], |
||||
335 | 26 | ) |
|||
336 | ); |
||||
337 | |||||
338 | // Increase the number of posts and topics on the board. |
||||
339 | if ($msgOptions['approved']) |
||||
340 | 26 | { |
|||
341 | $db->query('', ' |
||||
342 | 26 | UPDATE {db_prefix}boards |
|||
343 | SET num_posts = num_posts + 1' . ($new_topic ? ', num_topics = num_topics + 1' : '') . ' |
||||
344 | 26 | WHERE id_board = {int:id_board}', |
|||
345 | array( |
||||
346 | 'id_board' => $topicOptions['board'], |
||||
347 | 26 | ) |
|||
348 | ); |
||||
349 | } |
||||
350 | else |
||||
351 | { |
||||
352 | $db->query('', ' |
||||
353 | UPDATE {db_prefix}boards |
||||
354 | SET unapproved_posts = unapproved_posts + 1' . ($new_topic ? ', unapproved_topics = unapproved_topics + 1' : '') . ' |
||||
355 | WHERE id_board = {int:id_board}', |
||||
356 | array( |
||||
357 | 'id_board' => $topicOptions['board'], |
||||
358 | ) |
||||
359 | ); |
||||
360 | |||||
361 | // Add to the approval queue too. |
||||
362 | $db->insert('', |
||||
363 | '{db_prefix}approval_queue', |
||||
364 | array( |
||||
365 | 'id_msg' => 'int', |
||||
366 | ), |
||||
367 | array( |
||||
368 | $msgOptions['id'], |
||||
369 | ), |
||||
370 | array() |
||||
371 | ); |
||||
372 | } |
||||
373 | |||||
374 | // Mark inserted topic as read (only for the user calling this function). |
||||
375 | if (!empty($topicOptions['mark_as_read']) && User::$info->is_guest === false) |
||||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
376 | 26 | { |
|||
377 | // Since it's likely they *read* it before replying, let's try an UPDATE first. |
||||
378 | if (!$new_topic) |
||||
379 | 6 | { |
|||
380 | $flag = $db->query('', ' |
||||
381 | 2 | UPDATE {db_prefix}log_topics |
|||
382 | SET id_msg = {int:id_msg} |
||||
383 | WHERE id_member = {int:current_member} |
||||
384 | AND id_topic = {int:id_topic}', |
||||
385 | array( |
||||
386 | 'current_member' => $posterOptions['id'], |
||||
387 | 2 | 'id_msg' => $msgOptions['id'], |
|||
388 | 2 | 'id_topic' => $topicOptions['id'], |
|||
389 | 2 | ) |
|||
390 | )->affected_rows() != 0; |
||||
391 | 2 | } |
|||
392 | |||||
393 | if (empty($flag)) |
||||
394 | 6 | { |
|||
395 | require_once(SUBSDIR . '/Topic.subs.php'); |
||||
396 | 6 | markTopicsRead(array($posterOptions['id'], $topicOptions['id'], $msgOptions['id'], 0), false); |
|||
397 | 6 | } |
|||
398 | } |
||||
399 | |||||
400 | // If there's a custom search index, it may need updating... |
||||
401 | $searchAPI = new SearchApiWrapper(!empty($modSettings['search_index']) ? $modSettings['search_index'] : ''); |
||||
402 | 26 | $searchAPI->postCreated($msgOptions, $topicOptions, $posterOptions); |
|||
403 | 26 | ||||
404 | // Increase the post counter for the user that created the post. |
||||
405 | if (!empty($posterOptions['update_post_count']) && !empty($posterOptions['id']) && $msgOptions['approved']) |
||||
406 | 26 | { |
|||
407 | // Are you the one that happened to create this post? |
||||
408 | if (User::$info->id == $posterOptions['id']) |
||||
409 | 4 | { |
|||
410 | User::$info->posts++; |
||||
0 ignored issues
–
show
The property
posts does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
411 | 4 | } |
|||
412 | |||||
413 | require_once(SUBSDIR . '/Members.subs.php'); |
||||
414 | 4 | updateMemberData($posterOptions['id'], array('posts' => '+')); |
|||
415 | 4 | } |
|||
416 | |||||
417 | // They've posted, so they can make the view count go up one if they really want. (this is to keep views >= replies...) |
||||
418 | $_SESSION['last_read_topic'] = 0; |
||||
419 | 26 | ||||
420 | // Better safe than sorry. |
||||
421 | if (isset($_SESSION['topicseen_cache'][$topicOptions['board']])) |
||||
422 | 26 | { |
|||
423 | $_SESSION['topicseen_cache'][$topicOptions['board']]--; |
||||
424 | } |
||||
425 | |||||
426 | // Update all the stats so everyone knows about this new topic and message. |
||||
427 | require_once(SUBSDIR . '/Messages.subs.php'); |
||||
428 | 26 | updateMessageStats(true, $msgOptions['id']); |
|||
0 ignored issues
–
show
It seems like
$msgOptions['id'] can also be of type boolean ; however, parameter $max_msg_id of updateMessageStats() does only seem to accept integer|null , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
429 | 26 | ||||
430 | // Update the last message on the board assuming it's approved AND the topic is. |
||||
431 | if ($msgOptions['approved']) |
||||
432 | 26 | { |
|||
433 | updateLastMessages($topicOptions['board'], $new_topic || !empty($topicOptions['is_approved']) ? $msgOptions['id'] : 0); |
||||
0 ignored issues
–
show
It seems like
$new_topic || ! empty($t...? $msgOptions['id'] : 0 can also be of type boolean ; however, parameter $id_msg of updateLastMessages() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
434 | 26 | } |
|||
435 | |||||
436 | // Alright, done now... we can abort now, I guess... at least this much is done. |
||||
437 | ignore_user_abort($previous_ignore_user_abort); |
||||
0 ignored issues
–
show
$previous_ignore_user_abort of type integer is incompatible with the type boolean|null expected by parameter $enable of ignore_user_abort() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
438 | 26 | ||||
439 | // Success. |
||||
440 | return true; |
||||
441 | 26 | } |
|||
442 | |||||
443 | /** |
||||
444 | * Modifying a post... |
||||
445 | * |
||||
446 | * @param mixed[] $msgOptions |
||||
447 | * @param mixed[] $topicOptions |
||||
448 | * @param mixed[] $posterOptions |
||||
449 | * |
||||
450 | * @return bool |
||||
451 | * @package Posts |
||||
452 | * |
||||
453 | */ |
||||
454 | function modifyPost(&$msgOptions, &$topicOptions, &$posterOptions) |
||||
455 | { |
||||
456 | global $modSettings; |
||||
457 | |||||
458 | 2 | $db = database(); |
|||
459 | |||||
460 | 2 | $topicOptions['poll'] = isset($topicOptions['poll']) ? (int) $topicOptions['poll'] : null; |
|||
461 | $topicOptions['lock_mode'] = $topicOptions['lock_mode'] ?? null; |
||||
462 | 2 | $topicOptions['sticky_mode'] = $topicOptions['sticky_mode'] ?? null; |
|||
463 | 2 | ||||
464 | 2 | // This is longer than it has to be, but makes it so we only set/change what we have to. |
|||
465 | $messages_columns = array(); |
||||
466 | if (isset($posterOptions['name'])) |
||||
467 | 2 | { |
|||
468 | 2 | $messages_columns['poster_name'] = $posterOptions['name']; |
|||
469 | } |
||||
470 | 2 | ||||
471 | if (isset($posterOptions['email'])) |
||||
472 | { |
||||
473 | 2 | $messages_columns['poster_email'] = $posterOptions['email']; |
|||
474 | } |
||||
475 | 2 | ||||
476 | if (isset($msgOptions['icon'])) |
||||
477 | { |
||||
478 | 2 | $messages_columns['icon'] = $msgOptions['icon']; |
|||
479 | } |
||||
480 | 2 | ||||
481 | if (isset($msgOptions['subject'])) |
||||
482 | { |
||||
483 | 2 | $messages_columns['subject'] = $msgOptions['subject']; |
|||
484 | } |
||||
485 | 2 | ||||
486 | if (isset($msgOptions['body'])) |
||||
487 | { |
||||
488 | 2 | $messages_columns['body'] = $msgOptions['body']; |
|||
489 | |||||
490 | 2 | // using a custom search index, then lets get the old message so we can update our index as needed |
|||
491 | if (!empty($modSettings['search_custom_index_config'])) |
||||
492 | { |
||||
493 | 2 | require_once(SUBSDIR . '/Messages.subs.php'); |
|||
494 | $message = basicMessageInfo($msgOptions['id'], true, false, false); |
||||
495 | $msgOptions['old_body'] = $message['body']; |
||||
496 | } |
||||
497 | } |
||||
498 | |||||
499 | if (!empty($msgOptions['modify_time'])) |
||||
500 | { |
||||
501 | 2 | $messages_columns['modified_time'] = $msgOptions['modify_time']; |
|||
502 | $messages_columns['modified_name'] = $msgOptions['modify_name']; |
||||
503 | $messages_columns['id_msg_modified'] = $modSettings['maxMsgID']; |
||||
504 | } |
||||
505 | |||||
506 | if (isset($msgOptions['smileys_enabled'])) |
||||
507 | { |
||||
508 | 2 | $messages_columns['smileys_enabled'] = empty($msgOptions['smileys_enabled']) ? 0 : 1; |
|||
509 | } |
||||
510 | 2 | ||||
511 | // Which columns need to be ints? |
||||
512 | $messageInts = array('modified_time', 'id_msg_modified', 'smileys_enabled'); |
||||
513 | $update_parameters = array( |
||||
514 | 2 | 'id_msg' => $msgOptions['id'], |
|||
515 | ); |
||||
516 | 2 | ||||
517 | call_integration_hook('integrate_before_modify_post', array(&$messages_columns, &$update_parameters, &$msgOptions, &$topicOptions, &$posterOptions, &$messageInts)); |
||||
518 | |||||
519 | 2 | foreach ($messages_columns as $var => $val) |
|||
520 | { |
||||
521 | 2 | $messages_columns[$var] = $var . ' = {' . (in_array($var, $messageInts) ? 'int' : 'string') . ':var_' . $var . '}'; |
|||
522 | $update_parameters['var_' . $var] = $val; |
||||
523 | 2 | } |
|||
524 | 2 | ||||
525 | // Nothing to do? |
||||
526 | if (empty($messages_columns)) |
||||
527 | { |
||||
528 | 2 | return true; |
|||
529 | } |
||||
530 | |||||
531 | // Change the post. |
||||
532 | $db->query('', ' |
||||
533 | UPDATE {db_prefix}messages |
||||
534 | 2 | SET ' . implode(', ', $messages_columns) . ' |
|||
535 | WHERE id_msg = {int:id_msg}', |
||||
536 | 2 | $update_parameters |
|||
537 | ); |
||||
538 | 1 | ||||
539 | $attributes = array(); |
||||
540 | // Lock and or sticky the post. |
||||
541 | 2 | if ($topicOptions['sticky_mode'] !== null) |
|||
542 | { |
||||
543 | 2 | $attributes['is_sticky'] = $topicOptions['sticky_mode']; |
|||
544 | } |
||||
545 | |||||
546 | if ($topicOptions['lock_mode'] !== null) |
||||
547 | { |
||||
548 | 2 | $attributes['locked'] = $topicOptions['lock_mode']; |
|||
549 | } |
||||
550 | 2 | ||||
551 | if ($topicOptions['poll'] !== null) |
||||
552 | { |
||||
553 | 2 | $attributes['id_poll'] = $topicOptions['poll']; |
|||
554 | } |
||||
555 | |||||
556 | // If anything to do, do it. |
||||
557 | if (!empty($attributes)) |
||||
558 | { |
||||
559 | 2 | setTopicAttribute($topicOptions['id'], $attributes); |
|||
560 | } |
||||
561 | 2 | ||||
562 | // Mark the edited post as read. |
||||
563 | if (!empty($topicOptions['mark_as_read']) && User::$info->is_guest === false) |
||||
0 ignored issues
–
show
The property
is_guest does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
564 | { |
||||
565 | 2 | // Since it's likely they *read* it before editing, let's try an UPDATE first. |
|||
566 | $flag = $db->query('', ' |
||||
567 | UPDATE {db_prefix}log_topics |
||||
568 | 2 | SET id_msg = {int:id_msg} |
|||
569 | WHERE id_member = {int:current_member} |
||||
570 | AND id_topic = {int:id_topic}', |
||||
571 | array( |
||||
572 | 'current_member' => User::$info->id, |
||||
0 ignored issues
–
show
The property
id does not exist on ElkArte\Helper\ValuesContainer . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
573 | 'id_msg' => $modSettings['maxMsgID'], |
||||
574 | 2 | 'id_topic' => $topicOptions['id'], |
|||
575 | 2 | ) |
|||
576 | 2 | )->affected_rows() != 0; |
|||
577 | |||||
578 | 2 | if (empty($flag)) |
|||
579 | { |
||||
580 | 2 | require_once(SUBSDIR . '/Topic.subs.php'); |
|||
581 | markTopicsRead(array(User::$info->id, $topicOptions['id'], $modSettings['maxMsgID'], 0), false); |
||||
582 | } |
||||
583 | } |
||||
584 | |||||
585 | // If there's a custom search index, it needs to be modified... |
||||
586 | $searchAPI = new SearchApiWrapper(!empty($modSettings['search_index']) ? $modSettings['search_index'] : ''); |
||||
587 | $searchAPI->postModified($msgOptions, $topicOptions, $posterOptions); |
||||
588 | 2 | ||||
589 | 2 | if (isset($msgOptions['subject'])) |
|||
590 | { |
||||
591 | 2 | // Only update the subject if this was the first message in the topic. |
|||
592 | $request = $db->query('', ' |
||||
593 | SELECT |
||||
594 | 2 | id_topic |
|||
595 | FROM {db_prefix}topics |
||||
596 | WHERE id_first_msg = {int:id_first_msg} |
||||
597 | LIMIT 1', |
||||
598 | array( |
||||
599 | 'id_first_msg' => $msgOptions['id'], |
||||
600 | ) |
||||
601 | 2 | ); |
|||
602 | if ($request->num_rows() === 1) |
||||
603 | { |
||||
604 | 2 | require_once(SUBSDIR . '/Messages.subs.php'); |
|||
605 | updateSubjectStats($topicOptions['id'], $msgOptions['subject']); |
||||
606 | 2 | } |
|||
607 | 2 | $request->free_result(); |
|||
608 | } |
||||
609 | 2 | ||||
610 | // Finally, if we are setting the approved state we need to do much more work :( |
||||
611 | if ($modSettings['postmod_active'] && isset($msgOptions['approved'])) |
||||
612 | { |
||||
613 | 2 | approvePosts($msgOptions['id'], $msgOptions['approved']); |
|||
614 | } |
||||
615 | |||||
616 | return true; |
||||
617 | } |
||||
618 | 2 | ||||
619 | /** |
||||
620 | * Approve (or not) some posts... without permission checks... |
||||
621 | * |
||||
622 | * @param int|int[] $msgs - array of message ids |
||||
623 | * @param bool $approve = true |
||||
624 | * |
||||
625 | * @return bool|void |
||||
626 | * @package Posts |
||||
627 | */ |
||||
628 | function approvePosts($msgs, $approve = true) |
||||
629 | { |
||||
630 | global $modSettings; |
||||
631 | |||||
632 | $db = database(); |
||||
633 | |||||
634 | if (!is_array($msgs)) |
||||
635 | { |
||||
636 | $msgs = [$msgs]; |
||||
637 | } |
||||
638 | |||||
639 | if (empty($msgs)) |
||||
640 | { |
||||
641 | return false; |
||||
642 | } |
||||
643 | |||||
644 | // May as well start at the beginning, working out *what* we need to change. |
||||
645 | $request = $db->query('', ' |
||||
646 | SELECT |
||||
647 | m.id_msg, m.approved, m.id_topic, m.id_board, m.body, m.subject, m.id_member, |
||||
648 | t.id_first_msg, t.id_last_msg, t.approved AS topic_approved, |
||||
649 | COALESCE(mem.real_name, m.poster_name) AS poster_name, mem.signature, |
||||
650 | b.count_posts |
||||
651 | FROM {db_prefix}messages AS m |
||||
652 | INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
||||
653 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
||||
654 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||||
655 | WHERE m.id_msg IN ({array_int:message_list}) |
||||
656 | AND m.approved = {int:approved_state}', |
||||
657 | array( |
||||
658 | 'message_list' => $msgs, |
||||
659 | 'approved_state' => $approve ? 0 : 1, |
||||
660 | ) |
||||
661 | ); |
||||
662 | $msgs = []; |
||||
663 | $topics = []; |
||||
664 | $topic_changes = []; |
||||
665 | $board_changes = []; |
||||
666 | $notification_topics = []; |
||||
667 | $notification_posts = []; |
||||
668 | $member_post_changes = []; |
||||
669 | while ($row = $request->fetch_assoc()) |
||||
670 | { |
||||
671 | // Easy... |
||||
672 | $msgs[] = $row['id_msg']; |
||||
673 | $topics[] = $row['id_topic']; |
||||
674 | |||||
675 | // Ensure our change array exists already. |
||||
676 | if (!isset($topic_changes[$row['id_topic']])) |
||||
677 | { |
||||
678 | $topic_changes[$row['id_topic']] = [ |
||||
679 | 'id_last_msg' => $row['id_last_msg'], |
||||
680 | 'approved' => $row['topic_approved'], |
||||
681 | 'replies' => 0, |
||||
682 | 'unapproved_posts' => 0, |
||||
683 | ]; |
||||
684 | } |
||||
685 | if (!isset($board_changes[$row['id_board']])) |
||||
686 | { |
||||
687 | $board_changes[$row['id_board']] = [ |
||||
688 | 'posts' => 0, |
||||
689 | 'topics' => 0, |
||||
690 | 'unapproved_posts' => 0, |
||||
691 | 'unapproved_topics' => 0, |
||||
692 | ]; |
||||
693 | } |
||||
694 | |||||
695 | // If it's the first message then the topic state changes! |
||||
696 | if ($row['id_msg'] === $row['id_first_msg']) |
||||
697 | { |
||||
698 | $topic_changes[$row['id_topic']]['approved'] = $approve ? 1 : 0; |
||||
699 | |||||
700 | $board_changes[$row['id_board']]['unapproved_topics'] += $approve ? -1 : 1; |
||||
701 | $board_changes[$row['id_board']]['topics'] += $approve ? 1 : -1; |
||||
702 | |||||
703 | // Note we need to ensure we announce this topic! |
||||
704 | $notification_topics[] = [ |
||||
705 | 'body' => $row['body'], |
||||
706 | 'subject' => $row['subject'], |
||||
707 | 'name' => $row['poster_name'], |
||||
708 | 'board' => $row['id_board'], |
||||
709 | 'topic' => $row['id_topic'], |
||||
710 | 'msg' => $row['id_first_msg'], |
||||
711 | 'poster' => $row['id_member'], |
||||
712 | 'signature' => $row['signature'], |
||||
713 | ]; |
||||
714 | } |
||||
715 | else |
||||
716 | { |
||||
717 | $topic_changes[$row['id_topic']]['replies'] += $approve ? 1 : -1; |
||||
718 | |||||
719 | // This will be a post... but don't notify unless it's not followed by approved ones. |
||||
720 | if ($row['id_msg'] > $row['id_last_msg']) |
||||
721 | { |
||||
722 | $notification_posts[$row['id_topic']][] = [ |
||||
723 | 'id' => $row['id_msg'], |
||||
724 | 'body' => $row['body'], |
||||
725 | 'subject' => $row['subject'], |
||||
726 | 'name' => $row['poster_name'], |
||||
727 | 'topic' => $row['id_topic'], |
||||
728 | 'signature' => $row['signature'], |
||||
729 | ]; |
||||
730 | } |
||||
731 | } |
||||
732 | |||||
733 | // If this is being approved and id_msg is higher than the current id_last_msg then it changes. |
||||
734 | if ($approve && $row['id_msg'] > $topic_changes[$row['id_topic']]['id_last_msg']) |
||||
735 | { |
||||
736 | $topic_changes[$row['id_topic']]['id_last_msg'] = $row['id_msg']; |
||||
737 | } |
||||
738 | // If this is being unapproved, and it's equal to the id_last_msg we need to find a new one! |
||||
739 | elseif (!$approve) |
||||
740 | // Default to the first message and then we'll override in a bit ;) |
||||
741 | { |
||||
742 | $topic_changes[$row['id_topic']]['id_last_msg'] = $row['id_first_msg']; |
||||
743 | } |
||||
744 | |||||
745 | $topic_changes[$row['id_topic']]['unapproved_posts'] += $approve ? -1 : 1; |
||||
746 | $board_changes[$row['id_board']]['unapproved_posts'] += $approve ? -1 : 1; |
||||
747 | $board_changes[$row['id_board']]['posts'] += $approve ? 1 : -1; |
||||
748 | |||||
749 | // Post count for the user? |
||||
750 | if ($row['id_member'] && empty($row['count_posts'])) |
||||
751 | { |
||||
752 | $member_post_changes[$row['id_member']] = isset($member_post_changes[$row['id_member']]) ? $member_post_changes[$row['id_member']] + 1 : 1; |
||||
753 | } |
||||
754 | } |
||||
755 | $request->free_result(); |
||||
756 | |||||
757 | if (empty($msgs)) |
||||
758 | { |
||||
759 | return; |
||||
760 | } |
||||
761 | |||||
762 | // Now we have the differences make the changes, first the easy one. |
||||
763 | $db->query('', ' |
||||
764 | UPDATE {db_prefix}messages |
||||
765 | SET approved = {int:approved_state} |
||||
766 | WHERE id_msg IN ({array_int:message_list})', |
||||
767 | [ |
||||
768 | 'message_list' => $msgs, |
||||
769 | 'approved_state' => $approve ? 1 : 0, |
||||
770 | ] |
||||
771 | ); |
||||
772 | |||||
773 | // If we were un-approving find the last msg in the topics... |
||||
774 | if (!$approve) |
||||
775 | { |
||||
776 | $db->fetchQuery(' |
||||
777 | SELECT |
||||
778 | id_topic, MAX(id_msg) AS id_last_msg |
||||
779 | FROM {db_prefix}messages |
||||
780 | WHERE id_topic IN ({array_int:topic_list}) |
||||
781 | AND approved = {int:approved} |
||||
782 | GROUP BY id_topic', |
||||
783 | array( |
||||
784 | 'topic_list' => $topics, |
||||
785 | 'approved' => 1, |
||||
786 | ) |
||||
787 | )->fetch_callback( |
||||
788 | function ($row) use (&$topic_changes) { |
||||
789 | $topic_changes[$row['id_topic']]['id_last_msg'] = $row['id_last_msg']; |
||||
790 | } |
||||
791 | ); |
||||
792 | } |
||||
793 | |||||
794 | // ... next the topics... |
||||
795 | foreach ($topic_changes as $id => $changes) |
||||
796 | { |
||||
797 | $db->query('', ' |
||||
798 | UPDATE {db_prefix}topics |
||||
799 | SET |
||||
800 | approved = {int:approved}, |
||||
801 | unapproved_posts = CASE WHEN unapproved_posts + {int:unapproved_posts} < 0 THEN 0 ELSE unapproved_posts + {int:unapproved_posts} END, |
||||
802 | num_replies = CASE WHEN num_replies + {int:num_replies} < 0 THEN 0 ELSE num_replies + {int:num_replies} END, |
||||
803 | id_last_msg = {int:id_last_msg} |
||||
804 | WHERE id_topic = {int:id_topic}', |
||||
805 | [ |
||||
806 | 'approved' => $changes['approved'], |
||||
807 | 'unapproved_posts' => $changes['unapproved_posts'], |
||||
808 | 'num_replies' => $changes['replies'], |
||||
809 | 'id_last_msg' => $changes['id_last_msg'], |
||||
810 | 'id_topic' => $id, |
||||
811 | ] |
||||
812 | ); |
||||
813 | } |
||||
814 | |||||
815 | // ... finally the boards... |
||||
816 | foreach ($board_changes as $id => $changes) |
||||
817 | { |
||||
818 | $db->query('', ' |
||||
819 | UPDATE {db_prefix}boards |
||||
820 | SET |
||||
821 | num_posts = num_posts + {int:num_posts}, |
||||
822 | unapproved_posts = CASE WHEN unapproved_posts + {int:unapproved_posts} < 0 THEN 0 ELSE unapproved_posts + {int:unapproved_posts} END, |
||||
823 | num_topics = CASE WHEN num_topics + {int:num_topics} < 0 THEN 0 ELSE num_topics + {int:num_topics} END, |
||||
824 | unapproved_topics = CASE WHEN unapproved_topics + {int:unapproved_topics} < 0 THEN 0 ELSE unapproved_topics + {int:unapproved_topics} END |
||||
825 | WHERE id_board = {int:id_board}', |
||||
826 | array( |
||||
827 | 'num_posts' => $changes['posts'], |
||||
828 | 'unapproved_posts' => $changes['unapproved_posts'], |
||||
829 | 'num_topics' => $changes['topics'], |
||||
830 | 'unapproved_topics' => $changes['unapproved_topics'], |
||||
831 | 'id_board' => $id, |
||||
832 | ) |
||||
833 | ); |
||||
834 | } |
||||
835 | |||||
836 | // Finally, least importantly, notifications! |
||||
837 | if ($approve) |
||||
838 | { |
||||
839 | require_once(SUBSDIR . '/Notification.subs.php'); |
||||
840 | |||||
841 | if (!empty($notification_topics)) |
||||
842 | { |
||||
843 | sendBoardNotifications($notification_topics); |
||||
844 | } |
||||
845 | |||||
846 | if (!empty($notification_posts)) |
||||
847 | { |
||||
848 | sendApprovalNotifications($notification_posts); |
||||
849 | } |
||||
850 | |||||
851 | $db->query('', ' |
||||
852 | DELETE FROM {db_prefix}approval_queue |
||||
853 | WHERE id_msg IN ({array_int:message_list}) |
||||
854 | AND id_attach = {int:id_attach}', |
||||
855 | [ |
||||
856 | 'message_list' => $msgs, |
||||
857 | 'id_attach' => 0, |
||||
858 | ] |
||||
859 | ); |
||||
860 | } |
||||
861 | // If un-approving add to the approval queue! |
||||
862 | else |
||||
863 | { |
||||
864 | $msgInserts = array(); |
||||
865 | foreach ($msgs as $msg) |
||||
866 | { |
||||
867 | $msgInserts[] = array($msg); |
||||
868 | } |
||||
869 | |||||
870 | $db->insert('ignore', |
||||
871 | '{db_prefix}approval_queue', |
||||
872 | ['id_msg' => 'int'], |
||||
873 | $msgInserts, |
||||
874 | ['id_msg'] |
||||
875 | ); |
||||
876 | } |
||||
877 | |||||
878 | if (!empty($modSettings['mentions_enabled'])) |
||||
879 | { |
||||
880 | require_once(SUBSDIR . '/Mentions.subs.php'); |
||||
881 | toggleMentionsApproval($msgs, $approve); |
||||
882 | } |
||||
883 | |||||
884 | // Update the last messages on the boards... |
||||
885 | updateLastMessages(array_keys($board_changes)); |
||||
886 | |||||
887 | // Post count for the members? |
||||
888 | if (!empty($member_post_changes)) |
||||
889 | { |
||||
890 | require_once(SUBSDIR . '/Members.subs.php'); |
||||
891 | foreach ($member_post_changes as $id_member => $count_change) |
||||
892 | { |
||||
893 | updateMemberData($id_member, ['posts' => 'posts ' . ($approve ? '+' : '-') . ' ' . $count_change]); |
||||
894 | } |
||||
895 | } |
||||
896 | |||||
897 | return true; |
||||
898 | } |
||||
899 | |||||
900 | /** |
||||
901 | * Takes an array of board IDs and updates their last messages. |
||||
902 | * |
||||
903 | * - If the board has a parent, that parent board is also automatically updated. |
||||
904 | * - The columns updated are id_last_msg and last_updated. |
||||
905 | * - Note that id_last_msg should always be updated using this function, |
||||
906 | * and is not automatically updated upon other changes. |
||||
907 | * |
||||
908 | * @param int[]|int $setboards |
||||
909 | * @param int $id_msg = 0 |
||||
910 | * |
||||
911 | * @return bool |
||||
912 | * @package Posts |
||||
913 | * |
||||
914 | */ |
||||
915 | function updateLastMessages($setboards, $id_msg = 0) |
||||
916 | { |
||||
917 | global $board_info, $board; |
||||
918 | |||||
919 | 26 | $db = database(); |
|||
920 | |||||
921 | 26 | // Please - let's be sane. |
|||
922 | if (empty($setboards)) |
||||
923 | { |
||||
924 | 26 | return false; |
|||
925 | } |
||||
926 | |||||
927 | if (!is_array($setboards)) |
||||
928 | { |
||||
929 | 26 | $setboards = array($setboards); |
|||
930 | } |
||||
931 | 26 | ||||
932 | $lastMsg = array(); |
||||
933 | |||||
934 | 26 | // If we don't know the id_msg we need to find it. |
|||
935 | if (!$id_msg) |
||||
936 | { |
||||
937 | 26 | // Find the latest message on this board (highest id_msg.) |
|||
938 | $db->fetchQuery(' |
||||
939 | SELECT |
||||
940 | 12 | id_board, MAX(id_last_msg) AS id_msg |
|||
941 | FROM {db_prefix}topics |
||||
942 | WHERE id_board IN ({array_int:board_list}) |
||||
943 | AND approved = {int:approved} |
||||
944 | GROUP BY id_board', |
||||
945 | array( |
||||
946 | 'board_list' => $setboards, |
||||
947 | 'approved' => 1, |
||||
948 | 12 | ) |
|||
949 | 12 | )->fetch_callback( |
|||
950 | function ($row) use (&$lastMsg) { |
||||
951 | 12 | $lastMsg[$row['id_board']] = $row['id_msg']; |
|||
952 | } |
||||
953 | 12 | ); |
|||
954 | 12 | } |
|||
955 | else |
||||
956 | { |
||||
957 | // Just to note - there should only be one board passed if we are doing this. |
||||
958 | foreach ($setboards as $id_board) |
||||
959 | { |
||||
960 | 26 | $lastMsg[$id_board] = $id_msg; |
|||
961 | } |
||||
962 | 26 | } |
|||
963 | |||||
964 | $parent_boards = array(); |
||||
965 | |||||
966 | 26 | // Keep track of last modified dates. |
|||
967 | $lastModified = $lastMsg; |
||||
968 | |||||
969 | 26 | // Get all the sub-boards for the parents, if they have some... |
|||
970 | foreach ($setboards as $id_board) |
||||
971 | { |
||||
972 | 26 | if (!isset($lastMsg[$id_board])) |
|||
973 | { |
||||
974 | 26 | $lastMsg[$id_board] = 0; |
|||
975 | $lastModified[$id_board] = 0; |
||||
976 | } |
||||
977 | |||||
978 | if (!empty($board) && $id_board == $board) |
||||
979 | { |
||||
980 | 26 | $parents = $board_info['parent_boards']; |
|||
981 | } |
||||
982 | 4 | else |
|||
983 | { |
||||
984 | $parents = getBoardParents($id_board); |
||||
985 | } |
||||
986 | 22 | ||||
987 | // Ignore any parents on the top child level. |
||||
988 | foreach ($parents as $id => $parent) |
||||
989 | { |
||||
990 | 26 | if ($parent['level'] != 0) |
|||
991 | { |
||||
992 | 22 | // If we're already doing this one as a board, is this a higher last modified? |
|||
993 | if (isset($lastModified[$id]) && $lastModified[$id_board] > $lastModified[$id]) |
||||
994 | { |
||||
995 | $lastModified[$id] = $lastModified[$id_board]; |
||||
996 | } |
||||
997 | elseif (!isset($lastModified[$id]) && (!isset($parent_boards[$id]) || $parent_boards[$id] < $lastModified[$id_board])) |
||||
998 | { |
||||
999 | $parent_boards[$id] = $lastModified[$id_board]; |
||||
1000 | } |
||||
1001 | 13 | } |
|||
1002 | } |
||||
1003 | } |
||||
1004 | |||||
1005 | // Note to help understand what is happening here. For parents we update the timestamp of the last message for determining |
||||
1006 | // whether there are sub-boards which have not been read. For the boards themselves we update both this and id_last_msg. |
||||
1007 | $board_updates = array(); |
||||
1008 | $parent_updates = array(); |
||||
1009 | 26 | ||||
1010 | 26 | // Finally, to save on queries make the changes... |
|||
1011 | foreach ($parent_boards as $id => $msg) |
||||
1012 | { |
||||
1013 | 26 | if (!isset($parent_updates[$msg])) |
|||
1014 | { |
||||
1015 | $parent_updates[$msg] = array($id); |
||||
1016 | } |
||||
1017 | else |
||||
1018 | { |
||||
1019 | $parent_updates[$msg][] = $id; |
||||
1020 | } |
||||
1021 | } |
||||
1022 | |||||
1023 | foreach ($lastMsg as $id => $msg) |
||||
1024 | { |
||||
1025 | 26 | if (!isset($board_updates[$msg . '-' . $lastModified[$id]])) |
|||
1026 | { |
||||
1027 | 26 | $board_updates[$msg . '-' . $lastModified[$id]] = array( |
|||
1028 | 'id' => $msg, |
||||
1029 | 26 | 'updated' => $lastModified[$id], |
|||
1030 | 26 | 'boards' => array($id) |
|||
1031 | 26 | ); |
|||
1032 | 26 | } |
|||
1033 | else |
||||
1034 | { |
||||
1035 | $board_updates[$msg . '-' . $lastModified[$id]]['boards'][] = $id; |
||||
1036 | } |
||||
1037 | 13 | } |
|||
1038 | |||||
1039 | // Now commit the changes! |
||||
1040 | foreach ($parent_updates as $id_msg => $boards) |
||||
1041 | { |
||||
1042 | 26 | $db->query('', ' |
|||
1043 | UPDATE {db_prefix}boards |
||||
1044 | SET id_msg_updated = {int:id_msg_updated} |
||||
1045 | WHERE id_board IN ({array_int:board_list}) |
||||
1046 | AND id_msg_updated < {int:id_msg_updated}', |
||||
1047 | array( |
||||
1048 | 'board_list' => $boards, |
||||
1049 | 'id_msg_updated' => $id_msg, |
||||
1050 | ) |
||||
1051 | ); |
||||
1052 | } |
||||
1053 | foreach ($board_updates as $board_data) |
||||
1054 | { |
||||
1055 | 26 | $db->query('', ' |
|||
1056 | UPDATE {db_prefix}boards |
||||
1057 | 26 | SET id_last_msg = {int:id_last_msg}, id_msg_updated = {int:id_msg_updated} |
|||
1058 | WHERE id_board IN ({array_int:board_list})', |
||||
1059 | array( |
||||
1060 | 'board_list' => $board_data['boards'], |
||||
1061 | 'id_last_msg' => $board_data['id'], |
||||
1062 | 26 | 'id_msg_updated' => $board_data['updated'], |
|||
1063 | 26 | ) |
|||
1064 | 26 | ); |
|||
1065 | } |
||||
1066 | } |
||||
1067 | |||||
1068 | 26 | /** |
|||
1069 | * Get the latest post made on the system |
||||
1070 | * |
||||
1071 | * - respects approved, recycled, and board permissions |
||||
1072 | * |
||||
1073 | * @return array |
||||
1074 | * @package Posts |
||||
1075 | */ |
||||
1076 | function lastPost() |
||||
1077 | { |
||||
1078 | global $scripturl, $modSettings; |
||||
1079 | |||||
1080 | $db = database(); |
||||
1081 | |||||
1082 | // Find it by the board - better to order by board than sort the entire messages table. |
||||
1083 | $request = $db->fetchQuery(' |
||||
1084 | SELECT |
||||
1085 | ml.poster_time, ml.subject, ml.id_topic, ml.poster_name, SUBSTRING(ml.body, 1, 385) AS body, |
||||
1086 | ml.smileys_enabled |
||||
1087 | FROM {db_prefix}boards AS b |
||||
1088 | INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = b.id_last_msg) |
||||
1089 | WHERE {query_wanna_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
||||
1090 | AND b.id_board != {int:recycle_board}' : '') . ' |
||||
1091 | AND ml.approved = {int:is_approved} |
||||
1092 | ORDER BY b.id_msg_updated DESC |
||||
1093 | LIMIT 1', |
||||
1094 | array( |
||||
1095 | 'recycle_board' => $modSettings['recycle_board'], |
||||
1096 | 'is_approved' => 1, |
||||
1097 | ) |
||||
1098 | ); |
||||
1099 | if ($request->num_rows() === 0) |
||||
1100 | { |
||||
1101 | return array(); |
||||
1102 | } |
||||
1103 | $row = $request->fetch_assoc(); |
||||
1104 | $request->free_result(); |
||||
1105 | |||||
1106 | // Censor the subject and post... |
||||
1107 | $row['subject'] = censor($row['subject']); |
||||
1108 | $row['body'] = censor($row['body']); |
||||
1109 | |||||
1110 | $bbc_parser = ParserWrapper::instance(); |
||||
1111 | |||||
1112 | $row['body'] = strip_tags(strtr($bbc_parser->parseMessage($row['body'], $row['smileys_enabled']), array('<br />' => ' '))); |
||||
1113 | $row['body'] = Util::shorten_text($row['body'], !empty($modSettings['lastpost_preview_characters']) ? $modSettings['lastpost_preview_characters'] : 128, true); |
||||
1114 | |||||
1115 | // Send the data. |
||||
1116 | return array( |
||||
1117 | 'topic' => $row['id_topic'], |
||||
1118 | 'subject' => $row['subject'], |
||||
1119 | 'short_subject' => Util::shorten_text($row['subject'], !empty($modSettings['subject_length']) ? $modSettings['subject_length'] : 32) . '</a>', |
||||
1120 | 'preview' => $row['body'], |
||||
1121 | 'time' => standardTime($row['poster_time']), |
||||
1122 | 'html_time' => htmlTime($row['poster_time']), |
||||
1123 | 'timestamp' => forum_time(true, $row['poster_time']), |
||||
1124 | 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new', |
||||
1125 | 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.new;topicseen#new">' . $row['subject'] . '</a>' |
||||
1126 | ); |
||||
1127 | } |
||||
1128 | |||||
1129 | /** |
||||
1130 | * Prepares a post for the post form |
||||
1131 | * |
||||
1132 | * What it does: |
||||
1133 | * |
||||
1134 | * - Will add the appropriate Re: to the post subject if its a reply to an existing post |
||||
1135 | * - If quoting a post, or editing a post, this function also prepares the message body |
||||
1136 | * - returns array($subject, $message) or false on error |
||||
1137 | * |
||||
1138 | * @param int $editing |
||||
1139 | * @param int|null|false $topic |
||||
1140 | * @param string $first_subject |
||||
1141 | * @param int $msg_id |
||||
1142 | * |
||||
1143 | * @return false|mixed[] |
||||
1144 | * @throws \ElkArte\Exceptions\Exception quoted_post_deleted |
||||
1145 | * @package Posts |
||||
1146 | * |
||||
1147 | */ |
||||
1148 | function getFormMsgSubject($editing, $topic, $first_subject = '', $msg_id = 0) |
||||
1149 | { |
||||
1150 | global $modSettings; |
||||
1151 | |||||
1152 | $db = database(); |
||||
1153 | |||||
1154 | switch ($editing) |
||||
1155 | { |
||||
1156 | // Modifying an existing message |
||||
1157 | case 1: |
||||
1158 | require_once(SUBSDIR . '/Messages.subs.php'); |
||||
1159 | |||||
1160 | // Get the existing message. |
||||
1161 | $message = messageDetails((int) $msg_id, (int) $topic); |
||||
1162 | |||||
1163 | // The message they were trying to edit was most likely deleted. |
||||
1164 | if ($message === false) |
||||
0 ignored issues
–
show
|
|||||
1165 | { |
||||
1166 | return false; |
||||
1167 | } |
||||
1168 | |||||
1169 | $errors = checkMessagePermissions($message['message']); |
||||
1170 | |||||
1171 | prepareMessageContext($message); |
||||
1172 | |||||
1173 | if (!empty($errors)) |
||||
1174 | { |
||||
1175 | $message['errors'] = $errors; |
||||
1176 | } |
||||
1177 | |||||
1178 | return $message; |
||||
1179 | // Posting a quoted reply? |
||||
1180 | case 2: |
||||
1181 | // Make sure they _can_ quote this post, and if so get it. |
||||
1182 | $request = $db->query('', ' |
||||
1183 | SELECT |
||||
1184 | m.subject, COALESCE(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.body |
||||
1185 | FROM {db_prefix}messages AS m |
||||
1186 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board}) |
||||
1187 | LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
||||
1188 | WHERE m.id_msg = {int:id_msg}' . (!$modSettings['postmod_active'] || allowedTo('approve_posts') ? '' : ' |
||||
1189 | AND m.approved = {int:is_approved}') . ' |
||||
1190 | LIMIT 1', |
||||
1191 | array( |
||||
1192 | 'id_msg' => $msg_id, |
||||
1193 | 'is_approved' => 1, |
||||
1194 | ) |
||||
1195 | ); |
||||
1196 | if ($request->num_rows() === 0) |
||||
1197 | { |
||||
1198 | throw new \ElkArte\Exceptions\Exception('quoted_post_deleted', false); |
||||
1199 | } |
||||
1200 | list ($form_subject, $mname, $mdate, $form_message) = $request->fetch_row(); |
||||
1201 | $request->free_result(); |
||||
1202 | |||||
1203 | // Add 'Re: ' to the front of the quoted subject. |
||||
1204 | $response_prefix = response_prefix(); |
||||
1205 | if (trim($response_prefix) != '' && Util::strpos($form_subject, trim($response_prefix)) !== 0) |
||||
1206 | { |
||||
1207 | $form_subject = $response_prefix . $form_subject; |
||||
1208 | } |
||||
1209 | |||||
1210 | // Censor the message and subject. |
||||
1211 | $form_message = censor($form_message); |
||||
1212 | $form_subject = censor($form_subject); |
||||
1213 | |||||
1214 | $form_message = un_preparsecode($form_message); |
||||
1215 | $form_message = removeNestedQuotes($form_message); |
||||
1216 | |||||
1217 | // Add a quote string on the front and end. |
||||
1218 | $form_message = '[quote author=' . $mname . ' link=msg=' . (int) $msg_id . ' date=' . $mdate . ']' . "\n" . rtrim($form_message) . "\n" . '[/quote]'; |
||||
1219 | |||||
1220 | break; |
||||
1221 | // Posting a reply without a quote? |
||||
1222 | case 3: |
||||
1223 | // Get the first message's subject. |
||||
1224 | $form_subject = $first_subject; |
||||
1225 | |||||
1226 | // Add 'Re: ' to the front of the subject. |
||||
1227 | $response_prefix = response_prefix(); |
||||
1228 | if (trim($response_prefix) != '' && $form_subject != '' && Util::strpos($form_subject, trim($response_prefix)) !== 0) |
||||
1229 | { |
||||
1230 | $form_subject = $response_prefix . $form_subject; |
||||
1231 | } |
||||
1232 | |||||
1233 | // Censor the subject. |
||||
1234 | $form_subject = censor($form_subject); |
||||
1235 | |||||
1236 | $form_message = ''; |
||||
1237 | |||||
1238 | break; |
||||
1239 | case 4: |
||||
1240 | default: |
||||
1241 | $form_subject = $first_subject; |
||||
1242 | $form_message = ''; |
||||
1243 | |||||
1244 | break; |
||||
1245 | } |
||||
1246 | |||||
1247 | return array($form_subject, $form_message); |
||||
1248 | } |
||||
1249 | |||||
1250 | /** |
||||
1251 | * Update topic subject. |
||||
1252 | * |
||||
1253 | * - If $all is true, for all messages in the topic, otherwise only the first message. |
||||
1254 | * |
||||
1255 | * @param array $topic_info topic information as returned by getTopicInfo() |
||||
1256 | * @param string $custom_subject |
||||
1257 | * @param string $response_prefix = '' |
||||
1258 | * @param bool $all = false |
||||
1259 | * @package Posts |
||||
1260 | */ |
||||
1261 | function topicSubject($topic_info, $custom_subject, $response_prefix = '', $all = false) |
||||
1262 | { |
||||
1263 | $db = database(); |
||||
1264 | |||||
1265 | if ($all) |
||||
1266 | { |
||||
1267 | $db->query('', ' |
||||
1268 | UPDATE {db_prefix}messages |
||||
1269 | SET subject = {string:subject} |
||||
1270 | WHERE id_topic = {int:current_topic}', |
||||
1271 | array( |
||||
1272 | 'current_topic' => $topic_info['id_topic'], |
||||
1273 | 'subject' => $response_prefix . $custom_subject, |
||||
1274 | ) |
||||
1275 | ); |
||||
1276 | } |
||||
1277 | $db->query('', ' |
||||
1278 | UPDATE {db_prefix}messages |
||||
1279 | SET subject = {string:custom_subject} |
||||
1280 | WHERE id_msg = {int:id_first_msg}', |
||||
1281 | array( |
||||
1282 | 'id_first_msg' => $topic_info['id_first_msg'], |
||||
1283 | 'custom_subject' => $custom_subject, |
||||
1284 | ) |
||||
1285 | ); |
||||
1286 | } |
||||
1287 |