aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/bin/phpbbcli.php
blob: 3061fee817ed2fbbf9bca2ebdf5ce3478fa8172c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env php
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/

use Symfony\Component\Console\Input\ArgvInput;

if (php_sapi_name() != 'cli')
{
	echo 'This program must be run from the command line.' . PHP_EOL;
	exit(1);
}

define('IN_PHPBB', true);

$phpbb_root_path = __DIR__ . '/../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
require($phpbb_root_path . 'includes/startup.' . $phpEx);
require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);

$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
$phpbb_class_loader->register();

$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
extract($phpbb_config_php_file->get_all());

if (!defined('PHPBB_ENVIRONMENT'))
{
	@define('PHPBB_ENVIRONMENT', 'production');
}

require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/functions.' . $phpEx);
require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
require($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);

$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
$phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file);

$input = new ArgvInput();

if ($input->hasParameterOption(array('--env')))
{
	$phpbb_container_builder->with_environment($input->getParameterOption('--env'));
}

if ($input->hasParameterOption(array('--safe-mode')))
{
	$phpbb_container_builder->without_extensions();
	$phpbb_container_builder->without_cache();
}
else
{
	$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
	$phpbb_class_loader_ext->register();
}

$phpbb_container = $phpbb_container_builder->get_container();
$phpbb_container->get('request')->enable_super_globals();
require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx);

register_compatibility_globals();

/** @var \phpbb\language\language $language */
$language = $phpbb_container->get('language');
$language->set_default_language($phpbb_container->get('config')['default_lang']);
$language->add_lang(array('common', 'acp/common', 'cli'));

/* @var $user \phpbb\user */
$user = $phpbb_container->get('user');
$user->data['user_id'] = ANONYMOUS;
$user->ip = '127.0.0.1';

$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $language);
$application->setDispatcher($phpbb_container->get('dispatcher'));
$application->register_container_commands($phpbb_container->get('console.command_collection'));
$application->run($input);
46'>446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
<?php
/**
*
* @package phpbb
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/

namespace phpbb;

/**
* phpbb_visibility
* Handle fetching and setting the visibility for topics and posts
* @package phpbb
*/
class content_visibility
{
	/**
	* Database object
	* @var \phpbb\db\driver\driver_interface
	*/
	protected $db;

	/**
	* User object
	* @var \phpbb\user
	*/
	protected $user;

	/**
	* Auth object
	* @var \phpbb\auth\auth
	*/
	protected $auth;

	/**
	* phpBB root path
	* @var string
	*/
	protected $phpbb_root_path;

	/**
	* PHP Extension
	* @var string
	*/
	protected $php_ext;

