Merge pull request #2401 from wallabag/reset-account

Reset account
This commit is contained in:
Jeremy Benoist 2016-10-24 11:57:51 +02:00 committed by GitHub
commit 9313ea9d44
39 changed files with 717 additions and 63 deletions

View file

@ -29,8 +29,12 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
*/
public function up(Schema $schema)
{
$this->addSql('ALTER TABLE `'.$this->getTable('entry').'` ADD `uuid` LONGTEXT DEFAULT NULL');
$this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry')");
if ($this->connection->getDatabasePlatform()->getName() == 'postgresql') {
$this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD uuid UUID DEFAULT NULL');
} else {
$this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD uuid LONGTEXT DEFAULT NULL');
}
$this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_public', '1', 'entry')");
}
/**
@ -40,7 +44,7 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
$this->addSql('ALTER TABLE `'.$this->getTable('entry').'` DROP `uuid`');
$this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'share_public'");
$this->addSql('ALTER TABLE '.$this->getTable('entry').' DROP uuid');
$this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'share_public'");
}
}

View file

@ -29,10 +29,17 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
*/
public function up(Schema $schema)
{
if ($this->connection->getDatabasePlatform()->getName() == 'sqlite') {
$this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL');
} else {
$this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL');
break;
case 'mysql':
$this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
break;
case 'postgresql':
$this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name text DEFAULT NULL');
}
}

View file

