From fd822ade20a1407af6a464ffec71c4da0d330a3c Mon Sep 17 00:00:00 2001
From: rxu <rxu@mail.ru>
Date: Fri, 26 May 2017 20:27:30 +0700
Subject: [PATCH 1/4] [ticket/15238] Add console command to fix forums/modules
 left/right IDs

PHPBB3-15238
---
 phpBB/config/console.yml                      |   9 ++
 phpBB/language/en/cli.php                     |   2 +
 .../command/fixup/fix_left_right_ids.php      | 105 ++++++++++++++++++
 3 files changed, 116 insertions(+)
 create mode 100644 phpBB/phpbb/console/command/fixup/fix_left_right_ids.php

diff --git a/phpBB/config/console.yml b/phpBB/config/console.yml
index 4118803663..55ffd358e4 100644
--- a/phpBB/config/console.yml
+++ b/phpBB/config/console.yml
@@ -151,3 +151,12 @@ services:
             - %passwords.algorithms%
         tags:
             - { name: console.command }
+
+    console.command.fixup.fix_left_right_ids:
+        class: phpbb\console\command\fixup\fix_left_right_ids
+        arguments:
+            - @user
+            - @dbal.conn
+            - @cache.driver
+        tags:
+            - { name: console.command }
diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php
index 27e72d5ccd..4e27be48cc 100644
--- a/phpBB/language/en/cli.php
+++ b/phpBB/language/en/cli.php
@@ -55,6 +55,7 @@ $lang = array_merge($lang, array(
 	'CLI_DESCRIPTION_DISABLE_EXTENSION'			=> 'Disables the specified extension.',
 	'CLI_DESCRIPTION_ENABLE_EXTENSION'			=> 'Enables the specified extension.',
 	'CLI_DESCRIPTION_FIND_MIGRATIONS'			=> 'Finds migrations that are not depended upon.',
+	'CLI_DESCRIPTION_FIX_LEFT_RIGHT_IDS'		=> 'Repairs the tree structure of the forums and modules.',
 	'CLI_DESCRIPTION_GET_CONFIG'				=> 'Gets a configuration option’s value',
 	'CLI_DESCRIPTION_INCREMENT_CONFIG'			=> 'Increments a configuration option’s integer value',
 	'CLI_DESCRIPTION_LIST_EXTENSIONS'			=> 'Lists all extensions in the database and on the filesystem.',
@@ -78,6 +79,7 @@ $lang = array_merge($lang, array(
 	'CLI_EXTENSIONS_DISABLED'			=> 'Disabled',
 	'CLI_EXTENSIONS_ENABLED'			=> 'Enabled',
 
+	'CLI_FIXUP_FIX_LEFT_RIGHT_IDS_SUCCESS'		=> 'Successfully repaired the tree structure of the forums and modules.',
 	'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS'	=> 'Successfully recalculated all email hashes.',
 	'CLI_FIXUP_UPDATE_HASH_BCRYPT_SUCCESS'		=> 'Successfully updated outdated password hashes to bcrypt.'
 ));
diff --git a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
new file mode 100644
index 0000000000..df0968a601
--- /dev/null
+++ b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
@@ -0,0 +1,105 @@
+<?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.
+*
+*/
+namespace phpbb\console\command\fixup;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class fix_left_right_ids extends \phpbb\console\command\command
+{
+	/** @var \phpbb\user */
+	protected $user;
+
+	/** @var \phpbb\db\driver\driver_interface */
+	protected $db;
+
+	/** @var \phpbb\cache\driver\driver_interface */
+	protected $cache;
+
+	public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache)
+	{
+		$this->user = $user;
+		$this->db = $db;
+		$this->cache = $cache;
+
+		parent::__construct($user);
+	}
+
+	protected function configure()
+	{
+		$this
+			->setName('fixup:fix-left-right-ids')
+			->setDescription($this->user->lang('CLI_DESCRIPTION_FIX_LEFT_RIGHT_IDS'))
+		;
+	}
+
+	/**
+	* The code is mainly borrowed from Support toolkit for phpBB Olympus
+	*/
+	protected function execute(InputInterface $input, OutputInterface $output)
+	{
+		$changes_made = false;
+
+		// Fix Left/Right IDs for the modules table
+		$result = $this->db->sql_query('SELECT DISTINCT(module_class) FROM ' . MODULES_TABLE);
+		while ($row = $this->db->sql_fetchrow($result))
+		{
+			$i = 1;
+			$where = array('module_class = \'' . $row['module_class'] .'\'');
+			$changes_made = (($this->fixem($i, 'module_id', MODULES_TABLE, 0, $where)) || $changes_made) ? true : false;
+		}
+		$this->db->sql_freeresult($result);
+
+		// Fix the Left/Right IDs for the forums table
+		$i = 1;
+		$changes_made = (($this->fixem($i, 'forum_id', FORUMS_TABLE)) || $changes_made) ? true : false;
+
+		$this->cache->purge();
+
+		$output->writeln('<info>' . $this->user->lang('CLI_FIXUP_FIX_LEFT_RIGHT_IDS_SUCCESS') . '</info>');
+	}
+
+	function fixem(&$i, $pkey, $table, $parent_id = 0, $where = array())
+	{
+		$changes_made = false;
+		$sql = 'SELECT * FROM ' . $table . '
+			WHERE parent_id = ' . (int) $parent_id .
+			((!empty($where)) ? ' AND ' . implode(' AND ', $where) : '') . '
+			ORDER BY left_id ASC';
+		$result = $this->db->sql_query($sql);
+		while ($row = $this->db->sql_fetchrow($result))
+		{
+			// Update the left_id for this module
+			if ($row['left_id'] != $i)
+			{
+				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('left_id' => $i)) . " WHERE $pkey = {$row[$pkey]}");
+				$changes_made = true;
+			}
+			$i++;
+
+			// Go through children and update their left/right IDs
+			$changes_made = (($this->fixem($i, $pkey, $table, $row[$pkey], $where)) || $changes_made) ? true : false;
+
+			// Update the right_id for the module
+			if ($row['right_id'] != $i)
+			{
+				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('right_id' => $i)) . " WHERE $pkey = {$row[$pkey]}");
+				$changes_made = true;
+			}
+			$i++;
+		}
+		$this->db->sql_freeresult($result);
+
+		return $changes_made;
+	}
+}