	/**
	* Constructor
	*
	* @param	\phpbb\auth\auth		$auth	Auth object
	* @param	\phpbb\db\driver\driver_interface	$db		Database object
	* @param	\phpbb\user		$user	User object
	* @param	string		$phpbb_root_path	Root path
	* @param	string		$php_ext			PHP Extension
	* @return	null
	*/
	public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table)
	{
		$this->auth = $auth;
		$this->db = $db;
		$this->user = $user;
		$this->phpbb_root_path = $phpbb_root_path;
		$this->php_ext = $php_ext;
		$this->forums_table = $forums_table;
		$this->posts_table = $posts_table;
		$this->topics_table = $topics_table;
		$this->users_table = $users_table;
	}

	/**
	* Can the current logged-in user soft-delete posts?
	*
	* @param $forum_id		int		Forum ID whose permissions to check
	* @param $poster_id		int		Poster ID of the post in question
	* @param $post_locked	bool	Is the post locked?
	* @return bool
	*/
	public function can_soft_delete($forum_id, $poster_id, $post_locked)
	{
		if ($this->auth->acl_get('m_softdelete', $forum_id))
		{
			return true;
		}
		else if ($this->auth->acl_get('f_softdelete', $forum_id) && $poster_id == $this->user->data['user_id'] && !$post_locked)
		{
			return true;
		}

		return false;
	}

	/**
	* Get the topics post count or the forums post/topic count based on permissions
	*
	* @param $mode			string	One of topic_posts, forum_posts or forum_topics
	* @param $data			array	Array with the topic/forum data to calculate from
	* @param $forum_id		int		The forum id is used for permission checks
	* @return int	Number of posts/topics the user can see in the topic/forum
	*/
	public function get_count($mode, $data, $forum_id)
	{
		if (!$this->auth->acl_get('m_approve', $forum_id))
		{
			return (int) $data[$mode . '_approved'];
		}

		return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted'];
	}

	/**
	* Create topic/post visibility SQL for a given forum ID
	*
	* Note: Read permissions are not checked.
	*
	* @param $mode			string	Either "topic" or "post"
	* @param $forum_id		int		The forum id is used for permission checks
	* @param $table_alias	string	Table alias to prefix in SQL queries
	* @return string	The appropriate combination SQL logic for topic/post_visibility
	*/
	public function get_visibility_sql($mode, $forum_id, $table_alias = '')
	{
		if ($this->auth->acl_get('m_approve', $forum_id))
		{
			return '1 = 1';
		}

		return $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
	}

	/**
	* Create topic/post visibility SQL for a set of forums
	*
	* Note: Read permissions are not checked. Forums without read permissions
	*		should not be in $forum_ids
	*
	* @param $mode			string	Either "topic" or "post"
	* @param $forum_ids		array	Array of forum ids which the posts/topics are limited to
	* @param $table_alias	string	Table alias to prefix in SQL queries
	* @return string	The appropriate combination SQL logic for topic/post_visibility
	*/
	public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '')
	{
		$where_sql = '(';

		$approve_forums = array_intersect($forum_ids, array_keys($this->auth->acl_getf('m_approve', true)));

		if (sizeof($approve_forums))
		{
			// Remove moderator forums from the rest
			$forum_ids = array_diff($forum_ids, $approve_forums);

			if (!sizeof($forum_ids))
			{
				// The user can see all posts/topics in all specified forums
				return $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums);
			}
			else
			{
				// Moderator can view all posts/topics in some forums
				$where_sql .= $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ' OR ';
			}
		}
		else
		{
			// The user is just a normal user
			return $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
				AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true);
		}

		$where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
			AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids) . '))';

		return $where_sql;
	}

	/**
	* Create topic/post visibility SQL for all forums on the board
	*
	* Note: Read permissions are not checked. Forums without read permissions
	*		should be in $exclude_forum_ids
	*
	* @param $mode				string	Either "topic" or "post"
	* @param $exclude_forum_ids	array	Array of forum ids which are excluded
	* @param $table_alias		string	Table alias to prefix in SQL queries
	* @return string	The appropriate combination SQL logic for topic/post_visibility
	*/
	public function get_global_visibility_sql($mode, $exclude_forum_ids = array(), $table_alias = '')
	{
		$where_sqls = array();

		$approve_forums = array_diff(array_keys($this->auth->acl_getf('m_approve', true)), $exclude_forum_ids);

		if (sizeof($exclude_forum_ids))
		{
			$where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . '
				AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')';
		}
		else
		{
			$where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
		}

		if (sizeof($approve_forums))
		{
			$where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums);
			return '(' . implode(' OR ', $where_sqls) . ')';
		}

		// There is only one element, so we just return that one
		return $where_sqls[0];
	}

	/**
	* Change visibility status of one post or all posts of a topic
	*
	* @param $visibility	int		Element of {ITEM_APPROVED, ITEM_DELETED}
	* @param $post_id		mixed	Post ID or array of post IDs to act on,
	*								if it is empty, all posts of topic_id will be modified
	* @param $topic_id		int		Topic where $post_id is found
	* @param $forum_id		int		Forum where $topic_id is found
	* @param $user_id		int		User performing the action
	* @param $time			int		Timestamp when the action is performed
	* @param $reason		string	Reason why the visibilty was changed.
	* @param $is_starter	bool	Is this the first post of the topic changed?
	* @param $is_latest		bool	Is this the last post of the topic changed?
	* @param $limit_visibility	mixed	Limit updating per topic_id to a certain visibility
	* @param $limit_delete_time	mixed	Limit updating per topic_id to a certain deletion time
	* @return array		Changed post data, empty array if an error occured.
	*/
	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)
	{
		if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED)))
		{
			return array();
		}

		if ($post_id)
		{
			if (is_array($post_id))
			{
				$where_sql = $this->db->sql_in_set('post_id', array_map('intval', $post_id));
			}
			else
			{
				$where_sql = 'post_id = ' . (int) $post_id;
			}
			$where_sql .= ' AND topic_id = ' . (int) $topic_id;
		}
		else
		{
			$where_sql = 'topic_id = ' . (int) $topic_id;

			// Limit the posts to a certain visibility and deletion time
			// This allows us to only restore posts, that were approved
			// when the topic got soft deleted. So previous soft deleted
			// and unapproved posts are still soft deleted/unapproved
			if ($limit_visibility !== false)
			{
				$where_sql .= ' AND post_visibility = ' . (int) $limit_visibility;
			}

			if ($limit_delete_time !== false)
			{
				$where_sql .= ' AND post_delete_time = ' . (int) $limit_delete_time;
			}
		}

		$sql = 'SELECT poster_id, post_id, post_postcount, post_visibility
			FROM ' . $this->posts_table . '
			WHERE ' . $where_sql;
		$result = $this->db->sql_query($sql);

		$post_ids = $poster_postcounts = $postcounts = $postcount_visibility = array();
		while ($row = $this->db->sql_fetchrow($result))
		{
			$post_ids[] = (int) $row['post_id'];

			if ($row['post_visibility'] != $visibility)
			{
				if ($row['post_postcount'] && !isset($poster_postcounts[(int) $row['poster_id']]))
				{
					$poster_postcounts[(int) $row['poster_id']] = 1;
				}
				else if ($row['post_postcount'])
				{
					$poster_postcounts[(int) $row['poster_id']]++;
				}

				if (!isset($postcount_visibility[$row['post_visibility']]))
				{
					$postcount_visibility[$row['post_visibility']] = 1;
				}
				else
				{
					$postcount_visibility[$row['post_visibility']]++;
				}
			}
		}
		$this->db->sql_freeresult($result);

		if (empty($post_ids))
		{
			return array();
		}

		$data = array(
			'post_visibility'		=> (int) $visibility,
			'post_delete_user'		=> (int) $user_id,
			'post_delete_time'		=> ((int) $time) ?: time(),
			'post_delete_reason'	=> truncate_string($reason, 255, 255, false),
		);

		$sql = 'UPDATE ' . $this->posts_table . '
			SET ' . $this->db->sql_build_array('UPDATE', $data) . '
			WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
		$this->db->sql_query($sql);

		// Group the authors by post count, to reduce the number of queries
		foreach ($poster_postcounts as $poster_id => $num_posts)
		{
			$postcounts[$num_posts][] = $poster_id;
		}

		// Update users postcounts
		foreach ($postcounts as $num_posts => $poster_ids)
		{
			if ($visibility == ITEM_DELETED)
			{
				$sql = 'UPDATE ' . $this->users_table . '
					SET user_posts = 0
					WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
						AND user_posts < ' . $num_posts;
				$this->db->sql_query($sql);

				$sql = 'UPDATE ' . $this->users_table . '
					SET user_posts = user_posts - ' . $num_posts . '
					WHERE ' . $this->db->sql_in_set('user_id', $poster_ids) . '
						AND user_posts >= ' . $num_posts;
				$this->db->sql_query($sql);
			}
			else
			{
				$sql = 'UPDATE ' . $this->users_table . '
					SET user_posts = user_posts + ' . $num_posts . '
					WHERE ' . $this->db->sql_in_set('user_id', $poster_ids);
				$this->db->sql_query($sql);
			}
		}

		$update_topic_postcount = true;

		// Sync the first/last topic information if needed
		if (!$is_starter && $is_latest)
		{
			if (!function_exists('update_post_information'))
			{
				include($this->phpbb_root_path . 'includes/functions_posting.' . $this->php_ext);
			}

			// update_post_information can only update the last post info ...
			if ($topic_id)
			{
				update_post_information('topic', $topic_id, false);
			}
			if ($forum_id)
			{
				update_post_information('forum', $forum_id, false);
			}
		}
		else if ($is_starter && $topic_id)
		{
			if (!function_exists('sync'))
			{