aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb')
-rw-r--r--phpBB/phpbb/content_visibility.php112
-rw-r--r--phpBB/phpbb/db/migration/helper.php32
-rw-r--r--phpBB/phpbb/db/migration/tool/config.php5
-rw-r--r--phpBB/phpbb/db/migration/tool/config_text.php5
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php188
-rw-r--r--phpBB/phpbb/db/migration/tool/permission.php5
-rw-r--r--phpBB/phpbb/db/migrator.php169
-rw-r--r--phpBB/phpbb/db/migrator_output_handler_interface.php10
-rw-r--r--phpBB/phpbb/notification/method/messenger_base.php2
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php4
-rw-r--r--phpBB/phpbb/search/fulltext_native.php2
-rw-r--r--phpBB/phpbb/session.php20
12 files changed, 411 insertions, 143 deletions
diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php
index 147b8ebbff..bf7dc2c703 100644
--- a/phpBB/phpbb/content_visibility.php
+++ b/phpBB/phpbb/content_visibility.php
@@ -428,7 +428,35 @@ class content_visibility
'post_delete_time' => ((int) $time) ?: time(),
'post_delete_reason' => truncate_string($reason, 255, 255, false),
);
-
+ /**
+ * Perform actions right before the query to change post visibility
+ *
+ * @event core.set_post_visibility_before_sql
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool is_starter Are we changing the topic's starter?
+ * @var bool is_latest Are we changing the topic's latest post?
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'post_id',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'is_starter',
+ 'is_latest',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_before_sql', compact($vars)));
$sql = 'UPDATE ' . $this->posts_table . '
SET ' . $this->db->sql_build_array('UPDATE', $data) . '
WHERE ' . $this->db->sql_in_set('post_id', $post_ids);
@@ -585,7 +613,35 @@ class content_visibility
WHERE topic_id = ' . (int) $topic_id;
$this->db->sql_query($sql);
}
-
+ /**
+ * Perform actions after all steps to changing post visibility
+ *
+ * @event core.set_post_visibility_after
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are modified.
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool is_starter Are we changing the topic's starter?
+ * @var bool is_latest Are we changing the topic's latest post?
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'post_id',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'is_starter',
+ 'is_latest',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_after', compact($vars)));
return $data;
}
@@ -645,7 +701,31 @@ class content_visibility
'topic_delete_time' => ((int) $time) ?: time(),
'topic_delete_reason' => truncate_string($reason, 255, 255, false),
);
-
+ /**
+ * Perform actions right before the query to change topic visibility
+ *
+ * @event core.set_topic_visibility_before_sql
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'force_update_all',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars)));
$sql = 'UPDATE ' . $this->topics_table . '
SET ' . $this->db->sql_build_array('UPDATE', $data) . '
WHERE topic_id = ' . (int) $topic_id;
@@ -670,7 +750,31 @@ class content_visibility
{
$this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true);
}
-
+ /**
+ * Perform actions after all steps to changing topic visibility
+ *
+ * @event core.set_topic_visibility_after
+ * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE}
+ * @var int topic_id Topic of the post IDs to be modified.
+ * @var int forum_id Forum ID that the topic_id resides in.
+ * @var int user_id User ID doing this action.
+ * @var int timestamp Timestamp of this action.
+ * @var string reason Reason specified by the user for this change.
+ * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
+ * @var array data The data array for this action.
+ * @since 3.1.10-RC1
+ */
+ $vars = array(
+ 'visibility',
+ 'topic_id',
+ 'forum_id',
+ 'user_id',
+ 'timestamp',
+ 'reason',
+ 'force_update_all',
+ 'data',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars)));
return $data;
}
diff --git a/phpBB/phpbb/db/migration/helper.php b/phpBB/phpbb/db/migration/helper.php
index e40deeb37b..bce2efff51 100644
--- a/phpBB/phpbb/db/migration/helper.php
+++ b/phpBB/phpbb/db/migration/helper.php
@@ -81,4 +81,36 @@ class helper
return $steps;
}
+
+ /**
+ * Reverse the update steps from an array of data changes
+ *
+ * 'If' statements and custom methods will be skipped, for all
+ * other calls the reverse method of the tool class will be called
+ *
+ * @param array $steps Update changes from migration
+ *
+ * @return array
+ */
+ public function reverse_update_data($steps)
+ {
+ $reversed_array = array();
+
+ foreach ($steps as $step)
+ {
+ $parts = explode('.', $step[0]);
+ $parameters = $step[1];
+
+ $class = $parts[0];
+ $method = isset($parts[1]) ? $parts[1] : false;
+
+ if ($class !== 'if' && $class !== 'custom')
+ {
+ array_unshift($parameters, $method);
+ $reversed_array[] = array($class . '.reverse', $parameters);
+ }
+ }
+
+ return array_reverse($reversed_array);
+ }
}
diff --git a/phpBB/phpbb/db/migration/tool/config.php b/phpBB/phpbb/db/migration/tool/config.php
index f93e7118c4..33aa8ff026 100644
--- a/phpBB/phpbb/db/migration/tool/config.php
+++ b/phpBB/phpbb/db/migration/tool/config.php
@@ -150,6 +150,11 @@ class config implements \phpbb\db\migration\tool\tool_interface
$arguments[0],
);
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migration/tool/config_text.php b/phpBB/phpbb/db/migration/tool/config_text.php
index bf8ac55023..54b45f6f6d 100644
--- a/phpBB/phpbb/db/migration/tool/config_text.php
+++ b/phpBB/phpbb/db/migration/tool/config_text.php
@@ -115,6 +115,11 @@ class config_text implements \phpbb\db\migration\tool\tool_interface
$arguments[] = '';
}
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 035625b095..6d5378e35f 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -36,6 +36,9 @@ class module implements \phpbb\db\migration\tool\tool_interface
/** @var string */
protected $modules_table;
+ /** @var array */
+ protected $module_categories = array();
+
/**
* Constructor
*
@@ -87,30 +90,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
$parent_sql = '';
if ($parent !== false)
{
- // Allows '' to be sent as 0
- $parent = $parent ?: 0;
-
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- if (!$module_id)
- {
- return false;
- }
-
- $parent_sql = 'AND parent_id = ' . (int) $module_id;
- }
- else
- {
- $parent_sql = 'AND parent_id = ' . (int) $parent;
- }
+ $parent = $this->get_parent_module_id($parent, $module);
+ $parent_sql = 'AND parent_id = ' . (int) $parent;
}
$sql = 'SELECT module_id
@@ -171,15 +152,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
*/
public function add($class, $parent = 0, $data = array())
{
- // Allows '' to be sent as 0
- $parent = $parent ?: 0;
-
// allow sending the name as a string in $data to create a category
if (!is_array($data))
{
$data = array('module_langname' => $data);
}
+ $parent = $data['parent_id'] = $this->get_parent_module_id($parent, $data);
+
if (!isset($data['module_langname']))
{
// The "automatic" way
@@ -210,31 +190,14 @@ class module implements \phpbb\db\migration\tool\tool_interface
}
// The "manual" way
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- if (!$module_id)
- {
- throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent);
- }
-
- $parent = $data['parent_id'] = $module_id;
- }
- else if (!$this->exists($class, false, $parent))
+ if (!$this->exists($class, false, $parent))
{
throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent);
}
if ($this->exists($class, $parent, $data['module_langname']))
{
- return;
+ throw new \phpbb\db\migration\exception('MODULE_EXISTS', $module_id);
}
if (!class_exists('acp_modules'))
@@ -373,26 +336,8 @@ class module implements \phpbb\db\migration\tool\tool_interface
$parent_sql = '';
if ($parent !== false)
{
- // Allows '' to be sent as 0
- $parent = ($parent) ?: 0;
-
- if (!is_numeric($parent))
- {
- $sql = 'SELECT module_id
- FROM ' . $this->modules_table . "
- WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
- AND module_class = '" . $this->db->sql_escape($class) . "'";
- $result = $this->db->sql_query($sql);
- $module_id = $this->db->sql_fetchfield('module_id');
- $this->db->sql_freeresult($result);
-
- // we know it exists from the module_exists check
- $parent_sql = 'AND parent_id = ' . (int) $module_id;
- }
- else
- {
- $parent_sql = 'AND parent_id = ' . (int) $parent;
- }
+ $parent = $this->get_parent_module_id($parent, $module);
+ $parent_sql = 'AND parent_id = ' . (int) $parent;
}
$module_ids = array();
@@ -454,6 +399,11 @@ class module implements \phpbb\db\migration\tool\tool_interface
case 'remove':
$call = 'add';
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
@@ -487,4 +437,110 @@ class module implements \phpbb\db\migration\tool\tool_interface
return array_pop($module);
}
+
+ /**
+ * Get the list of installed module categories
+ * key - module_id
+ * value - module_langname
+ *
+ * @return null
+ */
+ protected function get_categories_list()
+ {
+ // Select the top level categories
+ // and 2nd level [sub]categories which exist for ACP only
+ $sql = 'SELECT m2.module_id, m2.module_langname
+ FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
+ WHERE m1.parent_id = 0
+ AND (m1.module_id = m2.module_id
+ OR m2.module_class = 'acp' AND m2.parent_id = m1.module_id)
+ ORDER BY m1.module_id, m2.module_id ASC";
+
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $this->module_categories[(int) $row['module_id']] = $row['module_langname'];
+ }
+ $this->db->sql_freeresult($result);
+ }
+
+ /**
+ * Get parent module id
+ *
+ * @param string|int $parent_id The parent module_id|module_langname
+ * @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding
+ * @return int The parent module_id
+ * @throws \phpbb\db\migration\exception
+ */
+ public function get_parent_module_id($parent_id, $data = '')
+ {
+ // Allow '' to be sent as 0
+ $parent_id = $parent_id ?: 0;
+
+ // If automatic adding is in action, convert array back to string to simplify things
+ if (is_array($data) && sizeof($data) == 1)
+ {
+ $data = $data['module_langname'];
+ }
+
+ if (!is_numeric($parent_id))
+ {
+ // Refresh the $module_categories array
+ $this->get_categories_list();
+
+ // Search for the parent module_langname
+ $ids = array_keys($this->module_categories, $parent_id);
+
+ switch (sizeof($ids))
+ {
+ // No parent with the given module_langname exist
+ case 0:
+ throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id);
+ break;
+
+ // Return the module id
+ case 1:
+ $parent_id = (int) $ids[0];
+ break;
+
+ // Several modules with the given module_langname were found
+ // Try to determine the parent_id by the neighbour module parent
+ default:
+ if (is_array($data) && (isset($data['before']) || isset($data['after'])))
+ {
+ $neighbour_module_langname = isset($data['before']) ? $data['before'] : $data['after'];
+ $sql = 'SELECT parent_id
+ FROM ' . $this->modules_table . "
+ WHERE module_langname = '" . $this->db->sql_escape($neighbour_module_langname) . "'
+ AND " . $this->db->sql_in_set('parent_id', $ids);
+ $result = $this->db->sql_query($sql);
+ $parent_id = (int) $this->db->sql_fetchfield('parent_id');
+ if (!$parent_id)
+ {
+ throw new \phpbb\db\migration\exception('PARENT_MODULE_FIND_ERROR', $data['parent_id']);
+ }
+ }
+ else if (!empty($data) && !is_array($data))
+ {
+ // The module_langname is set, checking for the module existance
+ // As more than 1 parents were found already, there's no way for null parent_id here
+ $sql = 'SELECT m2.module_id as module_parent_id
+ FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2
+ WHERE " . ((is_numeric($data)) ? 'm1.module_id = ' . (int) $data : "m1.module_langname = '" . $this->db->sql_escape($data)) . "'
+ AND m2.module_id = m1.parent_id
+ AND " . $this->db->sql_in_set('m2.module_id', $ids);
+ $result = $this->db->sql_query($sql);
+ $parent_id = (int) $this->db->sql_fetchfield('module_parent_id');
+ }
+ else
+ {
+ //Unable to get the parent module id, throwing an exception
+ throw new \phpbb\db\migration\exception('MODULE_EXIST_MULTIPLE', $parent_id);
+ }
+ break;
+ }
+ }
+
+ return $parent_id;
+ }
}
diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php
index ceff6d7d5a..9688420025 100644
--- a/phpBB/phpbb/db/migration/tool/permission.php
+++ b/phpBB/phpbb/db/migration/tool/permission.php
@@ -637,6 +637,11 @@ class permission implements \phpbb\db\migration\tool\tool_interface
$arguments[0],
);
break;
+
+ case 'reverse':
+ // Reversing a reverse is just the call itself
+ $call = array_shift($arguments);
+ break;
}
if ($call)
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 7fc3e787e2..4c4c0a8672 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -80,14 +80,14 @@ class migrator
*
* @var array
*/
- public $last_run_migration = false;
+ protected $last_run_migration = false;
/**
* The output handler. A null handler is configured by default.
*
* @var migrator_output_handler_interface
*/
- public $output_handler;
+ protected $output_handler;
/**
* Constructor of the database migrator
@@ -152,6 +152,7 @@ class migrator
$this->migration_state[$migration['migration_name']] = $migration;
$this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']);
+ $this->migration_state[$migration['migration_name']]['migration_data_state'] = !empty($migration['migration_data_state']) ? unserialize($migration['migration_data_state']) : '';
}
}
@@ -161,6 +162,19 @@ class migrator
}
/**
+ * Get an array with information about the last migration run.
+ *
+ * The array contains 'name', 'class' and 'state'. 'effectively_installed' is set
+ * and set to true if the last migration was effectively_installed.
+ *
+ * @return array
+ */
+ public function get_last_run_migration()
+ {
+ return $this->last_run_migration;
+ }
+
+ /**
* Sets the list of available migration class names to the given array.
*
* @param array $class_names An array of migration class names
@@ -297,38 +311,70 @@ class migrator
if (!$state['migration_schema_done'])
{
- $this->output_handler->write(array('MIGRATION_SCHEMA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_SCHEMA_RUNNING', $name), $verbosity);
$this->last_run_migration['task'] = 'process_schema_step';
+
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
$elapsed_time = microtime(true);
+
$steps = $this->helper->get_schema_steps($migration->update_schema());
$result = $this->process_data_step($steps, $state['migration_data_state']);
+
$elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_schema_done'] = ($result === true);
- $this->output_handler->write(array('MIGRATION_SCHEMA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ if ($state['migration_schema_done'])
+ {
+ $this->output_handler->write(array('MIGRATION_SCHEMA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ }
+ else
+ {
+ $this->output_handler->write(array('MIGRATION_SCHEMA_IN_PROGRESS', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_VERY_VERBOSE);
+ }
}
else if (!$state['migration_data_done'])
{
try
{
- $this->output_handler->write(array('MIGRATION_DATA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
+ $verbosity = empty($state['migration_data_state']) ?
+ migrator_output_handler_interface::VERBOSITY_VERBOSE : migrator_output_handler_interface::VERBOSITY_DEBUG;
+ $this->output_handler->write(array('MIGRATION_DATA_RUNNING', $name), $verbosity);
$this->last_run_migration['task'] = 'process_data_step';
+ $total_time = (is_array($state['migration_data_state']) && isset($state['migration_data_state']['_total_time'])) ?
+ $state['migration_data_state']['_total_time'] : 0.0;
$elapsed_time = microtime(true);
+
$result = $this->process_data_step($migration->update_data(), $state['migration_data_state']);
+
$elapsed_time = microtime(true) - $elapsed_time;
+ $total_time += $elapsed_time;
+
+ if (is_array($result))
+ {
+ $result['_total_time'] = $total_time;
+ }
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true);
$state['migration_end_time'] = ($result === true) ? time() : 0;
- if ($state['migration_schema_done'])
+ if ($state['migration_data_done'])
{
- $this->output_handler->write(array('MIGRATION_DATA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
+ $this->output_handler->write(array('MIGRATION_DATA_DONE', $name, $total_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
}
else
{
@@ -337,10 +383,12 @@ class migrator
}
catch (\phpbb\db\migration\exception $e)
{
- // Revert the schema changes
+ // Reset data state and revert the schema changes
+ $state['migration_data_state'] = '';
+ $this->set_migration_state($name, $state);
+
$this->revert_do($name);
- // Rethrow exception
throw $e;
}
}
@@ -416,19 +464,11 @@ class migrator
if ($state['migration_data_done'])
{
- if ($state['migration_data_state'] !== 'revert_data')
- {
- $result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true);
-
- $state['migration_data_state'] = ($result === true) ? 'revert_data' : $result;
- }
- else
- {
- $result = $this->process_data_step($migration->revert_data(), '', false);
+ $steps = array_merge($this->helper->reverse_update_data($migration->update_data()), $migration->revert_data());
+ $result = $this->process_data_step($steps, $state['migration_data_state']);
- $state['migration_data_state'] = ($result === true) ? '' : $result;
- $state['migration_data_done'] = ($result === true) ? false : true;
- }
+ $state['migration_data_state'] = ($result === true) ? '' : $result;
+ $state['migration_data_done'] = ($result === true) ? false : true;
$this->set_migration_state($name, $state);
}
@@ -446,8 +486,13 @@ class migrator
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ $this->last_run_migration = false;
unset($this->migration_state[$name]);
}
+ else
+ {
+ $this->set_migration_state($name, $state);
+ }
}
return true;
@@ -464,7 +509,12 @@ class migrator
*/
protected function process_data_step($steps, $state, $revert = false)
{
- $state = ($state) ? unserialize($state) : false;
+ if (sizeof($steps) === 0)
+ {
+ return true;
+ }
+
+ $state = is_array($state) ? $state : false;
// reverse order of steps if reverting
if ($revert === true)
@@ -472,54 +522,45 @@ class migrator
$steps = array_reverse($steps);
}
- foreach ($steps as $step_identifier => $step)
+ $step = $last_result = 0;
+ if ($state)
{
- $last_result = 0;
- if ($state)
- {
- // Continue until we reach the step that matches the last step called
- if ($state['step'] != $step_identifier)
- {
- continue;
- }
-
- // We send the result from last time to the callable function
- $last_result = $state['result'];
+ $step = $state['step'];
- // Set state to false since we reached the point we were at
- $state = false;
- }
+ // We send the result from last time to the callable function
+ $last_result = $state['result'];
+ }
- try
+ try
+ {
+ // Result will be null or true if everything completed correctly
+ // Stop after each update step, to let the updater control the script runtime
+ $result = $this->run_step($steps[$step], $last_result, $revert);
+ if (($result !== null && $result !== true) || $step + 1 < sizeof($steps))
{
- // Result will be null or true if everything completed correctly
- $result = $this->run_step($step, $last_result, $revert);
- if ($result !== null && $result !== true)
- {
- return serialize(array(
- 'result' => $result,
- 'step' => $step_identifier,
- ));
- }
+ return array(
+ 'result' => $result,
+ // Move on if the last call finished
+ 'step' => ($result !== null && $result !== true) ? $step : $step + 1,
+ );
}
- catch (\phpbb\db\migration\exception $e)
+ }
+ catch (\phpbb\db\migration\exception $e)
+ {
+ // We should try rolling back here
+ foreach ($steps as $reverse_step_identifier => $reverse_step)
{
- // We should try rolling back here
- foreach ($steps as $reverse_step_identifier => $reverse_step)
+ // If we've reached the current step we can break because we reversed everything that was run
+ if ($reverse_step_identifier == $step)
{
- // If we've reached the current step we can break because we reversed everything that was run
- if ($reverse_step_identifier == $step_identifier)
- {
- break;
- }
-
- // Reverse the step that was run
- $result = $this->run_step($reverse_step, false, !$revert);
+ break;
}
- // rethrow the exception
- throw $e;
+ // Reverse the step that was run
+ $result = $this->run_step($reverse_step, false, !$revert);
}
+
+ throw $e;
}
return true;
@@ -587,6 +628,13 @@ class migrator
throw new \phpbb\db\migration\exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step);
}
+ if ($reverse)
+ {
+ // We might get unexpected results when trying
+ // to revert this, so just avoid it
+ return false;
+ }
+
$condition = $parameters[0];
if (!$condition)
@@ -664,6 +712,7 @@ class migrator
{
$migration_row = $state;
$migration_row['migration_depends_on'] = serialize($state['migration_depends_on']);
+ $migration_row['migration_data_state'] = !empty($state['migration_data_state']) ? serialize($state['migration_data_state']) : '';
if (isset($this->migration_state[$name]))
{
diff --git a/phpBB/phpbb/db/migrator_output_handler_interface.php b/phpBB/phpbb/db/migrator_output_handler_interface.php
index a923af99f6..9947b51dcc 100644
--- a/phpBB/phpbb/db/migrator_output_handler_interface.php
+++ b/phpBB/phpbb/db/migrator_output_handler_interface.php
@@ -15,11 +15,11 @@ namespace phpbb\db;
interface migrator_output_handler_interface
{
- const VERBOSITY_QUIET = 0;
- const VERBOSITY_NORMAL = 1;
- const VERBOSITY_VERBOSE = 2;
- const VERBOSITY_VERY_VERBOSE = 3;
- const VERBOSITY_DEBUG = 4;
+ const VERBOSITY_QUIET = 16;
+ const VERBOSITY_NORMAL = 32;
+ const VERBOSITY_VERBOSE = 64;
+ const VERBOSITY_VERY_VERBOSE = 128;
+ const VERBOSITY_DEBUG = 256;
/**
* Write output using the configured closure.
diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php
index 3c6d617c66..0bfbfd6b02 100644
--- a/phpBB/phpbb/notification/method/messenger_base.php
+++ b/phpBB/phpbb/notification/method/messenger_base.php
@@ -81,7 +81,7 @@ abstract class messenger_base extends \phpbb\notification\method\base
$messenger->assign_vars(array_merge(array(
'USERNAME' => $user['username'],
- 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&amp;mode=notification_options',
+ 'U_NOTIFICATION_SETTINGS' => generate_board_url() . '/ucp.' . $this->php_ext . '?i=ucp_notifications&mode=notification_options',
), $notification->get_email_template_variables()));
$messenger->send($notify_method);
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index 3ddbd85b36..9faf5ca08b 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -177,8 +177,10 @@ class fulltext_mysql extends \phpbb\search\base
$engine === 'MyISAM' ||
// FULLTEXT is supported on InnoDB since MySQL 5.6.4 according to
// http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html
+ // We also require https://bugs.mysql.com/bug.php?id=67004 to be
+ // fixed for proper overall operation. Hence we require 5.6.8.
$engine === 'InnoDB' &&
- phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
+ phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>=');
if (!$fulltext_supported)
{
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index e2c02ffdab..63b0b24edf 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -1262,7 +1262,7 @@ class fulltext_native extends \phpbb\search\base
if (!$total_results && $is_mysql)
{
// Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
- $sql_calc = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql);
+ $sql_calc = str_replace('SELECT ' . $select, 'SELECT SQL_CALC_FOUND_ROWS ' . $select, $sql);
$result = $this->db->sql_query($sql_calc);
$this->db->sql_freeresult($result);
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index 83e87b7704..eb5543b50b 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -219,7 +219,7 @@ class session
function session_begin($update_session_page = true)
{
global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path;
- global $request, $phpbb_container;
+ global $request, $phpbb_container, $phpbb_dispatcher;
// Give us some basic information
$this->time_now = time();
@@ -281,11 +281,21 @@ class session
// Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
// it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
- $this->ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));
- $this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip));
+ $ip = htmlspecialchars_decode($request->server('REMOTE_ADDR'));
+ $ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $ip));
+
+ /**
+ * Event to alter user IP address
+ *
+ * @event core.session_ip_after
+ * @var string ip REMOTE_ADDR
+ * @since 3.1.10-RC1
+ */
+ $vars = array('ip');
+ extract($phpbb_dispatcher->trigger_event('core.session_ip_after', compact($vars)));
// split the list of IPs
- $ips = explode(' ', trim($this->ip));
+ $ips = explode(' ', trim($ip));
// Default IP if REMOTE_ADDR is invalid
$this->ip = '127.0.0.1';
@@ -1585,7 +1595,7 @@ class session
$this->data = array_merge($this->data, $sql_ary);
- if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts'])
+ if ($this->data['user_id'] != ANONYMOUS && isset($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts'])
{
$this->leave_newly_registered();
}