Compare commits

...

15 commits

Author SHA1 Message Date
rxu
8692e53916
Merge 3f4be7e3af into 6d6f4fdeba 2025-06-17 19:52:19 +07:00
Marc Alexander
6d6f4fdeba Merge branch '3.3.x' 2025-06-17 12:04:46 +00:00
Marc Alexander
35221f8ba5
Merge pull request #6826 from danieltj27/ticket/17522
[ticket/17522] Add event to member list to modify template vars
2025-06-17 14:04:28 +02:00
Marc Alexander
03031e846d Merge branch '3.3.x' 2025-06-17 09:39:08 +00:00
Marc Alexander
9219c03b36
Merge pull request #6831 from rxu/ticket/17527
[ticket/17527] Add Twig extensions existence check while registering
2025-06-17 11:30:52 +02:00
Daniel James
72c3745868 [ticket/17522] Change event name and update var type
PHPBB-17522
2025-06-17 07:18:41 +01:00
rxu
579b4a8287
[ticket/17527] Add Twig extensions existence check while registering
PHPBB-17527
2025-06-16 22:25:59 +07:00
rxu
3f4be7e3af
[ticket/17524] Try not to hit MSSQL index key length limitations
900 bytes for a clustered index. 1,700 bytes for a nonclustered index.
For SQL Server 2014 (12.x) and earlier, all versions supported 900 bytes
for all index types.

PHPBB-17524
2025-06-12 09:12:08 +07:00
rxu
c7e94d4632
[ticket/17524] Add test assertions
PHPBB-17524
2025-06-11 21:04:56 +07:00
rxu
51c997aa22
[ticket/17524] Add index migrator tests
PHPBB-17524
2025-06-11 14:48:12 +07:00
rxu
af93b1aee9
[ticket/17524] Add index data getter to db tools
PHPBB-17524
2025-06-10 11:31:48 +07:00
rxu
ba0282bf38
[ticket/17524] Add possibility to use index key length in migrations
PHPBB-17524
2025-06-10 10:16:02 +07:00
Daniel James
b6c42b3768 [ticket/17522] Switch array syntax to short code
PHPBB-17522
2025-06-06 11:50:49 +01:00
Daniel James
da2733a7d8 [ticket/17522] Change since from beta to release candidate
PHPBB-17522
2025-06-06 11:03:10 +01:00
Daniel James
b8204d24f9 [ticket/17522] Add event to member list to modify template vars
PHPBB-17522
2025-06-05 22:18:51 +01:00
5 changed files with 158 additions and 21 deletions

View file

@ -1681,6 +1681,18 @@ switch ($mode)
$memberrow = array_merge($memberrow, $cp_row['row']);
}
/**
* Modify the memberrow data before template variables are assigned.
*
* @event core.memberlist_modify_memberrow
* @var int user_id The current user ID.
* @var array row Array of raw user data.
* @var array memberrow Array of member template variables.
* @since 3.3.16-RC1
*/
$vars = ['user_id', 'row', 'memberrow'];
extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_memberrow', compact($vars)));
$template->assign_block_vars('memberrow', $memberrow);
if (isset($cp_row['blockrow']) && count($cp_row['blockrow']))

View file

