aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--app/DoctrineMigrations/Version20160410190541.php12
-rw-r--r--app/DoctrineMigrations/Version20160812120952.php15
-rw-r--r--app/DoctrineMigrations/Version20160911214952.php4
-rw-r--r--app/DoctrineMigrations/Version20160916201049.php6
-rw-r--r--app/DoctrineMigrations/Version20161001072726.php63
-rw-r--r--app/DoctrineMigrations/Version20161022134138.php77
-rw-r--r--app/config/config.yml2
-rw-r--r--app/config/config_test.yml2
-rw-r--r--app/config/parameters.yml.dist14
-rw-r--r--app/config/parameters_test.yml1
-rw-r--r--app/config/tests/parameters_test.mysql.yml1
-rw-r--r--app/config/tests/parameters_test.pgsql.yml1
-rw-r--r--app/config/tests/parameters_test.sqlite.yml1
-rw-r--r--docs/en/user/parameters.rst3
-rw-r--r--src/Wallabag/AnnotationBundle/Entity/Annotation.php2
-rw-r--r--src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php14
-rw-r--r--src/Wallabag/CoreBundle/Command/InstallCommand.php26
-rw-r--r--src/Wallabag/CoreBundle/Controller/ConfigController.php74
-rw-r--r--src/Wallabag/CoreBundle/Controller/TagController.php10
-rw-r--r--src/Wallabag/CoreBundle/Entity/Entry.php6
-rw-r--r--src/Wallabag/CoreBundle/Repository/EntryRepository.php14
-rw-r--r--src/Wallabag/CoreBundle/Repository/TagRepository.php18
-rw-r--r--src/Wallabag/CoreBundle/Resources/config/services.yml7
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.da.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.de.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.en.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.es.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml16
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.it.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml10
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml14
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig22
-rw-r--r--src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig16
-rw-r--r--src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php70
-rw-r--r--src/Wallabag/UserBundle/Resources/config/services.yml2
-rw-r--r--tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php145
39 files changed, 717 insertions, 63 deletions
diff --git a/app/DoctrineMigrations/Version20160410190541.php b/app/DoctrineMigrations/Version20160410190541.php
index 4014857b..c41b0465 100644
--- a/app/DoctrineMigrations/Version20160410190541.php
+++ b/app/DoctrineMigrations/Version20160410190541.php
@@ -29,8 +29,12 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
29 */ 29 */
30 public function up(Schema $schema) 30 public function up(Schema $schema)
31 { 31 {
32 $this->addSql('ALTER TABLE `'.$this->getTable('entry').'` ADD `uuid` LONGTEXT DEFAULT NULL'); 32 if ($this->connection->getDatabasePlatform()->getName() == 'postgresql') {
33 $this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry')"); 33 $this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD uuid UUID DEFAULT NULL');
34 } else {
35 $this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD uuid LONGTEXT DEFAULT NULL');
36 }
37 $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_public', '1', 'entry')");
34 } 38 }
35 39
36 /** 40 /**
@@ -40,7 +44,7 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
40 { 44 {
41 $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.'); 45 $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
42 46
43 $this->addSql('ALTER TABLE `'.$this->getTable('entry').'` DROP `uuid`'); 47 $this->addSql('ALTER TABLE '.$this->getTable('entry').' DROP uuid');
44 $this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'share_public'"); 48 $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'share_public'");
45 } 49 }
46} 50}
diff --git a/app/DoctrineMigrations/Version20160812120952.php b/app/DoctrineMigrations/Version20160812120952.php
index a8d3bcf2..39423e2f 100644
--- a/app/DoctrineMigrations/Version20160812120952.php
+++ b/app/DoctrineMigrations/Version20160812120952.php
@@ -29,10 +29,17 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
29 */ 29 */
30 public function up(Schema $schema) 30 public function up(Schema $schema)
31 { 31 {
32 if ($this->connection->getDatabasePlatform()->getName() == 'sqlite') { 32 switch ($this->connection->getDatabasePlatform()->getName()) {
33 $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL'); 33 case 'sqlite':
34 } else { 34 $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL');
35 $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL'); 35 break;
36
37 case 'mysql':
38 $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
39 break;
40
41 case 'postgresql':
42 $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name text DEFAULT NULL');
36 } 43 }
37 } 44 }
38 45
diff --git a/app/DoctrineMigrations/Version20160911214952.php b/app/DoctrineMigrations/Version20160911214952.php
index 35809cec..3f988ccf 100644
--- a/app/DoctrineMigrations/Version20160911214952.php
+++ b/app/DoctrineMigrations/Version20160911214952.php
@@ -29,8 +29,8 @@ class Version20160911214952 extends AbstractMigration implements ContainerAwareI
29 */ 29 */
30 public function up(Schema $schema) 30 public function up(Schema $schema)
31 { 31 {
32 $this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_redis\', \'0\', \'import\')'); 32 $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting').' (name, value, section) VALUES (\'import_with_redis\', \'0\', \'import\')');
33 $this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')'); 33 $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting').' (name, value, section) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')');
34 } 34 }
35 35
36 /** 36 /**
diff --git a/app/DoctrineMigrations/Version20160916201049.php b/app/DoctrineMigrations/Version20160916201049.php
index 202901e6..fc4e700a 100644
--- a/app/DoctrineMigrations/Version20160916201049.php
+++ b/app/DoctrineMigrations/Version20160916201049.php
@@ -30,7 +30,7 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
30 public function up(Schema $schema) 30 public function up(Schema $schema)
31 { 31 {
32 $this->addSql('ALTER TABLE '.$this->getTable('config').' ADD pocket_consumer_key VARCHAR(255) DEFAULT NULL'); 32 $this->addSql('ALTER TABLE '.$this->getTable('config').' ADD pocket_consumer_key VARCHAR(255) DEFAULT NULL');
33 $this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'pocket_consumer_key';"); 33 $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'pocket_consumer_key';");
34 } 34 }
35 35
36 /** 36 /**
@@ -40,7 +40,7 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
40 { 40 {
41 $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.'); 41 $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
42 42
43 $this->addSql('ALTER TABLE `'.$this->getTable('config').'` DROP pocket_consumer_key'); 43 $this->addSql('ALTER TABLE '.$this->getTable('config').' DROP pocket_consumer_key');
44 $this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('pocket_consumer_key', NULL, 'import')"); 44 $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('pocket_consumer_key', NULL, 'import')");
45 } 45 }
46} 46}
diff --git a/app/DoctrineMigrations/Version20161001072726.php b/app/DoctrineMigrations/Version20161001072726.php
new file mode 100644
index 00000000..237db932
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161001072726.php
@@ -0,0 +1,63 @@
1<?php
2
3namespace Application\Migrations;
4
5use Doctrine\DBAL\Migrations\AbstractMigration;
6use Doctrine\DBAL\Schema\Schema;
7use Symfony\Component\DependencyInjection\ContainerAwareInterface;
8use Symfony\Component\DependencyInjection\ContainerInterface;
9
10class Version20161001072726 extends AbstractMigration implements ContainerAwareInterface
11{
12 /**
13 * @var ContainerInterface
14 */
15 private $container;
16
17 public function setContainer(ContainerInterface $container = null)
18 {
19 $this->container = $container;
20 }
21
22 private function getTable($tableName)
23 {
24 return $this->container->getParameter('database_table_prefix') . $tableName;
25 }
26
27 /**
28 * @param Schema $schema
29 */
30 public function up(Schema $schema)
31 {
32 $this->skipIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
33
34 // remove all FK from entry_tag
35 $query = $this->connection->query("SELECT CONSTRAINT_NAME FROM information_schema.key_column_usage WHERE TABLE_NAME = '".$this->getTable('entry_tag')."' AND CONSTRAINT_NAME LIKE 'FK_%' AND TABLE_SCHEMA = '".$this->connection->getDatabase()."'");
36 $query->execute();
37
38 foreach ($query->fetchAll() as $fk) {
39 $this->addSql('ALTER TABLE '.$this->getTable('entry_tag').' DROP FOREIGN KEY '.$fk['CONSTRAINT_NAME']);
40 }
41
42 $this->addSql('ALTER TABLE '.$this->getTable('entry_tag').' ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES '.$this->getTable('entry').' (id) ON DELETE CASCADE');
43 $this->addSql('ALTER TABLE '.$this->getTable('entry_tag').' ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES '.$this->getTable('tag').' (id) ON DELETE CASCADE');
44
45 // remove entry FK from annotation
46 $query = $this->connection->query("SELECT CONSTRAINT_NAME FROM information_schema.key_column_usage WHERE TABLE_NAME = '".$this->getTable('annotation')."' AND CONSTRAINT_NAME LIKE 'FK_%' and COLUMN_NAME = 'entry_id' AND TABLE_SCHEMA = '".$this->connection->getDatabase()."'");
47 $query->execute();
48
49 foreach ($query->fetchAll() as $fk) {
50 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' DROP FOREIGN KEY '.$fk['CONSTRAINT_NAME']);
51 }
52
53 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES '.$this->getTable('entry').' (id) ON DELETE CASCADE');
54 }
55
56 /**
57 * @param Schema $schema
58 */
59 public function down(Schema $schema)
60 {
61 throw new SkipMigrationException('Too complex ...');
62 }
63}
diff --git a/app/DoctrineMigrations/Version20161022134138.php b/app/DoctrineMigrations/Version20161022134138.php
new file mode 100644
index 00000000..5cce55a5
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161022134138.php
@@ -0,0 +1,77 @@
1<?php
2
3namespace Application\Migrations;
4
5use Doctrine\DBAL\Migrations\AbstractMigration;
6use Doctrine\DBAL\Schema\Schema;
7use Symfony\Component\DependencyInjection\ContainerAwareInterface;
8use Symfony\Component\DependencyInjection\ContainerInterface;
9
10class Version20161022134138 extends AbstractMigration implements ContainerAwareInterface
11{
12 /**
13 * @var ContainerInterface
14 */
15 private $container;
16
17 public function setContainer(ContainerInterface $container = null)
18 {
19 $this->container = $container;
20 }
21
22 private function getTable($tableName)
23 {
24 return $this->container->getParameter('database_table_prefix') . $tableName;
25 }
26
27 /**
28 * @param Schema $schema
29 */
30 public function up(Schema $schema)
31 {
32 $this->skipIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'This migration only apply to MySQL');
33
34 $this->addSql('ALTER DATABASE '.$this->container->getParameter('database_name').' CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;');
35
36 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
37 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
38 $this->addSql('ALTER TABLE '.$this->getTable('tag').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
39 $this->addSql('ALTER TABLE '.$this->getTable('user').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
40
41 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
42 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `quote` `quote` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
43
44 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `title` `title` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
45 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `content` `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
46
47 $this->addSql('ALTER TABLE '.$this->getTable('tag').' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
48
49 $this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
50 }
51
52 /**
53 * @param Schema $schema
54 */
55 public function down(Schema $schema)
56 {
57 $this->skipIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'This migration only apply to MySQL');
58
59 $this->addSql('ALTER DATABASE '.$this->container->getParameter('database_name').' CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;');
60
61 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
62 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
63 $this->addSql('ALTER TABLE '.$this->getTable('tag').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
64 $this->addSql('ALTER TABLE '.$this->getTable('user').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
65
66 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `text` `text` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
67 $this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `quote` `quote` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
68
69 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `title` `title` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
70 $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `content` `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
71
72 $this->addSql('ALTER TABLE '.$this->getTable('tag').' CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
73
74 $this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
75
76 }
77}
diff --git a/app/config/config.yml b/app/config/config.yml
index b4760073..9dbc9d7c 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -75,7 +75,7 @@ doctrine:
75 dbname: "%database_name%" 75 dbname: "%database_name%"
76 user: "%database_user%" 76 user: "%database_user%"
77 password: "%database_password%" 77 password: "%database_password%"
78 charset: UTF8 78 charset: "%database_charset%"
79 path: "%database_path%" 79 path: "%database_path%"
80 unix_socket: "%database_socket%" 80 unix_socket: "%database_socket%"
81 server_version: 5.6 81 server_version: 5.6
diff --git a/app/config/config_test.yml b/app/config/config_test.yml
index 3eab6fb2..f5e2c25e 100644
--- a/app/config/config_test.yml
+++ b/app/config/config_test.yml
@@ -28,7 +28,7 @@ doctrine:
28 dbname: "%test_database_name%" 28 dbname: "%test_database_name%"
29 user: "%test_database_user%" 29 user: "%test_database_user%"
30 password: "%test_database_password%" 30 password: "%test_database_password%"
31 charset: UTF8 31 charset: "%test_database_charset%"
32 path: "%test_database_path%" 32 path: "%test_database_path%"
33 orm: 33 orm:
34 metadata_cache_driver: 34 metadata_cache_driver:
diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist
index ece4903a..7a22cb98 100644
--- a/app/config/parameters.yml.dist
+++ b/app/config/parameters.yml.dist
@@ -19,16 +19,18 @@ parameters:
19 database_path: "%kernel.root_dir%/../data/db/wallabag.sqlite" 19 database_path: "%kernel.root_dir%/../data/db/wallabag.sqlite"
20 database_table_prefix: wallabag_ 20 database_table_prefix: wallabag_
21 database_socket: null 21 database_socket: null
22 # with MySQL, use "utf8mb4" if you got problem with content with emojis
23 database_charset: utf8
22 24
23 mailer_transport: smtp 25 mailer_transport: smtp
24 mailer_host: 127.0.0.1 26 mailer_host: 127.0.0.1
25 mailer_user: ~ 27 mailer_user: ~
26 mailer_password: ~ 28 mailer_password: ~
27 29
28 locale: en 30 locale: en
29 31
30 # A secret key that's used to generate certain security-related tokens 32 # A secret key that's used to generate certain security-related tokens
31 secret: ovmpmAWXRCabNlMgzlzFXDYmCFfzGv 33 secret: ovmpmAWXRCabNlMgzlzFXDYmCFfzGv
32 34
33 # two factor stuff 35 # two factor stuff
34 twofactor_auth: true 36 twofactor_auth: true
diff --git a/app/config/parameters_test.yml b/app/config/parameters_test.yml
index 2943b27a..5f2e25bb 100644
--- a/app/config/parameters_test.yml
+++ b/app/config/parameters_test.yml
@@ -6,3 +6,4 @@ parameters:
6 test_database_user: null 6 test_database_user: null
7 test_database_password: null 7 test_database_password: null
8 test_database_path: '%kernel.root_dir%/../data/db/wallabag_test.sqlite' 8 test_database_path: '%kernel.root_dir%/../data/db/wallabag_test.sqlite'
9 test_database_charset: utf8
diff --git a/app/config/tests/parameters_test.mysql.yml b/app/config/tests/parameters_test.mysql.yml
index d8512845..bca2d466 100644
--- a/app/config/tests/parameters_test.mysql.yml
+++ b/app/config/tests/parameters_test.mysql.yml
@@ -6,3 +6,4 @@ parameters:
6 test_database_user: root 6 test_database_user: root
7 test_database_password: ~ 7 test_database_password: ~
8 test_database_path: ~ 8 test_database_path: ~
9 test_database_charset: utf8mb4
diff --git a/app/config/tests/parameters_test.pgsql.yml b/app/config/tests/parameters_test.pgsql.yml
index 41383868..3e18d4a0 100644
--- a/app/config/tests/parameters_test.pgsql.yml
+++ b/app/config/tests/parameters_test.pgsql.yml
@@ -6,3 +6,4 @@ parameters:
6 test_database_user: travis 6 test_database_user: travis
7 test_database_password: ~ 7 test_database_password: ~
8 test_database_path: ~ 8 test_database_path: ~
9 test_database_charset: utf8
diff --git a/app/config/tests/parameters_test.sqlite.yml b/app/config/tests/parameters_test.sqlite.yml
index 1952e3a6..b8a5f41a 100644
--- a/app/config/tests/parameters_test.sqlite.yml
+++ b/app/config/tests/parameters_test.sqlite.yml
@@ -6,3 +6,4 @@ parameters:
6 test_database_user: ~ 6 test_database_user: ~
7 test_database_password: ~ 7 test_database_password: ~
8 test_database_path: "%kernel.root_dir%/../data/db/wallabag_test.sqlite" 8 test_database_path: "%kernel.root_dir%/../data/db/wallabag_test.sqlite"
9 test_database_charset: utf8
diff --git a/docs/en/user/parameters.rst b/docs/en/user/parameters.rst
index 79c50871..2fca020e 100644
--- a/docs/en/user/parameters.rst
+++ b/docs/en/user/parameters.rst
@@ -11,7 +11,8 @@ What is the meaning of the parameters?
11 "database_password", "~", "password of that user" 11 "database_password", "~", "password of that user"
12 "database_path", "``""%kernel.root_dir%/../data/db/wallabag.sqlite""``", "only for SQLite, define where to put the database file. Leave it for other database" 12 "database_path", "``""%kernel.root_dir%/../data/db/wallabag.sqlite""``", "only for SQLite, define where to put the database file. Leave it for other database"
13 "database_table_prefix", "wallabag_", "all wallabag's tables will be prefixed with that string. You can include a ``_`` for clarity" 13 "database_table_prefix", "wallabag_", "all wallabag's tables will be prefixed with that string. You can include a ``_`` for clarity"
14 "database_socket", "null", "If your database is using a socket instead of tcp, put the path of the socket (other connection parameters will then be ignored" 14 "database_socket", "null", "If your database is using a socket instead of tcp, put the path of the socket (other connection parameters will then be ignored)"
15 "database_charset", "utf8mb4", "For PostgreSQL & SQLite you should use utf8, for MySQL use utf8mb4 which handle emoji"
15 16
16.. csv-table:: Configuration to send emails from wallabag 17.. csv-table:: Configuration to send emails from wallabag
17 :header: "name", "default", "description" 18 :header: "name", "default", "description"
diff --git a/src/Wallabag/AnnotationBundle/Entity/Annotation.php b/src/Wallabag/AnnotationBundle/Entity/Annotation.php
index c48d8731..0838f5aa 100644
--- a/src/Wallabag/AnnotationBundle/Entity/Annotation.php
+++ b/src/Wallabag/AnnotationBundle/Entity/Annotation.php
@@ -82,7 +82,7 @@ class Annotation
82 * @Exclude 82 * @Exclude
83 * 83 *
84 * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="annotations") 84 * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="annotations")
85 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id") 85 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
86 */ 86 */
87 private $entry; 87 private $entry;
88 88
diff --git a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
index 8cccffba..8d3f07ee 100644
--- a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
+++ b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
@@ -108,4 +108,18 @@ class AnnotationRepository extends EntityRepository
108 ->getQuery() 108 ->getQuery()
109 ->getSingleResult(); 109 ->getSingleResult();
110 } 110 }
111
112 /**
113 * Remove all annotations for a user id.
114 * Used when a user want to reset all informations.
115 *
116 * @param int $userId
117 */
118 public function removeAllByUserId($userId)
119 {
120 $this->getEntityManager()
121 ->createQuery('DELETE FROM Wallabag\AnnotationBundle\Entity\Annotation a WHERE a.user = :userId')
122 ->setParameter('userId', $userId)
123 ->execute();
124 }
111} 125}
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index 59110782..82cd9daf 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -40,7 +40,7 @@ class InstallCommand extends ContainerAwareCommand
40 { 40 {
41 $this 41 $this
42 ->setName('wallabag:install') 42 ->setName('wallabag:install')
43 ->setDescription('Wallabag installer.') 43 ->setDescription('wallabag installer.')
44 ->addOption( 44 ->addOption(
45 'reset', 45 'reset',
46 null, 46 null,
@@ -55,7 +55,7 @@ class InstallCommand extends ContainerAwareCommand
55 $this->defaultInput = $input; 55 $this->defaultInput = $input;
56 $this->defaultOutput = $output; 56 $this->defaultOutput = $output;
57 57
58 $output->writeln('<info>Installing Wallabag...</info>'); 58 $output->writeln('<info>Installing wallabag...</info>');
59 $output->writeln(''); 59 $output->writeln('');
60 60
61 $this 61 $this
@@ -65,7 +65,7 @@ class InstallCommand extends ContainerAwareCommand
65 ->setupConfig() 65 ->setupConfig()
66 ; 66 ;
67 67
68 $output->writeln('<info>Wallabag has been successfully installed.</info>'); 68 $output->writeln('<info>wallabag has been successfully installed.</info>');
69 $output->writeln('<comment>Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000</comment>'); 69 $output->writeln('<comment>Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000</comment>');
70 } 70 }
71 71
@@ -95,7 +95,8 @@ class InstallCommand extends ContainerAwareCommand
95 $help = ''; 95 $help = '';
96 96
97 try { 97 try {
98 $this->getContainer()->get('doctrine')->getManager()->getConnection()->connect(); 98 $conn = $this->getContainer()->get('doctrine')->getManager()->getConnection();
99 $conn->connect();
99 } catch (\Exception $e) { 100 } catch (\Exception $e) {
100 if (false === strpos($e->getMessage(), 'Unknown database') 101 if (false === strpos($e->getMessage(), 'Unknown database')
101 && false === strpos($e->getMessage(), 'database "'.$this->getContainer()->getParameter('database_name').'" does not exist')) { 102 && false === strpos($e->getMessage(), 'database "'.$this->getContainer()->getParameter('database_name').'" does not exist')) {
@@ -107,6 +108,21 @@ class InstallCommand extends ContainerAwareCommand
107 108
108 $rows[] = [$label, $status, $help]; 109 $rows[] = [$label, $status, $help];
109 110
111 // now check if MySQL isn't too old to handle utf8mb4
112 if ($conn->isConnected() && $conn->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MySqlPlatform) {
113 $version = $conn->query('select version()')->fetchColumn();
114 $minimalVersion = '5.5.4';
115
116 if (false === version_compare($version, $minimalVersion, '>')) {
117 $fulfilled = false;
118 $rows[] = [
119 '<comment>Database version</comment>',
120 '<error>ERROR!</error>',
121 'Your MySQL version ('.$version.') is too old, consider upgrading ('.$minimalVersion.'+).',
122 ];
123 }
124 }
125
110 foreach ($this->functionExists as $functionRequired) { 126 foreach ($this->functionExists as $functionRequired) {
111 $label = '<comment>'.$functionRequired.'</comment>'; 127 $label = '<comment>'.$functionRequired.'</comment>';
112 $status = '<info>OK!</info>'; 128 $status = '<info>OK!</info>';
@@ -131,7 +147,7 @@ class InstallCommand extends ContainerAwareCommand
131 throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.'); 147 throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.');
132 } 148 }
133 149
134 $this->defaultOutput->writeln('<info>Success! Your system can run Wallabag properly.</info>'); 150 $this->defaultOutput->writeln('<info>Success! Your system can run wallabag properly.</info>');
135 151
136 $this->defaultOutput->writeln(''); 152 $this->defaultOutput->writeln('');
137 153
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php
index abd35c02..8d391917 100644
--- a/src/Wallabag/CoreBundle/Controller/ConfigController.php
+++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php
@@ -225,6 +225,80 @@ class ConfigController extends Controller
225 } 225 }
226 226
227 /** 227 /**
228 * Remove all annotations OR tags OR entries for the current user.
229 *
230 * @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset")
231 *
232 * @return RedirectResponse
233 */
234 public function resetAction($type)
235 {
236 $em = $this->getDoctrine()->getManager();
237
238 switch ($type) {
239 case 'annotations':
240 $this->getDoctrine()
241 ->getRepository('WallabagAnnotationBundle:Annotation')
242 ->removeAllByUserId($this->getUser()->getId());
243 break;
244
245 case 'tags':
246 $this->removeAllTagsByUserId($this->getUser()->getId());
247 break;
248
249 case 'entries':
250 // SQLite doesn't care about cascading remove, so we need to manually remove associated stuf
251 // otherwise they won't be removed ...
252 if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
253 $this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId());
254 }
255
256 // manually remove tags to avoid orphan tag
257 $this->removeAllTagsByUserId($this->getUser()->getId());
258
259 $this->getDoctrine()
260 ->getRepository('WallabagCoreBundle:Entry')
261 ->removeAllByUserId($this->getUser()->getId());
262 }
263
264 $this->get('session')->getFlashBag()->add(
265 'notice',
266 'flashes.config.notice.'.$type.'_reset'
267 );
268
269 return $this->redirect($this->generateUrl('config').'#set3');
270 }
271
272 /**
273 * Remove all tags for a given user and cleanup orphan tags.
274 *
275 * @param int $userId
276 */
277 private function removeAllTagsByUserId($userId)
278 {
279 $tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId);
280
281 if (empty($tags)) {
282 return;
283 }
284
285 $this->getDoctrine()
286 ->getRepository('WallabagCoreBundle:Entry')
287 ->removeTags($userId, $tags);
288
289 // cleanup orphan tags
290 $em = $this->getDoctrine()->getManager();
291
292 foreach ($tags as $tag) {
293 if (count($tag->getEntries()) === 0) {
294 $em->remove($tag);
295 }
296 }
297
298 $em->flush();
299 }
300
301 /**
228 * Validate that a rule can be edited/deleted by the current user. 302 * Validate that a rule can be edited/deleted by the current user.
229 * 303 *
230 * @param TaggingRule $rule 304 * @param TaggingRule $rule
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php
index 5acc6852..4542d484 100644
--- a/src/Wallabag/CoreBundle/Controller/TagController.php
+++ b/src/Wallabag/CoreBundle/Controller/TagController.php
@@ -90,15 +90,15 @@ class TagController extends Controller
90 90
91 $flatTags = []; 91 $flatTags = [];
92 92
93 foreach ($tags as $key => $tag) { 93 foreach ($tags as $tag) {
94 $nbEntries = $this->getDoctrine() 94 $nbEntries = $this->getDoctrine()
95 ->getRepository('WallabagCoreBundle:Entry') 95 ->getRepository('WallabagCoreBundle:Entry')
96 ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag['id']); 96 ->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag->getId());
97 97
98 $flatTags[] = [ 98 $flatTags[] = [
99 'id' => $tag['id'], 99 'id' => $tag->getId(),
100 'label' => $tag['label'], 100 'label' => $tag->getLabel(),
101 'slug' => $tag['slug'], 101 'slug' => $tag->getSlug(),
102 'nbEntries' => $nbEntries, 102 'nbEntries' => $nbEntries,
103 ]; 103 ];
104 } 104 }
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index f2da3f4d..dd0f7e67 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -19,7 +19,7 @@ use Wallabag\AnnotationBundle\Entity\Annotation;
19 * 19 *
20 * @XmlRoot("entry") 20 * @XmlRoot("entry")
21 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository") 21 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository")
22 * @ORM\Table(name="`entry`") 22 * @ORM\Table(name="`entry`", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"})
23 * @ORM\HasLifecycleCallbacks() 23 * @ORM\HasLifecycleCallbacks()
24 * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())") 24 * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
25 */ 25 */
@@ -190,10 +190,10 @@ class Entry
190 * @ORM\JoinTable( 190 * @ORM\JoinTable(
191 * name="entry_tag", 191 * name="entry_tag",
192 * joinColumns={ 192 * joinColumns={
193 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id") 193 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
194 * }, 194 * },
195 * inverseJoinColumns={ 195 * inverseJoinColumns={
196 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id") 196 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="cascade")
197 * } 197 * }
198 * ) 198 * )
199 */ 199 */
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
index cd2b47b9..14616d88 100644
--- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
@@ -329,4 +329,18 @@ class EntryRepository extends EntityRepository
329 329
330 return $qb->getQuery()->getSingleScalarResult(); 330 return $qb->getQuery()->getSingleScalarResult();
331 } 331 }
332
333 /**
334 * Remove all entries for a user id.
335 * Used when a user want to reset all informations.
336 *
337 * @param int $userId
338 */
339 public function removeAllByUserId($userId)
340 {
341 $this->getEntityManager()
342 ->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId')
343 ->setParameter('userId', $userId)
344 ->execute();
345 }
332} 346}
diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php
index e76878d4..81445989 100644
--- a/src/Wallabag/CoreBundle/Repository/TagRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php
@@ -34,6 +34,9 @@ class TagRepository extends EntityRepository
34 34
35 /** 35 /**
36 * Find all tags per user. 36 * Find all tags per user.
37 * Instead of just left joined on the Entry table, we select only id and group by id to avoid tag multiplication in results.
38 * Once we have all tags id, we can safely request them one by one.
39 * This'll still be fastest than the previous query.
37 * 40 *
38 * @param int $userId 41 * @param int $userId
39 * 42 *
@@ -41,15 +44,20 @@ class TagRepository extends EntityRepository
41 */ 44 */
42 public function findAllTags($userId) 45 public function findAllTags($userId)
43 { 46 {
44 return $this->createQueryBuilder('t') 47 $ids = $this->createQueryBuilder('t')
45 ->select('t.slug', 't.label', 't.id') 48 ->select('t.id')
46 ->leftJoin('t.entries', 'e') 49 ->leftJoin('t.entries', 'e')
47 ->where('e.user = :userId')->setParameter('userId', $userId) 50 ->where('e.user = :userId')->setParameter('userId', $userId)
48 ->groupBy('t.slug') 51 ->groupBy('t.id')
49 ->addGroupBy('t.label')
50 ->addGroupBy('t.id')
51 ->getQuery() 52 ->getQuery()
52 ->getArrayResult(); 53 ->getArrayResult();
54
55 $tags = [];
56 foreach ($ids as $id) {
57 $tags[] = $this->find($id);
58 }
59
60 return $tags;
53 } 61 }
54 62
55 /** 63 /**
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index a4b727f4..048a72fc 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -129,3 +129,10 @@ services:
129 arguments: 129 arguments:
130 - '@twig' 130 - '@twig'
131 - '%kernel.debug%' 131 - '%kernel.debug%'
132
133 wallabag_core.subscriber.sqlite_cascade_delete:
134 class: Wallabag\CoreBundle\Subscriber\SQLiteCascadeDeleteSubscriber
135 arguments:
136 - "@doctrine"
137 tags:
138 - { name: doctrine.event_subscriber }
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index f5548a21..7c8ae66e 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'Emailadresse' 89 email_label: 'Emailadresse'
90 # twoFactorAuthentication_label: 'Two factor authentication' 90 # twoFactorAuthentication_label: 'Two factor authentication'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Gammel adgangskode' 104 old_password_label: 'Gammel adgangskode'
98 new_password_label: 'Ny adgangskode' 105 new_password_label: 'Ny adgangskode'
@@ -462,6 +469,9 @@ flashes:
462 # tagging_rules_deleted: 'Tagging rule deleted' 469 # tagging_rules_deleted: 'Tagging rule deleted'
463 # user_added: 'User "%username%" added' 470 # user_added: 'User "%username%" added'
464 # rss_token_updated: 'RSS token updated' 471 # rss_token_updated: 'RSS token updated'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 # entry_already_saved: 'Entry already saved on %date%' 477 # entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index 9edd7fb7..20f9753b 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'E-Mail-Adresse' 89 email_label: 'E-Mail-Adresse'
90 twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung' 90 twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Altes Kennwort' 104 old_password_label: 'Altes Kennwort'
98 new_password_label: 'Neues Kennwort' 105 new_password_label: 'Neues Kennwort'
@@ -462,6 +469,9 @@ flashes:
462 tagging_rules_deleted: 'Tagging-Regel gelöscht' 469 tagging_rules_deleted: 'Tagging-Regel gelöscht'
463 user_added: 'Benutzer "%username%" erstellt' 470 user_added: 'Benutzer "%username%" erstellt'
464 rss_token_updated: 'RSS-Token aktualisiert' 471 rss_token_updated: 'RSS-Token aktualisiert'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Eintrag bereits am %date% gespeichert' 477 entry_already_saved: 'Eintrag bereits am %date% gespeichert'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index b86145a0..35dde535 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'Email' 89 email_label: 'Email'
90 twoFactorAuthentication_label: 'Two factor authentication' 90 twoFactorAuthentication_label: 'Two factor authentication'
91 delete: 91 delete:
92 title: Delete my account (danger zone !) 92 title: Delete my account (a.k.a danger zone)
93 description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 confirm: Are you really sure? (it can't be UNDONE) 94 confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 button: Delete my account 95 button: Delete my account
96 reset:
97 title: Reset area (a.k.a danger zone)
98 description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 annotations: Remove ALL annotations
100 tags: Remove ALL tags
101 entries: Remove ALL entries
102 confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Current password' 104 old_password_label: 'Current password'
98 new_password_label: 'New password' 105 new_password_label: 'New password'
@@ -461,6 +468,9 @@ flashes:
461 tagging_rules_updated: 'Tagging rules updated' 468 tagging_rules_updated: 'Tagging rules updated'
462 tagging_rules_deleted: 'Tagging rule deleted' 469 tagging_rules_deleted: 'Tagging rule deleted'
463 rss_token_updated: 'RSS token updated' 470 rss_token_updated: 'RSS token updated'
471 annotations_reset: Annotations reset
472 tags_reset: Tags reset
473 entries_reset: Entries reset
464 entry: 474 entry:
465 notice: 475 notice:
466 entry_already_saved: 'Entry already saved on %date%' 476 entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index b7187f50..13f2e977 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'Direccion e-mail' 89 email_label: 'Direccion e-mail'
90 twoFactorAuthentication_label: 'Autentificación de dos factores' 90 twoFactorAuthentication_label: 'Autentificación de dos factores'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Contraseña actual' 104 old_password_label: 'Contraseña actual'
98 new_password_label: 'Nueva contraseña' 105 new_password_label: 'Nueva contraseña'
@@ -462,6 +469,9 @@ flashes:
462 tagging_rules_deleted: 'Regla de etiquetado actualizada' 469 tagging_rules_deleted: 'Regla de etiquetado actualizada'
463 user_added: 'Usuario "%username%" añadido' 470 user_added: 'Usuario "%username%" añadido'
464 rss_token_updated: 'RSS token actualizado' 471 rss_token_updated: 'RSS token actualizado'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Entrada ya guardada por %fecha%' 477 entry_already_saved: 'Entrada ya guardada por %fecha%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 0751752b..5ee1f62d 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'نشانی ایمیل' 89 email_label: 'نشانی ایمیل'
90 twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای' 90 twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'رمز قدیمی' 104 old_password_label: 'رمز قدیمی'
98 new_password_label: 'رمز تازه' 105 new_password_label: 'رمز تازه'
@@ -461,6 +468,9 @@ flashes:
461 tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد' 468 tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد'
462 user_added: 'کابر "%username%" افزوده شد' 469 user_added: 'کابر "%username%" افزوده شد'
463 rss_token_updated: 'کد آر-اس-اس به‌روز شد' 470 rss_token_updated: 'کد آر-اس-اس به‌روز شد'
471 # annotations_reset: Annotations reset
472 # tags_reset: Tags reset
473 # entries_reset: Entries reset
464 entry: 474 entry:
465 notice: 475 notice:
466 entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' 476 entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index 8d19ccb1..14bdbbc7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -91,8 +91,15 @@ config:
91 delete: 91 delete:
92 title: Supprimer mon compte (attention danger !) 92 title: Supprimer mon compte (attention danger !)
93 description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté. 93 description: Si vous confirmez la suppression de votre compte, TOUS les articles, TOUS les tags, TOUTES les annotations et votre compte seront DÉFINITIVEMENT supprimé (c'est IRRÉVERSIBLE). Vous serez ensuite déconnecté.
94 confirm: Vous êtes vraiment sûr ? (c'est IRRÉVERSIBLE !) 94 confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE)
95 button: 'Supprimer mon compte' 95 button: 'Supprimer mon compte'
96 reset:
97 title: Réinitialisation (attention danger !)
98 description: En cliquant sur les boutons ci-dessous vous avez la possibilité de supprimer certaines informations de votre compte. Attention, ces actions sont IRRÉVERSIBLES !
99 annotations: Supprimer TOUTES les annotations
100 tags: Supprimer TOUS les tags
101 entries: Supprimer TOUS les articles
102 confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
96 form_password: 103 form_password:
97 old_password_label: 'Mot de passe actuel' 104 old_password_label: 'Mot de passe actuel'
98 new_password_label: 'Nouveau mot de passe' 105 new_password_label: 'Nouveau mot de passe'
@@ -391,7 +398,7 @@ developer:
391 field_grant_types: 'Type de privilège accordé' 398 field_grant_types: 'Type de privilège accordé'
392 no_client: 'Aucun client pour le moment' 399 no_client: 'Aucun client pour le moment'
393 remove: 400 remove:
394 warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRREVERSIBLE !' 401 warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !'
395 warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag." 402 warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag."
396 action: 'Supprimer le client %name%' 403 action: 'Supprimer le client %name%'
397 client: 404 client:
@@ -462,9 +469,12 @@ flashes:
462 tagging_rules_deleted: 'Règle supprimée' 469 tagging_rules_deleted: 'Règle supprimée'
463 user_added: 'Utilisateur "%username%" ajouté' 470 user_added: 'Utilisateur "%username%" ajouté'
464 rss_token_updated: 'Jeton RSS mis à jour' 471 rss_token_updated: 'Jeton RSS mis à jour'
472 annotations_reset: Annotations supprimées
473 tags_reset: Tags supprimés
474 entries_reset: Articles supprimés
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Article déjà sauvergardé le %date%' 477 entry_already_saved: 'Article déjà sauvegardé le %date%'
468 entry_saved: 'Article enregistré' 478 entry_saved: 'Article enregistré'
469 entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu' 479 entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu'
470 entry_updated: 'Article mis à jour' 480 entry_updated: 'Article mis à jour'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index 4d3452ea..bc4448bd 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'E-mail' 89 email_label: 'E-mail'
90 twoFactorAuthentication_label: 'Two factor authentication' 90 twoFactorAuthentication_label: 'Two factor authentication'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Password corrente' 104 old_password_label: 'Password corrente'
98 new_password_label: 'Nuova password' 105 new_password_label: 'Nuova password'
@@ -462,6 +469,9 @@ flashes:
462 tagging_rules_deleted: 'Regola di tagging aggiornate' 469 tagging_rules_deleted: 'Regola di tagging aggiornate'
463 user_added: 'Utente "%username%" aggiunto' 470 user_added: 'Utente "%username%" aggiunto'
464 rss_token_updated: 'RSS token aggiornato' 471 rss_token_updated: 'RSS token aggiornato'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Contenuto già salvato in data %date%' 477 entry_already_saved: 'Contenuto già salvato in data %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index f14213c6..7d1a801a 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'Adreça de corrièl' 89 email_label: 'Adreça de corrièl'
90 twoFactorAuthentication_label: 'Dobla autentificacion' 90 twoFactorAuthentication_label: 'Dobla autentificacion'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Senhal actual' 104 old_password_label: 'Senhal actual'
98 new_password_label: 'Senhal novèl' 105 new_password_label: 'Senhal novèl'
@@ -462,6 +469,9 @@ flashes:
462 tagging_rules_deleted: 'Règla suprimida' 469 tagging_rules_deleted: 'Règla suprimida'
463 user_added: 'Utilizaire "%username%" ajustat' 470 user_added: 'Utilizaire "%username%" ajustat'
464 rss_token_updated: 'Geton RSS mes a jorn' 471 rss_token_updated: 'Geton RSS mes a jorn'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Article ja salvargardat lo %date%' 477 entry_already_saved: 'Article ja salvargardat lo %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index 6f22f90d..b05a9dfd 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -93,6 +93,13 @@ config:
93 description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany. 93 description: Jeżeli usuniesz swoje konto, wszystkie twoje artykuły, tagi, adnotacje, oraz konto zostaną trwale usunięte (operacja jest NIEODWRACALNA). Następnie zostaniesz wylogowany.
94 confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć) 94 confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
95 button: Usuń moje konto 95 button: Usuń moje konto
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Stare hasło' 104 old_password_label: 'Stare hasło'
98 new_password_label: 'Nowe hasło' 105 new_password_label: 'Nowe hasło'
@@ -462,6 +469,9 @@ flashes:
462 tagging_rules_deleted: 'Reguła tagowania usunięta' 469 tagging_rules_deleted: 'Reguła tagowania usunięta'
463 user_added: 'Użytkownik "%username%" dodany' 470 user_added: 'Użytkownik "%username%" dodany'
464 rss_token_updated: 'Token kanału RSS zaktualizowany' 471 rss_token_updated: 'Token kanału RSS zaktualizowany'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 entry_already_saved: 'Wpis już został dodany %date%' 477 entry_already_saved: 'Wpis już został dodany %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index 29db9c3e..571452c0 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'E-mail' 89 email_label: 'E-mail'
90 # twoFactorAuthentication_label: 'Two factor authentication' 90 # twoFactorAuthentication_label: 'Two factor authentication'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Parola veche' 104 old_password_label: 'Parola veche'
98 new_password_label: 'Parola nouă' 105 new_password_label: 'Parola nouă'
@@ -462,6 +469,9 @@ flashes:
462 # tagging_rules_deleted: 'Tagging rule deleted' 469 # tagging_rules_deleted: 'Tagging rule deleted'
463 # user_added: 'User "%username%" added' 470 # user_added: 'User "%username%" added'
464 # rss_token_updated: 'RSS token updated' 471 # rss_token_updated: 'RSS token updated'
472 # annotations_reset: Annotations reset
473 # tags_reset: Tags reset
474 # entries_reset: Entries reset
465 entry: 475 entry:
466 notice: 476 notice:
467 # entry_already_saved: 'Entry already saved on %date%' 477 # entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index 41e8e576..8e429653 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -89,10 +89,17 @@ config:
89 email_label: 'E-posta' 89 email_label: 'E-posta'
90 twoFactorAuthentication_label: 'İki adımlı doğrulama' 90 twoFactorAuthentication_label: 'İki adımlı doğrulama'
91 delete: 91 delete:
92 # title: Delete my account (danger zone !) 92 # title: Delete my account (a.k.a danger zone)
93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out. 93 # description: If you remove your account, ALL your articles, ALL your tags, ALL your annotations and your account will be PERMANENTLY removed (it can't be UNDONE). You'll then be logged out.
94 # confirm: Are you really sure? (it can't be UNDONE) 94 # confirm: Are you really sure? (THIS CAN'T BE UNDONE)
95 # button: Delete my account 95 # button: Delete my account
96 reset:
97 # title: Reset area (a.k.a danger zone)
98 # description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
99 # annotations: Remove ALL annotations
100 # tags: Remove ALL tags
101 # entries: Remove ALL entries
102 # confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
96 form_password: 103 form_password:
97 old_password_label: 'Eski şifre' 104 old_password_label: 'Eski şifre'
98 new_password_label: 'Yeni şifre' 105 new_password_label: 'Yeni şifre'
@@ -461,6 +468,9 @@ flashes:
461 tagging_rules_deleted: 'Tagging rule deleted' 468 tagging_rules_deleted: 'Tagging rule deleted'
462 user_added: 'User "%username%" added' 469 user_added: 'User "%username%" added'
463 rss_token_updated: 'RSS token updated' 470 rss_token_updated: 'RSS token updated'
471 # annotations_reset: Annotations reset
472 # tags_reset: Tags reset
473 # entries_reset: Entries reset
464 entry: 474 entry:
465 notice: 475 notice:
466 entry_already_saved: 'Entry already saved on %date%' 476 entry_already_saved: 'Entry already saved on %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
index 54508b6d..455d0295 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig
@@ -146,6 +146,28 @@
146 </fieldset> 146 </fieldset>
147 {% endif %} 147 {% endif %}
148 148
149 <h2>{{ 'config.reset.title'|trans }}</h2>
150 <fieldset class="w500p inline">
151 <p>{{ 'config.reset.description'|trans }}</p>
152 <ul>
153 <li>
154 <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
155 {{ 'config.reset.annotations'|trans }}
156 </a>
157 </li>
158 <li>
159 <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
160 {{ 'config.reset.tags'|trans }}
161 </a>
162 </li>
163 <li>
164 <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
165 {{ 'config.reset.entries'|trans }}
166 </a>
167 </li>
168 </ul>
169 </fieldset>
170
149 {{ form_widget(form.user._token) }} 171 {{ form_widget(form.user._token) }}
150 {{ form_widget(form.user.save) }} 172 {{ form_widget(form.user.save) }}
151 </form> 173 </form>
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
index 8434508d..79826e0f 100644
--- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig
@@ -168,6 +168,22 @@
168 {{ form_widget(form.user._token) }} 168 {{ form_widget(form.user._token) }}
169 </form> 169 </form>
170 170
171 <br /><hr /><br />
172
173 <div class="row">
174 <h5>{{ 'config.reset.title'|trans }}</h5>
175 <p>{{ 'config.reset.description'|trans }}</p>
176 <a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
177 {{ 'config.reset.annotations'|trans }}
178 </a>
179 <a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
180 {{ 'config.reset.tags'|trans }}
181 </a>
182 <a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
183 {{ 'config.reset.entries'|trans }}
184 </a>
185 </div>
186
171 {% if enabled_users > 1 %} 187 {% if enabled_users > 1 %}
172 <br /><hr /><br /> 188 <br /><hr /><br />
173 189
diff --git a/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php
new file mode 100644
index 00000000..f7210bd3
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Subscriber/SQLiteCascadeDeleteSubscriber.php
@@ -0,0 +1,70 @@
1<?php
2
3namespace Wallabag\CoreBundle\Subscriber;
4
5use Doctrine\Common\EventSubscriber;
6use Doctrine\ORM\Event\LifecycleEventArgs;
7use Wallabag\CoreBundle\Entity\Entry;
8use Doctrine\Bundle\DoctrineBundle\Registry;
9
10/**
11 * SQLite doesn't care about cascading remove, so we need to manually remove associated stuf for an Entry.
12 * Foreign Key Support can be enabled by running `PRAGMA foreign_keys = ON;` at runtime (AT RUNTIME !).
13 * But it needs a compilation flag that not all SQLite instance has ...
14 *
15 * @see https://www.sqlite.org/foreignkeys.html#fk_enable
16 */
17class SQLiteCascadeDeleteSubscriber implements EventSubscriber
18{
19 private $doctrine;
20
21 /**
22 * @param \Doctrine\Bundle\DoctrineBundle\Registry $doctrine
23 */
24 public function __construct(Registry $doctrine)
25 {
26 $this->doctrine = $doctrine;
27 }
28
29 /**
30 * @return array
31 */
32 public function getSubscribedEvents()
33 {
34 return [
35 'preRemove',
36 ];
37 }
38
39 /**
40 * We removed everything related to the upcoming removed entry because SQLite can't handle it on it own.
41 * We do it in the preRemove, because we can't retrieve tags in the postRemove (because the entry id is gone).
42 *
43 * @param LifecycleEventArgs $args
44 */
45 public function preRemove(LifecycleEventArgs $args)
46 {
47 $entity = $args->getEntity();
48
49 if (!$this->doctrine->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver ||
50 !$entity instanceof Entry) {
51 return;
52 }
53
54 $em = $this->doctrine->getManager();
55
56 if (null !== $entity->getTags()) {
57 foreach ($entity->getTags() as $tag) {
58 $entity->removeTag($tag);
59 }
60 }
61
62 if (null !== $entity->getAnnotations()) {
63 foreach ($entity->getAnnotations() as $annotation) {
64 $em->remove($annotation);
65 }
66 }
67
68 $em->flush();
69 }
70}
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml
index eb9c8e67..8062e53f 100644
--- a/src/Wallabag/UserBundle/Resources/config/services.yml
+++ b/src/Wallabag/UserBundle/Resources/config/services.yml
@@ -21,7 +21,7 @@ services:
21 arguments: 21 arguments:
22 - WallabagUserBundle:User 22 - WallabagUserBundle:User
23 23
24 wallabag_user.create_config: 24 wallabag_user.listener.create_config:
25 class: Wallabag\UserBundle\EventListener\CreateConfigListener 25 class: Wallabag\UserBundle\EventListener\CreateConfigListener
26 arguments: 26 arguments:
27 - "@doctrine.orm.entity_manager" 27 - "@doctrine.orm.entity_manager"
diff --git a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
index 5faa0130..8d0644d1 100644
--- a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
@@ -5,6 +5,9 @@ namespace Tests\Wallabag\CoreBundle\Controller;
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Wallabag\CoreBundle\Entity\Config; 6use Wallabag\CoreBundle\Entity\Config;
7use Wallabag\UserBundle\Entity\User; 7use Wallabag\UserBundle\Entity\User;
8use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\CoreBundle\Entity\Tag;
10use Wallabag\AnnotationBundle\Entity\Annotation;
8 11
9class ConfigControllerTest extends WallabagCoreTestCase 12class ConfigControllerTest extends WallabagCoreTestCase
10{ 13{
@@ -690,4 +693,146 @@ class ConfigControllerTest extends WallabagCoreTestCase
690 693
691 $this->assertEmpty($entries); 694 $this->assertEmpty($entries);
692 } 695 }
696
697 public function testReset()
698 {
699 $this->logInAs('empty');
700 $client = $this->getClient();
701
702 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
703
704 $user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
705
706 $tag = new Tag();
707 $tag->setLabel('super');
708 $em->persist($tag);
709
710 $entry = new Entry($user);
711 $entry->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
712 $entry->setContent('Youhou');
713 $entry->setTitle('Youhou');
714 $entry->addTag($tag);
715 $em->persist($entry);
716
717 $entry2 = new Entry($user);
718 $entry2->setUrl('http://www.lemonde.de/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
719 $entry2->setContent('Youhou');
720 $entry2->setTitle('Youhou');
721 $entry2->addTag($tag);
722 $em->persist($entry2);
723
724 $annotation = new Annotation($user);
725 $annotation->setText('annotated');
726 $annotation->setQuote('annotated');
727 $annotation->setRanges([]);
728 $annotation->setEntry($entry);
729 $em->persist($annotation);
730
731 $em->flush();
732
733 // reset annotations
734 $crawler = $client->request('GET', '/config#set3');
735
736 $this->assertEquals(200, $client->getResponse()->getStatusCode());
737
738 $crawler = $client->click($crawler->selectLink('config.reset.annotations')->link());
739
740 $this->assertEquals(302, $client->getResponse()->getStatusCode());
741 $this->assertContains('flashes.config.notice.annotations_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
742
743 $annotationsReset = $em
744 ->getRepository('WallabagAnnotationBundle:Annotation')
745 ->findAnnotationsByPageId($entry->getId(), $user->getId());
746
747 $this->assertEmpty($annotationsReset, 'Annotations were reset');
748
749 // reset tags
750 $crawler = $client->request('GET', '/config#set3');
751
752 $this->assertEquals(200, $client->getResponse()->getStatusCode());
753
754 $crawler = $client->click($crawler->selectLink('config.reset.tags')->link());
755
756 $this->assertEquals(302, $client->getResponse()->getStatusCode());
757 $this->assertContains('flashes.config.notice.tags_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
758
759 $tagReset = $em
760 ->getRepository('WallabagCoreBundle:Tag')
761 ->countAllTags($user->getId());
762
763 $this->assertEquals(0, $tagReset, 'Tags were reset');
764
765 // reset entries
766 $crawler = $client->request('GET', '/config#set3');
767
768 $this->assertEquals(200, $client->getResponse()->getStatusCode());
769
770 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
771
772 $this->assertEquals(302, $client->getResponse()->getStatusCode());
773 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
774
775 $entryReset = $em
776 ->getRepository('WallabagCoreBundle:Entry')
777 ->countAllEntriesByUsername($user->getId());
778
779 $this->assertEquals(0, $entryReset, 'Entries were reset');
780 }
781
782 public function testResetEntriesCascade()
783 {
784 $this->logInAs('empty');
785 $client = $this->getClient();
786
787 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
788
789 $user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
790
791 $tag = new Tag();
792 $tag->setLabel('super');
793 $em->persist($tag);
794
795 $entry = new Entry($user);
796 $entry->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
797 $entry->setContent('Youhou');
798 $entry->setTitle('Youhou');
799 $entry->addTag($tag);
800 $em->persist($entry);
801
802 $annotation = new Annotation($user);
803 $annotation->setText('annotated');
804 $annotation->setQuote('annotated');
805 $annotation->setRanges([]);
806 $annotation->setEntry($entry);
807 $em->persist($annotation);
808
809 $em->flush();
810
811 $crawler = $client->request('GET', '/config#set3');
812
813 $this->assertEquals(200, $client->getResponse()->getStatusCode());
814
815 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
816
817 $this->assertEquals(302, $client->getResponse()->getStatusCode());
818 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
819
820 $entryReset = $em
821 ->getRepository('WallabagCoreBundle:Entry')
822 ->countAllEntriesByUsername($user->getId());
823
824 $this->assertEquals(0, $entryReset, 'Entries were reset');
825
826 $tagReset = $em
827 ->getRepository('WallabagCoreBundle:Tag')
828 ->countAllTags($user->getId());
829
830 $this->assertEquals(0, $tagReset, 'Tags were reset');
831
832 $annotationsReset = $em
833 ->getRepository('WallabagAnnotationBundle:Annotation')
834 ->findAnnotationsByPageId($entry->getId(), $user->getId());
835
836 $this->assertEmpty($annotationsReset, 'Annotations were reset');
837 }
693} 838}