Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
content_visibility.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb;
015
016 /**
017 * phpbb_visibility
018 * Handle fetching and setting the visibility for topics and posts
019 */
020 class content_visibility
021 {
022 /**
023 * Database object
024 * @var \phpbb\db\driver\driver_interface
025 */
026 protected $db;
027
028 /**
029 * User object
030 * @var \phpbb\user
031 */
032 protected $user;
033
034 /**
035 * Auth object
036 * @var \phpbb\auth\auth
037 */
038 protected $auth;
039
040 /**
041 * config object
042 * @var \phpbb\config\config
043 */
044 protected $config;
045
046 /**
047 * Event dispatcher object
048 * @var \phpbb\event\dispatcher_interface
049 */
050 protected $phpbb_dispatcher;
051
052 /**
053 * phpBB root path
054 * @var string
055 */
056 protected $phpbb_root_path;
057
058 /**
059 * PHP Extension
060 * @var string
061 */
062 protected $php_ext;
063
064 /**
065 * Constructor
066 *
067 * @param \phpbb\auth\auth $auth Auth object
068 * @param \phpbb\config\config $config Config object
069 * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher Event dispatcher object
070 * @param \phpbb\db\driver\driver_interface $db Database object
071 * @param \phpbb\user $user User object
072 * @param string $phpbb_root_path Root path
073 * @param string $php_ext PHP Extension
074 * @param string $forums_table Forums table name
075 * @param string $posts_table Posts table name
076 * @param string $topics_table Topics table name
077 * @param string $users_table Users table name
078 */
079 public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
080 {
081 $this->auth = $auth;
082 $this->config = $config;
083 $this->phpbb_dispatcher = $phpbb_dispatcher;
084 $this->db = $db;
085 $this->user = $user;
086 $this->phpbb_root_path = $phpbb_root_path;
087 $this->php_ext = $php_ext;
088 $this->forums_table = $forums_table;
089 $this->posts_table = $posts_table;
090 $this->topics_table = $topics_table;
091 $this->users_table = $users_table;
092 }
093
094 /**
095 * Can the current logged-in user soft-delete posts?
096 *
097 * @param $forum_id int Forum ID whose permissions to check
098 * @param $poster_id int Poster ID of the post in question
099 * @param $post_locked bool Is the post locked?
100 * @return bool
101 */
102 public function can_soft_delete($forum_id, $poster_id, $post_locked)
103 {
104 if ($this->auth->acl_get('m_softdelete', $forum_id))
105 {
106 return true;
107 }
108 else if ($this->auth->acl_get('f_softdelete', $forum_id) && $poster_id == $this->user->data['user_id'] && !$post_locked)
109 {
110 return true;
111 }
112
113 return false;
114 }
115
116 /**
117 * Get the topics post count or the forums post/topic count based on permissions
118 *
119 * @param $mode string One of topic_posts, forum_posts or forum_topics
120 * @param $data array Array with the topic/forum data to calculate from
121 * @param $forum_id int The forum id is used for permission checks
122 * @return int Number of posts/topics the user can see in the topic/forum
123 */
124 public function get_count($mode, $data, $forum_id)
125 {
126 if (!$this->auth->acl_get('m_approve', $forum_id))
127 {
128 return (int) $data[$mode . '_approved'];
129 }
130
131 return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted'];
132 }
133
134 /**
135 * Create topic/post visibility SQL for a given forum ID
136 *
137 * Note: Read permissions are not checked.
138 *
139 * @param $mode string Either "topic" or "post"
140 * @param $forum_id int The forum id is used for permission checks
141 * @param $table_alias string Table alias to prefix in SQL queries
142 * @return string The appropriate combination SQL logic for topic/post_visibility
143 */
144 public function get_visibility_sql($mode, $forum_id, $table_alias = '')
145 {
146 $where_sql = '';
147
148 $get_visibility_sql_overwrite = false;
149
150 /**
151 * Allow changing the result of calling get_visibility_sql
152 *
153 * @event core.phpbb_content_visibility_get_visibility_sql_before
154 * @var string where_sql Extra visibility conditions. It must end with either an SQL "AND" or an "OR"
155 * @var string mode Either "topic" or "post" depending on the query this is being used in
156 * @var array forum_id The forum id in which the search is made.
157 * @var string table_alias Table alias to prefix in SQL queries
158 * @var mixed get_visibility_sql_overwrite If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event
159 * If false, get_visibility_sql continues normally
160 * It must be either boolean or string
161 * @since 3.1.4-RC1
162 */
163 $vars = array(
164 'where_sql',
165 'mode',
166 'forum_id',
167 'table_alias',
168 'get_visibility_sql_overwrite',
169 );
170 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_visibility_sql_before', compact($vars)));
171
172 if ($get_visibility_sql_overwrite !== false)
173 {
174 return $get_visibility_sql_overwrite;
175 }
176
177 if ($this->auth->acl_get('m_approve', $forum_id))
178 {
179 return $where_sql . '1 = 1';
180 }
181
182 return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
183 }
184
185 /**
186 * Create topic/post visibility SQL for a set of forums
187 *
188 * Note: Read permissions are not checked. Forums without read permissions
189 * should not be in $forum_ids
190 *
191 * @param $mode string Either "topic" or "post"
192 * @param $forum_ids array Array of forum ids which the posts/topics are limited to
193 * @param $table_alias string Table alias to prefix in SQL queries
194 * @return string The appropriate combination SQL logic for topic/post_visibility
195 */
196 public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '')
197 {
198 $where_sql = '(';
199
200 $approve_forums = array_intersect($forum_ids, array_keys($this->auth->acl_getf('m_approve', true)));
201
202 $get_forums_visibility_sql_overwrite = false;
203 /**
204 * Allow changing the result of calling get_forums_visibility_sql
205 *
206 * @event core.phpbb_content_visibility_get_forums_visibility_before
207 * @var string where_sql The action the user tried to execute
208 * @var string mode Either "topic" or "post" depending on the query this is being used in
209 * @var array forum_ids Array of forum ids which the posts/topics are limited to
210 * @var string table_alias Table alias to prefix in SQL queries
211 * @var array approve_forums Array of forums where the user has m_approve permissions
212 * @var mixed get_forums_visibility_sql_overwrite If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event
213 * If false, get_forums_visibility_sql continues normally
214 * It must be either boolean or string
215 * @since 3.1.3-RC1
216 */
217 $vars = array(
218 'where_sql',
219 'mode',
220 'forum_ids',
221 'table_alias',
222 'approve_forums',
223 'get_forums_visibility_sql_overwrite',
224 );
225 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_forums_visibility_before', compact($vars)));
226
227 if ($get_forums_visibility_sql_overwrite !== false)
228 {
229 return $get_forums_visibility_sql_overwrite;
230 }
231
232 if (sizeof($approve_forums))
233 {
234 // Remove moderator forums from the rest
235 $forum_ids = array_diff($forum_ids, $approve_forums);
236
237 if (!sizeof($forum_ids))
238 {
239 // The user can see all posts/topics in all specified forums
240 return $where_sql . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ')';
241 }
242 else
243 {
244 // Moderator can view all posts/topics in some forums
245 $where_sql .= $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ' OR ';
246 }
247 }
248 else
249 {
250 // The user is just a normal user
251 return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
252 AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . ')';
253 }
254
255 $where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
256 AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids) . '))';
257
258 return $where_sql;
259 }
260
261 /**
262 * Create topic/post visibility SQL for all forums on the board
263 *
264 * Note: Read permissions are not checked. Forums without read permissions
265 * should be in $exclude_forum_ids
266 *
267 * @param $mode string Either "topic" or "post"
268 * @param $exclude_forum_ids array Array of forum ids which are excluded
269 * @param $table_alias string Table alias to prefix in SQL queries
270 * @return string The appropriate combination SQL logic for topic/post_visibility
271 */
272 public function get_global_visibility_sql($mode, $exclude_forum_ids = array(), $table_alias = '')
273 {
274 $where_sqls = array();
275
276 $approve_forums = array_diff(array_keys($this->auth->acl_getf('m_approve', true)), $exclude_forum_ids);
277
278 $visibility_sql_overwrite = null;
279
280 /**
281 * Allow changing the result of calling get_global_visibility_sql
282 *
283 * @event core.phpbb_content_visibility_get_global_visibility_before
284 * @var array where_sqls The action the user tried to execute
285 * @var string mode Either "topic" or "post" depending on the query this is being used in
286 * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to
287 * @var string table_alias Table alias to prefix in SQL queries
288 * @var array approve_forums Array of forums where the user has m_approve permissions
289 * @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR")
290 * @since 3.1.3-RC1
291 */
292 $vars = array(
293 'where_sqls',
294 'mode',
295 'exclude_forum_ids',
296 'table_alias',
297 'approve_forums',
298 'visibility_sql_overwrite',
299 );
300 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_global_visibility_before', compact($vars)));
301
302 if ($visibility_sql_overwrite)
303 {
304 return $visibility_sql_overwrite;
305 }
306
307 if (sizeof($exclude_forum_ids))
308 {
309 $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . '
310 AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')';
311 }
312 else
313 {
314 $where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
315 }
316
317 if (sizeof($approve_forums))
318 {
319 $where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums);
320 return '(' . implode(' OR ', $where_sqls) . ')';
321 }
322
323 // There is only one element, so we just return that one
324 return $where_sqls[0];
325 }
326
327 /**
328 * Change visibility status of one post or all posts of a topic
329 *
330 * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
331 * @param $post_id mixed Post ID or array of post IDs to act on,
332 * if it is empty, all posts of topic_id will be modified
333 * @param $topic_id int Topic where $post_id is found
334 * @param $forum_id int Forum where $topic_id is found
335 * @param $user_id int User performing the action
336 * @param $time int Timestamp when the action is performed
337 * @param $reason string Reason why the visibility was changed.
338 * @param $is_starter bool Is this the first post of the topic changed?
339 * @param $is_latest bool Is this the last post of the topic changed?
340 * @param $limit_visibility mixed Limit updating per topic_id to a certain visibility
341 * @param $limit_delete_time mixed Limit updating per topic_id to a certain deletion time
342 * @return array Changed post data, empty array if an error occurred.
343 */
344 public function set_post_visibility($visibility, $post_id, $topic_id, $forum_id, $user_id, $time, $reason, $is_starter, $is_latest, $limit_visibility = false, $limit_delete_time = false)
345 {
346 if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
347 {
348 return array();
349 }
350
351 if ($post_id)
352 {
353 if (is_array($post_id))
354 {
355 $where_sql = $this->db->sql_in_set('post_id', array_map('intval', $post_id));
356 }
357 else
358 {
359 $where_sql = 'post_id = ' . (int) $post_id;
360 }
361 $where_sql .= ' AND topic_id = ' . (int) $topic_id;
362 }
363 else
364 {
365 $where_sql = 'topic_id = ' . (int) $topic_id;
366
367 // Limit the posts to a certain visibility and deletion time
368 // This allows us to only restore posts, that were approved
369 // when the topic got soft deleted. So previous soft deleted
370 // and unapproved posts are still soft deleted/unapproved
371 if ($limit_visibility !== false)
372 {
373 $where_sql .= ' AND post_visibility = ' . (int) $limit_visibility;
374 }
375
376 if ($limit_delete_time !== false)
377 {
378 $where_sql .= ' AND post_delete_time = ' . (int) $limit_delete_time;
379 }
380 }
381
382 $sql = 'SELECT poster_id, post_id, post_postcount, post_visibility
383 FROM ' . $this->posts_table . '
384 WHERE ' . $where_sql;
385 $result = $this->db->sql_query($sql);
386
387 $post_ids = $poster_postcounts = $postcounts = $postcount_visibility = array();
388 while ($row = $this->db->sql_fetchrow($result))
389 {
390 $post_ids[] = (int) $row['post_id'];
391
392 if ($row['post_visibility'] != $visibility)
393 {
394 if ($row['post_postcount'] && !isset($poster_postcounts[(int) $row['poster_id']]))
395 {
396 $poster_postcounts[(int) $row['poster_id']] = 1;
397 }
398 else if ($row['post_postcount'])
399 {
400 $poster_postcounts[(int) $row['poster_id']]++;
401 }
402
403 if (!isset($postcount_visibility[$row['post_visibility']]))
404 {
405 $postcount_visibility[$row['post_visibility']] = 1;
406 }
407 else
408 {
409 $postcount_visibility[$row['post_visibility']]++;
410 }
411 }
412 }
413 $this->db->sql_freeresult($result);
414
415 if (empty($post_ids))
416 {
417 return array();
418 }
419
420 if (!function_exists('truncate_string'))
421 {
422 include($this->phpbb_root_path . 'includes/functions_content.' . $this->php_ext);
423 }
424
425 $data = array(
426 'post_visibility' => (int) $visibility,
427 'post_delete_user' => (int) $user_id,
428 'post_delete_time' => ((int) $time) ?: time(),
429 'post_delete_reason' => truncate_string($reason, 255, 255, false),
430 );
431 /**
432 * Perform actions right before the query to change post visibility
433 *
434 * @event core.set_post_visibility_before_sql
435 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
436 * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
437 * @var int topic_id Topic of the post IDs to be modified.
438 * @var int forum_id Forum ID that the topic_id resides in.
439 * @var int user_id User ID doing this action.
440 * @var int timestamp Timestamp of this action.
441 * @var string reason Reason specified by the user for this change.
442 * @var bool is_starter Are we changing the topic's starter?
443 * @var bool is_latest Are we changing the topic's latest post?
444 * @var array data The data array for this action.
445 * @since 3.1.10-RC1
446 */
447 $vars = array(
448 'visibility',
449 'post_id',
450 'topic_id',
451 'forum_id',
452 'user_id',
453 'timestamp',
454 'reason',
455 'is_starter',
456 'is_latest',
457 'data',
458 );
459 extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_before_sql', compact($vars)));
460 $sql = 'UPDATE ' . $this->posts_table . '
461 SET ' . $this->db->sql_build_array('UPDATE', $data) . '
462 WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
463 $this->db->sql_query($sql);
464
465 // Group the authors by post count, to reduce the number of queries
466 foreach ($poster_postcounts as $poster_id => $num_posts)
467 {
468 $postcounts[$num_posts][] = $poster_id;
469 }
470
471 // Update users postcounts
472 foreach ($postcounts as $num_posts => $poster_ids)
473 {
474 if (in_array($visibility, array(ITEM_REAPPROVE, ITEM_DELETED)))
475 {
476 $sql = 'UPDATE ' . $this->users_table . '
477 SET user_posts = 0
478 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
479 AND user_posts < ' . $num_posts;
480 $this->db->sql_query($sql);
481
482 $sql = 'UPDATE ' . $this->users_table . '
483 SET user_posts = user_posts - ' . $num_posts . '
484 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
485 AND user_posts >= ' . $num_posts;
486 $this->db->sql_query($sql);
487 }
488 else
489 {
490 $sql = 'UPDATE ' . $this->users_table . '
491 SET user_posts = user_posts + ' . $num_posts . '
492 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids);
493 $this->db->sql_query($sql);
494 }
495 }
496
497 $update_topic_postcount = true;
498
499 // Sync the first/last topic information if needed
500 if (!$is_starter && $is_latest)
501 {
502 if (!function_exists('update_post_information'))
503 {
504 include($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext);
505 }
506
507 // update_post_information can only update the last post info ...
508 if ($topic_id)
509 {
510 update_post_information('topic', $topic_id, false);
511 }
512 if ($forum_id)
513 {
514 update_post_information('forum', $forum_id, false);
515 }
516 }
517 else if ($is_starter && $topic_id)
518 {
519 if (!function_exists('sync'))
520 {
521 include($this->phpbb_root_path . 'includes/functions_admin.' . $this->php_ext);
522 }
523
524 // ... so we need to use sync, if the first post is changed.
525 // The forum is resynced recursive by sync() itself.
526 sync('topic', 'topic_id', $topic_id, true);
527
528 // sync recalculates the topic replies and forum posts by itself, so we don't do that.
529 $update_topic_postcount = false;
530 }
531
532 $topic_update_array = array();
533 // Update the topic's reply count and the forum's post count
534 if ($update_topic_postcount)
535 {
536 $field_alias = array(
537 ITEM_APPROVED => 'posts_approved',
538 ITEM_UNAPPROVED => 'posts_unapproved',
539 ITEM_DELETED => 'posts_softdeleted',
540 ITEM_REAPPROVE => 'posts_unapproved',
541 );
542 $cur_posts = array_fill_keys($field_alias, 0);
543
544 foreach ($postcount_visibility as $post_visibility => $visibility_posts)
545 {
546 $cur_posts[$field_alias[(int) $post_visibility]] += $visibility_posts;
547 }
548
549 $sql_ary = array();
550 $recipient_field = $field_alias[$visibility];
551
552 foreach ($cur_posts as $field => $count)
553 {
554 // Decrease the count for the old statuses.
555 if ($count && $field != $recipient_field)
556 {
557 $sql_ary[$field] = " - $count";
558 }
559 }
560 // Add up the count from all statuses excluding the recipient status.
561 $count_increase = array_sum(array_diff($cur_posts, array($recipient_field)));
562
563 if ($count_increase)
564 {
565 $sql_ary[$recipient_field] = " + $count_increase";
566 }
567
568 if (sizeof($sql_ary))
569 {
570 $forum_sql = array();
571
572 foreach ($sql_ary as $field => $value_change)
573 {
574 $topic_update_array[] = 'topic_' . $field . ' = topic_' . $field . $value_change;
575 $forum_sql[] = 'forum_' . $field . ' = forum_' . $field . $value_change;
576 }
577
578 $sql = 'UPDATE ' . $this->forums_table . '
579 SET ' . implode(', ', $forum_sql) . '
580 WHERE forum_id = ' . (int) $forum_id;
581 $this->db->sql_query($sql);
582 }
583 }
584
585 if ($post_id)
586 {
587 $sql = 'SELECT 1 AS has_attachments
588 FROM ' . POSTS_TABLE . '
589 WHERE topic_id = ' . (int) $topic_id . '
590 AND post_attachment = 1
591 AND post_visibility = ' . ITEM_APPROVED . '
592 AND ' . $this->db->sql_in_set('post_id', $post_id, true);
593 $result = $this->db->sql_query_limit($sql, 1);
594
595 $has_attachment = (bool) $this->db->sql_fetchfield('has_attachments');
596 $this->db->sql_freeresult($result);
597
598 if ($has_attachment && $visibility == ITEM_APPROVED)
599 {
600 $topic_update_array[] = 'topic_attachment = 1';
601 }
602 else if (!$has_attachment && $visibility != ITEM_APPROVED)
603 {
604 $topic_update_array[] = 'topic_attachment = 0';
605 }
606 }
607
608 if (!empty($topic_update_array))
609 {
610 // Update the number for replies and posts, and update the attachments flag
611 $sql = 'UPDATE ' . $this->topics_table . '
612 SET ' . implode(', ', $topic_update_array) . '
613 WHERE topic_id = ' . (int) $topic_id;
614 $this->db->sql_query($sql);
615 }
616 /**
617 * Perform actions after all steps to changing post visibility
618 *
619 * @event core.set_post_visibility_after
620 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
621 * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
622 * @var int topic_id Topic of the post IDs to be modified.
623 * @var int forum_id Forum ID that the topic_id resides in.
624 * @var int user_id User ID doing this action.
625 * @var int timestamp Timestamp of this action.
626 * @var string reason Reason specified by the user for this change.
627 * @var bool is_starter Are we changing the topic's starter?
628 * @var bool is_latest Are we changing the topic's latest post?
629 * @var array data The data array for this action.
630 * @since 3.1.10-RC1
631 */
632 $vars = array(
633 'visibility',
634 'post_id',
635 'topic_id',
636 'forum_id',
637 'user_id',
638 'timestamp',
639 'reason',
640 'is_starter',
641 'is_latest',
642 'data',
643 );
644 extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_after', compact($vars)));
645 return $data;
646 }
647
648 /**
649 * Set topic visibility
650 *
651 * Allows approving (which is akin to undeleting/restore) or soft deleting an entire topic.
652 * Calls set_post_visibility as needed.
653 *
654 * Note: By default, when a soft deleted topic is restored. Only posts that
655 * were approved at the time of soft deleting, are being restored.
656 * Same applies to soft deleting. Only approved posts will be marked
657 * as soft deleted.
658 * If you want to update all posts, use the force option.
659 *
660 * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
661 * @param $topic_id mixed Topic ID to act on
662 * @param $forum_id int Forum where $topic_id is found
663 * @param $user_id int User performing the action
664 * @param $time int Timestamp when the action is performed
665 * @param $reason string Reason why the visibilty was changed.
666 * @param $force_update_all bool Force to update all posts within the topic
667 * @return array Changed topic data, empty array if an error occured.
668 */
669 public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false)
670 {
671 if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
672 {
673 return array();
674 }
675
676 if (!$force_update_all)
677 {
678 $sql = 'SELECT topic_visibility, topic_delete_time
679 FROM ' . $this->topics_table . '
680 WHERE topic_id = ' . (int) $topic_id;
681 $result = $this->db->sql_query($sql);
682 $original_topic_data = $this->db->sql_fetchrow($result);
683 $this->db->sql_freeresult($result);
684
685 if (!$original_topic_data)
686 {
687 // The topic does not exist...
688 return array();
689 }
690 }
691
692 if (!function_exists('truncate_string'))
693 {
694 include($this->phpbb_root_path . 'includes/functions_content.' . $this->php_ext);
695 }
696
697 // Note, we do not set a reason for the posts, just for the topic
698 $data = array(
699 'topic_visibility' => (int) $visibility,
700 'topic_delete_user' => (int) $user_id,
701 'topic_delete_time' => ((int) $time) ?: time(),
702 'topic_delete_reason' => truncate_string($reason, 255, 255, false),
703 );
704 /**
705 * Perform actions right before the query to change topic visibility
706 *
707 * @event core.set_topic_visibility_before_sql
708 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
709 * @var int topic_id Topic of the post IDs to be modified.
710 * @var int forum_id Forum ID that the topic_id resides in.
711 * @var int user_id User ID doing this action.
712 * @var int timestamp Timestamp of this action.
713 * @var string reason Reason specified by the user for this change.
714 * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
715 * @var array data The data array for this action.
716 * @since 3.1.10-RC1
717 */
718 $vars = array(
719 'visibility',
720 'topic_id',
721 'forum_id',
722 'user_id',
723 'timestamp',
724 'reason',
725 'force_update_all',
726 'data',
727 );
728 extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars)));
729 $sql = 'UPDATE ' . $this->topics_table . '
730 SET ' . $this->db->sql_build_array('UPDATE', $data) . '
731 WHERE topic_id = ' . (int) $topic_id;
732 $this->db->sql_query($sql);
733
734 if (!$this->db->sql_affectedrows())
735 {
736 return array();
737 }
738
739 if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED)
740 {
741 // If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion.
742 $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']);
743 }
744 else if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED)
745 {
746 // If we're soft deleting a topic we only mark approved posts as soft deleted.
747 $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']);
748 }
749 else
750 {
751 $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
752 }
753 /**
754 * Perform actions after all steps to changing topic visibility
755 *
756 * @event core.set_topic_visibility_after
757 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
758 * @var int topic_id Topic of the post IDs to be modified.
759 * @var int forum_id Forum ID that the topic_id resides in.
760 * @var int user_id User ID doing this action.
761 * @var int timestamp Timestamp of this action.
762 * @var string reason Reason specified by the user for this change.
763 * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
764 * @var array data The data array for this action.
765 * @since 3.1.10-RC1
766 */
767 $vars = array(
768 'visibility',
769 'topic_id',
770 'forum_id',
771 'user_id',
772 'timestamp',
773 'reason',
774 'force_update_all',
775 'data',
776 );
777 extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars)));
778 return $data;
779 }
780
781 /**
782 * Add post to topic and forum statistics
783 *
784 * @param $data array Contains information from the topics table about given topic
785 * @param &$sql_data array Populated with the SQL changes, may be empty at call time
786 * @return null
787 */
788 public function add_post_to_statistic($data, &$sql_data)
789 {
790 $sql_data[$this->topics_table] = (($sql_data[$this->topics_table]) ? $sql_data[$this->topics_table] . ', ' : '') . 'topic_posts_approved = topic_posts_approved + 1';
791
792 $sql_data[$this->forums_table] = (($sql_data[$this->forums_table]) ? $sql_data[$this->forums_table] . ', ' : '') . 'forum_posts_approved = forum_posts_approved + 1';
793
794 if ($data['post_postcount'])
795 {
796 $sql_data[$this->users_table] = (($sql_data[$this->users_table]) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts + 1';
797 }
798
799 $this->config->increment('num_posts', 1, false);
800 }
801
802 /**
803 * Remove post from topic and forum statistics
804 *
805 * @param $data array Contains information from the topics table about given topic
806 * @param &$sql_data array Populated with the SQL changes, may be empty at call time
807 * @return null
808 */
809 public function remove_post_from_statistic($data, &$sql_data)
810 {
811 if ($data['post_visibility'] == ITEM_APPROVED)
812 {
813 $sql_data[$this->topics_table] = ((!empty($sql_data[$this->topics_table])) ? $sql_data[$this->topics_table] . ', ' : '') . 'topic_posts_approved = topic_posts_approved - 1';
814 $sql_data[$this->forums_table] = ((!empty($sql_data[$this->forums_table])) ? $sql_data[$this->forums_table] . ', ' : '') . 'forum_posts_approved = forum_posts_approved - 1';
815
816 if ($data['post_postcount'])
817 {
818 $sql_data[$this->users_table] = ((!empty($sql_data[$this->users_table])) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts - 1';
819 }
820
821 $this->config->increment('num_posts', -1, false);
822 }
823 else if ($data['post_visibility'] == ITEM_UNAPPROVED || $data['post_visibility'] == ITEM_REAPPROVE)
824 {
825 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_unapproved = forum_posts_unapproved - 1';
826 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_unapproved = topic_posts_unapproved - 1';
827 }
828 else if ($data['post_visibility'] == ITEM_DELETED)
829 {
830 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_softdeleted = forum_posts_softdeleted - 1';
831 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_softdeleted = topic_posts_softdeleted - 1';
832 }
833 }
834
835 /**
836 * Remove topic from forum statistics
837 *
838 * @param $data array Post and topic data
839 * @param &$sql_data array Populated with the SQL changes, may be empty at call time
840 * @return null
841 */
842 public function remove_topic_from_statistic($data, &$sql_data)
843 {
844 if ($data['topic_visibility'] == ITEM_APPROVED)
845 {
846 $sql_data[FORUMS_TABLE] .= 'forum_posts_approved = forum_posts_approved - 1, forum_topics_approved = forum_topics_approved - 1';
847
848 if ($data['post_postcount'])
849 {
850 $sql_data[$this->users_table] = ((!empty($sql_data[$this->users_table])) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts - 1';
851 }
852 }
853 else if ($data['topic_visibility'] == ITEM_UNAPPROVED || $data['post_visibility'] == ITEM_REAPPROVE)
854 {
855 $sql_data[FORUMS_TABLE] .= 'forum_posts_unapproved = forum_posts_unapproved - 1, forum_topics_unapproved = forum_topics_unapproved - 1';
856 }
857 else if ($data['topic_visibility'] == ITEM_DELETED)
858 {
859 $sql_data[FORUMS_TABLE] .= 'forum_posts_softdeleted = forum_posts_softdeleted - 1, forum_topics_softdeleted = forum_topics_softdeleted - 1';
860 }
861
862 }
863 }
864