@ -29,8 +29,8 @@ class Version20160911214952 extends AbstractMigration implements ContainerAwareI
*/
public function up(Schema $schema)
{
$this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_redis\', \'0\', \'import\')');
$this->addSql('INSERT INTO `'.$this->getTable('craue_config_setting').'` (`name`, `value`, `section`) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')');
$this->addSql('INSERT INTO '.$this->getTable('craue_config_setting').' (name, value, section) VALUES (\'import_with_redis\', \'0\', \'import\')');
$this->addSql('INSERT INTO '.$this->getTable('craue_config_setting').' (name, value, section) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')');
}
/**

View file

@ -30,7 +30,7 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
public function up(Schema $schema)
{
$this->addSql('ALTER TABLE '.$this->getTable('config').' ADD pocket_consumer_key VARCHAR(255) DEFAULT NULL');
$this->addSql("DELETE FROM `".$this->getTable('craue_config_setting')."` WHERE `name` = 'pocket_consumer_key';");
$this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'pocket_consumer_key';");
}
/**
@ -40,7 +40,7 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
$this->addSql('ALTER TABLE `'.$this->getTable('config').'` DROP pocket_consumer_key');
$this->addSql("INSERT INTO `".$this->getTable('craue_config_setting')."` (`name`, `value`, `section`) VALUES ('pocket_consumer_key', NULL, 'import')");
$this->addSql('ALTER TABLE '.$this->getTable('config').' DROP pocket_consumer_key');
$this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('pocket_consumer_key', NULL, 'import')");
}
}

View file

@ -0,0 +1,63 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Version20161001072726 extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
private function getTable($tableName)
{
return $this->container->getParameter('database_table_prefix') . $tableName;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->skipIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
// remove all FK from entry_tag
$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()."'");
$query->execute();
foreach ($query->fetchAll() as $fk) {
$this->addSql('ALTER TABLE '.$this->getTable('entry_tag').' DROP FOREIGN KEY '.$fk['CONSTRAINT_NAME']);
}
$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');
$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');
// remove entry FK from annotation
$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()."'");
$query->execute();
foreach ($query->fetchAll() as $fk) {
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' DROP FOREIGN KEY '.$fk['CONSTRAINT_NAME']);
}
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES '.$this->getTable('entry').' (id) ON DELETE CASCADE');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
throw new SkipMigrationException('Too complex ...');
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Version20161022134138 extends AbstractMigration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
private function getTable($tableName)
{
return $this->container->getParameter('database_table_prefix') . $tableName;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
$this->skipIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'This migration only apply to MySQL');
$this->addSql('ALTER DATABASE '.$this->container->getParameter('database_name').' CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('tag').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('user').' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `quote` `quote` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `title` `title` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `content` `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('tag').' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$this->skipIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'This migration only apply to MySQL');
$this->addSql('ALTER DATABASE '.$this->container->getParameter('database_name').' CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('tag').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('user').' CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `text` `text` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('annotation').' CHANGE `quote` `quote` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `title` `title` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE `content` `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('tag').' CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
}
}

View file

@ -75,7 +75,7 @@ doctrine:
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
charset: "%database_charset%"
path: "%database_path%"
unix_socket: "%database_socket%"
server_version: 5.6

View file

@ -28,7 +28,7 @@ doctrine:
dbname: "%test_database_name%"
user: "%test_database_user%"
password: "%test_database_password%"
charset: UTF8
charset: "%test_database_charset%"
path: "%test_database_path%"
orm:
metadata_cache_driver:

View file

@ -19,16 +19,18 @@ parameters:
database_path: "%kernel.root_dir%/../data/db/wallabag.sqlite"
database_table_prefix: wallabag_
database_socket: null
# with MySQL, use "utf8mb4" if you got problem with content with emojis
database_charset: utf8
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: ~
mailer_password: ~
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: ~
mailer_password: ~
locale: en
locale: en
# A secret key that's used to generate certain security-related tokens
secret: ovmpmAWXRCabNlMgzlzFXDYmCFfzGv
secret: ovmpmAWXRCabNlMgzlzFXDYmCFfzGv
# two factor stuff
twofactor_auth: true

View file

@ -6,3 +6,4 @@ parameters:
test_database_user: null
test_database_password: null
test_database_path: '%kernel.root_dir%/../data/db/wallabag_test.sqlite'
test_database_charset: utf8

View file

@ -6,3 +6,4 @@ parameters:
test_database_user: root
test_database_password: ~
test_database_path: ~
test_database_charset: utf8mb4

View file

@ -6,3 +6,4 @@ parameters:
test_database_user: travis
test_database_password: ~
test_database_path: ~
test_database_charset: utf8

View file

@ -6,3 +6,4 @@ parameters:
test_database_user: ~
test_database_password: ~
test_database_path: "%kernel.root_dir%/../data/db/wallabag_test.sqlite"
test_database_charset: utf8

View file

@ -11,7 +11,8 @@ What is the meaning of the parameters?
"database_password", "~", "password of that user"
"database_path", "``""%kernel.root_dir%/../data/db/wallabag.sqlite""``", "only for SQLite, define where to put the database file. Leave it for other database"
"database_table_prefix", "wallabag_", "all wallabag's tables will be prefixed with that string. You can include a ``_`` for clarity"
"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"
"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)"
"database_charset", "utf8mb4", "For PostgreSQL & SQLite you should use utf8, for MySQL use utf8mb4 which handle emoji"
.. csv-table:: Configuration to send emails from wallabag
:header: "name", "default", "description"

View file

@ -82,7 +82,7 @@ class Annotation
* @Exclude
*
* @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry", inversedBy="annotations")
* @ORM\JoinColumn(name="entry_id", referencedColumnName="id")
* @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
*/
private $entry;

View file

@ -108,4 +108,18 @@ class AnnotationRepository extends EntityRepository
->getQuery()
->getSingleResult();
}
/**
* Remove all annotations for a user id.
* Used when a user want to reset all informations.
*
* @param int $userId
*/
public function removeAllByUserId($userId)
{
$this->getEntityManager()
->createQuery('DELETE FROM Wallabag\AnnotationBundle\Entity\Annotation a WHERE a.user = :userId')
->setParameter('userId', $userId)
->execute();
}
}

View file