@ -384,6 +384,42 @@ class doctrine implements tools_interface
}
}
/**
* Returns an array of the table index names and relevant data in format
* [
* [$index_name] = [
* 'columns' => (array) $index_columns,
* 'flags' => (array) $index_flags,
* 'options' => (array) $index_options,
* 'is_primary'=> (bool) $isPrimary,
* 'is_unique' => (bool) $isUnique,
* 'is_simple' => (bool) $isSimple,
* ]
*
* @param string $table_name
*
* @return array
*/
public function sql_get_table_index_data(string $table_name): array
{
$schema = $this->get_schema();
$table = $schema->getTable($table_name);
$indexes = [];
foreach ($table->getIndexes() as $index)
{
$indexes[$index->getName()] = [
'columns' => array_map('strtolower', $index->getUnquotedColumns()),
'flags' => $index->getFlags(),
'options' => $index->getOptions(),
'is_primary'=> $index->isPrimary(),
'is_unique' => $index->isUnique(),
'is_simple' => $index->isSimpleIndex(),
];
}
return $indexes;
}
/**
* Returns an array of indices for either unique and primary keys, or simple indices.
*
@ -635,25 +671,16 @@ class doctrine implements tools_interface
foreach ($table_data['KEYS'] as $key_name => $key_data)
{
$columns = (is_array($key_data[1])) ? $key_data[1] : [$key_data[1]];
// Supports key columns defined with there length
$columns = array_map(function (string $column)
{
if (strpos($column, ':') !== false)
{
$parts = explode(':', $column, 2);
return $parts[0];
}
return $column;
}, $columns);
$options = [];
$this->schema_get_index_key_data($columns, $options);
if ($key_data[0] === 'UNIQUE')
{
$table->addUniqueIndex($columns, $key_name);
$table->addUniqueIndex($columns, $key_name, $options);
}
else
{
$table->addIndex($columns, $key_name);
$table->addIndex($columns, $key_name, [], $options);
}
}
}
@ -836,7 +863,10 @@ class doctrine implements tools_interface
return;
}
$table->addIndex($columns, $index_name);
$options = [];
$this->schema_get_index_key_data($columns, $options);
$table->addIndex($columns, $index_name, [], $options);
}
/**
@ -858,7 +888,10 @@ class doctrine implements tools_interface
return;
}
$table->addUniqueIndex($columns, $index_name);
$options = [];
$this->schema_get_index_key_data($columns, $options);
$table->addUniqueIndex($columns, $index_name, $options);
}
/**
@ -897,6 +930,30 @@ class doctrine implements tools_interface
$table->setPrimaryKey($columns);
}
/**
* Checks if index data contains key length
* and put it into $options['lengths'] array.
* Handles key length in formats of 'keyname:123' or 'keyname(123)'
*
* @param array $columns
* @param array $options
*/
protected function schema_get_index_key_data(array &$columns, array &$options): void
{
if (!empty($columns))
{
$columns = array_map(function (string $column) use (&$options)
{
if (preg_match('/^([a-zA-Z0-9_]+)(?:(?:\:|\()([0-9]{1,3})\)?)?$/', $column, $parts))
{
$options['lengths'][] = $parts[2] ?? null;
return $parts[1];
}
return $column;
}, $columns);
}
}
/**
* Recreate an index of a table
*

View file

@ -88,7 +88,10 @@ class twig extends \phpbb\template\base
foreach ($extensions as $extension)
{
$this->twig->addExtension($extension);
if (!$this->twig->hasExtension(get_class($extension)))
{
$this->twig->addExtension($extension);
}
}
// Add admin namespace

View file

@ -22,12 +22,22 @@ class phpbb_dbal_migration_schema extends \phpbb\db\migration\migration
),
),
'add_tables' => array(
$this->table_prefix . 'foobar' => array(
'COLUMNS' => array(
'module_id' => array('UINT:3', NULL, 'auto_increment'),
),
$this->table_prefix . 'foobar' => [
'COLUMNS' => [
'module_id' => ['UINT:3', NULL, 'auto_increment'],
'user_id' => ['ULINT', 0],
'endpoint' => ['VCHAR:220', ''],
'expiration_time' => ['TIMESTAMP', 0],
'p256dh' => ['VCHAR:200', ''],
'auth' => ['VCHAR:100', ''],
],
'PRIMARY_KEY' => 'module_id',
),
'KEYS' => [
'i_simple' => ['INDEX', ['user_id', 'endpoint:191']],
'i_uniq' => ['UNIQUE', ['expiration_time', 'p256dh(100)']],
'i_auth' => ['INDEX', 'auth'],
],
],
),
);
}

View file

@ -408,6 +408,61 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case
$this->assertTrue($this->db_tools->sql_column_exists('phpbb_config', 'test_column1'));
$this->assertTrue($this->db_tools->sql_table_exists('phpbb_foobar'));
$index_data_row = $this->db_tools->sql_get_table_index_data('phpbb_foobar');
$this->assertEquals(4, count($index_data_row));
$this->assertTrue(isset($index_data_row['i_simple']));
$this->assertTrue(isset($index_data_row['i_uniq']));
$this->assertTrue(isset($index_data_row['i_auth']));
$is_mysql = $this->db->get_sql_layer() === 'mysqli'; // Key 'lengths' option only applies to MySQL indexes
// MSSQL primary index key has 'clustered' flag, 'nonclustered' otherwise
// See https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described?view=sql-server-ver17#indexes-and-constraints
$is_mssql = in_array($this->db->get_sql_layer(), ['mssqlnative', 'mssql_odbc']);
foreach ($index_data_row as $index_name => $index_data)
{
switch ($index_name)
{
case 'i_simple':
$this->assertEquals(['user_id', 'endpoint'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']);
$this->assertEquals(2, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
$this->assertEquals($is_mysql ? 191 : null, $index_data['options']['lengths'][1]);
break;
case 'i_uniq':
$this->assertEquals(['expiration_time', 'p256dh'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertTrue($index_data['is_unique']);
$this->assertFalse($index_data['is_simple']);
$this->assertEquals(2, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
$this->assertEquals($is_mysql ? 100 : null, $index_data['options']['lengths'][1]);
break;
case 'i_auth':
$this->assertEquals(['auth'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['nonclustered'] : [], $index_data['flags']);
$this->assertFalse($index_data['is_primary']);
$this->assertFalse($index_data['is_unique']);
$this->assertTrue($index_data['is_simple']);
$this->assertEquals(1, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
break;
default: // Primary key
$this->assertEquals(['module_id'], $index_data['columns']);
$this->assertEquals($is_mssql ? ['clustered'] : [], $index_data['flags']);
$this->assertTrue($index_data['is_primary']);
$this->assertTrue($index_data['is_unique']);
$this->assertFalse($index_data['is_simple']);
$this->assertEquals(1, count($index_data['options']['lengths']));
$this->assertEmpty($index_data['options']['lengths'][0]);
break;
}
}
while ($this->migrator->migration_state('phpbb_dbal_migration_schema'))
{
$this->migrator->revert('phpbb_dbal_migration_schema');