Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
n/a
0 / 0
50.00% covered (danger)
50.00%
1 / 2
CRAP
98.91% covered (success)
98.91%
91 / 92
phpbb_update_rows_avoiding_duplicates
0.00% covered (danger)
0.00%
0 / 1
9
97.56% covered (success)
97.56%
40 / 41
phpbb_update_rows_avoiding_duplicates_notify_status
100.00% covered (success)
100.00%
1 / 1
12
100.00% covered (success)
100.00%
51 / 51
<?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.
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
    exit;
}
/**
* Updates rows in given table from a set of values to a new value.
* If this results in rows violating uniqueness constraints, the duplicate
* rows are eliminated.
*
* The only supported table is bookmarks.
*
* @param \phpbb\db\driver\driver_interface $db Database object
* @param string $table Table on which to perform the update
* @param string $column Column whose values to change
* @param array $from_values An array of values that should be changed
* @param int $to_value The new value
* @return null
*/
function phpbb_update_rows_avoiding_duplicates(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value)
{
    $sql = "SELECT $column, user_id
        FROM $table
        WHERE " . $db->sql_in_set($column, $from_values);
    $result = $db->sql_query($sql);
    $old_user_ids = array();
    while ($row = $db->sql_fetchrow($result))
    {
        $old_user_ids[$row[$column]][] = (int) $row['user_id'];
    }
    $db->sql_freeresult($result);
    $sql = "SELECT $column, user_id
        FROM $table
        WHERE $column = " . (int) $to_value;
    $result = $db->sql_query($sql);
    $new_user_ids = array();
    while ($row = $db->sql_fetchrow($result))
    {
        $new_user_ids[$row[$column]][] = (int) $row['user_id'];
    }
    $db->sql_freeresult($result);
    $queries = array();
    foreach ($from_values as $from_value)
    {
        if (!isset($old_user_ids[$from_value]))
        {
            continue;
        }
        if (empty($new_user_ids))
        {
            $sql = "UPDATE $table
                SET $column = " . (int) $to_value . "
                WHERE $column = '" . $db->sql_escape($from_value) . "'";
            $queries[] = $sql;
        }
        else
        {
            $different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]);
            if (!empty($different_user_ids))
            {
                $sql = "UPDATE $table
                    SET $column = " . (int) $to_value . "
                    WHERE $column = '" . $db->sql_escape($from_value) . "'
                    AND " . $db->sql_in_set('user_id', $different_user_ids);
                $queries[] = $sql;
            }
        }
    }
    if (!empty($queries))
    {
        $db->sql_transaction('begin');
        foreach ($queries as $sql)
        {
            $db->sql_query($sql);
        }
        $sql = "DELETE FROM $table
            WHERE " . $db->sql_in_set($column, $from_values);
        $db->sql_query($sql);
        $db->sql_transaction('commit');
    }
}
/**
* Updates rows in given table from a set of values to a new value.
* If this results in rows violating uniqueness constraints, the duplicate
* rows are merged respecting notify_status (0 takes precedence over 1).
*
* The only supported table is topics_watch.
*
* @param \phpbb\db\driver\driver_interface $db Database object
* @param string $table Table on which to perform the update
* @param string $column Column whose values to change
* @param array $from_values An array of values that should be changed
* @param int $to_value The new value
* @return null
*/
function phpbb_update_rows_avoiding_duplicates_notify_status(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value)
{
    $sql = "SELECT $column, user_id, notify_status
        FROM $table
        WHERE " . $db->sql_in_set($column, $from_values);
    $result = $db->sql_query($sql);
    $old_user_ids = array();
    while ($row = $db->sql_fetchrow($result))
    {
        $old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id'];
    }
    $db->sql_freeresult($result);
    $sql = "SELECT $column, user_id
        FROM $table
        WHERE $column = " . (int) $to_value;
    $result = $db->sql_query($sql);
    $new_user_ids = array();
    while ($row = $db->sql_fetchrow($result))
    {
        $new_user_ids[$row[$column]][] = (int) $row['user_id'];
    }
    $db->sql_freeresult($result);
    $queries = array();
    $extra_updates = array(
        0 => 'notify_status = 0',
        1 => '',
    );
    foreach ($from_values as $from_value)
    {
        foreach ($extra_updates as $notify_status => $extra_update)
        {
            if (!isset($old_user_ids[$notify_status][$from_value]))
            {
                continue;
            }
            if (empty($new_user_ids))
            {
                $sql = "UPDATE $table
                    SET $column = " . (int) $to_value . "
                    WHERE $column = '" . $db->sql_escape($from_value) . "'";
                $queries[] = $sql;
            }
            else
            {
                $different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]);
                if (!empty($different_user_ids))
                {
                    $sql = "UPDATE $table
                        SET $column = " . (int) $to_value . "
                        WHERE $column = '" . $db->sql_escape($from_value) . "'
                        AND " . $db->sql_in_set('user_id', $different_user_ids);
                    $queries[] = $sql;
                }
                if ($extra_update)
                {
                    $same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids);
                    if (!empty($same_user_ids))
                    {
                        $sql = "UPDATE $table
                            SET $extra_update
                            WHERE $column = '" . (int) $to_value . "'
                            AND " . $db->sql_in_set('user_id', $same_user_ids);
                        $queries[] = $sql;
                    }
                }
            }
        }
    }
    if (!empty($queries))
    {
        $db->sql_transaction('begin');
        foreach ($queries as $sql)
        {
            $db->sql_query($sql);
        }
        $sql = "DELETE FROM $table
            WHERE " . $db->sql_in_set($column, $from_values);
        $db->sql_query($sql);
        $db->sql_transaction('commit');
    }
}