@ -40,7 +40,7 @@ class InstallCommand extends ContainerAwareCommand
{
$this
->setName('wallabag:install')
->setDescription('Wallabag installer.')
->setDescription('wallabag installer.')
->addOption(
'reset',
null,
@ -55,7 +55,7 @@ class InstallCommand extends ContainerAwareCommand
$this->defaultInput = $input;
$this->defaultOutput = $output;
$output->writeln('<info>Installing Wallabag...</info>');
$output->writeln('<info>Installing wallabag...</info>');
$output->writeln('');
$this
@ -65,7 +65,7 @@ class InstallCommand extends ContainerAwareCommand
->setupConfig()
;
$output->writeln('<info>Wallabag has been successfully installed.</info>');
$output->writeln('<info>wallabag has been successfully installed.</info>');
$output->writeln('<comment>Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000</comment>');
}
@ -95,7 +95,8 @@ class InstallCommand extends ContainerAwareCommand
$help = '';
try {
$this->getContainer()->get('doctrine')->getManager()->getConnection()->connect();
$conn = $this->getContainer()->get('doctrine')->getManager()->getConnection();
$conn->connect();
} catch (\Exception $e) {
if (false === strpos($e->getMessage(), 'Unknown database')
&& false === strpos($e->getMessage(), 'database "'.$this->getContainer()->getParameter('database_name').'" does not exist')) {
@ -107,6 +108,21 @@ class InstallCommand extends ContainerAwareCommand
$rows[] = [$label, $status, $help];
// now check if MySQL isn't too old to handle utf8mb4
if ($conn->isConnected() && $conn->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MySqlPlatform) {
$version = $conn->query('select version()')->fetchColumn();
$minimalVersion = '5.5.4';
if (false === version_compare($version, $minimalVersion, '>')) {
$fulfilled = false;
$rows[] = [
'<comment>Database version</comment>',
'<error>ERROR!</error>',
'Your MySQL version ('.$version.') is too old, consider upgrading ('.$minimalVersion.'+).',
];
}
}
foreach ($this->functionExists as $functionRequired) {
$label = '<comment>'.$functionRequired.'</comment>';
$status = '<info>OK!</info>';
@ -131,7 +147,7 @@ class InstallCommand extends ContainerAwareCommand
throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.');
}
$this->defaultOutput->writeln('<info>Success! Your system can run Wallabag properly.</info>');
$this->defaultOutput->writeln('<info>Success! Your system can run wallabag properly.</info>');
$this->defaultOutput->writeln('');

View file

@ -224,6 +224,80 @@ class ConfigController extends Controller
return $this->redirect($this->generateUrl('config').'?tagging-rule='.$rule->getId().'#set5');
}
/**
* Remove all annotations OR tags OR entries for the current user.
*
* @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset")
*
* @return RedirectResponse
*/
public function resetAction($type)
{
$em = $this->getDoctrine()->getManager();
switch ($type) {
case 'annotations':
$this->getDoctrine()
->getRepository('WallabagAnnotationBundle:Annotation')
->removeAllByUserId($this->getUser()->getId());
break;
case 'tags':
$this->removeAllTagsByUserId($this->getUser()->getId());
break;
case 'entries':
// SQLite doesn't care about cascading remove, so we need to manually remove associated stuf
// otherwise they won't be removed ...
if ($this->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
$this->getDoctrine()->getRepository('WallabagAnnotationBundle:Annotation')->removeAllByUserId($this->getUser()->getId());
}
// manually remove tags to avoid orphan tag
$this->removeAllTagsByUserId($this->getUser()->getId());
$this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->removeAllByUserId($this->getUser()->getId());
}
$this->get('session')->getFlashBag()->add(
'notice',
'flashes.config.notice.'.$type.'_reset'
);
return $this->redirect($this->generateUrl('config').'#set3');
}
/**
* Remove all tags for a given user and cleanup orphan tags.
*
* @param int $userId
*/
private function removeAllTagsByUserId($userId)
{
$tags = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findAllTags($userId);
if (empty($tags)) {
return;
}
$this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->removeTags($userId, $tags);
// cleanup orphan tags
$em = $this->getDoctrine()->getManager();
foreach ($tags as $tag) {
if (count($tag->getEntries()) === 0) {
$em->remove($tag);
}
}
$em->flush();
}
/**
* Validate that a rule can be edited/deleted by the current user.
*

View file

@ -90,15 +90,15 @@ class TagController extends Controller
$flatTags = [];
foreach ($tags as $key => $tag) {
foreach ($tags as $tag) {
$nbEntries = $this->getDoctrine()
->getRepository('WallabagCoreBundle:Entry')
->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag['id']);
->countAllEntriesByUserIdAndTagId($this->getUser()->getId(), $tag->getId());
$flatTags[] = [
'id' => $tag['id'],
'label' => $tag['label'],
'slug' => $tag['slug'],
'id' => $tag->getId(),
'label' => $tag->getLabel(),
'slug' => $tag->getSlug(),
'nbEntries' => $nbEntries,
];
}

View file

@ -19,7 +19,7 @@ use Wallabag\AnnotationBundle\Entity\Annotation;
*
* @XmlRoot("entry")
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository")
* @ORM\Table(name="`entry`")
* @ORM\Table(name="`entry`", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"})
* @ORM\HasLifecycleCallbacks()
* @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
*/
@ -190,10 +190,10 @@ class Entry
* @ORM\JoinTable(
* name="entry_tag",
* joinColumns={
* @ORM\JoinColumn(name="entry_id", referencedColumnName="id")
* @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="cascade")
* }
* )
*/

View file

@ -329,4 +329,18 @@ class EntryRepository extends EntityRepository
return $qb->getQuery()->getSingleScalarResult();
}
/**
* Remove all entries for a user id.
* Used when a user want to reset all informations.
*
* @param int $userId
*/
public function removeAllByUserId($userId)
{
$this->getEntityManager()
->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.user = :userId')
->setParameter('userId', $userId)
->execute();
}
}

