Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
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 /**
136 * Check topic/post visibility for a given forum ID
137 *
138 * Note: Read permissions are not checked.
139 *
140 * @param $mode string Either "topic" or "post"
141 * @param $forum_id int The forum id is used for permission checks
142 * @param $data array Array with item information to check visibility
143 * @return bool True if the item is visible, false if not
144 */
145 public function is_visible($mode, $forum_id, $data)
146 {
147 $visibility = $data[$mode . '_visibility'];
148 $poster_key = ($mode === 'topic') ? 'topic_poster' : 'poster_id';
149 $is_visible = ($visibility == ITEM_APPROVED) ||
150 ($this->config['display_unapproved_posts'] &&
151 ($this->user->data['user_id'] != ANONYMOUS) &&
152 ($visibility == ITEM_UNAPPROVED || $visibility == ITEM_REAPPROVE) &&
153 ($this->user->data['user_id'] == $data[$poster_key])) ||
154 $this->auth->acl_get('m_approve', $forum_id);
155
156 /**
157 * Allow changing the result of calling is_visible
158 *
159 * @event core.phpbb_content_visibility_is_visible
160 * @var bool is_visible Default visibility condition, to be modified by extensions if needed.
161 * @var string mode Either "topic" or "post"
162 * @var int forum_id Forum id of the current item
163 * @var array data Array of item information
164 * @since 3.2.2-RC1
165 */
166 $vars = array(
167 'is_visible',
168 'mode',
169 'forum_id',
170 'data',
171 );
172 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_is_visible', compact($vars)));
173
174 return $is_visible;
175 }
176
177 /**
178 * Create topic/post visibility SQL for a given forum ID
179 *
180 * Note: Read permissions are not checked.
181 *
182 * @param $mode string Either "topic" or "post"
183 * @param $forum_id int The forum id is used for permission checks
184 * @param $table_alias string Table alias to prefix in SQL queries
185 * @return string The appropriate combination SQL logic for topic/post_visibility
186 */
187 public function get_visibility_sql($mode, $forum_id, $table_alias = '')
188 {
189 $where_sql = '';
190
191 $get_visibility_sql_overwrite = false;
192
193 /**
194 * Allow changing the result of calling get_visibility_sql
195 *
196 * @event core.phpbb_content_visibility_get_visibility_sql_before
197 * @var string where_sql Extra visibility conditions. It must end with either an SQL "AND" or an "OR"
198 * @var string mode Either "topic" or "post" depending on the query this is being used in
199 * @var array forum_id The forum id in which the search is made.
200 * @var string table_alias Table alias to prefix in SQL queries
201 * @var mixed get_visibility_sql_overwrite If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event
202 * If false, get_visibility_sql continues normally
203 * It must be either boolean or string
204 * @since 3.1.4-RC1
205 */
206 $vars = array(
207 'where_sql',
208 'mode',
209 'forum_id',
210 'table_alias',
211 'get_visibility_sql_overwrite',
212 );
213 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_visibility_sql_before', compact($vars)));
214
215 if ($get_visibility_sql_overwrite !== false)
216 {
217 return $get_visibility_sql_overwrite;
218 }
219
220 if ($this->auth->acl_get('m_approve', $forum_id))
221 {
222 $where_sql .= '1 = 1';
223 }
224 else
225 {
226 $visibility_query = $table_alias . $mode . '_visibility = ';
227
228 $where_sql .= '(' . $visibility_query . ITEM_APPROVED . ')';
229 if ($this->config['display_unapproved_posts'] && ($this->user->data['user_id'] != ANONYMOUS))
230 {
231 $poster_key = ($mode === 'topic') ? 'topic_poster' : 'poster_id';
232 $where_sql .= ' OR ((' . $visibility_query . ITEM_UNAPPROVED . ' OR ' . $visibility_query . ITEM_REAPPROVE .')';
233 $where_sql .= ' AND ' . $table_alias . $poster_key . ' = ' . ((int) $this->user->data['user_id']) . ')';
234 }
235 }
236 return '(' . $where_sql . ')';
237 }
238
239 /**
240 * Create topic/post visibility SQL for a set of forums
241 *
242 * Note: Read permissions are not checked. Forums without read permissions
243 * should not be in $forum_ids
244 *
245 * @param $mode string Either "topic" or "post"
246 * @param $forum_ids array Array of forum ids which the posts/topics are limited to
247 * @param $table_alias string Table alias to prefix in SQL queries
248 * @return string The appropriate combination SQL logic for topic/post_visibility
249 */
250 public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '')
251 {
252 $where_sql = '';
253
254 $approve_forums = array_keys($this->auth->acl_getf('m_approve', true));
255 if (!empty($forum_ids) && !empty($approve_forums))
256 {
257 $approve_forums = array_intersect($forum_ids, $approve_forums);
258 $forum_ids = array_diff($forum_ids, $approve_forums);
259 }
260
261 $get_forums_visibility_sql_overwrite = false;
262 /**
263 * Allow changing the result of calling get_forums_visibility_sql
264 *
265 * @event core.phpbb_content_visibility_get_forums_visibility_before
266 * @var string where_sql Extra visibility conditions. It must end with either an SQL "AND" or an "OR"
267 * @var string mode Either "topic" or "post" depending on the query this is being used in
268 * @var array forum_ids Array of forum ids which the posts/topics are limited to
269 * @var string table_alias Table alias to prefix in SQL queries
270 * @var array approve_forums Array of forums where the user has m_approve permissions
271 * @var mixed get_forums_visibility_sql_overwrite If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event
272 * If false, get_forums_visibility_sql continues normally
273 * It must be either boolean or string
274 * @since 3.1.3-RC1
275 */
276 $vars = array(
277 'where_sql',
278 'mode',
279 'forum_ids',
280 'table_alias',
281 'approve_forums',
282 'get_forums_visibility_sql_overwrite',
283 );
284 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_forums_visibility_before', compact($vars)));
285
286 if ($get_forums_visibility_sql_overwrite !== false)
287 {
288 return $get_forums_visibility_sql_overwrite;
289 }
290
291 // Moderator can view all posts/topics in the moderated forums
292 $where_sql .= '(' . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums, false, true) . ' OR ';
293 // Normal user can view approved items only
294 $where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
295 AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . '))';
296
297 return '(' . $where_sql . ')';
298 }
299
300 /**
301 * Create topic/post visibility SQL for all forums on the board
302 *
303 * Note: Read permissions are not checked. Forums without read permissions
304 * should be in $exclude_forum_ids
305 *
306 * @param $mode string Either "topic" or "post"
307 * @param $exclude_forum_ids array Array of forum ids which are excluded
308 * @param $table_alias string Table alias to prefix in SQL queries
309 * @return string The appropriate combination SQL logic for topic/post_visibility
310 */
311 public function get_global_visibility_sql($mode, $exclude_forum_ids = array(), $table_alias = '')
312 {
313 $where_sqls = array();
314
315 $approve_forums = array_diff(array_keys($this->auth->acl_getf('m_approve', true)), $exclude_forum_ids);
316
317 $visibility_sql_overwrite = null;
318
319 /**
320 * Allow changing the result of calling get_global_visibility_sql
321 *
322 * @event core.phpbb_content_visibility_get_global_visibility_before
323 * @var array where_sqls Array of extra visibility conditions. Will be joined by imploding with "OR".
324 * @var string mode Either "topic" or "post" depending on the query this is being used in
325 * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to
326 * @var string table_alias Table alias to prefix in SQL queries
327 * @var array approve_forums Array of forums where the user has m_approve permissions
328 * @var string visibility_sql_overwrite If not empty, forces the function to return visibility_sql_overwrite after executing the event
329 * @since 3.1.3-RC1
330 */
331 $vars = array(
332 'where_sqls',
333 'mode',
334 'exclude_forum_ids',
335 'table_alias',
336 'approve_forums',
337 'visibility_sql_overwrite',
338 );
339 extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_global_visibility_before', compact($vars)));
340
341 if ($visibility_sql_overwrite)
342 {
343 return $visibility_sql_overwrite;
344 }
345
346 // Include approved items in all forums but the excluded
347 $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true, true) . '
348 AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')';
349
350 // If user has moderator permissions, add everything in the moderated forums
351 if (count($approve_forums))
352 {
353 $where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums);
354 }
355
356 return '(' . implode(' OR ', $where_sqls) . ')';
357 }
358
359 /**
360 * Change visibility status of one post or all posts of a topic
361 *
362 * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
363 * @param $post_id mixed Post ID or array of post IDs to act on,
364 * if it is empty, all posts of topic_id will be modified
365 * @param $topic_id int Topic where $post_id is found
366 * @param $forum_id int Forum where $topic_id is found
367 * @param $user_id int User performing the action
368 * @param $time int Timestamp when the action is performed
369 * @param $reason string Reason why the visibility was changed.
370 * @param $is_starter bool Is this the first post of the topic changed?
371 * @param $is_latest bool Is this the last post of the topic changed?
372 * @param $limit_visibility mixed Limit updating per topic_id to a certain visibility
373 * @param $limit_delete_time mixed Limit updating per topic_id to a certain deletion time
374 * @return array Changed post data, empty array if an error occurred.
375 */
376 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)
377 {
378 if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
379 {
380 return array();
381 }
382
383 if ($post_id)
384 {
385 if (is_array($post_id))
386 {
387 $where_sql = $this->db->sql_in_set('post_id', array_map('intval', $post_id));
388 }
389 else
390 {
391 $where_sql = 'post_id = ' . (int) $post_id;
392 }
393 $where_sql .= ' AND topic_id = ' . (int) $topic_id;
394 }
395 else
396 {
397 $where_sql = 'topic_id = ' . (int) $topic_id;
398
399 // Limit the posts to a certain visibility and deletion time
400 // This allows us to only restore posts, that were approved
401 // when the topic got soft deleted. So previous soft deleted
402 // and unapproved posts are still soft deleted/unapproved
403 if ($limit_visibility !== false)
404 {
405 $where_sql .= ' AND post_visibility = ' . (int) $limit_visibility;
406 }
407
408 if ($limit_delete_time !== false)
409 {
410 $where_sql .= ' AND post_delete_time = ' . (int) $limit_delete_time;
411 }
412 }
413
414 $sql = 'SELECT poster_id, post_id, post_postcount, post_visibility
415 FROM ' . $this->posts_table . '
416 WHERE ' . $where_sql;
417 $result = $this->db->sql_query($sql);
418
419 $post_ids = $poster_postcounts = $postcounts = $postcount_visibility = array();
420 while ($row = $this->db->sql_fetchrow($result))
421 {
422 $post_ids[] = (int) $row['post_id'];
423
424 if ($row['post_visibility'] != $visibility)
425 {
426 if ($row['post_postcount'] && !isset($poster_postcounts[(int) $row['poster_id']]))
427 {
428 $poster_postcounts[(int) $row['poster_id']] = 1;
429 }
430 else if ($row['post_postcount'])
431 {
432 $poster_postcounts[(int) $row['poster_id']]++;
433 }
434
435 if (!isset($postcount_visibility[$row['post_visibility']]))
436 {
437 $postcount_visibility[$row['post_visibility']] = 1;
438 }
439 else
440 {
441 $postcount_visibility[$row['post_visibility']]++;
442 }
443 }
444 }
445 $this->db->sql_freeresult($result);
446
447 if (empty($post_ids))
448 {
449 return array();
450 }
451
452 if (!function_exists('truncate_string'))
453 {
454 include($this->phpbb_root_path . 'includes/functions_content.' . $this->php_ext);
455 }
456
457 $data = array(
458 'post_visibility' => (int) $visibility,
459 'post_delete_user' => (int) $user_id,
460 'post_delete_time' => ((int) $time) ?: time(),
461 'post_delete_reason' => truncate_string($reason, 255, 255, false),
462 );
463 /**
464 * Perform actions right before the query to change post visibility
465 *
466 * @event core.set_post_visibility_before_sql
467 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
468 * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
469 * @var int topic_id Topic of the post IDs to be modified.
470 * @var int forum_id Forum ID that the topic_id resides in.
471 * @var int user_id User ID doing this action.
472 * @var int time Timestamp of this action.
473 * @var string reason Reason specified by the user for this change.
474 * @var bool is_starter Are we changing the topic's starter?
475 * @var bool is_latest Are we changing the topic's latest post?
476 * @var array data The data array for this action.
477 * @since 3.1.10-RC1
478 * @changed 3.2.2-RC1 Use time instead of non-existent timestamp
479 */
480 $vars = array(
481 'visibility',
482 'post_id',
483 'topic_id',
484 'forum_id',
485 'user_id',
486 'time',
487 'reason',
488 'is_starter',
489 'is_latest',
490 'data',
491 );
492 extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_before_sql', compact($vars)));
493 $sql = 'UPDATE ' . $this->posts_table . '
494 SET ' . $this->db->sql_build_array('UPDATE', $data) . '
495 WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
496 $this->db->sql_query($sql);
497
498 // Group the authors by post count, to reduce the number of queries
499 foreach ($poster_postcounts as $poster_id => $num_posts)
500 {
501 $postcounts[$num_posts][] = $poster_id;
502 }
503
504 $postcount_change = 0;
505
506 // Update users postcounts
507 foreach ($postcounts as $num_posts => $poster_ids)
508 {
509 if (in_array($visibility, array(ITEM_REAPPROVE, ITEM_DELETED)))
510 {
511 $postcount_change -= $num_posts;
512
513 $sql = 'UPDATE ' . $this->users_table . '
514 SET user_posts = 0
515 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
516 AND user_posts < ' . $num_posts;
517 $this->db->sql_query($sql);
518
519 $sql = 'UPDATE ' . $this->users_table . '
520 SET user_posts = user_posts - ' . $num_posts . '
521 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
522 AND user_posts >= ' . $num_posts;
523 $this->db->sql_query($sql);
524 }
525 else
526 {
527 $postcount_change += $num_posts;
528
529 $sql = 'UPDATE ' . $this->users_table . '
530 SET user_posts = user_posts + ' . $num_posts . '
531 WHERE ' . $this->db->sql_in_set('user_id', $poster_ids);
532 $this->db->sql_query($sql);
533 }
534 }
535
536 if ($postcount_change != 0)
537 {
538 $this->config->increment('num_posts', $postcount_change, false);
539 }
540
541 $update_topic_postcount = true;
542
543 // Sync the first/last topic information if needed
544 if (!$is_starter && $is_latest)
545 {
546 if (!function_exists('update_post_information'))
547 {
548 include($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext);
549 }
550
551 // update_post_information can only update the last post info ...
552 if ($topic_id)
553 {
554 update_post_information('topic', $topic_id, false);
555 }
556 if ($forum_id)
557 {
558 update_post_information('forum', $forum_id, false);
559 }
560 }
561 else if ($is_starter && $topic_id)
562 {
563 if (!function_exists('sync'))
564 {
565 include($this->phpbb_root_path . 'includes/functions_admin.' . $this->php_ext);
566 }
567
568 // ... so we need to use sync, if the first post is changed.
569 // The forum is resynced recursive by sync() itself.
570 sync('topic', 'topic_id', $topic_id, true);
571
572 // sync recalculates the topic replies and forum posts by itself, so we don't do that.
573 $update_topic_postcount = false;
574 }
575
576 $topic_update_array = array();
577 // Update the topic's reply count and the forum's post count
578 if ($update_topic_postcount)
579 {
580 $field_alias = array(
581 ITEM_APPROVED => 'posts_approved',
582 ITEM_UNAPPROVED => 'posts_unapproved',
583 ITEM_DELETED => 'posts_softdeleted',
584 ITEM_REAPPROVE => 'posts_unapproved',
585 );
586 $cur_posts = array_fill_keys($field_alias, 0);
587
588 foreach ($postcount_visibility as $post_visibility => $visibility_posts)
589 {
590 $cur_posts[$field_alias[(int) $post_visibility]] += $visibility_posts;
591 }
592
593 $sql_ary = array();
594 $recipient_field = $field_alias[$visibility];
595
596 foreach ($cur_posts as $field => $count)
597 {
598 // Decrease the count for the old statuses.
599 if ($count && $field != $recipient_field)
600 {
601 $sql_ary[$field] = " - $count";
602 }
603 }
604 // Add up the count from all statuses excluding the recipient status.
605 $count_increase = array_sum(array_diff($cur_posts, array($recipient_field)));
606
607 if ($count_increase)
608 {
609 $sql_ary[$recipient_field] = " + $count_increase";
610 }
611
612 if (count($sql_ary))
613 {
614 $forum_sql = array();
615
616 foreach ($sql_ary as $field => $value_change)
617 {
618 $topic_update_array[] = 'topic_' . $field . ' = topic_' . $field . $value_change;
619 $forum_sql[] = 'forum_' . $field . ' = forum_' . $field . $value_change;
620 }
621
622 $sql = 'UPDATE ' . $this->forums_table . '
623 SET ' . implode(', ', $forum_sql) . '
624 WHERE forum_id = ' . (int) $forum_id;
625 $this->db->sql_query($sql);
626 }
627 }
628
629 if ($post_id)
630 {
631 $sql = 'SELECT 1 AS has_attachments
632 FROM ' . POSTS_TABLE . '
633 WHERE topic_id = ' . (int) $topic_id . '
634 AND post_attachment = 1
635 AND post_visibility = ' . ITEM_APPROVED . '
636 AND ' . $this->db->sql_in_set('post_id', $post_id, true);
637 $result = $this->db->sql_query_limit($sql, 1);
638
639 $has_attachment = (bool) $this->db->sql_fetchfield('has_attachments');
640 $this->db->sql_freeresult($result);
641
642 if ($has_attachment && $visibility == ITEM_APPROVED)
643 {
644 $topic_update_array[] = 'topic_attachment = 1';
645 }
646 else if (!$has_attachment && $visibility != ITEM_APPROVED)
647 {
648 $topic_update_array[] = 'topic_attachment = 0';
649 }
650 }
651
652 if (!empty($topic_update_array))
653 {
654 // Update the number for replies and posts, and update the attachments flag
655 $sql = 'UPDATE ' . $this->topics_table . '
656 SET ' . implode(', ', $topic_update_array) . '
657 WHERE topic_id = ' . (int) $topic_id;
658 $this->db->sql_query($sql);
659 }
660 /**
661 * Perform actions after all steps to changing post visibility
662 *
663 * @event core.set_post_visibility_after
664 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
665 * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
666 * @var int topic_id Topic of the post IDs to be modified.
667 * @var int forum_id Forum ID that the topic_id resides in.
668 * @var int user_id User ID doing this action.
669 * @var int time Timestamp of this action.
670 * @var string reason Reason specified by the user for this change.
671 * @var bool is_starter Are we changing the topic's starter?
672 * @var bool is_latest Are we changing the topic's latest post?
673 * @var array data The data array for this action.
674 * @since 3.1.10-RC1
675 * @changed 3.2.2-RC1 Use time instead of non-existent timestamp
676 */
677 $vars = array(
678 'visibility',
679 'post_id',
680 'topic_id',
681 'forum_id',
682 'user_id',
683 'time',
684 'reason',
685 'is_starter',
686 'is_latest',
687 'data',
688 );
689 extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_after', compact($vars)));
690 return $data;
691 }
692
693 /**
694 * Set topic visibility
695 *
696 * Allows approving (which is akin to undeleting/restore) or soft deleting an entire topic.
697 * Calls set_post_visibility as needed.
698 *
699 * Note: By default, when a soft deleted topic is restored. Only posts that
700 * were approved at the time of soft deleting, are being restored.
701 * Same applies to soft deleting. Only approved posts will be marked
702 * as soft deleted.
703 * If you want to update all posts, use the force option.
704 *
705 * @param $visibility int Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
706 * @param $topic_id mixed Topic ID to act on
707 * @param $forum_id int Forum where $topic_id is found
708 * @param $user_id int User performing the action
709 * @param $time int Timestamp when the action is performed
710 * @param $reason string Reason why the visibilty was changed.
711 * @param $force_update_all bool Force to update all posts within the topic
712 * @return array Changed topic data, empty array if an error occurred.
713 */
714 public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false)
715 {
716 if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE)))
717 {
718 return array();
719 }
720
721 if (!$force_update_all)
722 {
723 $sql = 'SELECT topic_visibility, topic_delete_time
724 FROM ' . $this->topics_table . '
725 WHERE topic_id = ' . (int) $topic_id;
726 $result = $this->db->sql_query($sql);
727 $original_topic_data = $this->db->sql_fetchrow($result);
728 $this->db->sql_freeresult($result);
729
730 if (!$original_topic_data)
731 {
732 // The topic does not exist...
733 return array();
734 }
735 }
736
737 if (!function_exists('truncate_string'))
738 {
739 include($this->phpbb_root_path . 'includes/functions_content.' . $this->php_ext);
740 }
741
742 // Note, we do not set a reason for the posts, just for the topic
743 $data = array(
744 'topic_visibility' => (int) $visibility,
745 'topic_delete_user' => (int) $user_id,
746 'topic_delete_time' => ((int) $time) ?: time(),
747 'topic_delete_reason' => truncate_string($reason, 255, 255, false),
748 );
749 /**
750 * Perform actions right before the query to change topic visibility
751 *
752 * @event core.set_topic_visibility_before_sql
753 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
754 * @var int topic_id Topic of the post IDs to be modified.
755 * @var int forum_id Forum ID that the topic_id resides in.
756 * @var int user_id User ID doing this action.
757 * @var int time Timestamp of this action.
758 * @var string reason Reason specified by the user for this change.
759 * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
760 * @var array data The data array for this action.
761 * @since 3.1.10-RC1
762 * @changed 3.2.2-RC1 Use time instead of non-existent timestamp
763 */
764 $vars = array(
765 'visibility',
766 'topic_id',
767 'forum_id',
768 'user_id',
769 'time',
770 'reason',
771 'force_update_all',
772 'data',
773 );
774 extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars)));
775 $sql = 'UPDATE ' . $this->topics_table . '
776 SET ' . $this->db->sql_build_array('UPDATE', $data) . '
777 WHERE topic_id = ' . (int) $topic_id;
778 $this->db->sql_query($sql);
779
780 if (!$this->db->sql_affectedrows())
781 {
782 return array();
783 }
784
785 if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED)
786 {
787 // If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion.
788 $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']);
789 }
790 else if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED)
791 {
792 // If we're soft deleting a topic we only mark approved posts as soft deleted.
793 $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']);
794 }
795 else
796 {
797 $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
798 }
799 /**
800 * Perform actions after all steps to changing topic visibility
801 *
802 * @event core.set_topic_visibility_after
803 * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
804 * @var int topic_id Topic of the post IDs to be modified.
805 * @var int forum_id Forum ID that the topic_id resides in.
806 * @var int user_id User ID doing this action.
807 * @var int time Timestamp of this action.
808 * @var string reason Reason specified by the user for this change.
809 * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
810 * @var array data The data array for this action.
811 * @since 3.1.10-RC1
812 * @changed 3.2.2-RC1 Use time instead of non-existent timestamp
813 */
814 $vars = array(
815 'visibility',
816 'topic_id',
817 'forum_id',
818 'user_id',
819 'time',
820 'reason',
821 'force_update_all',
822 'data',
823 );
824 extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars)));
825 return $data;
826 }
827
828 /**
829 * Add post to topic and forum statistics
830 *
831 * @param $data array Contains information from the topics table about given topic
832 * @param $sql_data array Populated with the SQL changes, may be empty at call time (by reference)
833 * @return null
834 */
835 public function add_post_to_statistic($data, &$sql_data)
836 {
837 $sql_data[$this->topics_table] = (($sql_data[$this->topics_table]) ? $sql_data[$this->topics_table] . ', ' : '') . 'topic_posts_approved = topic_posts_approved + 1';
838
839 $sql_data[$this->forums_table] = (($sql_data[$this->forums_table]) ? $sql_data[$this->forums_table] . ', ' : '') . 'forum_posts_approved = forum_posts_approved + 1';
840
841 if ($data['post_postcount'])
842 {
843 $sql_data[$this->users_table] = (($sql_data[$this->users_table]) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts + 1';
844 }
845
846 $this->config->increment('num_posts', 1, false);
847 }
848
849 /**
850 * Remove post from topic and forum statistics
851 *
852 * @param $data array Contains information from the topics table about given topic
853 * @param $sql_data array Populated with the SQL changes, may be empty at call time (by reference)
854 * @return null
855 */
856 public function remove_post_from_statistic($data, &$sql_data)
857 {
858 if ($data['post_visibility'] == ITEM_APPROVED)
859 {
860 $sql_data[$this->topics_table] = ((!empty($sql_data[$this->topics_table])) ? $sql_data[$this->topics_table] . ', ' : '') . 'topic_posts_approved = topic_posts_approved - 1';
861 $sql_data[$this->forums_table] = ((!empty($sql_data[$this->forums_table])) ? $sql_data[$this->forums_table] . ', ' : '') . 'forum_posts_approved = forum_posts_approved - 1';
862
863 if ($data['post_postcount'])
864 {
865 $sql_data[$this->users_table] = ((!empty($sql_data[$this->users_table])) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts - 1';
866 }
867
868 $this->config->increment('num_posts', -1, false);
869 }
870 else if ($data['post_visibility'] == ITEM_UNAPPROVED || $data['post_visibility'] == ITEM_REAPPROVE)
871 {
872 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_unapproved = forum_posts_unapproved - 1';
873 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_unapproved = topic_posts_unapproved - 1';
874 }
875 else if ($data['post_visibility'] == ITEM_DELETED)
876 {
877 $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_softdeleted = forum_posts_softdeleted - 1';
878 $sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_softdeleted = topic_posts_softdeleted - 1';
879 }
880 }
881
882 /**
883 * Remove topic from forum statistics
884 *
885 * @param $data array Post and topic data
886 * @param $sql_data array Populated with the SQL changes, may be empty at call time (by reference)
887 * @return null
888 */
889 public function remove_topic_from_statistic($data, &$sql_data)
890 {
891 if ($data['topic_visibility'] == ITEM_APPROVED)
892 {
893 $sql_data[FORUMS_TABLE] .= 'forum_posts_approved = forum_posts_approved - 1, forum_topics_approved = forum_topics_approved - 1';
894
895 if ($data['post_postcount'])
896 {
897 $sql_data[$this->users_table] = ((!empty($sql_data[$this->users_table])) ? $sql_data[$this->users_table] . ', ' : '') . 'user_posts = user_posts - 1';
898 }
899 }
900 else if ($data['topic_visibility'] == ITEM_UNAPPROVED || $data['post_visibility'] == ITEM_REAPPROVE)
901 {
902 $sql_data[FORUMS_TABLE] .= 'forum_posts_unapproved = forum_posts_unapproved - 1, forum_topics_unapproved = forum_topics_unapproved - 1';
903 }
904 else if ($data['topic_visibility'] == ITEM_DELETED)
905 {
906 $sql_data[FORUMS_TABLE] .= 'forum_posts_softdeleted = forum_posts_softdeleted - 1, forum_topics_softdeleted = forum_topics_softdeleted - 1';
907 }
908
909 }
910 }
911