From c1fa252fc1fd9855d4a6dac92ece9a1690cda7bc Mon Sep 17 00:00:00 2001
From: rxu <rxu@mail.ru>
Date: Tue, 6 Jun 2017 00:50:22 +0700
Subject: [PATCH 2/4] [ticket/15238] Code cleanup, add docblocks

PHPBB3-15238
---
 .../command/fixup/fix_left_right_ids.php      | 50 +++++++++++++++----
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
index df0968a601..3781a411f1 100644
--- a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
+++ b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
@@ -26,6 +26,13 @@ class fix_left_right_ids extends \phpbb\console\command\command
 	/** @var \phpbb\cache\driver\driver_interface */
 	protected $cache;
 
+	/**
+	* Constructor
+	*
+	* @param \phpbb\user							$user	User instance
+	* @param \phpbb\db\driver\driver_interface		$db		Database connection
+	* @param \phpbb\cache\driver\driver_interface	$cache	Cache instance
+	*/
 	public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache)
 	{
 		$this->user = $user;
@@ -35,6 +42,9 @@ class fix_left_right_ids extends \phpbb\console\command\command
 		parent::__construct($user);
 	}
 
+	/**
+	* {@inheritdoc}
+	*/
 	protected function configure()
 	{
 		$this
@@ -44,32 +54,50 @@ class fix_left_right_ids extends \phpbb\console\command\command
 	}
 
 	/**
+	* Executes the command fixup:fix-left-right-ids.
+	*
+	* Repairs the tree structure of the forums and modules.
 	* The code is mainly borrowed from Support toolkit for phpBB Olympus
+	*
+	* @param InputInterface  $input  An InputInterface instance
+	* @param OutputInterface $output An OutputInterface instance
+	*
+	* @return void
 	*/
 	protected function execute(InputInterface $input, OutputInterface $output)
 	{
-		$changes_made = false;
-
 		// Fix Left/Right IDs for the modules table
 		$result = $this->db->sql_query('SELECT DISTINCT(module_class) FROM ' . MODULES_TABLE);
 		while ($row = $this->db->sql_fetchrow($result))
 		{
 			$i = 1;
-			$where = array('module_class = \'' . $row['module_class'] .'\'');
-			$changes_made = (($this->fixem($i, 'module_id', MODULES_TABLE, 0, $where)) || $changes_made) ? true : false;
+			$where = array("module_class = '" . $this->db->sql_escape($row['module_class']) . "'");
+			$this->fix_ids_tree($i, 'module_id', MODULES_TABLE, 0, $where);
 		}
 		$this->db->sql_freeresult($result);
 
 		// Fix the Left/Right IDs for the forums table
 		$i = 1;
-		$changes_made = (($this->fixem($i, 'forum_id', FORUMS_TABLE)) || $changes_made) ? true : false;
+		$this->fix_ids_tree($i, 'forum_id', FORUMS_TABLE);
 
 		$this->cache->purge();
 
 		$output->writeln('<info>' . $this->user->lang('CLI_FIXUP_FIX_LEFT_RIGHT_IDS_SUCCESS') . '</info>');
 	}
 
