aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKevin Decherf <kevin@kdecherf.com>2019-05-11 20:07:38 +0200
committerKevin Decherf <kevin@kdecherf.com>2019-05-19 23:37:49 +0200
commitfeb239ea1006685ab3862c988309a1a5a9659559 (patch)
tree034e26b367d06796a4f7888847cff76b1401ad7a
parentde1162b91a205a98a3f8ed01bd80285793b18380 (diff)
downloadwallabag-feb239ea1006685ab3862c988309a1a5a9659559.tar.gz
wallabag-feb239ea1006685ab3862c988309a1a5a9659559.tar.zst
wallabag-feb239ea1006685ab3862c988309a1a5a9659559.zip
mysql: change collation of tag table
utf8mb4_unicode_ci considers that 'caché' is equal to 'cache' which can lead to attaching incorrect tags to entries. This issue is due to some unicode normalization done by MySQL. utf8mb4_bin makes no unicode normalization, letting wallabag to consider 'cache' and 'caché' as two different tags. We change the collation of the whole table as Doctrine does not support setting a collation on a column for a specific platform (it tries to apply utf8mb4_bin even for pgsql and sqlite). Fixes #3302 Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
-rw-r--r--app/DoctrineMigrations/Version20190511165128.php30
-rw-r--r--src/Wallabag/CoreBundle/Entity/Tag.php5
-rw-r--r--tests/Wallabag/CoreBundle/Controller/TagControllerTest.php46
3 files changed, 80 insertions, 1 deletions
diff --git a/app/DoctrineMigrations/Version20190511165128.php b/app/DoctrineMigrations/Version20190511165128.php
new file mode 100644
index 00000000..7b6b1bec
--- /dev/null
+++ b/app/DoctrineMigrations/Version20190511165128.php
@@ -0,0 +1,30 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Application\Migrations;
6
7use Doctrine\DBAL\Schema\Schema;
8use Wallabag\CoreBundle\Doctrine\WallabagMigration;
9
10/**
11 * Convert tab label to utf8mb4_bin (MySQL only).
12 */
13final class Version20190511165128 extends WallabagMigration
14{
15 public function up(Schema $schema): void
16 {
17 $this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
18
19 $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
20 $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
21 }
22
23 public function down(Schema $schema): void
24 {
25 $this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
26
27 $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
28 $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
29 }
30}
diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php
index a6dc8c50..95c47bbd 100644
--- a/src/Wallabag/CoreBundle/Entity/Tag.php
+++ b/src/Wallabag/CoreBundle/Entity/Tag.php
@@ -13,7 +13,10 @@ use JMS\Serializer\Annotation\XmlRoot;
13 * Tag. 13 * Tag.
14 * 14 *
15 * @XmlRoot("tag") 15 * @XmlRoot("tag")
16 * @ORM\Table(name="`tag`") 16 * @ORM\Table(
17 * name="`tag`",
18 * options={"collate"="utf8mb4_bin", "charset"="utf8mb4"},
19 * )
17 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TagRepository") 20 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TagRepository")
18 * @ExclusionPolicy("all") 21 * @ExclusionPolicy("all")
19 */ 22 */
diff --git a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
index be17dcf5..47c83a7b 100644
--- a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
@@ -221,4 +221,50 @@ class TagControllerTest extends WallabagCoreTestCase
221 $this->assertInstanceOf(Tag::class, $newTag, 'Tag "specific label" exists.'); 221 $this->assertInstanceOf(Tag::class, $newTag, 'Tag "specific label" exists.');
222 $this->assertTrue($newTag->hasEntry($freshEntry), 'Tag "specific label" is assigned to the entry.'); 222 $this->assertTrue($newTag->hasEntry($freshEntry), 'Tag "specific label" is assigned to the entry.');
223 } 223 }
224
225 public function testAddUnicodeTagLabel()
226 {
227 $this->logInAs('admin');
228 $client = $this->getClient();
229
230 $entry = new Entry($this->getLoggedInUser());
231 $entry->setUrl('http://0.0.0.0/tag-caché');
232 $this->getEntityManager()->persist($entry);
233 $this->getEntityManager()->flush();
234 $this->getEntityManager()->clear();
235
236 $crawler = $client->request('GET', '/view/' . $entry->getId());
237
238 $form = $crawler->filter('form[name=tag]')->form();
239
240 $data = [
241 'tag[label]' => 'cache',
242 ];
243
244 $client->submit($form, $data);
245
246 $crawler = $client->request('GET', '/view/' . $entry->getId());
247
248 $form = $crawler->filter('form[name=tag]')->form();
249
250 $data = [
251 'tag[label]' => 'caché',
252 ];
253
254 $client->submit($form, $data);
255
256 $newEntry = $client->getContainer()
257 ->get('doctrine.orm.entity_manager')
258 ->getRepository('WallabagCoreBundle:Entry')
259 ->find($entry->getId());
260
261 $tags = $newEntry->getTags()->toArray();
262 foreach ($tags as $key => $tag) {
263 $tags[$key] = $tag->getLabel();
264 }
265
266 $this->assertGreaterThanOrEqual(2, \count($tags));
267 $this->assertNotFalse(array_search('cache', $tags, true), 'Tag cache is assigned to the entry');
268 $this->assertNotFalse(array_search('caché', $tags, true), 'Tag caché is assigned to the entry');
269 }
224} 270}