View file

@ -34,6 +34,9 @@ class TagRepository extends EntityRepository
/**
* Find all tags per user.
* Instead of just left joined on the Entry table, we select only id and group by id to avoid tag multiplication in results.
* Once we have all tags id, we can safely request them one by one.
* This'll still be fastest than the previous query.
*
* @param int $userId
*
@ -41,15 +44,20 @@ class TagRepository extends EntityRepository
*/
public function findAllTags($userId)
{
return $this->createQueryBuilder('t')
->select('t.slug', 't.label', 't.id')
$ids = $this->createQueryBuilder('t')
->select('t.id')
->leftJoin('t.entries', 'e')
->where('e.user = :userId')->setParameter('userId', $userId)
->groupBy('t.slug')
->addGroupBy('t.label')
->addGroupBy('t.id')
->groupBy('t.id')
->getQuery()
->getArrayResult();
$tags = [];
foreach ($ids as $id) {
$tags[] = $this->find($id);
}
return $tags;
}
/**

View file

@ -129,3 +129,10 @@ services:
arguments:
- '@twig'
- '%kernel.debug%'
wallabag_core.subscriber.sqlite_cascade_delete:
class: Wallabag\CoreBundle\Subscriber\SQLiteCascadeDeleteSubscriber
arguments:
- "@doctrine"
tags:
- { name: doctrine.event_subscriber }

View file

@ -89,10 +89,17 @@ config:
email_label: 'Emailadresse'
# twoFactorAuthentication_label: 'Two factor authentication'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Gammel adgangskode'
new_password_label: 'Ny adgangskode'
@ -462,6 +469,9 @@ flashes:
# tagging_rules_deleted: 'Tagging rule deleted'
# user_added: 'User "%username%" added'
# rss_token_updated: 'RSS token updated'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
# entry_already_saved: 'Entry already saved on %date%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'E-Mail-Adresse'
twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Altes Kennwort'
new_password_label: 'Neues Kennwort'
@ -462,6 +469,9 @@ flashes:
tagging_rules_deleted: 'Tagging-Regel gelöscht'
user_added: 'Benutzer "%username%" erstellt'
rss_token_updated: 'RSS-Token aktualisiert'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Eintrag bereits am %date% gespeichert'

View file

@ -89,10 +89,17 @@ config:
email_label: 'Email'
twoFactorAuthentication_label: 'Two factor authentication'
delete:
title: Delete my account (danger zone !)
title: Delete my account (a.k.a danger zone)
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.
confirm: Are you really sure? (it can't be UNDONE)
confirm: Are you really sure? (THIS CAN'T BE UNDONE)
button: Delete my account
reset:
title: Reset area (a.k.a danger zone)
description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
annotations: Remove ALL annotations
tags: Remove ALL tags
entries: Remove ALL entries
confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Current password'
new_password_label: 'New password'
@ -461,6 +468,9 @@ flashes:
tagging_rules_updated: 'Tagging rules updated'
tagging_rules_deleted: 'Tagging rule deleted'
rss_token_updated: 'RSS token updated'
annotations_reset: Annotations reset
tags_reset: Tags reset
entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Entry already saved on %date%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'Direccion e-mail'
twoFactorAuthentication_label: 'Autentificación de dos factores'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Contraseña actual'
new_password_label: 'Nueva contraseña'
@ -462,6 +469,9 @@ flashes:
tagging_rules_deleted: 'Regla de etiquetado actualizada'
user_added: 'Usuario "%username%" añadido'
rss_token_updated: 'RSS token actualizado'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Entrada ya guardada por %fecha%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'نشانی ایمیل'
twoFactorAuthentication_label: 'تأیید ۲مرحله‌ای'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'رمز قدیمی'
new_password_label: 'رمز تازه'
@ -461,6 +468,9 @@ flashes:
tagging_rules_deleted: 'قانون برچسب‌گذاری پاک شد'
user_added: 'کابر "%username%" افزوده شد'
rss_token_updated: 'کد آر-اس-اس به‌روز شد'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود'

View file

@ -91,8 +91,15 @@ config:
delete:
title: Supprimer mon compte (attention danger !)
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é.
confirm: Vous êtes vraiment sûr ? (c'est IRRÉVERSIBLE !)
confirm: Vous êtes vraiment sûr ? (C'EST IRRÉVERSIBLE)
button: 'Supprimer mon compte'
reset:
title: Réinitialisation (attention danger !)
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 !
annotations: Supprimer TOUTES les annotations
tags: Supprimer TOUS les tags
entries: Supprimer TOUS les articles
confirm: Êtes-vous vraiment vraiment sûr ? (C'EST IRRÉVERSIBLE)
form_password:
old_password_label: 'Mot de passe actuel'
new_password_label: 'Nouveau mot de passe'
@ -391,7 +398,7 @@ developer:
field_grant_types: 'Type de privilège accordé'
no_client: 'Aucun client pour le moment'
remove:
warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRREVERSIBLE !'
warn_message_1: 'Vous avez la possibilité de supprimer le client %name%. Cette action est IRRÉVERSIBLE !'
warn_message_2: "Si vous supprimez le client %name%, toutes les applications qui l'utilisaient ne fonctionneront plus avec votre compte wallabag."
action: 'Supprimer le client %name%'
client:
@ -462,9 +469,12 @@ flashes:
tagging_rules_deleted: 'Règle supprimée'
user_added: 'Utilisateur "%username%" ajouté'
rss_token_updated: 'Jeton RSS mis à jour'
annotations_reset: Annotations supprimées
tags_reset: Tags supprimés
entries_reset: Articles supprimés
entry:
notice:
entry_already_saved: 'Article déjà sauvergardé le %date%'
entry_already_saved: 'Article déjà sauvegardé le %date%'
entry_saved: 'Article enregistré'
entry_saved_failed: 'Article enregistré mais impossible de récupérer le contenu'
entry_updated: 'Article mis à jour'

View file

@ -89,10 +89,17 @@ config:
email_label: 'E-mail'
twoFactorAuthentication_label: 'Two factor authentication'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Password corrente'
new_password_label: 'Nuova password'
@ -462,6 +469,9 @@ flashes:
tagging_rules_deleted: 'Regola di tagging aggiornate'
user_added: 'Utente "%username%" aggiunto'
rss_token_updated: 'RSS token aggiornato'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Contenuto già salvato in data %date%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'Adreça de corrièl'
twoFactorAuthentication_label: 'Dobla autentificacion'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Senhal actual'
new_password_label: 'Senhal novèl'
@ -462,6 +469,9 @@ flashes:
tagging_rules_deleted: 'Règla suprimida'
user_added: 'Utilizaire "%username%" ajustat'
rss_token_updated: 'Geton RSS mes a jorn'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Article ja salvargardat lo %date%'

View file

@ -93,6 +93,13 @@ config:
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.
confirm: Jesteś pewien? (tej operacji NIE MOŻNA cofnąć)
button: Usuń moje konto
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Stare hasło'
new_password_label: 'Nowe hasło'
@ -462,6 +469,9 @@ flashes:
tagging_rules_deleted: 'Reguła tagowania usunięta'
user_added: 'Użytkownik "%username%" dodany'
rss_token_updated: 'Token kanału RSS zaktualizowany'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Wpis już został dodany %date%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'E-mail'
# twoFactorAuthentication_label: 'Two factor authentication'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Parola veche'
new_password_label: 'Parola nouă'
@ -462,6 +469,9 @@ flashes:
# tagging_rules_deleted: 'Tagging rule deleted'
# user_added: 'User "%username%" added'
# rss_token_updated: 'RSS token updated'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
# entry_already_saved: 'Entry already saved on %date%'

View file

@ -89,10 +89,17 @@ config:
email_label: 'E-posta'
twoFactorAuthentication_label: 'İki adımlı doğrulama'
delete:
# title: Delete my account (danger zone !)
# title: Delete my account (a.k.a danger zone)
# 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.
# confirm: Are you really sure? (it can't be UNDONE)
# confirm: Are you really sure? (THIS CAN'T BE UNDONE)
# button: Delete my account
reset:
# title: Reset area (a.k.a danger zone)
# description: By hiting buttons below you'll have ability to remove some informations from your account. Be aware that these actions are IRREVERSIBLE.
# annotations: Remove ALL annotations
# tags: Remove ALL tags
# entries: Remove ALL entries
# confirm: Are you really really sure? (THIS CAN'T BE UNDONE)
form_password:
old_password_label: 'Eski şifre'
new_password_label: 'Yeni şifre'
@ -461,6 +468,9 @@ flashes:
tagging_rules_deleted: 'Tagging rule deleted'
user_added: 'User "%username%" added'
rss_token_updated: 'RSS token updated'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Entry already saved on %date%'

View file

@ -146,6 +146,28 @@
</fieldset>
{% endif %}
<h2>{{ 'config.reset.title'|trans }}</h2>
<fieldset class="w500p inline">
<p>{{ 'config.reset.description'|trans }}</p>
<ul>
<li>
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.annotations'|trans }}
</a>
</li>
<li>
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.tags'|trans }}
</a>
</li>
<li>
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.entries'|trans }}
</a>
</li>
</ul>
</fieldset>
{{ form_widget(form.user._token) }}
{{ form_widget(form.user.save) }}
</form>

View file

@ -168,6 +168,22 @@
{{ form_widget(form.user._token) }}
</form>
<br /><hr /><br />
<div class="row">
<h5>{{ 'config.reset.title'|trans }}</h5>
<p>{{ 'config.reset.description'|trans }}</p>
<a href="{{ path('config_reset', { type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.annotations'|trans }}
</a>
<a href="{{ path('config_reset', { type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.tags'|trans }}
</a>
<a href="{{ path('config_reset', { type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.entries'|trans }}
</a>
</div>
{% if enabled_users > 1 %}
<br /><hr /><br />

View file

@ -0,0 +1,70 @@
<?php
namespace Wallabag\CoreBundle\Subscriber;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Wallabag\CoreBundle\Entity\Entry;
use Doctrine\Bundle\DoctrineBundle\Registry;
/**
* SQLite doesn't care about cascading remove, so we need to manually remove associated stuf for an Entry.
* Foreign Key Support can be enabled by running `PRAGMA foreign_keys = ON;` at runtime (AT RUNTIME !).
* But it needs a compilation flag that not all SQLite instance has ...
*
* @see https://www.sqlite.org/foreignkeys.html#fk_enable
*/
class SQLiteCascadeDeleteSubscriber implements EventSubscriber
{
private $doctrine;
/**
* @param \Doctrine\Bundle\DoctrineBundle\Registry $doctrine
*/
public function __construct(Registry $doctrine)
{
$this->doctrine = $doctrine;
}
/**
* @return array
*/
public function getSubscribedEvents()
{
return [
'preRemove',
];
}
/**
* We removed everything related to the upcoming removed entry because SQLite can't handle it on it own.
* We do it in the preRemove, because we can't retrieve tags in the postRemove (because the entry id is gone).
*
* @param LifecycleEventArgs $args
*/
public function preRemove(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!$this->doctrine->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver ||
!$entity instanceof Entry) {
return;
}
$em = $this->doctrine->getManager();
if (null !== $entity->getTags()) {
foreach ($entity->getTags() as $tag) {
$entity->removeTag($tag);
}
}
if (null !== $entity->getAnnotations()) {
foreach ($entity->getAnnotations() as $annotation) {
$em->remove($annotation);
}
}
$em->flush();
}
}

