Skip to content

Commit f2fcaa8

Browse files
committed
daos/mysql: Add colors to tags without one
When user specified a source tag with a same name but a different letter casing as another existing tag, the MySQL backend would think the tag already exists and not create a color for it. This would break, for example, OPML export, which expects every tag to have a color associated with it. The bug has been fixed in the previous commit but there can still be such erroneously created tags from before. Let’s go through all tags mentioned in the `source` table and ensure the `tags` table is up to date. If a tag with a different casing and a color exists, let’s consider it the canonical casing and update the source tag to that. Fixes: #1438
1 parent c1ecc5e commit f2fcaa8

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

src/daos/mysql/Database.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use daos\CommonSqlDatabase;
88
use helpers\DatabaseConnection;
9+
use helpers\StringKeyedArray;
910
use Monolog\Logger;
1011

1112
/**
@@ -292,6 +293,77 @@ public function __construct(DatabaseConnection $connection, Logger $logger) {
292293
$this->exec('INSERT INTO ' . $this->connection->getTableNamePrefix() . 'version (version) VALUES (14)');
293294
$this->commit();
294295
}
296+
if ($version < 15) {
297+
$this->logger->debug('Upgrading database schema to version 15 by ensuring all tags have colors');
298+
299+
$this->beginTransaction();
300+
301+
/** @var StringKeyedArray<bool> */
302+
$coloredTags = new StringKeyedArray();
303+
/** @var StringKeyedArray<string> */
304+
$coloredTagsNormalised = new StringKeyedArray();
305+
/** @var StringKeyedArray<string> */
306+
$tagsWithoutColor = new StringKeyedArray();
307+
308+
$tags = $this->exec('SELECT tag, LOWER(tag) as normal FROM ' . $this->connection->getTableNamePrefix() . 'tags');
309+
foreach ($tags as $tag) {
310+
$coloredTags[$tag['tag']] = true;
311+
$coloredTagsNormalised[$tag['normal']] = $tag['tag'];
312+
}
313+
314+
$sources = $this->exec('SELECT id, tags, LOWER(tags) as normal FROM ' . $this->connection->getTableNamePrefix() . 'sources');
315+
foreach ($sources as $source) {
316+
if ($source['tags'] === '') {
317+
continue;
318+
}
319+
320+
$shouldUpdateSourceTags = false;
321+
322+
$sourceTags = explode(',', $source['tags']);
323+
$sourceTagPairs = array_map(
324+
null,
325+
$sourceTags,
326+
explode(',', $source['normal'])
327+
);
328+
foreach ($sourceTagPairs as $key => [$tag, $normal]) {
329+
// If the tag does not have associated color:
330+
if (!isset($coloredTags[$tag])) {
331+
// Try to match it to a differently-cased tag.
332+
if (isset($coloredTagsNormalised[$normal])) {
333+
$sourceTags[$key] = $coloredTagsNormalised[$normal];
334+
$shouldUpdateSourceTags = true;
335+
} else {
336+
// Otherwise mark it for assigning a color.
337+
$tagsWithoutColor[$normal] = $tag;
338+
}
339+
}
340+
}
341+
342+
if ($shouldUpdateSourceTags) {
343+
$this->exec(
344+
'UPDATE ' . $this->connection->getTableNamePrefix() . 'sources SET tags = :tags WHERE id = :id',
345+
[
346+
'id' => $source['id'],
347+
'tags' => implode(',', $sourceTags),
348+
]
349+
);
350+
}
351+
}
352+
353+
// Add color to all tags without one.
354+
foreach ($tagsWithoutColor as $tag) {
355+
$this->exec(
356+
'INSERT INTO ' . $this->connection->getTableNamePrefix() . 'tags(tag, color) VALUES (:tag, :color)',
357+
[
358+
'tag' => $tag,
359+
'color' => '#df1818',
360+
]
361+
);
362+
}
363+
364+
$this->exec('INSERT INTO ' . $this->connection->getTableNamePrefix() . 'version (version) VALUES (15)');
365+
$this->commit();
366+
}
295367
}
296368

297369
/**

0 commit comments

Comments
 (0)