13 private $utf8mb4_tables = [
15 'access_collection_membership',
21 'entity_relationships',
27 'users_remember_me_cookies',
39 private $non_mb4_columns = [
78 'name' =>
'object_class',
83 'name' =>
'object_type',
88 'name' =>
'object_subtype',
98 'name' =>
'river_key',
100 'columns' => [
'object_type',
'object_subtype',
'event']
125 $rows =
_elgg_services()->db->getConnection(
'read')->executeQuery(
"SHOW TABLE STATUS FROM `{$config['database']}`");
127 $prefixed_table_names = array_map(
function ($t) use (
$config) {
128 return "{$config['prefix']}{$t}";
129 }, $this->utf8mb4_tables);
131 foreach (
$rows->fetchAllAssociative() as $row) {
132 $row = (object) $row;
133 if (in_array($row->Name, $prefixed_table_names) && $row->Collation !==
'utf8mb4_general_ci') {
157 $db_result =
_elgg_services()->db->getConnection(
'read')->executeQuery(
"SHOW GLOBAL VARIABLES LIKE 'innodb_large_prefix'");
158 $rows = $db_result->fetchAllAssociative();
160 if (empty(
$rows) ||
$rows[0][
'Value'] ===
'OFF') {
162 _elgg_services()->db->getConnection(
'write')->executeStatement(
"SET GLOBAL innodb_large_prefix = 'ON'");
167 $result->
addError(
"Failure to set 'innodb_large_prefix'. Ask your database administrator for more information.");
168 $result->
addError(
"Alternatively ask the database administrator to (temporarily) set 'innodb_large_prefix' to 'ON'.");
169 $result->
addError($e->getMessage());
177 $connection->executeStatement(
" 179 `{$config['database']}` 180 CHARACTER SET = utf8mb4 181 COLLATE = utf8mb4_unicode_ci 184 foreach ($this->utf8mb4_tables as
$table) {
185 if (!empty($this->non_mb4_columns[$table])) {
186 foreach ($this->non_mb4_columns[$table] as
$column =>
$index) {
189 $connection->executeStatement(
" 190 ALTER TABLE {$config['prefix']}{$table} 194 $connection->executeStatement(
" 195 ALTER TABLE {$config['prefix']}{$table} 196 DROP KEY {$index['name']} 203 $connection->executeStatement(
" 204 ALTER TABLE {$config['prefix']}{$table} 208 $connection->executeStatement(
" 209 ALTER TABLE {$config['prefix']}{$table} 210 CONVERT TO CHARACTER SET utf8mb4 211 COLLATE utf8mb4_general_ci 214 if (!empty($this->non_mb4_columns[$table])) {
215 foreach ($this->non_mb4_columns[$table] as
$column =>
$index) {
216 if (empty(
$index[
'columns'])) {
218 $connection->executeStatement(
" 219 ALTER TABLE {$config['prefix']}{$table} 220 MODIFY $column VARCHAR(255) 222 COLLATE utf8_unicode_ci 232 $sql .=
" UNIQUE ({$index['name']})";
233 }
else if (
$index[
'primary']) {
234 $sql .=
" PRIMARY KEY ({$index['name']})";
237 $key_columns =
implode(
',', $key_columns);
238 $sql .=
" KEY {$index['name']} ($key_columns)";
241 $connection->executeStatement(
" 242 ALTER TABLE {$config['prefix']}{$table} 250 $result->
addError($e->getMessage());
Updates database charset to utf8mb4.
Interface to be implement for asynchronous upgrades, i.e.
getVersion()
{Version of the upgrade.This tells the date when the upgrade was added. It consists of eight digits a...
countItems()
{The total number of items to process during the upgrade.If unknown, Batch::UNKNOWN_COUNT should be r...
addFailures(int $num=1)
Increment failure count.
shouldBeSkipped()
{Should this upgrade be skipped?If true, the upgrade will not be performed and cannot be accessed lat...
addSuccesses(int $num=1)
Set an item (or items) as successfully upgraded.
$config
Advanced site settings, debugging section.
addError($message)
Add new error message to the batch.
Result of a single BatchUpgrade run.
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
_elgg_services()
Get the global service provider.
needsIncrementOffset()
{Should the run() method receive an offset representing all processed items?If true, run() will receive as $offset the number of items already processed. This is useful if you are only modifying data, and need to use the $offset in a function like elgg_get_entities*() to know how many to skip over.If false, run() will receive as $offset the total number of failures. This should be used if your process deletes or moves data out of the way of the process. E.g. if you delete 50 objects on each run(), you may still use the $offset to skip objects that already failed once.bool}
run(Result $result, $offset)
{Runs upgrade on a single batch of items.If countItems() returns Batch::UNKNOWN_COUNT, this method must call $result->markCompleted() when the upgrade is complete.Result of the batch (this must be returned) Number to skip when processingResult}