View file

@ -21,7 +21,7 @@ services:
arguments:
- WallabagUserBundle:User
wallabag_user.create_config:
wallabag_user.listener.create_config:
class: Wallabag\UserBundle\EventListener\CreateConfigListener
arguments:
- "@doctrine.orm.entity_manager"

View file

@ -5,6 +5,9 @@ namespace Tests\Wallabag\CoreBundle\Controller;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Wallabag\CoreBundle\Entity\Config;
use Wallabag\UserBundle\Entity\User;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\AnnotationBundle\Entity\Annotation;
class ConfigControllerTest extends WallabagCoreTestCase
{
@ -690,4 +693,146 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertEmpty($entries);
}
public function testReset()
{
$this->logInAs('empty');
$client = $this->getClient();
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
$tag = new Tag();
$tag->setLabel('super');
$em->persist($tag);
$entry = new Entry($user);
$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');
$entry->setContent('Youhou');
$entry->setTitle('Youhou');
$entry->addTag($tag);
$em->persist($entry);
$entry2 = new Entry($user);
$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');
$entry2->setContent('Youhou');
$entry2->setTitle('Youhou');
$entry2->addTag($tag);
$em->persist($entry2);
$annotation = new Annotation($user);
$annotation->setText('annotated');
$annotation->setQuote('annotated');
$annotation->setRanges([]);
$annotation->setEntry($entry);
$em->persist($annotation);
$em->flush();
// reset annotations
$crawler = $client->request('GET', '/config#set3');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$crawler = $client->click($crawler->selectLink('config.reset.annotations')->link());
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertContains('flashes.config.notice.annotations_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
$annotationsReset = $em
->getRepository('WallabagAnnotationBundle:Annotation')
->findAnnotationsByPageId($entry->getId(), $user->getId());
$this->assertEmpty($annotationsReset, 'Annotations were reset');
// reset tags
$crawler = $client->request('GET', '/config#set3');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$crawler = $client->click($crawler->selectLink('config.reset.tags')->link());
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertContains('flashes.config.notice.tags_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
$tagReset = $em
->getRepository('WallabagCoreBundle:Tag')
->countAllTags($user->getId());
$this->assertEquals(0, $tagReset, 'Tags were reset');
// reset entries
$crawler = $client->request('GET', '/config#set3');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
$entryReset = $em
->getRepository('WallabagCoreBundle:Entry')
->countAllEntriesByUsername($user->getId());
$this->assertEquals(0, $entryReset, 'Entries were reset');
}
public function testResetEntriesCascade()
{
$this->logInAs('empty');
$client = $this->getClient();
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
$tag = new Tag();
$tag->setLabel('super');
$em->persist($tag);
$entry = new Entry($user);
$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');
$entry->setContent('Youhou');
$entry->setTitle('Youhou');
$entry->addTag($tag);
$em->persist($entry);
$annotation = new Annotation($user);
$annotation->setText('annotated');
$annotation->setQuote('annotated');
$annotation->setRanges([]);
$annotation->setEntry($entry);
$em->persist($annotation);
$em->flush();
$crawler = $client->request('GET', '/config#set3');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
$this->assertEquals(302, $client->getResponse()->getStatusCode());
$this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
$entryReset = $em
->getRepository('WallabagCoreBundle:Entry')
->countAllEntriesByUsername($user->getId());
$this->assertEquals(0, $entryReset, 'Entries were reset');
$tagReset = $em
->getRepository('WallabagCoreBundle:Tag')
->countAllTags($user->getId());
$this->assertEquals(0, $tagReset, 'Tags were reset');
$annotationsReset = $em
->getRepository('WallabagAnnotationBundle:Annotation')
->findAnnotationsByPageId($entry->getId(), $user->getId());
$this->assertEmpty($annotationsReset, 'Annotations were reset');
}
}