-	function fixem(&$i, $pkey, $table, $parent_id = 0, $where = array())
+	/**
+	 * Item's tree structure rebuild helper
+	 * The item is either forum or ACP/MCP/UCP module
+	 *
+	 * @param int		$i			Item id offset index
+	 * @param string	$field		The key field to fix, forum_id|module_id
+	 * @param string	$table		The table name to perform, FORUMS_TABLE|MODULES_TABLE
+	 * @param int		$parent_id	Parent item id
+	 * @param string	$where		Additional WHERE clause condition
+	 *
+	 * @return bool	True on rebuild success, false otherwise
+	 */
+	function fix_ids_tree(&$i, $field, $table, $parent_id = 0, $where = array())
 	{
 		$changes_made = false;
 		$sql = 'SELECT * FROM ' . $table . '
@@ -79,21 +107,21 @@ class fix_left_right_ids extends \phpbb\console\command\command
 		$result = $this->db->sql_query($sql);
 		while ($row = $this->db->sql_fetchrow($result))
 		{
-			// Update the left_id for this module
+			// Update the left_id for the item
 			if ($row['left_id'] != $i)
 			{
-				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('left_id' => $i)) . " WHERE $pkey = {$row[$pkey]}");
+				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('left_id' => $i)) . " WHERE $field = " . (int) $row[$field]);
 				$changes_made = true;
 			}
 			$i++;
 
 			// Go through children and update their left/right IDs
-			$changes_made = (($this->fixem($i, $pkey, $table, $row[$pkey], $where)) || $changes_made) ? true : false;
+			$changes_made = (($this->fix_ids_tree($i, $field, $table, $row[$field], $where)) || $changes_made) ? true : false;
 
-			// Update the right_id for the module
+			// Update the right_id for the item
 			if ($row['right_id'] != $i)
 			{
-				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('right_id' => $i)) . " WHERE $pkey = {$row[$pkey]}");
+				$this->db->sql_query('UPDATE ' . $table . ' SET ' . $this->db->sql_build_array('UPDATE', array('right_id' => $i)) . " WHERE $field = " . (int) $row[$field]);
 				$changes_made = true;
 			}
 			$i++;

From 840cb510e47e3ed27fa5c07e0f05cf8598b88879 Mon Sep 17 00:00:00 2001
From: rxu <rxu@mail.ru>
Date: Sun, 18 Jun 2017 23:15:05 +0700
Subject: [PATCH 3/4] [ticket/15238] More code cleanup

PHPBB3-15238
---
 phpBB/phpbb/console/command/fixup/fix_left_right_ids.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
index 3781a411f1..bcaf0043e1 100644
--- a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
+++ b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
@@ -10,6 +10,7 @@
 * the docs/CREDITS.txt file.
 *
 */
+
 namespace phpbb\console\command\fixup;
 
 use Symfony\Component\Console\Input\InputInterface;
@@ -93,7 +94,7 @@ class fix_left_right_ids extends \phpbb\console\command\command
 	 * @param string	$field		The key field to fix, forum_id|module_id
 	 * @param string	$table		The table name to perform, FORUMS_TABLE|MODULES_TABLE
 	 * @param int		$parent_id	Parent item id
-	 * @param string	$where		Additional WHERE clause condition
+	 * @param array		$where		Additional WHERE clause condition
 	 *
 	 * @return bool	True on rebuild success, false otherwise
 	 */

From 9402339af91dd81465ff5fdde0ccf4dab349d397 Mon Sep 17 00:00:00 2001
From: rxu <rxu@mail.ru>
Date: Tue, 20 Jun 2017 21:06:01 +0700
Subject: [PATCH 4/4] [ticket/15238] Add missing protected keyword

PHPBB3-15238
---
 phpBB/phpbb/console/command/fixup/fix_left_right_ids.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
index bcaf0043e1..f55e1761bc 100644
--- a/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
+++ b/phpBB/phpbb/console/command/fixup/fix_left_right_ids.php
@@ -98,7 +98,7 @@ class fix_left_right_ids extends \phpbb\console\command\command
 	 *
 	 * @return bool	True on rebuild success, false otherwise
 	 */
-	function fix_ids_tree(&$i, $field, $table, $parent_id = 0, $where = array())
+	protected function fix_ids_tree(&$i, $field, $table, $parent_id = 0, $where = array())
 	{
 		$changes_made = false;
 		$sql = 'SELECT * FROM ' . $table . '