From: Jeremy Benoist
Date: Thu, 26 Jan 2017 12:32:07 +0000 (+0100)
Subject: Merge remote-tracking branch 'origin/master' into 2.2
X-Git-Tag: 2.2.0~3^2
X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=refs%2Fpull%2F2416%2Fhead;hp=05fa529bcfde01be5d320cb532900d72cf4b0830;p=github%2Fwallabag%2Fwallabag.git
Merge remote-tracking branch 'origin/master' into 2.2
---
diff --git a/.editorconfig b/.editorconfig
index d4ef7349..92c9a4c3 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,6 +9,6 @@ indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
-[*.css]
+[*.{js,css}]
indent_style = space
indent_size = 2
diff --git a/.eslintrc.json b/.eslintrc.json
index 1137e2fc..3aee614f 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -2,7 +2,11 @@
"extends": "airbnb-base",
"parser": "babel-eslint",
"env": {
- "browser": true
+ "browser": true,
+ "es6": true
+ },
+ "globals": {
+ "Routing": true
},
"rules": {
"import/no-extraneous-dependencies": ["error", {"devDependencies": true, "optionalDependencies": true, "peerDependencies": true}]
diff --git a/.gitignore b/.gitignore
index 32b0fbbb..84fb95d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,8 @@ web/uploads/
!web/bundles
web/bundles/*
!web/bundles/wallabagcore
+/web/assets/images/*
+!web/assets/images/.gitkeep
# Build
/app/build
@@ -34,7 +36,6 @@ web/bundles/*
/composer.phar
# Data for wallabag
-data/assets/*
data/db/wallabag*.sqlite
# Docker container logs and data
diff --git a/.travis.yml b/.travis.yml
index a8f6a744..8c8093bf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,7 +57,6 @@ before_script:
- if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi;
# xdebug isn't enable for PHP 7.1
- if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi
- - if [[ $PHP = 5.5 ]]; then composer require "phpunit/phpunit:4.*" --no-update; fi;
- composer self-update --no-progress
- if [[ $DB = pgsql ]]; then psql -c 'create database wallabag_test;' -U postgres; fi;
@@ -72,9 +71,9 @@ before_install:
script:
- travis_wait bash composer install -o --no-interaction --no-progress --prefer-dist
- ant prepare-$DB
- - if [[ $VALIDATE_TRANSLATION_FILE = '' ]]; then phpunit -v ; fi;
+ - if [[ $VALIDATE_TRANSLATION_FILE = '' ]]; then ./bin/simple-phpunit -v ; fi;
- if [[ $CS_FIXER = run ]]; then php bin/php-cs-fixer fix src/ --verbose --dry-run ; fi;
- if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v ; fi;
- if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml app/Resources/CraueConfigBundle/translations -v ; fi;
- - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml app/Resources/FOSUserBundle/translations -v ; fi;
+ - if [[ $VALIDATE_TRANSLATION_FILE = run ]]; then php bin/console lint:yaml src/Wallabag/UserBundle/Resources/translations -v ; fi;
- if [[ $ASSETS = build ]]; then ./node_modules/grunt-cli/bin/grunt tests; fi;
diff --git a/Makefile b/Makefile
index 83c5f37a..b3335261 100755
--- a/Makefile
+++ b/Makefile
@@ -27,8 +27,7 @@ build: ## Run grunt
@grunt
test: ## Launch wallabag testsuite
- @if [ ! -d "vendor/phpunit" ]; then composer install; fi
- @ant prepare && vendor/phpunit/phpunit/phpunit -v
+ @ant prepare && bin/simple-phpunit -v
release: ## Create a package. Need a VERSION parameter (eg: `make release VERSION=master`).
ifndef VERSION
diff --git a/app/AppKernel.php b/app/AppKernel.php
index 52f85558..c8382d5f 100644
--- a/app/AppKernel.php
+++ b/app/AppKernel.php
@@ -29,8 +29,9 @@ class AppKernel extends Kernel
new KPhoen\RulerZBundle\KPhoenRulerZBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
new Craue\ConfigBundle\CraueConfigBundle(),
- new Lexik\Bundle\MaintenanceBundle\LexikMaintenanceBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
+ new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
+ new BD\GuzzleSiteAuthenticatorBundle\BDGuzzleSiteAuthenticatorBundle(),
// wallabag bundles
new Wallabag\CoreBundle\WallabagCoreBundle(),
diff --git a/app/DoctrineMigrations/Version20160410190541.php b/app/DoctrineMigrations/Version20160410190541.php
index f034b0e4..ebf4135f 100644
--- a/app/DoctrineMigrations/Version20160410190541.php
+++ b/app/DoctrineMigrations/Version20160410190541.php
@@ -7,6 +7,9 @@ use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+/**
+ * Added foreign keys for account resetting
+ */
class Version20160410190541 extends AbstractMigration implements ContainerAwareInterface
{
/**
@@ -21,7 +24,7 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
@@ -29,13 +32,15 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
*/
public function up(Schema $schema)
{
- 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');
- }
+ $entryTable = $schema->getTable($this->getTable('entry'));
- $this->addSql("INSERT INTO \"".$this->getTable('craue_config_setting')."\" (name, value, section) VALUES ('share_public', '1', 'entry')");
+ $this->skipIf($entryTable->hasColumn('uid'), 'It seems that you already played this migration.');
+
+ $entryTable->addColumn('uid', 'string', [
+ 'notnull' => false,
+ 'length' => 23,
+ ]);
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_public', '1', 'entry')");
}
/**
@@ -43,9 +48,9 @@ class Version20160410190541 extends AbstractMigration implements ContainerAwareI
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $entryTable->dropColumn('uid');
- $this->addSql('ALTER TABLE "'.$this->getTable('entry').'" DROP uuid');
- $this->addSql("DELETE FROM \"".$this->getTable('craue_config_setting')."\" WHERE name = 'share_public'");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'share_public'");
}
}
diff --git a/app/DoctrineMigrations/Version20160812120952.php b/app/DoctrineMigrations/Version20160812120952.php
index 3aafea64..bd6e8d63 100644
--- a/app/DoctrineMigrations/Version20160812120952.php
+++ b/app/DoctrineMigrations/Version20160812120952.php
@@ -7,6 +7,9 @@ use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+/**
+ * Added name field on wallabag_oauth2_clients
+ */
class Version20160812120952 extends AbstractMigration implements ContainerAwareInterface
{
/**
@@ -21,7 +24,7 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
@@ -29,16 +32,10 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
*/
public function up(Schema $schema)
{
- 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');
- }
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+ $this->skipIf($clientsTable->hasColumn('name'), 'It seems that you already played this migration.');
+
+ $clientsTable->addColumn('name', 'blob');
}
/**
@@ -46,8 +43,7 @@ class Version20160812120952 extends AbstractMigration implements ContainerAwareI
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
-
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' DROP COLUMN name');
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+ $clientsTable->dropColumn('name');
}
}
diff --git a/app/DoctrineMigrations/Version20160911214952.php b/app/DoctrineMigrations/Version20160911214952.php
index f14f7bc6..edef81ed 100644
--- a/app/DoctrineMigrations/Version20160911214952.php
+++ b/app/DoctrineMigrations/Version20160911214952.php
@@ -7,6 +7,9 @@ use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+/**
+ * Added settings for RabbitMQ and Redis imports
+ */
class Version20160911214952 extends AbstractMigration implements ContainerAwareInterface
{
/**
@@ -21,7 +24,7 @@ class Version20160911214952 extends AbstractMigration implements ContainerAwareI
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
@@ -29,8 +32,25 @@ 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\')');
+ $redis = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_redis'");
+
+ if (false === $redis) {
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('import_with_redis', 0, 'import')");
+ }
+
+ $rabbitmq = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_rabbitmq'");
+
+ if (false === $rabbitmq) {
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('import_with_rabbitmq', 0, 'import')");
+ }
+
+ $this->skipIf(false !== $rabbitmq && false !== $redis, 'It seems that you already played this migration.');
}
/**
@@ -38,5 +58,7 @@ class Version20160911214952 extends AbstractMigration implements ContainerAwareI
*/
public function down(Schema $schema)
{
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_redis';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_rabbitmq';");
}
}
diff --git a/app/DoctrineMigrations/Version20160916201049.php b/app/DoctrineMigrations/Version20160916201049.php
index 0d2edf9e..9f8e77e7 100644
--- a/app/DoctrineMigrations/Version20160916201049.php
+++ b/app/DoctrineMigrations/Version20160916201049.php
@@ -7,6 +7,9 @@ use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+/**
+ * Added pocket_consumer_key field on wallabag_config
+ */
class Version20160916201049 extends AbstractMigration implements ContainerAwareInterface
{
/**
@@ -21,7 +24,7 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
@@ -29,8 +32,12 @@ 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';");
+ $configTable = $schema->getTable($this->getTable('config'));
+
+ $this->skipIf($configTable->hasColumn('pocket_consumer_key'), 'It seems that you already played this migration.');
+
+ $configTable->addColumn('pocket_consumer_key', 'string', ['notnull' => false]);
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'pocket_consumer_key';");
}
/**
@@ -38,9 +45,8 @@ class Version20160916201049 extends AbstractMigration implements ContainerAwareI
*/
public function down(Schema $schema)
{
- $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')");
+ $configTable = $schema->getTable($this->getTable('config'));
+ $configTable->dropColumn('pocket_consumer_key');
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('pocket_consumer_key', NULL, 'import')");
}
}
diff --git a/app/DoctrineMigrations/Version20161001072726.php b/app/DoctrineMigrations/Version20161001072726.php
new file mode 100644
index 00000000..f247c236
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161001072726.php
@@ -0,0 +1,127 @@
+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
+ switch ($this->connection->getDatabasePlatform()->getName()) {
+ case 'mysql':
+ $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']);
+ }
+ break;
+
+ case 'postgresql':
+ // http://dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
+ $query = $this->connection->query("
+ SELECT conrelid::regclass AS table_from
+ ,conname
+ ,pg_get_constraintdef(c.oid)
+ FROM pg_constraint c
+ JOIN pg_namespace n ON n.oid = c.connamespace
+ WHERE contype = 'f'
+ AND conrelid::regclass::text = '".$this->getTable('entry_tag')."'
+ AND n.nspname = 'public';"
+ );
+ $query->execute();
+
+ foreach ($query->fetchAll() as $fk) {
+ $this->addSql('ALTER TABLE '.$this->getTable('entry_tag').' DROP CONSTRAINT '.$fk['conname']);
+ }
+ break;
+ }
+
+ $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
+
+ switch ($this->connection->getDatabasePlatform()->getName()) {
+ case 'mysql':
+ $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']);
+ }
+ break;
+
+ case 'postgresql':
+ // http://dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
+ $query = $this->connection->query("
+ SELECT conrelid::regclass AS table_from
+ ,conname
+ ,pg_get_constraintdef(c.oid)
+ FROM pg_constraint c
+ JOIN pg_namespace n ON n.oid = c.connamespace
+ WHERE contype = 'f'
+ AND conrelid::regclass::text = '".$this->getTable('annotation')."'
+ AND n.nspname = 'public'
+ AND pg_get_constraintdef(c.oid) LIKE '%entry_id%';"
+ );
+ $query->execute();
+
+ foreach ($query->fetchAll() as $fk) {
+ $this->addSql('ALTER TABLE '.$this->getTable('annotation').' DROP CONSTRAINT '.$fk['conname']);
+ }
+ break;
+ }
+
+ $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 ...');
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161022134138.php b/app/DoctrineMigrations/Version20161022134138.php
new file mode 100644
index 00000000..c71166a0
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161022134138.php
@@ -0,0 +1,85 @@
+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->connection->getParams()['dbname'].' CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;');
+
+ // convert field length for utf8mb4
+ // http://stackoverflow.com/a/31474509/569101
+ $this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL;');
+ $this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE salt salt VARCHAR(180) NOT NULL;');
+ $this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE password password VARCHAR(180) NOT NULL;');
+
+ $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->connection->getParams()['dbname'].' 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;');
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161024212538.php b/app/DoctrineMigrations/Version20161024212538.php
new file mode 100644
index 00000000..ecb872d1
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161024212538.php
@@ -0,0 +1,67 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+
+ $this->skipIf($clientsTable->hasColumn('user_id'), 'It seems that you already played this migration.');
+
+ $clientsTable->addColumn('user_id', 'integer', ['notnull' => false]);
+
+ $clientsTable->addForeignKeyConstraint(
+ $this->getTable('user'),
+ ['user_id'],
+ ['id'],
+ ['onDelete' => 'CASCADE'],
+ $this->constraintName
+ );
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+
+ $this->skipIf(!$clientsTable->hasColumn('user_id'), 'It seems that you already played this migration.');
+
+ $clientsTable->dropColumn('user_id', 'integer');
+
+ if ($this->connection->getDatabasePlatform()->getName() != 'sqlite') {
+ $clientsTable->removeForeignKey($this->constraintName);
+ }
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161031132655.php b/app/DoctrineMigrations/Version20161031132655.php
new file mode 100644
index 00000000..83b97ca9
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161031132655.php
@@ -0,0 +1,52 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $images = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'download_images_enabled'");
+
+ $this->skipIf(false !== $images, 'It seems that you already played this migration.');
+
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('download_images_enabled', 0, 'misc')");
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'download_images_enabled';");
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161104073720.php b/app/DoctrineMigrations/Version20161104073720.php
new file mode 100644
index 00000000..fb8f5fa1
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161104073720.php
@@ -0,0 +1,53 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf($entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+
+ $entryTable->addIndex(['created_at'], $this->indexName);
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf(false === $entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+
+ $entryTable->dropIndex($this->indexName);
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161106113822.php b/app/DoctrineMigrations/Version20161106113822.php
new file mode 100644
index 00000000..de3702a4
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161106113822.php
@@ -0,0 +1,56 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $configTable = $schema->getTable($this->getTable('config'));
+
+ $this->skipIf($configTable->hasColumn('action_mark_as_read'), 'It seems that you already played this migration.');
+
+ $configTable->addColumn('action_mark_as_read', 'integer', [
+ 'default' => 0,
+ 'notnull' => false,
+ ]);
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $configTable = $schema->getTable($this->getTable('config'));
+
+ $this->skipIf(!$configTable->hasColumn('action_mark_as_read'), 'It seems that you already played this migration.');
+
+ $configTable->dropColumn('action_mark_as_read');
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161117071626.php b/app/DoctrineMigrations/Version20161117071626.php
new file mode 100644
index 00000000..8daa2142
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161117071626.php
@@ -0,0 +1,64 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $share = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'share_unmark'");
+
+ if (false === $share) {
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_unmark', 0, 'entry')");
+ }
+
+ $unmark = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'unmark_url'");
+
+ if (false === $unmark) {
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')");
+ }
+
+ $this->skipIf(false !== $share && false !== $unmark, 'It seems that you already played this migration.');
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'share_unmark';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'unmark_url';");
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161118134328.php b/app/DoctrineMigrations/Version20161118134328.php
new file mode 100644
index 00000000..7b2eeb7b
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161118134328.php
@@ -0,0 +1,56 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+
+ $this->skipIf($entryTable->hasColumn('http_status'), 'It seems that you already played this migration.');
+
+ $entryTable->addColumn('http_status', 'string', [
+ 'length' => 3,
+ 'notnull' => false,
+ ]);
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+
+ $this->skipIf(!$entryTable->hasColumn('http_status'), 'It seems that you already played this migration.');
+
+ $entryTable->dropColumn('http_status');
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161122144743.php b/app/DoctrineMigrations/Version20161122144743.php
new file mode 100644
index 00000000..388a0e4b
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161122144743.php
@@ -0,0 +1,52 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $access = $this->container
+ ->get('doctrine.orm.default_entity_manager')
+ ->getConnection()
+ ->fetchArray('SELECT * FROM '.$this->getTable('craue_config_setting')." WHERE name = 'restricted_access'");
+
+ $this->skipIf(false !== $access, 'It seems that you already played this migration.');
+
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('restricted_access', 0, 'entry')");
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'restricted_access';");
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161122203647.php b/app/DoctrineMigrations/Version20161122203647.php
new file mode 100644
index 00000000..9b17d6ef
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161122203647.php
@@ -0,0 +1,63 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $userTable = $schema->getTable($this->getTable('user'));
+
+ $this->skipIf(false === $userTable->hasColumn('expired') || false === $userTable->hasColumn('credentials_expired'), 'It seems that you already played this migration.');
+
+ $userTable->dropColumn('expired');
+ $userTable->dropColumn('credentials_expired');
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $userTable = $schema->getTable($this->getTable('user'));
+
+ $this->skipIf(true === $userTable->hasColumn('expired') || true === $userTable->hasColumn('credentials_expired'), 'It seems that you already played this migration.');
+
+ $userTable->addColumn('expired', 'smallint', ['notnull' => false]);
+ $userTable->addColumn('credentials_expired', 'smallint', ['notnull' => false]);
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161128084725.php b/app/DoctrineMigrations/Version20161128084725.php
new file mode 100644
index 00000000..ea370076
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161128084725.php
@@ -0,0 +1,49 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $configTable = $schema->getTable($this->getTable('config'));
+ $this->skipIf($configTable->hasColumn('list_mode'), 'It seems that you already played this migration.');
+
+ $configTable->addColumn('list_mode', 'integer', ['notnull' => false]);
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $configTable = $schema->getTable($this->getTable('config'));
+ $configTable->dropColumn('list_mode');
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161128131503.php b/app/DoctrineMigrations/Version20161128131503.php
new file mode 100644
index 00000000..b71aa38b
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161128131503.php
@@ -0,0 +1,61 @@
+ 'smallint',
+ 'credentials_expire_at' => 'datetime',
+ 'expires_at' => 'datetime',
+ ];
+
+ /**
+ * @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)
+ {
+ $userTable = $schema->getTable($this->getTable('user'));
+
+ foreach ($this->fields as $field => $type) {
+ $this->skipIf(!$userTable->hasColumn($field), 'It seems that you already played this migration.');
+ $userTable->dropColumn($field);
+ }
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $userTable = $schema->getTable($this->getTable('user'));
+
+ foreach ($this->fields as $field => $type) {
+ $this->skipIf($userTable->hasColumn($field), 'It seems that you already played this migration.');
+ $userTable->addColumn($field, $type, ['notnull' => false]);
+ }
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161214094402.php b/app/DoctrineMigrations/Version20161214094402.php
new file mode 100644
index 00000000..db125f76
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161214094402.php
@@ -0,0 +1,75 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+
+ $this->skipIf($entryTable->hasColumn('uid'), 'It seems that you already played this migration.');
+
+ switch ($this->connection->getDatabasePlatform()->getName()) {
+ case 'sqlite':
+ $this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM '.$this->getTable('entry'));
+ $this->addSql('DROP TABLE '.$this->getTable('entry'));
+ $this->addSql('CREATE TABLE '.$this->getTable('entry').' (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT "0", PRIMARY KEY(id));');
+ $this->addSql('INSERT INTO '.$this->getTable('entry').' (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry;');
+ $this->addSql('DROP TABLE __temp__wallabag_entry');
+ break;
+ case 'mysql':
+ $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE uuid uid VARCHAR(23)');
+ break;
+ case 'postgresql':
+ $this->addSql('ALTER TABLE '.$this->getTable('entry').' RENAME uuid TO uid');
+ }
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+
+ $this->skipIf($entryTable->hasColumn('uuid'), 'It seems that you already played this migration.');
+
+ switch ($this->connection->getDatabasePlatform()->getName()) {
+ case 'sqlite':
+ throw new SkipMigrationException('Too complex ...');
+ break;
+ case 'mysql':
+ $this->addSql('ALTER TABLE '.$this->getTable('entry').' CHANGE uid uuid VARCHAR(23)');
+ break;
+ case 'postgresql':
+ $this->addSql('ALTER TABLE '.$this->getTable('entry').' RENAME uid TO uuid');
+ }
+ }
+}
diff --git a/app/DoctrineMigrations/Version20161214094403.php b/app/DoctrineMigrations/Version20161214094403.php
new file mode 100644
index 00000000..5948b5fa
--- /dev/null
+++ b/app/DoctrineMigrations/Version20161214094403.php
@@ -0,0 +1,53 @@
+container = $container;
+ }
+
+ private function getTable($tableName)
+ {
+ return $this->container->getParameter('database_table_prefix').$tableName;
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function up(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf($entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+
+ $entryTable->addIndex(['uid'], $this->indexName);
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf(false === $entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+
+ $entryTable->dropIndex($this->indexName);
+ }
+}
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
index 3e11d675..c65463db 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.da.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Download billeder på din server
carrot: Aktiver deling til Carrot
diaspora_url: Diaspora URL, hvis tjenesten er aktiv
@@ -15,6 +16,7 @@ share_diaspora: Aktiver deling til Diaspora
share_mail: Aktiver deling med email
share_shaarli: Aktiver deling gennem Shaarli
share_twitter: Aktiver deling gennem Twitter
+share_unmark: Aktiver deling gennem Unmark.it
show_printlink: Vis et link til print-indhold
wallabag_support_url: Support-URL for wallabag
wallabag_url: URL for *sin* wallabag-installation
@@ -29,3 +31,5 @@ piwik_enabled: Aktiver Piwik
demo_mode_enabled: "Aktiver demo-indstilling? (anvendes kun til wallabags offentlige demo)"
demo_mode_username: "Demobruger"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
index c74b5c1f..bc378147 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.de.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Bilder auf den Server herunterladen
carrot: Teilen zu Carrot aktivieren
diaspora_url: Diaspora-URL, sofern der Service aktiviert ist
@@ -15,6 +16,7 @@ share_diaspora: Teilen zu Diaspora aktiveren
share_mail: Teilen via E-Mail aktiveren
share_shaarli: Teilen zu Shaarli aktiveren
share_twitter: Teilen zu Twitter aktiveren
+share_unmark: Teilen zu Unmark.it aktiveren
show_printlink: Link anzeigen, um den Inhalt auszudrucken
wallabag_support_url: Support-URL für wallabag
wallabag_url: URL von *deiner* wallabag-Instanz
@@ -29,3 +31,5 @@ piwik_enabled: Piwik aktivieren
demo_mode_enabled: "Test-Modus aktivieren? (nur für die öffentliche wallabag-Demo genutzt)"
demo_mode_username: "Test-Benutzer"
share_public: Erlaube eine öffentliche URL für Einträge
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
index 77c09db4..52cb8e20 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.en.yml
@@ -1,3 +1,4 @@
+settings_changed: Configuration updated
download_pictures: Download pictures on your server
carrot: Enable share to Carrot
diaspora_url: Diaspora URL, if the service is enabled
@@ -15,6 +16,7 @@ share_diaspora: Enable share to Diaspora
share_mail: Enable share by email
share_shaarli: Enable share to Shaarli
share_twitter: Enable share to Twitter
+share_unmark: Enable share to Unmark.it
show_printlink: Display a link to print content
wallabag_support_url: Support URL for wallabag
wallabag_url: URL of *your* wallabag instance
@@ -29,3 +31,5 @@ piwik_enabled: Enable Piwik
demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)"
demo_mode_username: "Demo user"
share_public: Allow public url for entries
+download_images_enabled: Download images locally
+restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
index baa83849..dbec0e81 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.es.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Descargar imágenes
carrot: Activar compartir con Carrot
diaspora_url: Diaspora URL, si el servicio está activado
@@ -15,6 +16,7 @@ share_diaspora: Activar compartir con Diaspora
share_mail: Activar compartir con email
share_shaarli: Activar compartir con Shaarli
share_twitter: Activar compartir con Twitter
+share_unmark: Activar compartir con Unmark.it
show_printlink: Mostrar un enlace para imprimir contenido
wallabag_support_url: URL de soporte de wallabag
wallabag_url: URL de *tu* instancia de wallabag
@@ -29,3 +31,5 @@ piwik_enabled: Activar Piwik
demo_mode_enabled: "Activar modo demo (sólo usado para la demo de wallabag)"
demo_mode_username: "Nombre de usuario demo"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
index b394977e..7a341e0b 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fa.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: تصاÙÛر را در کارگزار Ø®Ùدتا٠باربگÛرÛد
carrot: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ù Carrot
diaspora_url: ÙشاÙÛ DiasporaØ Ø§Ú¯Ø± Ùعا٠بÙد
@@ -15,6 +16,7 @@ share_diaspora: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ù Diaspora
share_mail: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ø§ اÛÙ
ÛÙ
share_shaarli: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ù Shaarli
share_twitter: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ù Twitter
+share_unmark: ÙعاÙâØ³Ø§Ø²Û ÙÙ
âرساÙÛ Ø¨Ù Unmark.it
show_printlink: ÙÙ
اÛØ´ Ù¾ÛÙÙØ¯Û Ø¨Ø±Ø§Û Úاپ Ù
Ø·Ùب
wallabag_support_url: ÙشاÙÛ ØµÙØÙ٠پشتÛباÙÛ wallabag
wallabag_url: ÙشاÙÛ ØµÙØÙÙ wallabag *Ø´Ù
ا*
@@ -29,3 +31,5 @@ modify_settings: "اعÙ
اÙ"
# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)"
# demo_mode_username: "Demo user"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
index 31a80880..f5c886d6 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.fr.yml
@@ -1,3 +1,4 @@
+settings_changed: Configuration mise à jour
download_pictures: Télécharger les images sur le serveur
carrot: Activer le partage vers Carrot
diaspora_url: URL de Diaspora, si le service Diaspora est activé
@@ -15,6 +16,7 @@ share_diaspora: Activer le partage vers Diaspora
share_mail: Activer le partage par email
share_shaarli: Activer le partage vers Shaarli
share_twitter: Activer le partage vers Twitter
+share_unmark: Activer le partage vers Unmark.it
show_printlink: Afficher un lien pour imprimer
wallabag_support_url: URL de support de wallabag
wallabag_url: URL de *votre* instance de wallabag
@@ -29,3 +31,5 @@ piwik_enabled: Activer Piwik
demo_mode_enabled: "Activer le mode démo ? (utiliser uniquement pour la démo publique de wallabag)"
demo_mode_username: "Utilisateur de la démo"
share_public: Autoriser une URL publique pour les articles
+download_images_enabled: Télécharger les images en local
+restricted_access: Activer l'authentification pour les articles derrière un paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
index ba038556..88a1b4f6 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.it.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Scarica le immagini sul tuo server
carrot: Abilita la condivisione con Carrot
diaspora_url: Diaspora URL, se il servizio è abilitato
@@ -15,6 +16,7 @@ share_diaspora: Abilita la condivisione con Diaspora
share_mail: Abilita la condivisione per email
share_shaarli: Abilita la condivisione con Shaarli
share_twitter: Abilita la condivisione con Twitter
+share_unmark: Abilita la condivisione con Unmark.it
show_printlink: Mostra un collegamento per stampare il contenuto
wallabag_support_url: URL di supporto per wallabag
wallabag_url: URL della *tua* installazione di wallabag
@@ -29,3 +31,5 @@ piwik_enabled: Abilita Piwik
demo_mode_enabled: "Abilita modalità demo ? (usato solo per la demo pubblica di wallabag)"
demo_mode_username: "Utente Demo"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
index 55249e33..00deeade 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.oc.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Telecargar los imatges sul servidor
carrot: Activar lo partatge cap a Carrot
diaspora_url: URL de Diaspora, se lo servici Diaspora es activat
@@ -15,6 +16,7 @@ share_diaspora: Activar lo partatge cap a Diaspora
share_mail: Activar lo partatge per corrièl
share_shaarli: Activar lo partatge cap a Shaarli
share_twitter: Activar lo partatge cap a Twitter
+share_unmark: Activar lo partatge cap a Unmark.it
show_printlink: Afichar un ligam per imprimir
wallabag_support_url: URL d'assisténcia de wallabag
wallabag_url: URL de *vòstra* instà ncia de wallabag
@@ -29,3 +31,5 @@ piwik_enabled: Activar Piwik
demo_mode_enabled: "Activar lo mode demostracion ? (utilizar solament per la demostracion publica de wallabag)"
demo_mode_username: "Utilizaire de la demostracion"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
index 42cc5b52..744031e8 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pl.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Pobierz obrazy na swój serwer
carrot: WÅÄ
cz udostÄpnianie dla Carrot
diaspora_url: Adres URL Diaspora, jeżeli usÅuga jest wÅÄ
czona
@@ -15,6 +16,7 @@ share_diaspora: WÅÄ
cz udostÄpnianie dla Diaspora
share_mail: WÅÄ
cz udostÄpnianie przez email
share_shaarli: WÅÄ
cz udostÄpnianie dla Shaarli
share_twitter: WÅÄ
cz udostÄpnianie dla Twitter
+share_unmark: WÅÄ
cz udostÄpnianie dla Unmark.it
show_printlink: Pokaż link do wydrukowania zawartoÅci
wallabag_support_url: Adres URL wsparcia dla wallabag
wallabag_url: Adres *twojej* instacji wallabag
@@ -29,3 +31,5 @@ piwik_enabled: WÅacz Piwik
demo_mode_enabled: "WÅacz tryb demo? (używany wyÅÄ
cznie dla publicznej demonstracji Wallabag)"
demo_mode_username: "Użytkownik Demonstracyjny"
share_public: Zezwalaj na publiczny adres url dla wpisow
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
index e8260422..1edde87a 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.pt.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: Download imagens no seu servidor
carrot: Habilitar compartilhamento para o Carrot
diaspora_url: URL Diaspora, se o serviço está habilitado
@@ -8,12 +9,14 @@ export_csv: Habilita exportação para CSV
export_json: Habilita exportação para JSON
export_txt: Habilita exportação para TXT
export_xml: Habilita exportação para XML
-pocket_consumer_key: Chave de consumidor do Pocket para importar conteúdo (https://getpocket.com/developer/docs/authentication)
+# import_with_rabbitmq: Enable RabbitMQ to import data asynchronously
+# import_with_redis: Enable Redis to import data asynchronously
shaarli_url: URL Shaarli, se o serviço está habilitado
share_diaspora: Habilitar compartilhamento para o Diaspora
share_mail: Habilitar compartilhamento por e-mail
share_shaarli: Habilitar compartilhamento para o Shaarli
share_twitter: Habilitar compartilhamento para o Twitter
+share_unmark: Habilitar compartilhamento para o Unmark.it
show_printlink: Mostrar um link para imprimir o conteúdo
wallabag_support_url: URL de Suporte do wallabag
wallabag_url: URL de *sua* instância do wallabag
@@ -27,3 +30,6 @@ piwik_site_id: ID de seu website Piwik
piwik_enabled: Habilitar Piwik
demo_mode_enabled: "Habilitar modo demo? (somente usado para o demo público do wallabag)"
demo_mode_username: "Usuário demo"
+# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
index 8e72b955..f0c935d3 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.ro.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
download_pictures: DescarcÄ poze pe server
carrot: Permite share cÄtre Carrot
diaspora_url: Diaspora URL, dacÄ serviciul este permis
@@ -15,6 +16,7 @@ share_diaspora: Permite share cÄtre Diaspora
share_mail: Permite share prin email
share_shaarli: Permite share cÄtre Shaarli
share_twitter: Permite share cÄtre Twitter
+share_unmark: Permite share cÄtre Unmark.it
show_printlink: AfiÈeazÄ un link pentru a printa content-ul
wallabag_support_url: URL-ul de suport pentru wallabag
wallabag_url: URL-ul instanÈei tale wallabag
@@ -29,3 +31,5 @@ modify_settings: "aplicÄ"
# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)"
# demo_mode_username: "Demo user"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
index 55f70843..eb40fc5e 100644
--- a/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
+++ b/app/Resources/CraueConfigBundle/translations/CraueConfigBundle.tr.yml
@@ -1,3 +1,4 @@
+# settings_changed: Configuration updated
# download_pictures: Download pictures on your server
# carrot: Enable share to Carrot
# diaspora_url: Diaspora URL, if the service is enabled
@@ -15,6 +16,7 @@
# share_mail: Enable share by email
# share_shaarli: Enable share to Shaarli
# share_twitter: Enable share to Twitter
+# share_unmark: Enable share to Unmark.it
# show_printlink: Display a link to print content
# wallabag_support_url: Support URL for wallabag
# wallabag_url: URL of *your* wallabag instance
@@ -29,3 +31,5 @@
# demo_mode_enabled: "Enable demo mode ? (only used for the wallabag public demo)"
# demo_mode_username: "Demo user"
# share_public: Allow public url for entries
+# download_images_enabled: Download images locally
+# restricted_access: Enable authentication for websites with paywall
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.da.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.da.yml
deleted file mode 100644
index 015989ef..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.da.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Log ind"
-Enter your email address below and we'll send you password reset instructions.: "Indtast din emailadresse nedenfor, så sender vi dig instrukser til at nulstille din adgangskode."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.de.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.de.yml
deleted file mode 100644
index 944a0d41..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.de.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Anmelden"
-Enter your email address below and we'll send you password reset instructions.: "Tippe deine E-Mail-Adresse unten ein und wir senden dir die Anweisungen, wie du dein Kennwort zurücksetzen kannst."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.es.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.es.yml
deleted file mode 100644
index 968eb241..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.es.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Logearse"
-Enter your email address below and we'll send you password reset instructions.: "Introduzca su dirección de email y le enviaremos las instrucciones para resetear su contraseña."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml
deleted file mode 100644
index 1c5ea640..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.fr.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Se connecter"
-Enter your email address below and we'll send you password reset instructions.: "Renseignez votre adresse courriel, nous vous enverrons les instructions pour réinitialiser votre mot de passe."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.oc.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.oc.yml
deleted file mode 100644
index b8a75172..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.oc.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Se connectar"
-Enter your email address below and we'll send you password reset instructions.: "Picatz vòstra adreça de corrièl çai-jos, vos mandarem las instruccions per reïnicializar vòstre senhal."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.pl.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.pl.yml
deleted file mode 100644
index 7e0a2490..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.pl.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Logowanie"
-Enter your email address below and we'll send you password reset instructions.: "Wpisz poniżej swój adres email, abyÅmy mogli wysÅaÄ ci instrukcjÄ resetowania hasÅa."
diff --git a/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml b/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml
deleted file mode 100644
index 85eadfd8..00000000
--- a/app/Resources/FOSUserBundle/translations/FOSUserBundle.pt.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-Login: "Login"
-Enter your email address below and we'll send you password reset instructions.: "Digite seu endereço de e-mail para enviarmos as instruções de recupeção de sua senha."
diff --git a/app/Resources/static/themes/_global/img/icons/unmark-icon--black.png b/app/Resources/static/themes/_global/img/icons/unmark-icon--black.png
new file mode 100644
index 00000000..45f679ee
Binary files /dev/null and b/app/Resources/static/themes/_global/img/icons/unmark-icon--black.png differ
diff --git a/app/Resources/static/themes/_global/img/list.png b/app/Resources/static/themes/_global/img/list.png
new file mode 100755
index 00000000..bd5aff5a
Binary files /dev/null and b/app/Resources/static/themes/_global/img/list.png differ
diff --git a/app/Resources/static/themes/_global/img/table.png b/app/Resources/static/themes/_global/img/table.png
new file mode 100755
index 00000000..859c4cd8
Binary files /dev/null and b/app/Resources/static/themes/_global/img/table.png differ
diff --git a/app/Resources/static/themes/_global/js/bookmarklet.js b/app/Resources/static/themes/_global/js/bookmarklet.js
index 5174ff47..a497628b 100644
--- a/app/Resources/static/themes/_global/js/bookmarklet.js
+++ b/app/Resources/static/themes/_global/js/bookmarklet.js
@@ -1,4 +1,3 @@
-
top['bookmarklet-url@wallabag.org'] =
'bag it!' +
'' +
diff --git a/data/assets/.gitignore b/app/Resources/static/themes/_global/js/shortcuts/entry.js
similarity index 100%
rename from data/assets/.gitignore
rename to app/Resources/static/themes/_global/js/shortcuts/entry.js
diff --git a/app/Resources/static/themes/_global/js/shortcuts/main.js b/app/Resources/static/themes/_global/js/shortcuts/main.js
new file mode 100644
index 00000000..c81bf869
--- /dev/null
+++ b/app/Resources/static/themes/_global/js/shortcuts/main.js
@@ -0,0 +1,15 @@
+import Mousetrap from 'mousetrap';
+
+/** Shortcuts **/
+
+/* Go to */
+Mousetrap.bind('g u', () => { window.location.href = Routing.generate('homepage'); });
+Mousetrap.bind('g s', () => { window.location.href = Routing.generate('starred'); });
+Mousetrap.bind('g r', () => { window.location.href = Routing.generate('archive'); });
+Mousetrap.bind('g a', () => { window.location.href = Routing.generate('all'); });
+Mousetrap.bind('g t', () => { window.location.href = Routing.generate('tag'); });
+Mousetrap.bind('g c', () => { window.location.href = Routing.generate('config'); });
+Mousetrap.bind('g i', () => { window.location.href = Routing.generate('import'); });
+Mousetrap.bind('g d', () => { window.location.href = Routing.generate('developer'); });
+Mousetrap.bind('?', () => { window.location.href = Routing.generate('howto'); });
+Mousetrap.bind('g l', () => { window.location.href = Routing.generate('fos_user_security_logout'); });
diff --git a/app/Resources/static/themes/_global/js/tools.js b/app/Resources/static/themes/_global/js/tools.js
index ab30deb1..cee84fa8 100644
--- a/app/Resources/static/themes/_global/js/tools.js
+++ b/app/Resources/static/themes/_global/js/tools.js
@@ -1,4 +1,9 @@
-const $ = require('jquery');
+import $ from 'jquery';
+import './shortcuts/main';
+import './shortcuts/entry';
+
+/* Allows inline call qr-code call */
+import jrQrcode from 'jr-qrcode'; // eslint-disable-line
function supportsLocalStorage() {
try {
@@ -30,7 +35,7 @@ function initFilters() {
// no display if filters not available
if ($('div').is('#filters')) {
$('#button_filters').show();
- $('.button-collapse-right').sideNav({ edge: 'right' });
+ $('.js-filters-action').sideNav({ edge: 'right' });
$('#clear_form_filters').on('click', () => {
$('#filters input').val('');
$('#filters :checked').removeAttr('checked');
@@ -43,7 +48,7 @@ function initExport() {
// no display if export not available
if ($('div').is('#export')) {
$('#button_export').show();
- $('.button-collapse-right').sideNav({ edge: 'right' });
+ $('.js-export-action').sideNav({ edge: 'right' });
}
}
diff --git a/app/Resources/static/themes/baggy/css/main.css b/app/Resources/static/themes/baggy/css/main.css
index 4dfa8790..e16846ea 100755
--- a/app/Resources/static/themes/baggy/css/main.css
+++ b/app/Resources/static/themes/baggy/css/main.css
@@ -297,18 +297,14 @@ h2::after {
text-decoration: none;
}
-#listmode a:hover {
- opacity: 1;
-}
-
#listmode.tablemode {
- background-image: url("../img/baggy/table.png");
+ background-image: url("../../_global/img/table.png");
background-repeat: no-repeat;
background-position: bottom;
}
#listmode.listmode {
- background-image: url("../img/baggy/list.png");
+ background-image: url("../../_global/img/list.png");
background-repeat: no-repeat;
background-position: bottom;
}
@@ -352,9 +348,9 @@ footer a {
letter-spacing: -5px;
}
-.listmode .entry {
- width: 100% !important;
- margin-left: 0 !important;
+.listmode.entry {
+ width: 100%;
+ height: inherit;
}
.card-entry-labels {
@@ -588,6 +584,7 @@ div.pagination ul {
text-align: left;
font-style: italic;
color: #999;
+ display: inline-flex;
}
div.pagination ul > * {
@@ -620,6 +617,10 @@ div.pagination ul .current {
background-color: #ccc;
}
+.hide {
+ display: none;
+}
+
/* ==========================================================================
2.1 = "save a link" related styles
========================================================================== */
@@ -936,6 +937,11 @@ a.add-to-wallabag-link-after::after {
background-image: url("../../_global/img/icons/diaspora-icon--black.png");
}
+/* Unmark.it */
+.icon-image--unmark {
+ background-image: url("../../_global/img/icons/unmark-icon--black.png");
+}
+
/* shaarli */
.icon-image--shaarli {
background-image: url("../../_global/img/icons/shaarli.png");
diff --git a/app/Resources/static/themes/baggy/js/autoCompleteTags.js b/app/Resources/static/themes/baggy/js/autoCompleteTags.js
index f287ebfa..64fdaa92 100755
--- a/app/Resources/static/themes/baggy/js/autoCompleteTags.js
+++ b/app/Resources/static/themes/baggy/js/autoCompleteTags.js
@@ -5,4 +5,4 @@ function extractLast(term) {
return split(term).pop();
}
-export { split, extractLast };
+export default { split, extractLast };
diff --git a/app/Resources/static/themes/baggy/js/init.js b/app/Resources/static/themes/baggy/js/init.js
index dc11043a..05360a28 100755
--- a/app/Resources/static/themes/baggy/js/init.js
+++ b/app/Resources/static/themes/baggy/js/init.js
@@ -1,11 +1,26 @@
-import { savePercent, retrievePercent } from '../../_global/js/tools';
-import { toggleSaveLinkForm } from './uiTools';
+/* jQuery */
+import $ from 'jquery';
+
+/* eslint-disable no-unused-vars */
+/* jquery has default scope */
+import cookie from 'jquery.cookie';
+import ui from 'jquery-ui-browserify';
+/* eslint-enable no-unused-vars */
+
+/* Annotations */
+import annotator from 'annotator';
-const $ = global.jquery = require('jquery');
-require('jquery.cookie');
-require('jquery-ui-browserify');
-const annotator = require('annotator');
+/* Shortcuts */
+import './shortcuts/main';
+import './shortcuts/entry';
+import '../../_global/js/shortcuts/main';
+import '../../_global/js/shortcuts/entry';
+
+/* Tools */
+import { savePercent, retrievePercent } from '../../_global/js/tools';
+import toggleSaveLinkForm from './uiTools';
+global.jquery = $;
$.fn.ready(() => {
const $listmode = $('#listmode');
diff --git a/app/Resources/static/themes/baggy/js/shortcuts/entry.js b/app/Resources/static/themes/baggy/js/shortcuts/entry.js
new file mode 100644
index 00000000..c87408b9
--- /dev/null
+++ b/app/Resources/static/themes/baggy/js/shortcuts/entry.js
@@ -0,0 +1,26 @@
+import Mousetrap from 'mousetrap';
+import $ from 'jquery';
+
+$(document).ready(() => {
+ if ($('#article').length > 0) {
+ /* Article view */
+ Mousetrap.bind('o', () => {
+ $('div#article_toolbar ul.links a.original')[0].click();
+ });
+
+ /* mark as favorite */
+ Mousetrap.bind('f', () => {
+ $('div#article_toolbar ul.links a.favorite')[0].click();
+ });
+
+ /* mark as read */
+ Mousetrap.bind('a', () => {
+ $('div#article_toolbar ul.links a.markasread')[0].click();
+ });
+
+ /* delete */
+ Mousetrap.bind('del', () => {
+ $('div#article_toolbar ul.links a.delete')[0].click();
+ });
+ }
+});
diff --git a/app/Resources/static/themes/baggy/js/shortcuts/main.js b/app/Resources/static/themes/baggy/js/shortcuts/main.js
new file mode 100644
index 00000000..aed09aee
--- /dev/null
+++ b/app/Resources/static/themes/baggy/js/shortcuts/main.js
@@ -0,0 +1,7 @@
+$(document).ready(() => {
+ Mousetrap.bind('s', () => {
+ $('#search').trigger('click');
+ $('#search_entry_term').focus();
+ return false;
+ });
+});
diff --git a/app/Resources/static/themes/baggy/js/uiTools.js b/app/Resources/static/themes/baggy/js/uiTools.js
index 900b2707..713c53f7 100644
--- a/app/Resources/static/themes/baggy/js/uiTools.js
+++ b/app/Resources/static/themes/baggy/js/uiTools.js
@@ -1,4 +1,4 @@
-const $ = require('jquery');
+import $ from 'jquery';
function toggleSaveLinkForm(url, event) {
$('#add-link-result').empty();
@@ -32,4 +32,4 @@ function toggleSaveLinkForm(url, event) {
plainUrl.focus();
}
-export { toggleSaveLinkForm };
+export default toggleSaveLinkForm;
diff --git a/app/Resources/static/themes/material/css/main.css b/app/Resources/static/themes/material/css/main.css
index 408fe14c..f43e6042 100755
--- a/app/Resources/static/themes/material/css/main.css
+++ b/app/Resources/static/themes/material/css/main.css
@@ -150,6 +150,11 @@
background-image: url("../../_global/img/icons/diaspora-icon--black.png");
}
+/* Unmark.it */
+.icon-image--unmark {
+ background-image: url("../../_global/img/icons/unmark-icon--black.png");
+}
+
/* Shaarli */
.icon-image--shaarli {
background-image: url("../../_global/img/icons/shaarli.png");
@@ -159,7 +164,7 @@ body {
display: flex;
min-height: 100vh;
flex-direction: column;
- background: #f0f0f0;
+ background: #fafafa;
}
body.login main {
@@ -189,7 +194,6 @@ main,
.results {
height: 1em;
- line-height: 30px;
}
.results .nb-results,
@@ -198,6 +202,14 @@ main,
margin-bottom: 0;
}
+.results .nb-results {
+ display: inline-flex;
+}
+
+.results a {
+ color: #444;
+}
+
.pagination {
float: right;
}
@@ -271,6 +283,16 @@ nav input {
color: #aaa;
}
+nav {
+ height: auto;
+}
+
+.nav-wrapper {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
.nav-wrapper .button-collapse {
padding: 0 15px;
}
@@ -279,8 +301,10 @@ nav input {
display: none;
}
-.nav-panels {
- overflow: hidden;
+.nav-panel-buttom {
+ display: flex;
+ flex-grow: 1;
+ justify-content: flex-end;
}
.nav-panel-buttom li {
@@ -317,11 +341,13 @@ nav input {
color: #444;
}
-.input-field.nav-panel-add label {
+.input-field.nav-panel-add label,
+.input-field.nav-panel-search label {
left: 1rem;
}
-.input-field.nav-panel-add .close {
+.input-field.nav-panel-add .close,
+.input-field.nav-panel-search .close {
position: absolute;
top: 0;
right: 1rem;
@@ -340,8 +366,10 @@ nav input {
}
.input-field.nav-panel-add,
-.input-field.nav-panel-add form {
- height: 100%;
+.input-field.nav-panel-add form,
+.input-field.nav-panel-search,
+.input-field.nav-panel-search form {
+ flex-grow: 1;
}
/* ==========================================================================
@@ -411,7 +439,6 @@ nav ul a:hover {
.side-nav.fixed.right-aligned {
right: -250px;
left: auto !important;
- overflow-y: visible;
}
#filters div.with-checkbox {
@@ -535,6 +562,18 @@ a.original {
line-height: 24px;
}
+.card .card-action ul.tools li a.tool {
+ margin-right: 5px !important;
+}
+
+.card-stacked:hover ul.tools-list {
+ display: block;
+}
+
+.card-stacked ul.tools-list {
+ display: none;
+}
+
.card .card-action a {
color: #fff;
margin: 0;
@@ -587,7 +626,55 @@ a.original {
#article {
font-size: 20px;
margin: 0 auto;
- max-width: 40em;
+ max-width: 45em;
+}
+
+#article article {
+ color: #424242;
+ font-size: 18px;
+ line-height: 1.7em;
+}
+
+#article article h1,
+#article article h2,
+#article article h3,
+#article article h4,
+#article article h5,
+#article article h6 {
+ color: #212121;
+}
+
+#article article h1 strong,
+#article article h2 strong,
+#article article h3 strong,
+#article article h4 strong,
+#article article h5 strong,
+#article article h6 strong {
+ font-weight: 500;
+}
+
+#article article h6 {
+ font-size: 1.2rem;
+}
+
+#article article h5 {
+ font-size: 1.6rem;
+}
+
+#article article h4 {
+ font-size: 1.9rem;
+}
+
+#article article h3 {
+ font-size: 2.2rem;
+}
+
+#article article h2 {
+ font-size: 2.5rem;
+}
+
+#article article h1 {
+ font-size: 2.7rem;
}
#article img,
@@ -596,6 +683,46 @@ a.original {
height: auto;
}
+#article article a {
+ border-bottom: 1px dotted #03a9f4;
+ text-decoration: none;
+}
+
+#article article a:hover {
+ border-bottom-style: solid;
+}
+
+#article article ul {
+ padding-left: 30px;
+}
+
+#article article ul,
+#article article ul li {
+ list-style-type: disc;
+}
+
+#article article blockquote {
+ font-style: italic;
+}
+
+#article article strong {
+ font-weight: bold;
+}
+
+#article article pre {
+ box-sizing: border-box;
+ margin: 0 0 1.75em;
+ border: #e3f2fd 1px solid;
+ width: 100%;
+ padding: 10px;
+ font-family: monospace;
+ font-size: 0.8em;
+ white-space: pre;
+ overflow: auto;
+ background: #f5f5f5;
+ border-radius: 3px;
+}
+
#article > header > h1 {
font-size: 2em;
margin: 2.1rem 0 0.68rem;
@@ -691,6 +818,14 @@ article aside .tools li {
width: auto;
}
+ .nav-panels .action {
+ padding-right: 0.75rem;
+ }
+
+ .nav-panel-buttom {
+ justify-content: space-around;
+ }
+
#article {
max-width: 35em;
margin-left: auto;
@@ -727,11 +862,13 @@ article aside .tools li {
.pagination li.next {
width: auto;
}
-}
-@media only screen and (min-width: 400px) {
- .nav-panel-buttom {
- float: right;
+ .drag-target + .drag-target {
+ height: 50%;
+ }
+
+ .drag-target + .drag-target + .drag-target {
+ top: 50%;
}
}
diff --git a/app/Resources/static/themes/material/js/init.js b/app/Resources/static/themes/material/js/init.js
index a68269e0..0b2832c0 100755
--- a/app/Resources/static/themes/material/js/init.js
+++ b/app/Resources/static/themes/material/js/init.js
@@ -1,10 +1,21 @@
+/* jQuery */
+import $ from 'jquery';
+
+/* Annotations */
+import annotator from 'annotator';
+
+/* Tools */
import { savePercent, retrievePercent, initFilters, initExport } from '../../_global/js/tools';
-const $ = require('jquery');
+/* Import shortcuts */
+import './shortcuts/main';
+import './shortcuts/entry';
+import '../../_global/js/shortcuts/main';
+import '../../_global/js/shortcuts/entry';
-global.jQuery = $;
require('materialize'); // eslint-disable-line
-const annotator = require('annotator');
+
+global.jQuery = $;
$(document).ready(() => {
// sideNav
@@ -44,7 +55,7 @@ $(document).ready(() => {
$('.nav-panels .action').hide(100);
$('.nav-panel-menu').addClass('hidden');
$('.nav-panels').css('background', 'white');
- $('#searchfield').focus();
+ $('#search_entry_term').focus();
return false;
});
$('.close').on('click', () => {
diff --git a/app/Resources/static/themes/material/js/shortcuts/entry.js b/app/Resources/static/themes/material/js/shortcuts/entry.js
new file mode 100644
index 00000000..e19800bd
--- /dev/null
+++ b/app/Resources/static/themes/material/js/shortcuts/entry.js
@@ -0,0 +1,26 @@
+import Mousetrap from 'mousetrap';
+import $ from 'jquery';
+
+$(document).ready(() => {
+ if ($('#article').length > 0) {
+ /* open original article */
+ Mousetrap.bind('o', () => {
+ $('ul.side-nav a.original i')[0].click();
+ });
+
+ /* mark as favorite */
+ Mousetrap.bind('f', () => {
+ $('ul.side-nav a.favorite i')[0].click();
+ });
+
+ /* mark as read */
+ Mousetrap.bind('a', () => {
+ $('ul.side-nav a.markasread i')[0].click();
+ });
+
+ /* delete */
+ Mousetrap.bind('del', () => {
+ $('ul.side-nav a.delete i')[0].click();
+ });
+ }
+});
diff --git a/app/Resources/static/themes/material/js/shortcuts/main.js b/app/Resources/static/themes/material/js/shortcuts/main.js
new file mode 100644
index 00000000..0a2d2a69
--- /dev/null
+++ b/app/Resources/static/themes/material/js/shortcuts/main.js
@@ -0,0 +1,75 @@
+import Mousetrap from 'mousetrap';
+import $ from 'jquery';
+
+function toggleFocus(cardToToogleFocus) {
+ if (cardToToogleFocus) {
+ $(cardToToogleFocus).toggleClass('z-depth-4');
+ }
+}
+
+$(document).ready(() => {
+ const cards = $('#content').find('.card');
+ const cardNumber = cards.length;
+ let cardIndex = 0;
+ /* If we come from next page */
+ if (window.location.hash === '#prev') {
+ cardIndex = cardNumber - 1;
+ }
+ let card = cards[cardIndex];
+ const pagination = $('.pagination');
+
+ /* Show nothing on quickstart */
+ if ($('#content > div.quickstart').length > 0) {
+ return;
+ }
+
+ /* Focus current card */
+ toggleFocus(card);
+
+ /* Actions */
+ Mousetrap.bind('g n', () => {
+ $('#nav-btn-add').trigger('click');
+ return false;
+ });
+
+ Mousetrap.bind('s', () => {
+ $('#nav-btn-search').trigger('click');
+ return false;
+ });
+
+ Mousetrap.bind('esc', () => {
+ $('.close').trigger('click');
+ });
+
+ /* Select right card. If there's a next page, go to next page */
+ Mousetrap.bind('right', () => {
+ if (cardIndex >= 0 && cardIndex < cardNumber - 1) {
+ toggleFocus(card);
+ cardIndex += 1;
+ card = cards[cardIndex];
+ toggleFocus(card);
+ return;
+ }
+ if (pagination.length > 0 && pagination.find('li.next:not(.disabled)').length > 0 && cardIndex === cardNumber - 1) {
+ window.location.href = window.location.origin + $(pagination).find('li.next a').attr('href');
+ }
+ });
+
+ /* Select previous card. If there's a previous page, go to next page */
+ Mousetrap.bind('left', () => {
+ if (cardIndex > 0 && cardIndex < cardNumber) {
+ toggleFocus(card);
+ cardIndex -= 1;
+ card = cards[cardIndex];
+ toggleFocus(card);
+ return;
+ }
+ if (pagination.length > 0 && $(pagination).find('li.prev:not(.disabled)').length > 0 && cardIndex === 0) {
+ window.location.href = `${window.location.origin + $(pagination).find('li.prev a').attr('href')}#prev`;
+ }
+ });
+
+ Mousetrap.bind('enter', () => {
+ window.location.href = window.location.origin + $(card).find('span.card-title a').attr('href');
+ });
+});
diff --git a/app/config/config.yml b/app/config/config.yml
index ca0ba1d8..68f70d67 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -51,6 +51,8 @@ wallabag_core:
rss_limit: 50
reading_speed: 1
cache_lifetime: 10
+ action_mark_as_read: 1
+ list_mode: 1
fetching_error_message: |
wallabag can't retrieve contents for this article. Please troubleshoot this issue.
@@ -78,7 +80,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
@@ -115,12 +117,26 @@ swiftmailer:
fos_rest:
param_fetcher_listener: true
body_listener: true
- format_listener: true
view:
+ mime_types:
+ csv:
+ - 'text/csv'
+ - 'text/plain'
+ pdf:
+ - 'application/pdf'
+ epub:
+ - 'application/epub+zip'
+ mobi:
+ - 'application/x-mobipocket-ebook'
view_response_listener: 'force'
formats:
xml: true
- json : true
+ json: true
+ txt: true
+ csv: true
+ pdf: true
+ epub: true
+ mobi: true
templating_formats:
html: true
force_redirects:
@@ -129,10 +145,21 @@ fos_rest:
default_engine: twig
routing_loader:
default_format: json
+ format_listener:
+ enabled: true
+ rules:
+ - { path: "^/api/entries/([0-9]+)/export.(.*)", priorities: ['epub', 'mobi', 'pdf', 'txt', 'csv'], fallback_format: json, prefer_extension: false }
+ - { path: "^/api", priorities: ['json', 'xml'], fallback_format: json, prefer_extension: false }
+ - { path: "^/annotations", priorities: ['json', 'xml'], fallback_format: json, prefer_extension: false }
+ # for an unknown reason, EACH REQUEST goes to FOS\RestBundle\EventListener\FormatListener
+ # so we need to add custom rule for custom api export but also for all other routes of the application...
+ - { path: '^/', priorities: ['text/html', '*/*'], fallback_format: html, prefer_extension: false }
nelmio_api_doc:
sandbox:
enabled: false
+ cache:
+ enabled: true
name: wallabag API documentation
nelmio_cors:
@@ -185,6 +212,7 @@ fos_user:
from_email:
address: "%from_email%"
sender_name: wallabag
+
fos_oauth_server:
db_driver: orm
client_class: Wallabag\ApiBundle\Entity\Client
@@ -192,7 +220,7 @@ fos_oauth_server:
refresh_token_class: Wallabag\ApiBundle\Entity\RefreshToken
auth_code_class: Wallabag\ApiBundle\Entity\AuthCode
service:
- user_provider: fos_user.user_manager
+ user_provider: fos_user.user_provider.username_email
options:
refresh_token_lifetime: 1209600
@@ -213,16 +241,6 @@ kphoen_rulerz:
executors:
doctrine: true
-lexik_maintenance:
- authorized:
- ips: ['127.0.0.1']
- driver:
- ttl: 3600
- class: 'Lexik\Bundle\MaintenanceBundle\Drivers\DatabaseDriver'
- response:
- code: 503
- status: "wallabag Service Temporarily Unavailable"
-
old_sound_rabbit_mq:
connections:
default:
@@ -243,6 +261,11 @@ old_sound_rabbit_mq:
exchange_options:
name: 'wallabag.import.readability'
type: topic
+ import_pinboard:
+ connection: default
+ exchange_options:
+ name: 'wallabag.import.pinboard'
+ type: topic
import_instapaper:
connection: default
exchange_options:
@@ -277,6 +300,7 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.pocket'
callback: wallabag_import.consumer.amqp.pocket
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_readability:
connection: default
exchange_options:
@@ -285,6 +309,7 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.readability'
callback: wallabag_import.consumer.amqp.readability
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_instapaper:
connection: default
exchange_options:
@@ -293,6 +318,16 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.instapaper'
callback: wallabag_import.consumer.amqp.instapaper
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
+ import_pinboard:
+ connection: default
+ exchange_options:
+ name: 'wallabag.import.pinboard'
+ type: topic
+ queue_options:
+ name: 'wallabag.import.pinboard'
+ callback: wallabag_import.consumer.amqp.pinboard
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_wallabag_v1:
connection: default
exchange_options:
@@ -301,6 +336,7 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.wallabag_v1'
callback: wallabag_import.consumer.amqp.wallabag_v1
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_wallabag_v2:
connection: default
exchange_options:
@@ -309,6 +345,7 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.wallabag_v2'
callback: wallabag_import.consumer.amqp.wallabag_v2
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_firefox:
connection: default
exchange_options:
@@ -317,6 +354,7 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.firefox'
callback: wallabag_import.consumer.amqp.firefox
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
import_chrome:
connection: default
exchange_options:
@@ -325,3 +363,18 @@ old_sound_rabbit_mq:
queue_options:
name: 'wallabag.import.chrome'
callback: wallabag_import.consumer.amqp.chrome
+ qos_options: {prefetch_count: "%rabbitmq_prefetch_count%"}
+
+fos_js_routing:
+ routes_to_expose:
+ - homepage
+ - starred
+ - archive
+ - all
+ - tag
+ - config
+ - import
+ - developer
+ - howto
+ - fos_user_security_logout
+ - new
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:
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:
diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist
index ece4903a..97f51ed1 100644
--- a/app/config/parameters.yml.dist
+++ b/app/config/parameters.yml.dist
@@ -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
@@ -47,9 +49,14 @@ parameters:
rabbitmq_port: 5672
rabbitmq_user: guest
rabbitmq_password: guest
+ rabbitmq_prefetch_count: 10
# Redis processing
redis_scheme: tcp
redis_host: localhost
redis_port: 6379
redis_path: null
+ redis_password: null
+
+ # sites credentials
+ sites_credentials: {}
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:
test_database_user: null
test_database_password: null
test_database_path: '%kernel.root_dir%/../data/db/wallabag_test.sqlite'
+ test_database_charset: utf8
diff --git a/app/config/routing.yml b/app/config/routing.yml
index 750ed435..0bd2d130 100644
--- a/app/config/routing.yml
+++ b/app/config/routing.yml
@@ -17,10 +17,6 @@ wallabag_api:
type: annotation
prefix: /
-wallabag_api:
- resource: "@WallabagApiBundle/Resources/config/routing.yml"
- prefix: /
-
app:
resource: "@WallabagCoreBundle/Controller/"
type: annotation
@@ -52,3 +48,6 @@ craue_config_settings_modify:
path: /settings
defaults:
_controller: CraueConfigBundle:Settings:modify
+
+fos_js_routing:
+ resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
diff --git a/app/config/routing_rest.yml b/app/config/routing_rest.yml
index 52d395dd..29f4ab14 100644
--- a/app/config/routing_rest.yml
+++ b/app/config/routing_rest.yml
@@ -1,4 +1,3 @@
Rest_Wallabag:
- type : rest
- resource: "@WallabagApiBundle/Resources/config/routing_rest.yml"
-
+ type : rest
+ resource: "@WallabagApiBundle/Resources/config/routing_rest.yml"
diff --git a/app/config/services.yml b/app/config/services.yml
index a57ef0f3..9a1ce80b 100644
--- a/app/config/services.yml
+++ b/app/config/services.yml
@@ -32,13 +32,13 @@ services:
- { name: twig.extension }
wallabag.locale_listener:
- class: Wallabag\CoreBundle\EventListener\LocaleListener
+ class: Wallabag\CoreBundle\Event\Listener\LocaleListener
arguments: ["%kernel.default_locale%"]
tags:
- { name: kernel.event_subscriber }
wallabag.user_locale_listener:
- class: Wallabag\CoreBundle\EventListener\UserLocaleListener
+ class: Wallabag\CoreBundle\Event\Listener\UserLocaleListener
arguments: ["@session"]
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin }
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:
test_database_user: root
test_database_password: ~
test_database_path: ~
+ 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:
test_database_user: travis
test_database_password: ~
test_database_path: ~
+ 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:
test_database_user: ~
test_database_password: ~
test_database_path: "%kernel.root_dir%/../data/db/wallabag_test.sqlite"
+ test_database_charset: utf8
diff --git a/build.xml b/build.xml
index 37b40743..b5727e62 100644
--- a/build.xml
+++ b/build.xml
@@ -1,9 +1,9 @@
-
-
-
+
+
+
@@ -26,11 +26,6 @@
-
-
-
-
-
@@ -39,46 +34,133 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/composer.json b/composer.json
index 70f5fc99..767d9c82 100644
--- a/composer.json
+++ b/composer.json
@@ -43,13 +43,13 @@
"ext-iconv": "*",
"ext-tokenizer": "*",
"ext-pdo": "*",
- "symfony/symfony": "3.1.*",
+ "symfony/symfony": "3.2.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"twig/extensions": "~1.0",
"symfony/swiftmailer-bundle": "^2.3",
- "symfony/monolog-bundle": "^2.8",
+ "symfony/monolog-bundle": "^3.0",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
@@ -58,37 +58,39 @@
"jms/serializer-bundle": "~1.1",
"nelmio/api-doc-bundle": "~2.7",
"mgargano/simplehtmldom": "~1.5",
- "tecnickcom/tcpdf": "~6.2",
+ "tecnickcom/tc-lib-pdf": "dev-master",
"simplepie/simplepie": "~1.3.1",
"willdurand/hateoas-bundle": "~1.0",
"htmlawed/htmlawed": "~1.1.19",
"liip/theme-bundle": "~1.1",
"lexik/form-filter-bundle": "~5.0",
"j0k3r/graby": "~1.0",
- "friendsofsymfony/user-bundle": "dev-master#e168ed64629d034cb9cbbffb9d4350f62ef04fab as 2.0.x-dev",
+ "friendsofsymfony/user-bundle": "2.0.x-dev",
"friendsofsymfony/oauth-server-bundle": "^1.5",
"stof/doctrine-extensions-bundle": "^1.2",
"scheb/two-factor-bundle": "~2.0",
"grandt/phpepub": "~4.0",
"wallabag/php-mobi": "~1.0.0",
"kphoen/rulerz-bundle": "~0.10",
+ "kphoen/rulerz": "0.19.1",
"guzzlehttp/guzzle": "^5.3.1",
"doctrine/doctrine-migrations-bundle": "^1.0",
"paragonie/random_compat": "~1.0",
"craue/config-bundle": "~1.4",
"mnapoli/piwik-twig-extension": "^1.0",
- "lexik/maintenance-bundle": "~2.1",
"ocramius/proxy-manager": "1.*",
"white-october/pagerfanta-bundle": "^1.0",
"php-amqplib/rabbitmq-bundle": "^1.8",
"predis/predis": "^1.0",
- "javibravo/simpleue": "^1.0"
+ "javibravo/simpleue": "^1.0",
+ "symfony/dom-crawler": "^3.1",
+ "friendsofsymfony/jsrouting-bundle": "^1.6",
+ "bdunogier/guzzle-site-authenticator": "dev-master"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "~2.2",
"doctrine/data-fixtures": "~1.1.1",
"sensio/generator-bundle": "^3.0",
- "phpunit/phpunit": "~4.0",
"symfony/phpunit-bridge": "^3.0",
"friendsofphp/php-cs-fixer": "~1.9",
"m6web/redis-mock": "^2.0"
@@ -98,6 +100,7 @@
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
+ "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
],
"post-install-cmd": [
@@ -113,6 +116,7 @@
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
+ "symfony-assets-install": "symlink",
"incenteev-parameters": {
"file": "app/config/parameters.yml"
}
diff --git a/data/sql/mysql_base.sql b/data/sql/mysql_base.sql
new file mode 100644
index 00000000..13fa6302
--- /dev/null
+++ b/data/sql/mysql_base.sql
@@ -0,0 +1,25 @@
+CREATE TABLE wallabag_craue_config_setting (name VARCHAR(255) NOT NULL, value VARCHAR(255) DEFAULT NULL, section VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_5D9649505E237E06 (name), PRIMARY KEY(name)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE `wallabag_entry` (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, title LONGTEXT DEFAULT NULL, url LONGTEXT DEFAULT NULL, is_archived TINYINT(1) NOT NULL, is_starred TINYINT(1) NOT NULL, content LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype LONGTEXT DEFAULT NULL, language LONGTEXT DEFAULT NULL, reading_time INT DEFAULT NULL, domain_name LONGTEXT DEFAULT NULL, preview_picture LONGTEXT DEFAULT NULL, is_public TINYINT(1) DEFAULT '0', INDEX IDX_F4D18282A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_entry_tag (entry_id INT NOT NULL, tag_id INT NOT NULL, INDEX IDX_C9F0DD7CBA364942 (entry_id), INDEX IDX_C9F0DD7CBAD26311 (tag_id), PRIMARY KEY(entry_id, tag_id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE `wallabag_config` (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, theme VARCHAR(255) NOT NULL, items_per_page INT NOT NULL, language VARCHAR(255) NOT NULL, rss_token VARCHAR(255) DEFAULT NULL, rss_limit INT DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, UNIQUE INDEX UNIQ_87E64C53A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE `wallabag_tagging_rule` (id INT AUTO_INCREMENT NOT NULL, config_id INT DEFAULT NULL, rule VARCHAR(255) NOT NULL, tags LONGTEXT NOT NULL COMMENT '(DC2Type:simple_array)', INDEX IDX_2D9B3C5424DB0683 (config_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE `wallabag_tag` (id INT AUTO_INCREMENT NOT NULL, `label` LONGTEXT NOT NULL, slug VARCHAR(128) NOT NULL, UNIQUE INDEX UNIQ_4CA58A8C989D9B62 (slug), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_oauth2_clients (id INT AUTO_INCREMENT NOT NULL, random_id VARCHAR(255) NOT NULL, redirect_uris LONGTEXT NOT NULL COMMENT '(DC2Type:array)', secret VARCHAR(255) NOT NULL, allowed_grant_types LONGTEXT NOT NULL COMMENT '(DC2Type:array)', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_oauth2_access_tokens (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_368A42095F37A13B (token), INDEX IDX_368A420919EB6921 (client_id), INDEX IDX_368A4209A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_oauth2_refresh_tokens (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_20C9FB245F37A13B (token), INDEX IDX_20C9FB2419EB6921 (client_id), INDEX IDX_20C9FB24A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_oauth2_auth_codes (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, redirect_uri LONGTEXT NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_EE52E3FA5F37A13B (token), INDEX IDX_EE52E3FA19EB6921 (client_id), INDEX IDX_EE52E3FAA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE `wallabag_user` (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled TINYINT(1) NOT NULL, salt VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, locked TINYINT(1) NOT NULL, expired TINYINT(1) NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(255) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)', credentials_expired TINYINT(1) NOT NULL, credentials_expire_at DATETIME DEFAULT NULL, name LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INT DEFAULT NULL, twoFactorAuthentication TINYINT(1) NOT NULL, trusted LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json_array)', UNIQUE INDEX UNIQ_1D63E7E592FC23A8 (username_canonical), UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF (email_canonical), UNIQUE INDEX UNIQ_1D63E7E5C05FB297 (confirmation_token), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+CREATE TABLE wallabag_annotation (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, entry_id INT DEFAULT NULL, text LONGTEXT NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, quote VARCHAR(255) NOT NULL, ranges LONGTEXT NOT NULL COMMENT '(DC2Type:array)', INDEX IDX_A7AED006A76ED395 (user_id), INDEX IDX_A7AED006BA364942 (entry_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
+ALTER TABLE `wallabag_entry` ADD CONSTRAINT FK_F4D18282A76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_C9F0DD7CBA364942 FOREIGN KEY (entry_id) REFERENCES `wallabag_entry` (id);
+ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_C9F0DD7CBAD26311 FOREIGN KEY (tag_id) REFERENCES `wallabag_tag` (id);
+ALTER TABLE `wallabag_config` ADD CONSTRAINT FK_87E64C53A76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE `wallabag_tagging_rule` ADD CONSTRAINT FK_2D9B3C5424DB0683 FOREIGN KEY (config_id) REFERENCES `wallabag_config` (id);
+ALTER TABLE wallabag_oauth2_access_tokens ADD CONSTRAINT FK_368A420919EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id);
+ALTER TABLE wallabag_oauth2_access_tokens ADD CONSTRAINT FK_368A4209A76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE wallabag_oauth2_refresh_tokens ADD CONSTRAINT FK_20C9FB2419EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id);
+ALTER TABLE wallabag_oauth2_refresh_tokens ADD CONSTRAINT FK_20C9FB24A76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE wallabag_oauth2_auth_codes ADD CONSTRAINT FK_EE52E3FA19EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id);
+ALTER TABLE wallabag_oauth2_auth_codes ADD CONSTRAINT FK_EE52E3FAA76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_A7AED006A76ED395 FOREIGN KEY (user_id) REFERENCES `wallabag_user` (id);
+ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_A7AED006BA364942 FOREIGN KEY (entry_id) REFERENCES `wallabag_entry` (id);
diff --git a/data/sql/pgsql_base.sql b/data/sql/pgsql_base.sql
new file mode 100644
index 00000000..6688fe83
--- /dev/null
+++ b/data/sql/pgsql_base.sql
@@ -0,0 +1,62 @@
+CREATE TABLE wallabag_craue_config_setting (name VARCHAR(255) NOT NULL, value VARCHAR(255) DEFAULT NULL, section VARCHAR(255) DEFAULT NULL, PRIMARY KEY(name));
+CREATE UNIQUE INDEX UNIQ_5D9649505E237E06 ON wallabag_craue_config_setting (name);
+CREATE TABLE "wallabag_entry" (id INT NOT NULL, user_id INT DEFAULT NULL, title TEXT DEFAULT NULL, url TEXT DEFAULT NULL, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, mimetype TEXT DEFAULT NULL, language TEXT DEFAULT NULL, reading_time INT DEFAULT NULL, domain_name TEXT DEFAULT NULL, preview_picture TEXT DEFAULT NULL, is_public BOOLEAN DEFAULT 'false', PRIMARY KEY(id));
+CREATE INDEX IDX_F4D18282A76ED395 ON "wallabag_entry" (user_id);
+CREATE TABLE wallabag_entry_tag (entry_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY(entry_id, tag_id));
+CREATE INDEX IDX_C9F0DD7CBA364942 ON wallabag_entry_tag (entry_id);
+CREATE INDEX IDX_C9F0DD7CBAD26311 ON wallabag_entry_tag (tag_id);
+CREATE TABLE "wallabag_config" (id INT NOT NULL, user_id INT DEFAULT NULL, theme VARCHAR(255) NOT NULL, items_per_page INT NOT NULL, language VARCHAR(255) NOT NULL, rss_token VARCHAR(255) DEFAULT NULL, rss_limit INT DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON "wallabag_config" (user_id);
+CREATE TABLE "wallabag_tagging_rule" (id INT NOT NULL, config_id INT DEFAULT NULL, rule VARCHAR(255) NOT NULL, tags TEXT NOT NULL, PRIMARY KEY(id));
+CREATE INDEX IDX_2D9B3C5424DB0683 ON "wallabag_tagging_rule" (config_id);
+COMMENT ON COLUMN "wallabag_tagging_rule".tags IS '(DC2Type:simple_array)';
+CREATE TABLE "wallabag_tag" (id INT NOT NULL, label TEXT NOT NULL, slug VARCHAR(128) NOT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_4CA58A8C989D9B62 ON "wallabag_tag" (slug);
+CREATE TABLE wallabag_oauth2_clients (id INT NOT NULL, random_id VARCHAR(255) NOT NULL, redirect_uris TEXT NOT NULL, secret VARCHAR(255) NOT NULL, allowed_grant_types TEXT NOT NULL, PRIMARY KEY(id));
+COMMENT ON COLUMN wallabag_oauth2_clients.redirect_uris IS '(DC2Type:array)';
+COMMENT ON COLUMN wallabag_oauth2_clients.allowed_grant_types IS '(DC2Type:array)';
+CREATE TABLE wallabag_oauth2_access_tokens (id INT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_368A42095F37A13B ON wallabag_oauth2_access_tokens (token);
+CREATE INDEX IDX_368A420919EB6921 ON wallabag_oauth2_access_tokens (client_id);
+CREATE INDEX IDX_368A4209A76ED395 ON wallabag_oauth2_access_tokens (user_id);
+CREATE TABLE wallabag_oauth2_refresh_tokens (id INT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_20C9FB245F37A13B ON wallabag_oauth2_refresh_tokens (token);
+CREATE INDEX IDX_20C9FB2419EB6921 ON wallabag_oauth2_refresh_tokens (client_id);
+CREATE INDEX IDX_20C9FB24A76ED395 ON wallabag_oauth2_refresh_tokens (user_id);
+CREATE TABLE wallabag_oauth2_auth_codes (id INT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, redirect_uri TEXT NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_EE52E3FA5F37A13B ON wallabag_oauth2_auth_codes (token);
+CREATE INDEX IDX_EE52E3FA19EB6921 ON wallabag_oauth2_auth_codes (client_id);
+CREATE INDEX IDX_EE52E3FAA76ED395 ON wallabag_oauth2_auth_codes (user_id);
+CREATE TABLE "wallabag_user" (id INT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, last_login TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, locked BOOLEAN NOT NULL, expired BOOLEAN NOT NULL, expires_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, confirmation_token VARCHAR(255) DEFAULT NULL, password_requested_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, roles TEXT NOT NULL, credentials_expired BOOLEAN NOT NULL, credentials_expire_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, name TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, authCode INT DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted TEXT DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON "wallabag_user" (username_canonical);
+CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON "wallabag_user" (email_canonical);
+CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON "wallabag_user" (confirmation_token);
+COMMENT ON COLUMN "wallabag_user".roles IS '(DC2Type:array)';
+COMMENT ON COLUMN "wallabag_user".trusted IS '(DC2Type:json_array)';
+CREATE TABLE wallabag_annotation (id INT NOT NULL, user_id INT DEFAULT NULL, entry_id INT DEFAULT NULL, text TEXT NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, quote VARCHAR(255) NOT NULL, ranges TEXT NOT NULL, PRIMARY KEY(id));
+CREATE INDEX IDX_A7AED006A76ED395 ON wallabag_annotation (user_id);
+CREATE INDEX IDX_A7AED006BA364942 ON wallabag_annotation (entry_id);
+COMMENT ON COLUMN wallabag_annotation.ranges IS '(DC2Type:array)';
+CREATE SEQUENCE "entry_id_seq" INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE "config_id_seq" INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE "tagging_rule_id_seq" INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE "tag_id_seq" INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE oauth2_clients_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE oauth2_access_tokens_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE oauth2_refresh_tokens_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE oauth2_auth_codes_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE "user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1;
+CREATE SEQUENCE annotation_id_seq INCREMENT BY 1 MINVALUE 1 START 1;
+ALTER TABLE "wallabag_entry" ADD CONSTRAINT FK_F4D18282A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_C9F0DD7CBA364942 FOREIGN KEY (entry_id) REFERENCES "wallabag_entry" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_C9F0DD7CBAD26311 FOREIGN KEY (tag_id) REFERENCES "wallabag_tag" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE "wallabag_config" ADD CONSTRAINT FK_87E64C53A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE "wallabag_tagging_rule" ADD CONSTRAINT FK_2D9B3C5424DB0683 FOREIGN KEY (config_id) REFERENCES "wallabag_config" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_access_tokens ADD CONSTRAINT FK_368A420919EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_access_tokens ADD CONSTRAINT FK_368A4209A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_refresh_tokens ADD CONSTRAINT FK_20C9FB2419EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_refresh_tokens ADD CONSTRAINT FK_20C9FB24A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_auth_codes ADD CONSTRAINT FK_EE52E3FA19EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_oauth2_auth_codes ADD CONSTRAINT FK_EE52E3FAA76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_A7AED006A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_A7AED006BA364942 FOREIGN KEY (entry_id) REFERENCES "wallabag_entry" (id) NOT DEFERRABLE INITIALLY IMMEDIATE;
diff --git a/data/sql/sqlite_base.sql b/data/sql/sqlite_base.sql
new file mode 100644
index 00000000..d2780d96
--- /dev/null
+++ b/data/sql/sqlite_base.sql
@@ -0,0 +1,33 @@
+CREATE TABLE wallabag_craue_config_setting (name VARCHAR(255) NOT NULL, value VARCHAR(255) DEFAULT NULL, section VARCHAR(255) DEFAULT NULL, PRIMARY KEY(name));
+CREATE UNIQUE INDEX UNIQ_5D9649505E237E06 ON wallabag_craue_config_setting (name);
+CREATE TABLE "wallabag_tagging_rule" (id INTEGER NOT NULL, config_id INTEGER DEFAULT NULL, rule VARCHAR(255) NOT NULL, tags CLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_2D9B3C5424DB0683 FOREIGN KEY (config_id) REFERENCES "wallabag_config" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE INDEX IDX_2D9B3C5424DB0683 ON "wallabag_tagging_rule" (config_id);
+CREATE TABLE "wallabag_tag" (id INTEGER NOT NULL, label CLOB NOT NULL, slug VARCHAR(128) NOT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_4CA58A8C989D9B62 ON "wallabag_tag" (slug);
+CREATE TABLE "wallabag_entry" (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, title CLOB DEFAULT NULL, url CLOB DEFAULT NULL, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL, language CLOB DEFAULT NULL, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL, preview_picture CLOB DEFAULT NULL, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id), CONSTRAINT FK_F4D18282A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE INDEX IDX_F4D18282A76ED395 ON "wallabag_entry" (user_id);
+CREATE TABLE wallabag_entry_tag (entry_id INTEGER NOT NULL, tag_id INTEGER NOT NULL, PRIMARY KEY(entry_id, tag_id), CONSTRAINT FK_C9F0DD7CBA364942 FOREIGN KEY (entry_id) REFERENCES "wallabag_entry" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_C9F0DD7CBAD26311 FOREIGN KEY (tag_id) REFERENCES "wallabag_tag" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE INDEX IDX_C9F0DD7CBA364942 ON wallabag_entry_tag (entry_id);
+CREATE INDEX IDX_C9F0DD7CBAD26311 ON wallabag_entry_tag (tag_id);
+CREATE TABLE "wallabag_config" (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL, rss_token VARCHAR(255) DEFAULT NULL, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_87E64C53A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON "wallabag_config" (user_id);
+CREATE TABLE wallabag_oauth2_refresh_tokens (id INTEGER NOT NULL, client_id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INTEGER DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_20C9FB2419EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_20C9FB24A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE UNIQUE INDEX UNIQ_20C9FB245F37A13B ON wallabag_oauth2_refresh_tokens (token);
+CREATE INDEX IDX_20C9FB2419EB6921 ON wallabag_oauth2_refresh_tokens (client_id);
+CREATE INDEX IDX_20C9FB24A76ED395 ON wallabag_oauth2_refresh_tokens (user_id);
+CREATE TABLE wallabag_oauth2_access_tokens (id INTEGER NOT NULL, client_id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INTEGER DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_368A420919EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_368A4209A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE UNIQUE INDEX UNIQ_368A42095F37A13B ON wallabag_oauth2_access_tokens (token);
+CREATE INDEX IDX_368A420919EB6921 ON wallabag_oauth2_access_tokens (client_id);
+CREATE INDEX IDX_368A4209A76ED395 ON wallabag_oauth2_access_tokens (user_id);
+CREATE TABLE wallabag_oauth2_auth_codes (id INTEGER NOT NULL, client_id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, token VARCHAR(255) NOT NULL, redirect_uri CLOB NOT NULL, expires_at INTEGER DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_EE52E3FA19EB6921 FOREIGN KEY (client_id) REFERENCES wallabag_oauth2_clients (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_EE52E3FAA76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE UNIQUE INDEX UNIQ_EE52E3FA5F37A13B ON wallabag_oauth2_auth_codes (token);
+CREATE INDEX IDX_EE52E3FA19EB6921 ON wallabag_oauth2_auth_codes (client_id);
+CREATE INDEX IDX_EE52E3FAA76ED395 ON wallabag_oauth2_auth_codes (user_id);
+CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, random_id VARCHAR(255) NOT NULL, redirect_uris CLOB NOT NULL, secret VARCHAR(255) NOT NULL, allowed_grant_types CLOB NOT NULL, PRIMARY KEY(id));
+CREATE TABLE "wallabag_user" (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, locked BOOLEAN NOT NULL, expired BOOLEAN NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(255) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL, credentials_expired BOOLEAN NOT NULL, credentials_expire_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL, PRIMARY KEY(id));
+CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON "wallabag_user" (username_canonical);
+CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON "wallabag_user" (email_canonical);
+CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON "wallabag_user" (confirmation_token);
+CREATE TABLE wallabag_annotation (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, entry_id INTEGER DEFAULT NULL, text CLOB NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, quote VARCHAR(255) NOT NULL, ranges CLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_A7AED006A76ED395 FOREIGN KEY (user_id) REFERENCES "wallabag_user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_A7AED006BA364942 FOREIGN KEY (entry_id) REFERENCES "wallabag_entry" (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
+CREATE INDEX IDX_A7AED006A76ED395 ON wallabag_annotation (user_id);
+CREATE INDEX IDX_A7AED006BA364942 ON wallabag_annotation (entry_id);
diff --git a/docs/de/developer/asynchronous.rst b/docs/de/developer/asynchronous.rst
index 1d241a72..742dd3e5 100644
--- a/docs/de/developer/asynchronous.rst
+++ b/docs/de/developer/asynchronous.rst
@@ -47,6 +47,7 @@ Bearbeite deine ``app/config/parameters.yml``-Datei, um die RabbitMQ-Parameter z
rabbitmq_port: 5672
rabbitmq_user: guest
rabbitmq_password: guest
+ rabbitmq_prefetch_count: 10 # lesen http://www.rabbitmq.com/consumer-prefetch.html
RabbitMQ in wallabag aktivieren
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,10 +150,10 @@ Abhängig davon, über welchen Service du importieren möchtest, musst du den en
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# für den Chrome-Import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
Wenn du den Import nur für einige Artikel nutzen willst, kannst du die Nummer festlegen (hier: 12) und der Consumer wird nach dem zwölften Artikel aufhören:
.. code:: bash
- bin/console wallabag:import:redis-worker -e=prod pocket -vv --maxIterations=12
\ No newline at end of file
+ bin/console wallabag:import:redis-worker -e=prod pocket -vv --maxIterations=12
diff --git a/docs/de/developer/maintenance.rst b/docs/de/developer/maintenance.rst
deleted file mode 100644
index 31343876..00000000
--- a/docs/de/developer/maintenance.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-Wartungsmodus
-=============
-
-Wenn du längere Aufgaben auf deiner wallabag Instanz ausführen willst, kannst du den Wartungsmodus aktivieren.
-Keiner wird dann Zugang zu deiner Instanz haben.
-
-Aktivieren des Wartungsmodus
-----------------------------
-
-Um den Wartungsmodus zu aktivieren, führe folgendes Kommando aus:
-
-::
-
- bin/console lexik:maintenance:lock -e=prod --no-interaction
-
-Du kannst deine IP Adresse in ``app/config/config.yml`` setzen, wenn du Zugriff zu wallabag haben willst, auch wenn der Wartungsmodus aktiv ist. Zum Beispiel:
-
-::
-
- lexik_maintenance:
- authorized:
- ips: ['127.0.0.1']
-
-
-Deaktivieren des Wartungsmodus
-------------------------
-
-Um den Wartungsmodus zu deaktivieren, führe dieses Kommando aus:
-
-::
-
- bin/console lexik:maintenance:unlock -e=prod
diff --git a/docs/de/developer/paywall.rst b/docs/de/developer/paywall.rst
new file mode 100644
index 00000000..365027b4
--- /dev/null
+++ b/docs/de/developer/paywall.rst
@@ -0,0 +1,56 @@
+Articles behind a paywall
+=========================
+
+wallabag can fetch articles from websites which use a paywall system.
+
+Enable paywall authentication
+-----------------------------
+
+In internal settings, in the **Article** section, enable authentication for websites with paywall (with the value 1).
+
+Configure credentials in wallabag
+---------------------------------
+
+Edit your ``app/config/parameters.yml`` file to edit credentials for each website with paywall. Here is an example for some french websites:
+
+.. code:: yaml
+
+ sites_credentials:
+ mediapart.fr: {username: "myMediapartLogin", password: "mypassword"}
+ arretsurimages.net: {username: "myASILogin", password: "mypassword"}
+
+.. note::
+
+ These credentials will be shared between each user of your wallabag instance.
+
+Parsing configuration files
+---------------------------
+
+.. note::
+
+ Read `this part of the documentation `_ to understand the configuration files.
+
+Each parsing configuration file needs to be improved by adding ``requires_login``, ``login_uri``,
+``login_username_field``, ``login_password_field`` and ``not_logged_in_xpath``.
+
+Be careful, the login form must be in the page content when wallabag loads it. It's impossible for wallabag to be authenticated
+on a website where the login form is loaded after the page (by ajax for example).
+
+``login_uri`` is the action URL of the form (``action`` attribute in the form).
+``login_username_field`` is the ``name`` attribute of the login field.
+``login_password_field`` is the ``name`` attribute of the password field.
+
+For example:
+
+.. code::
+
+ title://div[@id="titrage-contenu"]/h1[@class="title"]
+ body: //div[@class="contenu-html"]/div[@class="page-pane"]
+
+ requires_login: yes
+
+ login_uri: http://www.arretsurimages.net/forum/login.php
+ login_username_field: username
+ login_password_field: password
+
+ not_logged_in_xpath: //body[@class="not-logged-in"]
diff --git a/docs/de/developer/translate.rst b/docs/de/developer/translate.rst
index 50e136ea..10544e31 100644
--- a/docs/de/developer/translate.rst
+++ b/docs/de/developer/translate.rst
@@ -20,7 +20,7 @@ der ISO 639-1 Code deiner Sprache ist (`siehe Wikipedia `_ about that, which means you'll find the ``next``, ``previous`` & ``last`` page link inside the `` tag of each RSS feed.
+
Benutzer-Informationen
----------------------
diff --git a/docs/de/user/filters.rst b/docs/de/user/filters.rst
index c9cda6b6..94b82b24 100644
--- a/docs/de/user/filters.rst
+++ b/docs/de/user/filters.rst
@@ -30,6 +30,11 @@ Sprache
wallabag (via graby) kann die Artikelsprache erkennen. Es ist einfach für dich, Artikel
in einer bestimmten Sprache zu filtern.
+HTTP status
+-----------
+
+You can retrieve the articles by filtering by their HTTP status code: 200, 404, 500, etc.
+
Lesezeit
--------
diff --git a/docs/de/user/import.rst b/docs/de/user/import.rst
index 55ab9291..399a1b98 100644
--- a/docs/de/user/import.rst
+++ b/docs/de/user/import.rst
@@ -42,35 +42,50 @@ Du musst wallabag erlauben, mit deinem Pocketaccount zu interagieren.
Deine Daten werden importiert. Datenimport kann ein sehr anspruchsvoller Prozess für deinen Server
sein (wir müssen daran arbeiten, um diesen Import zu verbessern).
-Readability
------------
+Von Readability
+----------------
-Exportiere deine Readability-Daten
+Exportiere deine Readability Daten
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Auf der Seite Tools (`https://www.readability.com/tools/ `_), klicke auf "Exportiere deine Daten" in dem Abschnitt "Daten Export". Du wirst eine E-Mail empfangen, um eine JSON Datei herunterladen zu können (Datei endet aber nicht auf .json).
+
+Importiere deine Daten in wallabag 2.x
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Auf der Tools-Seite (`https://www.readability.com/tools/ `_), klicke auf "Daten exportieren" im "Daten-Export"-Abschnitt. Du wirst eine E-Mail mit einem Downloadlink zu einer JSON-Datei erhalten, welche zugegebenermaÃen nicht mit .json endet.
+Klicke auf den ``Importieren`` Link im Menü, auf ``Importiere Inhalte`` in dem Readability Abschnitt und wähle dann deine JSON Datei aus und lade sie hoch.
+
+Deine Daten werden importiert. Der Datenimport can ein beanspruchender Prozess für deinen Server sein.
+
+Von Pinboard
+-------------
+
+Exportiere deine Pinboard Daten
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Auf der Seite Backup (`https://pinboard.in/settings/backup `_), klicke auf "JSON" in dem Abschnitt "Lesezeichen". Eine JSON Datei wird heruntergeladen (z.B. ``pinboard_export``).
Importiere deine Daten in wallabag 2.x
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Klicke auf den ``Importieren``-Link im Menü, auf ``Inhalte importieren`` im Readability-Abschnitt und wähle dann deine JSON-Datei aus und lade sie hoch.
+Klicke auf den ``Importieren`` Link im Menü, auf ``Importiere Inhalte`` in dem Pinboard Abschnitt und wähle dann deine JSON Datei aus und lade sie hoch.
-Deine Daten werden dann importiert. Dies kann eine starke Belastung für den Server sein.
+Deine Daten werden importiert. Der Datenimport can ein beanspruchender Prozess für deinen Server sein.
-Instapaper
-----------
+Von Instapaper
+---------------
-Exportiere deine Instapaper-Daten
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Exportiere deine Instapaper Daten
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Klicke in den Einstellungen (`https://www.instapaper.com/user `_) auf "CSV-Datei herunterladen" im Export-Abschnitt. Eine CSV-Datei mit dem Namen ``instapaper-export.csv`` wird heruntergeladen.
+Auf der Seite Einstellungen (`https://www.instapaper.com/user `_), klicke auf "Download .CSV Datei" in dem Abschnitt "Export". Eine CSV Datei wird heruntergeladen (z.B. ``instapaper-export.csv``).
Importiere deine Daten in wallabag 2.x
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Klicke auf den ``Importieren``-Link im Menü, auf ``Inhalte importieren`` im Instapaper-Abschnitt und wähle dann deine CSV-Datei aus und lade sie hoch.
+Klicke auf den ``Importieren`` Link im Menü, auf ``Importiere Inhalte`` in dem Instapaper Abschnitt und wähle dann deine JSON Datei aus und lade sie hoch.
-Deine Daten werden dann importiert. Dies kann eine starke Belastung für den Server sein.
+Deine Daten werden importiert. Der Datenimport can ein beanspruchender Prozess für deinen Server sein.
wallabag 1.x
------------
@@ -134,4 +149,4 @@ Als Ergebnis wirst du so etwas erhalten:
Start : 05-04-2016 11:36:07 ---
403 imported
0 already saved
- End : 05-04-2016 11:36:09 ---
\ No newline at end of file
+ End : 05-04-2016 11:36:09 ---
diff --git a/docs/de/user/installation.rst b/docs/de/user/installation.rst
index 131aa1f8..cec62d18 100644
--- a/docs/de/user/installation.rst
+++ b/docs/de/user/installation.rst
@@ -16,7 +16,7 @@ Composer installieren:
::
- curl -s http://getcomposer.org/installer | php
+ curl -s https://getcomposer.org/installer | php
Du kannst eine spezifische Anleitung `hier `__ finden.
@@ -86,7 +86,7 @@ Führe dieses Kommando aus, um das neueste Paket herunterzuladen und zu entpacke
.. code-block:: bash
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+ wget https://wllbg.org/latest-v2-package && tar xvf latest-v2-package
Du findest die `md5 Hashsumme des neuesten Pakets auf unserer Website `_.
diff --git a/docs/de/user/parameters.rst b/docs/de/user/parameters.rst
index a5a4e4f2..8d8f9206 100644
--- a/docs/de/user/parameters.rst
+++ b/docs/de/user/parameters.rst
@@ -39,6 +39,7 @@ Wenn du nicht weiÃt, welchen Wert du setzen sollst, belasse es bei dem Standard
redis_host: localhost
redis_port: 6379
redis_path: null
+ redis_password: null
Bedeutung von jedem Parameter
-----------------------------
@@ -91,3 +92,4 @@ Bedeutung von jedem Parameter
"redis_host", "localhost", "IP oder Hostname des Zielservers (ignoriert bei Unix Schema)"
"redis_port", "6379", "TCP/IP Port des Zielservers (ignoriert bei Unix Schema)"
"redis_path", "null", "Pfad zur Unix Domain Socket Datei, wenn Redis Unix Domain Sockets nutzt"
+ "redis_password", "null", "Kennwort, welches in der Redis-Server-Konfiguration definiert ist (Parameter `requirepass` in `redis.conf`)"
diff --git a/docs/de/user/query-upgrade-21-22.rst b/docs/de/user/query-upgrade-21-22.rst
new file mode 100644
index 00000000..cd201dc2
--- /dev/null
+++ b/docs/de/user/query-upgrade-21-22.rst
@@ -0,0 +1,797 @@
+Migration 20161001072726
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBA364942
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBAD26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP FOREIGN KEY FK_A7AED006BA364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cba364942
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cbad26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP CONSTRAINT fk_a7aed006ba364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+SQLite
+^^^^^^
+
+This migration can only be executed safely on MySQL or PostgreSQL.
+
+Migration 20161022134138
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL;
+ ALTER TABLE wallabag_user CHANGE salt salt VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_user CHANGE password password VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+
+PostgreSQL and SQLite
+^^^^^^^^^^^^^^^^^^^^^
+
+This migration only apply to MySQL.
+
+Migration 20161024212538
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT NOT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP FOREIGN KEY IDX_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT DEFAULT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP CONSTRAINT idx_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id), CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_635D765EA76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+
+Migration 20161031132655
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+Migration 20161104073720
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_created_at
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+
+Migration 20161106113822
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN action_mark_as_read INTEGER DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161117071626
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+Migration 20161118134328
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD COLUMN http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+
+Migration 20161122144743
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+Migration 20161122203647
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired, DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL, ADD credentials_expired SMALLINT DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired
+ ALTER TABLE wallabag_user DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expired SMALLINT DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, locked BOOLEAN NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, credentials_expire_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expired SMALLINT DEFAULT NULL
+
+Migration 20161128084725
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN list_mode INTEGER DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161128131503
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked, DROP credentials_expire_at, DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL, ADD credentials_expire_at DATETIME DEFAULT NULL, ADD expires_at DATETIME DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked
+ ALTER TABLE wallabag_user DROP credentials_expire_at
+ ALTER TABLE wallabag_user DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expire_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+ ALTER TABLE wallabag_user ADD expires_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expire_at DATETIME DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN expires_at DATETIME DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, expired SMALLINT DEFAULT NULL, credentials_expired SMALLINT DEFAULT NULL, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+
+Migration 20161214094403
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_uid
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
diff --git a/docs/de/user/upgrade.rst b/docs/de/user/upgrade.rst
index ad020dd8..1107616e 100644
--- a/docs/de/user/upgrade.rst
+++ b/docs/de/user/upgrade.rst
@@ -3,42 +3,53 @@ wallabag-Installation aktualisieren
Du wirst hier mehrere Wege finden, um deine wallabag zu aktualisieren:
+- `von 2.1.x zu 2.2.x <#upgrade-von-2-1-x-zu-2-2-x>`_
- `von 2.0.x zu 2.1.1 <#upgrade-von-2-0-x-zu-2-1-1>`_
-- `von 2.1.x zu 2.1.y <#upgrade-von-2-1-x-zu-2-1-y>`_
- `von 1.x zu 2.x <#upgrade-von-1-x>`_
-Upgrade von 2.0.x zu 2.1.1
----------------------------
-
-.. warning::
-
- Mache eine Sicherung deines Pocket-Consumer-Key, falls hinzugefügt, da dieser nach dem Upgrade erneut hinzugefügt werden muss.
+Upgrade von 2.1.x zu 2.2.x
+--------------------------
Upgrade auf einem dedizierten Webserver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- rm -rf var/cache/*
- git fetch origin
- git fetch --tags
- git checkout 2.1.1 --force
- SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
- php bin/console doctrine:migrations:migrate --env=prod
- php bin/console cache:clear --env=prod
+ make update
+
+Erklärungen über die Datenbankmigration
+"""""""""""""""""""""""""""""""""""""""
+
+Während des Updates migrieren wir die Datenbank.
+
+Alle Datenbankmigrationen sind im Verzeichnis ``app/DoctrineMigrations`` gespeichert. Jede von ihnen kann einzeln ausgeführt werden:
+``bin/console doctrine:migrations:execute 20161001072726 --env=prod``.
+
+Dies ist die Migrationsliste von 2.1.x auf 2.2.0:
+
+* ``20161001072726``: Fremdschlüssel für das Zurücksetzen des Kontos hinzugefügt
+* ``20161022134138``: Datenbank zum ``utf8mb4``-Encoding ändern (nur für MySQL)
+* ``20161024212538``: ``user_id``-Spalte zu ``oauth2_clients`` hinzugefügt, um Benutzer davon abzuhalten, API-Clients anderer Nutzer zu löschen
+* ``20161031132655``: Interne Einstellung für das (de-)aktivieren vom Bilder-Download hinzugefügt
+* ``20161104073720``: ``created_at``-Index zur ``entry``-Tabelle hinzugefügt
+* ``20161106113822``: ``action_mark_as_read``-Feld zur ``config``-Tabelle hinzugefügt
+* ``20161117071626``: Interne Einstellung zum Teilen mit unmark.it hinzugefügt
+* ``20161118134328``: ``http_status``-Feld zur ``entry``-Tabelle hinzugefügt
+* ``20161122144743``: Interne Einstellung für das (de-)aktivieren zum Holen von Artikeln mit einer Paywall hinzugefügt
+* ``20161122203647``: ``expired``- und ``credentials_expired``-Feld aus der ``user``-Tabelle entfernt
Upgrade auf einem Shared Hosting
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sichere deine ``app/config/parameters.yml``-Datei.
-Lade das 2.1.1-Release von wallabag herunter:
+Lade das letzte Release von wallabag herunter:
.. code-block:: bash
- wget http://framabag.org/wallabag-release-2.1.1.tar.gz && tar xvf wallabag-release-2.1.1.tar.gz
+ wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
-(md5 hash of the 2.1.1 package: ``9584a3b60a2b2a4de87f536548caac93``)
+Du findest den `aktuellen MD5-Hash auf unserer Webseite `_.
Extrahiere das Archiv in deinen wallabag-Ordner und ersetze die ``app/config/parameters.yml`` mit deiner.
@@ -48,42 +59,42 @@ Falls du SQLite nutzt, musst du auÃerdem deinen ``data/``-Ordner in die neue In
Leere den ``var/cache``-Ordner.
-Du musst einige SQL-Abfragen durchführen, um deine Datenbank zu aktualisieren. Wir gehen in diesem Fall davon aus, dass das Tabellenpräfix ``wallabag_`` ist und eine MySQL-Datenbank verwendet wird:
+Du musst einige SQL-Abfragen durchführen, um deine Datenbank zu aktualisieren. Wir gehen in diesem Fall davon aus, dass das Tabellenpräfix ``wallabag_`` ist.
-.. code-block:: sql
+`You can find all the queries here `_.
- ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
- ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
- ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
- DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
+Upgrade von 2.0.x zu 2.1.1
+---------------------------
-Upgrade von 2.1.x zu 2.1.y
------------------------------
+.. warning::
+
+ Mache eine Sicherung deines Pocket-Consumer-Key, falls hinzugefügt, da dieser nach dem Upgrade erneut hinzugefügt werden muss.
Upgrade auf einem dedizierten Webserver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Um deine wallabag-Installation auf die letzte Version zu aktualisieren, führe den folgenden Befehl in deinem wallabag-Ordner aus:
-
::
- make update
+ rm -rf var/cache/*
+ git fetch origin
+ git fetch --tags
+ git checkout 2.1.1 --force
+ SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
+ php bin/console doctrine:migrations:migrate --env=prod
+ php bin/console cache:clear --env=prod
Upgrade auf einem Shared Hosting
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sichere deine ``app/config/parameters.yml``-Datei.
-Lade das letzte Release von wallabag herunter:
+Lade das 2.1.1-Release von wallabag herunter:
.. code-block:: bash
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+ wget http://framabag.org/wallabag-release-2.1.1.tar.gz && tar xvf wallabag-release-2.1.1.tar.gz
-Du findest den `aktuellen MD5-Hash auf unserer Webseite `_.
+(md5 hash of the 2.1.1 package: ``9584a3b60a2b2a4de87f536548caac93``)
Extrahiere das Archiv in deinen wallabag-Ordner und ersetze die ``app/config/parameters.yml`` mit deiner.
@@ -93,6 +104,18 @@ Falls du SQLite nutzt, musst du auÃerdem deinen ``data/``-Ordner in die neue In
Leere den ``var/cache``-Ordner.
+Du musst einige SQL-Abfragen durchführen, um deine Datenbank zu aktualisieren. Wir gehen in diesem Fall davon aus, dass das Tabellenpräfix ``wallabag_`` ist und eine MySQL-Datenbank verwendet wird:
+
+.. code-block:: sql
+
+ ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
+ ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
+ ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
+ DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
+
Upgrade von 1.x
---------------
@@ -100,4 +123,4 @@ Es gibt kein automatisiertes Skript, um wallabag 1.x auf wallabag 2.x zu aktuali
- deine Daten exportieren
- wallabag 2.x installieren (Dokumentation `_ )
-- die Daten in die neue Installation importieren (`Dokumentation `_ )
\ No newline at end of file
+- die Daten in die neue Installation importieren (`Dokumentation `_ )
diff --git a/docs/en/developer/asynchronous.rst b/docs/en/developer/asynchronous.rst
index 6a991cf6..2e409e4a 100644
--- a/docs/en/developer/asynchronous.rst
+++ b/docs/en/developer/asynchronous.rst
@@ -48,6 +48,7 @@ Edit your ``app/config/parameters.yml`` file to edit RabbitMQ configuration. The
rabbitmq_port: 5672
rabbitmq_user: guest
rabbitmq_password: guest
+ rabbitmq_prefetch_count: 10 # read http://www.rabbitmq.com/consumer-prefetch.html
Enable RabbitMQ in wallabag
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -150,7 +151,7 @@ Depending on which service you want to import from you need to enable one (or ma
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# for Chrome import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
If you want to launch the import only for some messages and not all, you can specify this number (here 12) and the worker will stop right after the 12th message :
diff --git a/docs/en/developer/maintenance.rst b/docs/en/developer/maintenance.rst
deleted file mode 100644
index 6d55ed60..00000000
--- a/docs/en/developer/maintenance.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-Maintenance mode
-================
-
-If you have some long tasks to do on your wallabag instance, you can enable a maintenance mode.
-Nobody will have access to your instance.
-
-Enable maintenance mode
------------------------
-
-To enable maintenance mode, execute this command:
-
-::
-
- bin/console lexik:maintenance:lock --no-interaction -e=prod
-
-You can set your IP address in ``app/config/config.yml`` if you want to access to wallabag even if maintenance mode is enabled. For example:
-
-::
-
- lexik_maintenance:
- authorized:
- ips: ['127.0.0.1']
-
-
-Disable maintenance mode
-------------------------
-
-To disable maintenance mode, execute this command:
-
-::
-
- bin/console lexik:maintenance:unlock -e=prod
diff --git a/docs/en/developer/paywall.rst b/docs/en/developer/paywall.rst
new file mode 100644
index 00000000..365027b4
--- /dev/null
+++ b/docs/en/developer/paywall.rst
@@ -0,0 +1,56 @@
+Articles behind a paywall
+=========================
+
+wallabag can fetch articles from websites which use a paywall system.
+
+Enable paywall authentication
+-----------------------------
+
+In internal settings, in the **Article** section, enable authentication for websites with paywall (with the value 1).
+
+Configure credentials in wallabag
+---------------------------------
+
+Edit your ``app/config/parameters.yml`` file to edit credentials for each website with paywall. Here is an example for some french websites:
+
+.. code:: yaml
+
+ sites_credentials:
+ mediapart.fr: {username: "myMediapartLogin", password: "mypassword"}
+ arretsurimages.net: {username: "myASILogin", password: "mypassword"}
+
+.. note::
+
+ These credentials will be shared between each user of your wallabag instance.
+
+Parsing configuration files
+---------------------------
+
+.. note::
+
+ Read `this part of the documentation `_ to understand the configuration files.
+
+Each parsing configuration file needs to be improved by adding ``requires_login``, ``login_uri``,
+``login_username_field``, ``login_password_field`` and ``not_logged_in_xpath``.
+
+Be careful, the login form must be in the page content when wallabag loads it. It's impossible for wallabag to be authenticated
+on a website where the login form is loaded after the page (by ajax for example).
+
+``login_uri`` is the action URL of the form (``action`` attribute in the form).
+``login_username_field`` is the ``name`` attribute of the login field.
+``login_password_field`` is the ``name`` attribute of the password field.
+
+For example:
+
+.. code::
+
+ title://div[@id="titrage-contenu"]/h1[@class="title"]
+ body: //div[@class="contenu-html"]/div[@class="page-pane"]
+
+ requires_login: yes
+
+ login_uri: http://www.arretsurimages.net/forum/login.php
+ login_username_field: username
+ login_password_field: password
+
+ not_logged_in_xpath: //body[@class="not-logged-in"]
diff --git a/docs/en/developer/translate.rst b/docs/en/developer/translate.rst
index d412d3e9..1e5d5009 100644
--- a/docs/en/developer/translate.rst
+++ b/docs/en/developer/translate.rst
@@ -20,7 +20,7 @@ is the ISO 639-1 code of your language (`see wikipedia `_ about that, which means you'll find the ``next``, ``previous`` & ``last`` page link inside the `` tag of each RSS feed.
+
User information
----------------
You can change your name, your email address and enable ``Two factor authentication``.
+If the wallabag instance has more than one enabled user, you can delete your account here. **Take care, we delete all your data**.
+
Two factor authentication (2FA)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/user/filters.rst b/docs/en/user/filters.rst
index 4d1df6eb..aae8a749 100644
--- a/docs/en/user/filters.rst
+++ b/docs/en/user/filters.rst
@@ -30,6 +30,11 @@ Language
wallabag (via graby) can detect article language. It's easy to you to retrieve articles
written in a specific language.
+HTTP status
+-----------
+
+You can retrieve the articles by filtering by their HTTP status code: 200, 404, 500, etc.
+
Reading time
------------
diff --git a/docs/en/user/import.rst b/docs/en/user/import.rst
index a6754fa0..f420a131 100644
--- a/docs/en/user/import.rst
+++ b/docs/en/user/import.rst
@@ -1,13 +1,13 @@
Migrate from ...
================
-In wallabag 2.x, you can import data from:
+In wallabag 2.x, you can import data from:
-- `Pocket <#id1>`_
-- `Readability <#id2>`_
-- `Instapaper <#id4>`_
-- `wallabag 1.x <#id6>`_
-- `wallabag 2.x <#id7>`_
+- `Pocket <#id1>`_
+- `Readability <#id2>`_
+- `Instapaper <#id4>`_
+- `wallabag 1.x <#id6>`_
+- `wallabag 2.x <#id7>`_
We also developed `a script to execute migrations via command-line interface <#import-via-command-line-interface-cli>`_.
@@ -57,8 +57,24 @@ and then select your json file and upload it.
Your data will be imported. Data import can be a demanding process for your server.
-Instapaper
-----------
+From Pinboard
+-------------
+
+Export your Pinboard data
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the backup (`https://pinboard.in/settings/backup `_) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like ``pinboard_export``).
+
+Import your data into wallabag 2.x
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Click on ``Import`` link in the menu, on ``Import contents`` in Pinboard section
+and then select your json file and upload it.
+
+Your data will be imported. Data import can be a demanding process for your server.
+
+From Instapaper
+---------------
Export your Instapaper data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/user/installation.rst b/docs/en/user/installation.rst
index 77ef60a8..7d3bcf61 100644
--- a/docs/en/user/installation.rst
+++ b/docs/en/user/installation.rst
@@ -16,7 +16,7 @@ Install Composer:
::
- curl -s http://getcomposer.org/installer | php
+ curl -s https://getcomposer.org/installer | php
You can find specific instructions `here `__.
@@ -85,7 +85,7 @@ Execute this command to download and extract the latest package:
.. code-block:: bash
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+ wget https://wllbg.org/latest-v2-package && tar xvf latest-v2-package
You will find the `md5 hash of the latest package on our website `_.
diff --git a/docs/en/user/parameters.rst b/docs/en/user/parameters.rst
index 2b02a34d..d8a209e7 100644
--- a/docs/en/user/parameters.rst
+++ b/docs/en/user/parameters.rst
@@ -39,6 +39,7 @@ If you don't know which value you need to set, please leave the default one.
redis_host: localhost
redis_port: 6379
redis_path: null
+ redis_password: null
Meaning of each parameter
-------------------------
@@ -55,6 +56,7 @@ Meaning of each parameter
"database_path", "``""%kernel.root_dir%/../data/db/wallabag.sqlite""``", "only for SQLite, define where to put the database file. Leave it empty 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_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"
@@ -91,3 +93,4 @@ Meaning of each parameter
"redis_host", "localhost", "IP or hostname of the target server (ignored for unix scheme)"
"redis_port", "6379", "TCP/IP port of the target server (ignored for unix scheme)"
"redis_path", "null", "Path of the UNIX domain socket file used when connecting to Redis using UNIX domain sockets"
+ "redis_password", "null", "Password defined in the Redis server configuration (parameter `requirepass` in `redis.conf`)"
diff --git a/docs/en/user/query-upgrade-21-22.rst b/docs/en/user/query-upgrade-21-22.rst
new file mode 100644
index 00000000..cd201dc2
--- /dev/null
+++ b/docs/en/user/query-upgrade-21-22.rst
@@ -0,0 +1,797 @@
+Migration 20161001072726
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBA364942
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBAD26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP FOREIGN KEY FK_A7AED006BA364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cba364942
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cbad26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP CONSTRAINT fk_a7aed006ba364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+SQLite
+^^^^^^
+
+This migration can only be executed safely on MySQL or PostgreSQL.
+
+Migration 20161022134138
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL;
+ ALTER TABLE wallabag_user CHANGE salt salt VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_user CHANGE password password VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+
+PostgreSQL and SQLite
+^^^^^^^^^^^^^^^^^^^^^
+
+This migration only apply to MySQL.
+
+Migration 20161024212538
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT NOT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP FOREIGN KEY IDX_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT DEFAULT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP CONSTRAINT idx_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id), CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_635D765EA76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+
+Migration 20161031132655
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+Migration 20161104073720
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_created_at
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+
+Migration 20161106113822
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN action_mark_as_read INTEGER DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161117071626
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+Migration 20161118134328
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD COLUMN http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+
+Migration 20161122144743
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+Migration 20161122203647
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired, DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL, ADD credentials_expired SMALLINT DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired
+ ALTER TABLE wallabag_user DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expired SMALLINT DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, locked BOOLEAN NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, credentials_expire_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expired SMALLINT DEFAULT NULL
+
+Migration 20161128084725
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN list_mode INTEGER DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161128131503
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked, DROP credentials_expire_at, DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL, ADD credentials_expire_at DATETIME DEFAULT NULL, ADD expires_at DATETIME DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked
+ ALTER TABLE wallabag_user DROP credentials_expire_at
+ ALTER TABLE wallabag_user DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expire_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+ ALTER TABLE wallabag_user ADD expires_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expire_at DATETIME DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN expires_at DATETIME DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, expired SMALLINT DEFAULT NULL, credentials_expired SMALLINT DEFAULT NULL, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+
+Migration 20161214094403
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_uid
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
diff --git a/docs/en/user/upgrade.rst b/docs/en/user/upgrade.rst
index 544d57eb..99260e13 100644
--- a/docs/en/user/upgrade.rst
+++ b/docs/en/user/upgrade.rst
@@ -1,21 +1,87 @@
+==================================
Upgrade your wallabag installation
==================================
You will find here different ways to upgrade your wallabag:
+- `from 2.1.x to 2.2.x <#upgrading-from-2-1-x-to-2-2-x>`_
- `from 2.0.x to 2.1.1 <#upgrade-from-2-0-x-to-2-1-1>`_
-- `from 2.1.x to 2.1.y <#upgrading-from-2-1-x-to-2-1-y>`_
- `from 1.x to 2.x <#from-wallabag-1-x>`_
+*****************************
+Upgrading from 2.1.x to 2.2.x
+*****************************
+
+Upgrade on a dedicated web server
+=================================
+
+::
+
+ make update
+
+Explanations about database migrations
+--------------------------------------
+
+During the update, we execute database migrations.
+
+All the database migrations are stored in ``app/DoctrineMigrations``. You can execute each migration individually:
+``bin/console doctrine:migrations:execute 20161001072726 --env=prod``.
+
+You can also cancel each migration individually: ``bin/console doctrine:migrations:execute 20161001072726 --down --env=prod``.
+
+Here is the migrations list for 2.1.x to 2.2.0 release:
+
+* ``20161001072726``: added foreign keys for account resetting
+* ``20161022134138``: converted database to ``utf8mb4`` encoding (for MySQL only)
+* ``20161024212538``: added ``user_id`` column on ``oauth2_clients`` to prevent users to delete API clients from other users
+* ``20161031132655``: added the internal setting to enable/disable downloading pictures
+* ``20161104073720``: added ``created_at`` index on ``entry`` table
+* ``20161106113822``: added ``action_mark_as_read`` field on ``config`` table
+* ``20161117071626``: added the internal setting to share articles to unmark.it
+* ``20161118134328``: added ``http_status`` field on ``entry`` table
+* ``20161122144743``: added the internal setting to enable/disable fetching articles with paywall
+* ``20161122203647``: dropped ``expired`` and ``credentials_expired`` fields on ``user`` table
+* ``20161128084725``: added ``list_mode`` field on ``config`` table
+* ``20161128131503``: dropped ``locked``, ``credentials_expire_at`` and ``expires_at`` fields on ``user`` table
+* ``20161214094403``: added ``uid`` index on ``entry`` table
+
+Upgrade on a shared hosting
+===========================
+
+Backup your ``app/config/parameters.yml`` file.
+
+Download the last release of wallabag:
+
+.. code-block:: bash
+
+ wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+
+You will find the `md5 hash of the latest package on our website `_.
+
+Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours.
+
+Please check that your ``app/config/parameters.yml`` contains all the required parameters. You can find `here a documentation about parameters `_.
+
+If you use SQLite, you must also copy your ``data/`` folder inside the new installation.
+
+Empty ``var/cache`` folder.
+
+You must run some SQL queries to upgrade your database. We assume that the table prefix is ``wallabag_``. Don't forgete to backup your database before migrating.
+
+You may encounter issues with indexes names: if so, please change queries with the correct index name.
+
+`You can find all the queries here `_.
+
+***************************
Upgrade from 2.0.x to 2.1.1
----------------------------
+***************************
.. warning::
Before this migration, if you configured the Pocket import by adding your consumer key in Internal settings, please do a backup of it: you'll have to add it into the Config page after the upgrade.
Upgrade on a dedicated web server
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+=================================
::
@@ -28,7 +94,7 @@ Upgrade on a dedicated web server
php bin/console cache:clear --env=prod
Upgrade on a shared hosting
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+===========================
Backup your ``app/config/parameters.yml`` file.
@@ -60,41 +126,9 @@ You must run some SQL queries to upgrade your database. We assume that the table
ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
-Upgrading from 2.1.x to 2.1.y
------------------------------
-
-Upgrade on a dedicated web server
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In order to upgrade your wallabag installation and get the last version, run the following command in you wallabag folder:
-
-::
-
- make update
-
-Upgrade on a shared hosting
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Backup your ``app/config/parameters.yml`` file.
-
-Download the last release of wallabag:
-
-.. code-block:: bash
-
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
-
-You will find the `md5 hash of the latest package on our website `_.
-
-Extract the archive in your wallabag folder and replace ``app/config/parameters.yml`` with yours.
-
-Please check that your ``app/config/parameters.yml`` contains all the required parameters. You can find `here a documentation about parameters `_.
-
-If you use SQLite, you must also copy your ``data/`` folder inside the new installation.
-
-Empty ``var/cache`` folder.
-
+*****************
From wallabag 1.x
------------------
+*****************
There is no automatic script to update from wallabag 1.x to wallabag 2.x. You need to:
diff --git a/docs/fr/developer/asynchronous.rst b/docs/fr/developer/asynchronous.rst
index c5489228..ff22daea 100644
--- a/docs/fr/developer/asynchronous.rst
+++ b/docs/fr/developer/asynchronous.rst
@@ -49,6 +49,7 @@ Modifiez votre fichier ``app/config/parameters.yml`` pour éditer la configurati
rabbitmq_port: 5672
rabbitmq_user: guest
rabbitmq_password: guest
+ rabbitmq_prefetch_count: 10 # lire http://www.rabbitmq.com/consumer-prefetch.html
Activer RabbitMQ dans wallabag
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -150,7 +151,7 @@ En fonction du service dont vous souhaitez importer vos données, vous devez act
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# for Chrome import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
Si vous souhaitez démarrer l'import pour quelques messages uniquement, vous pouvez spécifier cette valeur en paramètre (ici 12) et le client va s'arrêter après le 12ème message :
diff --git a/docs/fr/developer/maintenance.rst b/docs/fr/developer/maintenance.rst
deleted file mode 100644
index 8007a85f..00000000
--- a/docs/fr/developer/maintenance.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-Mode maintenance
-================
-
-Si vous devez effectuer de longues tâches sur votre instance de wallabag, vous pouvez activer le mode maintenance.
-Plus personne ne pourra accéder à wallabag.
-
-Activer le mode maintenance
----------------------------
-
-Pour activer le mode maintenance, exécutez cette commande :
-
-::
-
- bin/console lexik:maintenance:lock --no-interaction -e=prod
-
-Vous pouvez spécifier votre adresse IP dans ``app/config/config.yml`` si vous souhaitez accéder à wallabag même si
- le mode maintenance est activé. Par exemple :
-
-::
-
- lexik_maintenance:
- authorized:
- ips: ['127.0.0.1']
-
-
-Désactiver le mode maintenance
-------------------------------
-
-Pour désactiver le mode maintenance, exécutez cette commande :
-
-::
-
- bin/console lexik:maintenance:unlock -e=prod
diff --git a/docs/fr/developer/paywall.rst b/docs/fr/developer/paywall.rst
new file mode 100644
index 00000000..c1c410b1
--- /dev/null
+++ b/docs/fr/developer/paywall.rst
@@ -0,0 +1,56 @@
+Articles derrière un paywall
+============================
+
+wallabag peut récupérer le contenu des articles des sites qui utilisent un système de paiement.
+
+Activer l'authentification pour les paywall
+-------------------------------------------
+
+Dans les paramètres internes, section **Article**, activez l'authentification pour les articles derrière un paywall (avec la valeur 1).
+
+Configurer les accès dans wallabag
+----------------------------------
+
+Ãditez le fichier ``app/config/parameters.yml`` pour modifier les accès aux sites avec paywall. Voici un exemple pour certains sites :
+
+.. code:: yaml
+
+ sites_credentials:
+ mediapart.fr: {username: "myMediapartLogin", password: "mypassword"}
+ arretsurimages.net: {username: "myASILogin", password: "mypassword"}
+
+.. note::
+
+ Ces accès seront partagés entre chaque utilisateur de votre instance wallabag.
+
+Fichiers de configuration pour parser les articles
+--------------------------------------------------
+
+.. note::
+
+ Lisez `cette documentation `_ pour en savoir plus sur ces fichiers de configuration.
+
+Chaque fichier de configuration doit être enrichi en ajoutant ``requires_login``, ``login_uri``,
+``login_username_field``, ``login_password_field`` et ``not_logged_in_xpath``.
+
+Attention, le formulaire de connexion doit se trouver dans le contenu de la page lors du chargement de celle-ci.
+Il sera impossible pour wallabag de se connecter à un site dont le formulaire de connexion est chargé après coup (en ajax par exemple).
+
+``login_uri`` correspond à l'URL à laquelle le formulaire est soumis (attribut ``action`` du formulaire).
+``login_username_field`` correspond à l'attribut ``name`` du champ de l'identifiant.
+``login_password_field`` correspond à l'attribut ``name`` du champ du mot de passe.
+
+Par exemple :
+
+.. code::
+
+ title://div[@id="titrage-contenu"]/h1[@class="title"]
+ body: //div[@class="contenu-html"]/div[@class="page-pane"]
+
+ requires_login: yes
+
+ login_uri: http://www.arretsurimages.net/forum/login.php
+ login_username_field: username
+ login_password_field: password
+
+ not_logged_in_xpath: //body[@class="not-logged-in"]
diff --git a/docs/fr/developer/translate.rst b/docs/fr/developer/translate.rst
index 902c29ad..870d1c20 100644
--- a/docs/fr/developer/translate.rst
+++ b/docs/fr/developer/translate.rst
@@ -21,7 +21,7 @@ où CODE est le code ISO 639-1 de votre langue (`cf wikipedia `_, ce qui signifie que vous trouverez la page suivante (``next``), précédente (``previous``) et la dernière (``last``) dans la balise `` de chaque flux RSS.
+
Mon compte
----------
Vous pouvez ici modifier votre nom, votre adresse email et activer la ``Double authentification``.
+Si l'instance de wallabag compte plus d'un utilisateur actif, vous pouvez supprimer ici votre compte. **Attention, nous supprimons toutes vos données**.
+
Double authentification (2FA)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/fr/user/filters.rst b/docs/fr/user/filters.rst
index 449bf010..5807bdbd 100644
--- a/docs/fr/user/filters.rst
+++ b/docs/fr/user/filters.rst
@@ -30,6 +30,11 @@ Langage
wallabag (via graby) peut détecter la langue dans laquelle l'article est écrit.
C'est ainsi facile pour vous de retrouver des articles écrits dans une langue spécifique.
+Statut HTTP
+-----------
+
+Vous pouvez retrouver des articles en filtrant par leur code HTTP : 200, 404, 500, etc.
+
Temps de lecture
----------------
diff --git a/docs/fr/user/import.rst b/docs/fr/user/import.rst
index a5d53247..9a2dda8f 100644
--- a/docs/fr/user/import.rst
+++ b/docs/fr/user/import.rst
@@ -1,13 +1,13 @@
Migrer depuis ...
=================
-Dans wallabag 2.x, vous pouvez importer des données depuis :
+Dans wallabag 2.x, vous pouvez importer des données depuis :
-- `Pocket <#id1>`_
-- `Readability <#id2>`_
-- `Instapaper <#id4>`_
-- `wallabag 1.x <#id6>`_
-- `wallabag 2.x <#id7>`_
+- `Pocket <#id1>`_
+- `Readability <#id2>`_
+- `Instapaper <#id4>`_
+- `wallabag 1.x <#id6>`_
+- `wallabag 2.x <#id7>`_
Nous avons aussi développé `un script pour exécuter des migrations via la ligne de commande <#import-via-la-ligne-de-commande-cli>`_.
@@ -58,8 +58,24 @@ la section Readability et ensuite sélectionnez votre fichier json pour l'upload
Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur.
-Instapaper
-----------
+Depuis Pinboard
+---------------
+
+Exportez vos données de Pinboard
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sur la page « Backup » (`https://pinboard.in/settings/backup `_), cliquez sur « JSON » dans la section « Bookmarks ». Un fichier json (sans extension) sera téléchargé (``pinboard_export``).
+
+Importez vos données dans wallabag 2.x
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Cliquez sur le lien ``Importer`` dans le menu, sur ``Importer les contenus`` dans
+la section Pinboard et ensuite sélectionnez votre fichier json pour l'uploader.
+
+Vos données vont être importées. L'import de données est une action qui peut être couteuse pour votre serveur.
+
+Depuis Instapaper
+-----------------
Exportez vos données de Instapaper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -136,4 +152,4 @@ Vous obtiendrez :
Start : 05-04-2016 11:36:07 ---
403 imported
0 already saved
- End : 05-04-2016 11:36:09 ---
\ No newline at end of file
+ End : 05-04-2016 11:36:09 ---
diff --git a/docs/fr/user/installation.rst b/docs/fr/user/installation.rst
index f6afcda6..9ef5ee98 100644
--- a/docs/fr/user/installation.rst
+++ b/docs/fr/user/installation.rst
@@ -16,7 +16,7 @@ Installation de Composer :
::
- curl -s http://getcomposer.org/installer | php
+ curl -s https://getcomposer.org/installer | php
Vous pouvez trouver des instructions spécifiques `ici (en anglais) `__.
@@ -82,7 +82,7 @@ Exécutez cette commande pour télécharger et décompresser l'archive :
.. code-block:: bash
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+ wget https://wllbg.org/latest-v2-package && tar xvf latest-v2-package
Vous trouverez `le hash md5 du dernier package sur notre site `_.
diff --git a/docs/fr/user/parameters.rst b/docs/fr/user/parameters.rst
index d1c20ceb..b2e33524 100644
--- a/docs/fr/user/parameters.rst
+++ b/docs/fr/user/parameters.rst
@@ -39,6 +39,7 @@ Si vous ne savez pas quelle valeur vous devez mettre, laissez celle par défaut.
redis_host: localhost
redis_port: 6379
redis_path: null
+ redis_password: null
Meaning of each parameter
-------------------------
@@ -91,3 +92,4 @@ Meaning of each parameter
"redis_host", "localhost", "IP ou hôte du serveur cible (ignoré pour un schéma unix)"
"redis_port", "6379", "Port TCP/IP du serveur cible (ignoré pour un schéma unix)"
"redis_path", "null", "Chemin du fichier de socket du domaine UNIX utilisé quand on se connecte à Redis en utilisant les sockets du domaine UNIX"
+ "redis_password", "null", "Mot de passe défini dans la configuration serveur de Redis (paramètre `requirepass` dans `redis.conf`)"
diff --git a/docs/fr/user/query-upgrade-21-22.rst b/docs/fr/user/query-upgrade-21-22.rst
new file mode 100644
index 00000000..cd201dc2
--- /dev/null
+++ b/docs/fr/user/query-upgrade-21-22.rst
@@ -0,0 +1,797 @@
+Migration 20161001072726
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBA364942
+ ALTER TABLE wallabag_entry_tag DROP FOREIGN KEY FK_C9F0DD7CBAD26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP FOREIGN KEY FK_A7AED006BA364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cba364942
+ ALTER TABLE wallabag_entry_tag DROP CONSTRAINT fk_c9f0dd7cbad26311
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_entry_tag ADD CONSTRAINT FK_entry_tag_tag FOREIGN KEY (tag_id) REFERENCES wallabag_tag (id) ON DELETE CASCADE
+ ALTER TABLE wallabag_annotation DROP CONSTRAINT fk_a7aed006ba364942
+ ALTER TABLE wallabag_annotation ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES wallabag_entry (id) ON DELETE CASCADE
+
+Migration down
+""""""""""""""
+
+We didn't write down migration for ``20161001072726``.
+
+SQLite
+^^^^^^
+
+This migration can only be executed safely on MySQL or PostgreSQL.
+
+Migration 20161022134138
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE confirmation_token confirmation_token VARCHAR(180) DEFAULT NULL;
+ ALTER TABLE wallabag_user CHANGE salt salt VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_user CHANGE password password VARCHAR(180) NOT NULL;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER DATABASE wallabag CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `text` `text` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_annotation CHANGE `quote` `quote` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `title` `title` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_entry CHANGE `content` `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_tag CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+ ALTER TABLE wallabag_user CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;
+
+PostgreSQL and SQLite
+^^^^^^^^^^^^^^^^^^^^^
+
+This migration only apply to MySQL.
+
+Migration 20161024212538
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT NOT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP FOREIGN KEY IDX_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients ADD user_id INT DEFAULT NULL
+ ALTER TABLE wallabag_oauth2_clients ADD CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_oauth2_clients DROP CONSTRAINT idx_user_oauth_client
+ ALTER TABLE wallabag_oauth2_clients DROP user_id
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id), CONSTRAINT IDX_user_oauth_client FOREIGN KEY (user_id) REFERENCES wallabag_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+ CREATE INDEX IDX_635D765EA76ED395 ON wallabag_oauth2_clients (user_id)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_635D765EA76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM wallabag_oauth2_clients
+ DROP TABLE wallabag_oauth2_clients
+ CREATE TABLE wallabag_oauth2_clients (id INTEGER NOT NULL, random_id VARCHAR(255) NOT NULL COLLATE BINARY, redirect_uris CLOB NOT NULL COLLATE BINARY, secret VARCHAR(255) NOT NULL COLLATE BINARY, allowed_grant_types CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_oauth2_clients (id, random_id, redirect_uris, secret, allowed_grant_types, name) SELECT id, random_id, redirect_uris, secret, allowed_grant_types, name FROM __temp__wallabag_oauth2_clients
+ DROP TABLE __temp__wallabag_oauth2_clients
+
+Migration 20161031132655
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('download_images_enabled', 0, 'misc')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'download_images_enabled';
+
+Migration 20161104073720
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_created_at
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX IDX_entry_created_at ON wallabag_entry (created_at)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_created_at
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+
+Migration 20161106113822
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD action_mark_as_read INT DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP action_mark_as_read
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN action_mark_as_read INTEGER DEFAULT 0
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161117071626
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('share_unmark', 0, 'entry')
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'share_unmark';
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'unmark_url';
+
+Migration 20161118134328
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry DROP http_status
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_entry ADD COLUMN http_status VARCHAR(3) DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uuid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uuid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+
+Migration 20161122144743
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ INSERT INTO wallabag_craue_config_setting (name, value, section) VALUES ('restricted_access', 0, 'entry')
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DELETE FROM wallabag_craue_config_setting WHERE name = 'restricted_access';
+
+Migration 20161122203647
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired, DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL, ADD credentials_expired SMALLINT DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP expired
+ ALTER TABLE wallabag_user DROP credentials_expired
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expired SMALLINT DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, locked BOOLEAN NOT NULL, expires_at DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, credentials_expire_at DATETIME DEFAULT NULL, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, locked, expires_at, confirmation_token, password_requested_at, roles, credentials_expire_at, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN expired SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expired SMALLINT DEFAULT NULL
+
+Migration 20161128084725
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD list_mode INT DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config DROP list_mode
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_config ADD COLUMN list_mode INTEGER DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_87E64C53A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_config AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM wallabag_config
+ DROP TABLE wallabag_config
+ CREATE TABLE wallabag_config (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, theme VARCHAR(255) NOT NULL COLLATE BINARY, items_per_page INTEGER NOT NULL, language VARCHAR(255) NOT NULL COLLATE BINARY, rss_token VARCHAR(255) DEFAULT NULL COLLATE BINARY, rss_limit INTEGER DEFAULT NULL, reading_speed DOUBLE PRECISION DEFAULT NULL, pocket_consumer_key VARCHAR(255) DEFAULT NULL COLLATE BINARY, PRIMARY KEY(id))
+ INSERT INTO wallabag_config (id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key) SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key FROM __temp__wallabag_config
+ DROP TABLE __temp__wallabag_config
+ CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON wallabag_config (user_id)
+
+Migration 20161128131503
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked, DROP credentials_expire_at, DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL, ADD credentials_expire_at DATETIME DEFAULT NULL, ADD expires_at DATETIME DEFAULT NULL
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user DROP locked
+ ALTER TABLE wallabag_user DROP credentials_expire_at
+ ALTER TABLE wallabag_user DROP expires_at
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD credentials_expire_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+ ALTER TABLE wallabag_user ADD expires_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ ALTER TABLE wallabag_user ADD COLUMN locked SMALLINT DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN credentials_expire_at DATETIME DEFAULT NULL
+ ALTER TABLE wallabag_user ADD COLUMN expires_at DATETIME DEFAULT NULL
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX UNIQ_1D63E7E592FC23A8
+ DROP INDEX UNIQ_1D63E7E5A0D96FBF
+ DROP INDEX UNIQ_1D63E7E5C05FB297
+ CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM wallabag_user
+ DROP TABLE wallabag_user
+ CREATE TABLE wallabag_user (id INTEGER NOT NULL, username VARCHAR(180) NOT NULL COLLATE BINARY, username_canonical VARCHAR(180) NOT NULL COLLATE BINARY, email VARCHAR(180) NOT NULL COLLATE BINARY, email_canonical VARCHAR(180) NOT NULL COLLATE BINARY, enabled BOOLEAN NOT NULL, salt VARCHAR(255) NOT NULL COLLATE BINARY, password VARCHAR(255) NOT NULL COLLATE BINARY, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL COLLATE BINARY, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL COLLATE BINARY, name CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, twoFactorAuthentication BOOLEAN NOT NULL, trusted CLOB DEFAULT NULL COLLATE BINARY, expired SMALLINT DEFAULT NULL, credentials_expired SMALLINT DEFAULT NULL, PRIMARY KEY(id))
+ INSERT INTO wallabag_user (id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired) SELECT id, username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles, name, created_at, updated_at, authCode, twoFactorAuthentication, trusted, expired, credentials_expired FROM __temp__wallabag_user
+ DROP TABLE __temp__wallabag_user
+ CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON wallabag_user (username_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON wallabag_user (email_canonical)
+ CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON wallabag_user (confirmation_token)
+
+Migration 20161214094403
+------------------------
+
+MySQL
+^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid ON wallabag_entry
+
+PostgreSQL
+^^^^^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX idx_entry_uid
+
+SQLite
+^^^^^^
+
+Migration up
+""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_F4D18282A76ED395
+ DROP INDEX created_at_idx
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_entry_uid ON wallabag_entry (uid)
+
+Migration down
+""""""""""""""
+
+.. code-block:: sql
+
+ DROP INDEX IDX_entry_uid
+ DROP INDEX created_at_idx
+ DROP INDEX IDX_F4D18282A76ED395
+ CREATE TEMPORARY TABLE __temp__wallabag_entry AS SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM wallabag_entry
+ DROP TABLE wallabag_entry
+ CREATE TABLE wallabag_entry (id INTEGER NOT NULL, user_id INTEGER DEFAULT NULL, uid CLOB DEFAULT NULL COLLATE BINARY, title CLOB DEFAULT NULL COLLATE BINARY, url CLOB DEFAULT NULL COLLATE BINARY, is_archived BOOLEAN NOT NULL, is_starred BOOLEAN NOT NULL, content CLOB DEFAULT NULL COLLATE BINARY, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, mimetype CLOB DEFAULT NULL COLLATE BINARY, language CLOB DEFAULT NULL COLLATE BINARY, reading_time INTEGER DEFAULT NULL, domain_name CLOB DEFAULT NULL COLLATE BINARY, preview_picture CLOB DEFAULT NULL COLLATE BINARY, is_public BOOLEAN DEFAULT '0', PRIMARY KEY(id))
+ INSERT INTO wallabag_entry (id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public) SELECT id, user_id, uid, title, url, is_archived, is_starred, content, created_at, updated_at, mimetype, language, reading_time, domain_name, preview_picture, is_public FROM __temp__wallabag_entry
+ DROP TABLE __temp__wallabag_entry
+ CREATE INDEX created_at_idx ON wallabag_entry (created_at)
+ CREATE INDEX IDX_F4D18282A76ED395 ON wallabag_entry (user_id)
diff --git a/docs/fr/user/upgrade.rst b/docs/fr/user/upgrade.rst
index c3d33904..088b19a0 100644
--- a/docs/fr/user/upgrade.rst
+++ b/docs/fr/user/upgrade.rst
@@ -3,41 +3,53 @@ Mettre à jour votre installation de wallabag
Vous trouverez ici différentes manières de mettre à jour wallabag :
+- `de la 2.1.x à la 2.2.x <#mettre-a-jour-de-la-2-1-x-a-la-2-2-x>`_
- `de la 2.0.x à la 2.1.1 <#mettre-a-jour-de-la-2-0-x-a-la-2-1-1>`_
-- `de la 2.1.x à la 2.1.y <#mettre-a-jour-de-la-2-1-x-a-la-2-1-y>`_
- `de la 1.x à la 2.x <#depuis-wallabag-1-x>`_
-Mettre à jour de la 2.0.x à la 2.1.1
+Mettre à jour de la 2.1.x à la 2.2.x
------------------------------------
-.. warning::
-Avant cette migration, si vous aviez configuré l'import depuis Pocket en ajoutant votre consumer key dans les paramètres internes, pensez à effectuer une sauvegarde de celle-ci : vous devrez l'ajouter dans la configuration de wallabag après la mise à jour.
-
Mise à jour sur un serveur dédié
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- rm -rf var/cache/*
- git fetch origin
- git fetch --tags
- git checkout 2.1.1 --force
- SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
- php bin/console doctrine:migrations:migrate --env=prod
- php bin/console cache:clear --env=prod
+ make update
+
+Explications à propos des migrations de base de données
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Durant la mise à jour, nous exécutons des migrations de base de données.
+
+Toutes les migrations de base de données sont stockées dans le dossier ``app/DoctrineMigrations``. Vous pouvez exécuter chaque migration individuellement :
+``bin/console doctrine:migrations:execute 20161001072726 --env=prod``.
+
+Voici la liste des migrations de la 2.1.x à la 2.2.0 :
+
+* ``20161001072726``: ajout de clés étrangères pour la réinitialisation de compte
+* ``20161022134138``: conversion de la base de données à l'encodage ``utf8mb4`` (pour MySQL uniquement)
+* ``20161024212538``: ajout de la colonne ``user_id`` sur la table ``oauth2_clients`` pour empêcher les utilisateurs de supprimer des clients API d'autres utilisateurs
+* ``20161031132655``: ajout du paramètre interne pour activer/désactiver le téléchargement des images
+* ``20161104073720``: ajout de l'index ``created_at`` sur la table ``entry``
+* ``20161106113822``: ajout du champ ``action_mark_as_read`` sur la table ``config``
+* ``20161117071626``: ajout du paramètre interne pour partager ses articles vers unmark.it
+* ``20161118134328``: ajout du champ ``http_status`` sur la table ``entry``
+* ``20161122144743``: ajout du paramètre interne pour activer/désactiver la récupération d'articles derrière un paywall
+* ``20161122203647``: suppression des champs ``expired`` et ``credentials_expired`` sur la table ``user``
Mise à jour sur un hébergement mutualisé
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Effectuez une sauvegarde du fichier ``app/config/parameters.yml``.
-Téléchargez la version 2.1.1 de wallabag :
+Téléchargez la dernière version de wallabag :
.. code-block:: bash
- wget http://framabag.org/wallabag-release-2.1.1.tar.gz && tar xvf wallabag-release-2.1.1.tar.gz
+ wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
-(hash md5 de l'archive 2.1.1 : ``9584a3b60a2b2a4de87f536548caac93``)
+Vous trouverez `le hash md5 du dernier package sur notre site `_.
Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre.
@@ -47,42 +59,42 @@ Si vous utilisez SQLite, vous devez également conserver le contenu du répertoi
Videz le répertoire ``var/cache``.
-Vous allez devoir également exécuter des requêtes SQL pour mettre à jour votre base de données. Nous partons du principe que le préfixe de vos tables est ``wallabag_`` et que le serveur SQL est un serveur MySQL :
+Vous allez devoir également exécuter des requêtes SQL pour mettre à jour votre base de données. Nous partons du principe que le préfixe de vos tables est ``wallabag_``.
-.. code-block:: sql
+`Vous trouverez toutes les requêtes à exécuter ici `_.
- ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
- ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
- INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
- ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
- DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
-Mettre à jour de la 2.1.x à la 2.1.y
+Mettre à jour de la 2.0.x à la 2.1.1
------------------------------------
+.. warning::
+Avant cette migration, si vous aviez configuré l'import depuis Pocket en ajoutant votre consumer key dans les paramètres internes, pensez à effectuer une sauvegarde de celle-ci : vous devrez l'ajouter dans la configuration de wallabag après la mise à jour.
+
Mise à jour sur un serveur dédié
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Pour mettre à jour votre installation de wallabag et récupérer la dernière version, exécutez la commande suivante dans votre répertoire d'installation :
-
::
- make update
+ rm -rf var/cache/*
+ git fetch origin
+ git fetch --tags
+ git checkout 2.1.1 --force
+ SYMFONY_ENV=prod composer install --no-dev -o --prefer-dist
+ php bin/console doctrine:migrations:migrate --env=prod
+ php bin/console cache:clear --env=prod
Mise à jour sur un hébergement mutualisé
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Effectuez une sauvegarde du fichier ``app/config/parameters.yml``.
-Téléchargez la dernière version de wallabag :
+Téléchargez la version 2.1.1 de wallabag :
.. code-block:: bash
- wget http://wllbg.org/latest-v2-package && tar xvf latest-v2-package
+ wget http://framabag.org/wallabag-release-2.1.1.tar.gz && tar xvf wallabag-release-2.1.1.tar.gz
-Vous trouverez `le hash md5 du dernier package sur notre site `_.
+(hash md5 de l'archive 2.1.1 : ``9584a3b60a2b2a4de87f536548caac93``)
Décompressez l'archive dans votre répertoire d'installation et remplacez le fichier ``app/config/parameters.yml`` avec le votre.
@@ -92,6 +104,18 @@ Si vous utilisez SQLite, vous devez également conserver le contenu du répertoi
Videz le répertoire ``var/cache``.
+Vous allez devoir également exécuter des requêtes SQL pour mettre à jour votre base de données. Nous partons du principe que le préfixe de vos tables est ``wallabag_`` et que le serveur SQL est un serveur MySQL :
+
+.. code-block:: sql
+
+ ALTER TABLE `wallabag_entry` ADD `uuid` LONGTEXT DEFAULT NULL;
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('share_public', '1', 'entry');
+ ALTER TABLE `wallabag_oauth2_clients` ADD name longtext COLLATE 'utf8_unicode_ci' DEFAULT NULL;
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_redis', '0', 'import');
+ INSERT INTO `wallabag_craue_config_setting` (`name`, `value`, `section`) VALUES ('import_with_rabbitmq', '0', 'import');
+ ALTER TABLE `wallabag_config` ADD `pocket_consumer_key` VARCHAR(255) DEFAULT NULL;
+ DELETE FROM `wallabag_craue_config_setting` WHERE `name` = 'pocket_consumer_key';
+
Depuis wallabag 1.x
-------------------
diff --git a/package.json b/package.json
index ace74c7f..209c46c6 100644
--- a/package.json
+++ b/package.json
@@ -100,5 +100,9 @@
"stylelint": "^7.3.1",
"stylelint-config-standard": "^13.0.2",
"through": "^2.3.8"
+ },
+ "dependencies": {
+ "jr-qrcode": "^1.0.5",
+ "mousetrap": "^1.6.0"
}
}
diff --git a/scripts/update.sh b/scripts/update.sh
index a29e0168..e6ed58b7 100644
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -16,4 +16,5 @@ git fetch --tags
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
git checkout $TAG --force
SYMFONY_ENV=$ENV $COMPOSER_COMMAND install --no-dev -o --prefer-dist
+php bin/console doctrine:migrations:migrate --no-interaction --env=$ENV
php bin/console cache:clear --env=$ENV
diff --git a/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php b/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
index ad083e31..c13a034f 100644
--- a/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
+++ b/src/Wallabag/AnnotationBundle/Controller/WallabagAnnotationController.php
@@ -3,9 +3,8 @@
namespace Wallabag\AnnotationBundle\Controller;
use FOS\RestBundle\Controller\FOSRestController;
-use Nelmio\ApiDocBundle\Annotation\ApiDoc;
+use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Wallabag\AnnotationBundle\Entity\Annotation;
use Wallabag\CoreBundle\Entity\Entry;
@@ -15,42 +14,35 @@ class WallabagAnnotationController extends FOSRestController
/**
* Retrieve annotations for an entry.
*
- * @ApiDoc(
- * requirements={
- * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
- * }
- * )
+ * @param Entry $entry
+ *
+ * @see Wallabag\ApiBundle\Controller\WallabagRestController
*
- * @return Response
+ * @return JsonResponse
*/
public function getAnnotationsAction(Entry $entry)
{
$annotationRows = $this
- ->getDoctrine()
- ->getRepository('WallabagAnnotationBundle:Annotation')
- ->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId());
+ ->getDoctrine()
+ ->getRepository('WallabagAnnotationBundle:Annotation')
+ ->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId());
$total = count($annotationRows);
$annotations = ['total' => $total, 'rows' => $annotationRows];
$json = $this->get('serializer')->serialize($annotations, 'json');
- return $this->renderJsonResponse($json);
+ return (new JsonResponse())->setJson($json);
}
/**
* Creates a new annotation.
*
- * @param Entry $entry
+ * @param Request $request
+ * @param Entry $entry
*
- * @ApiDoc(
- * requirements={
- * {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
- * {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the annotation"},
- * {"name"="text", "dataType"="string", "required"=true, "description"=""},
- * }
- * )
+ * @return JsonResponse
*
- * @return Response
+ * @see Wallabag\ApiBundle\Controller\WallabagRestController
*/
public function postAnnotationAction(Request $request, Entry $entry)
{
@@ -75,21 +67,20 @@ class WallabagAnnotationController extends FOSRestController
$json = $this->get('serializer')->serialize($annotation, 'json');
- return $this->renderJsonResponse($json);
+ return (new JsonResponse())->setJson($json);
}
/**
* Updates an annotation.
*
- * @ApiDoc(
- * requirements={
- * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
- * }
- * )
+ * @see Wallabag\ApiBundle\Controller\WallabagRestController
*
* @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
*
- * @return Response
+ * @param Annotation $annotation
+ * @param Request $request
+ *
+ * @return JsonResponse
*/
public function putAnnotationAction(Annotation $annotation, Request $request)
{
@@ -104,21 +95,19 @@ class WallabagAnnotationController extends FOSRestController
$json = $this->get('serializer')->serialize($annotation, 'json');
- return $this->renderJsonResponse($json);
+ return (new JsonResponse())->setJson($json);
}
/**
* Removes an annotation.
*
- * @ApiDoc(
- * requirements={
- * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
- * }
- * )
+ * @see Wallabag\ApiBundle\Controller\WallabagRestController
*
* @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
*
- * @return Response
+ * @param Annotation $annotation
+ *
+ * @return JsonResponse
*/
public function deleteAnnotationAction(Annotation $annotation)
{
@@ -128,19 +117,6 @@ class WallabagAnnotationController extends FOSRestController
$json = $this->get('serializer')->serialize($annotation, 'json');
- return $this->renderJsonResponse($json);
- }
-
- /**
- * Send a JSON Response.
- * We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string.
- *
- * @param string $json
- *
- * @return Response
- */
- private function renderJsonResponse($json, $code = 200)
- {
- return new Response($json, $code, ['application/json']);
+ return (new JsonResponse())->setJson($json);
}
}
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
* @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;
diff --git a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
index 5f7da70e..8d3f07ee 100644
--- a/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
+++ b/src/Wallabag/AnnotationBundle/Repository/AnnotationRepository.php
@@ -50,7 +50,8 @@ class AnnotationRepository extends EntityRepository
{
return $this->createQueryBuilder('a')
->andWhere('a.id = :annotationId')->setParameter('annotationId', $annotationId)
- ->getQuery()->getSingleResult()
+ ->getQuery()
+ ->getSingleResult()
;
}
@@ -67,7 +68,8 @@ class AnnotationRepository extends EntityRepository
return $this->createQueryBuilder('a')
->where('a.entry = :entryId')->setParameter('entryId', $entryId)
->andwhere('a.user = :userId')->setParameter('userId', $userId)
- ->getQuery()->getResult()
+ ->getQuery()
+ ->getResult()
;
}
@@ -106,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();
+ }
}
diff --git a/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php b/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php
new file mode 100644
index 00000000..2dd26c07
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/AnnotationRestController.php
@@ -0,0 +1,111 @@
+validateAuthentication();
+
+ return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:getAnnotations', [
+ 'entry' => $entry,
+ ]);
+ }
+
+ /**
+ * Creates a new annotation.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"},
+ * {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the annotation"},
+ * {"name"="text", "dataType"="string", "required"=true, "description"=""},
+ * }
+ * )
+ *
+ * @param Request $request
+ * @param Entry $entry
+ *
+ * @return JsonResponse
+ */
+ public function postAnnotationAction(Request $request, Entry $entry)
+ {
+ $this->validateAuthentication();
+
+ return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:postAnnotation', [
+ 'request' => $request,
+ 'entry' => $entry,
+ ]);
+ }
+
+ /**
+ * Updates an annotation.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
+ * }
+ * )
+ *
+ * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
+ *
+ * @param Annotation $annotation
+ * @param Request $request
+ *
+ * @return JsonResponse
+ */
+ public function putAnnotationAction(Annotation $annotation, Request $request)
+ {
+ $this->validateAuthentication();
+
+ return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:putAnnotation', [
+ 'annotation' => $annotation,
+ 'request' => $request,
+ ]);
+ }
+
+ /**
+ * Removes an annotation.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="annotation", "dataType"="string", "requirement"="\w+", "description"="The annotation ID"}
+ * }
+ * )
+ *
+ * @ParamConverter("annotation", class="WallabagAnnotationBundle:Annotation")
+ *
+ * @param Annotation $annotation
+ *
+ * @return JsonResponse
+ */
+ public function deleteAnnotationAction(Annotation $annotation)
+ {
+ $this->validateAuthentication();
+
+ return $this->forward('WallabagAnnotationBundle:WallabagAnnotation:deleteAnnotation', [
+ 'annotation' => $annotation,
+ ]);
+ }
+}
diff --git a/src/Wallabag/ApiBundle/Controller/DeveloperController.php b/src/Wallabag/ApiBundle/Controller/DeveloperController.php
index 5a36a260..9cb1b626 100644
--- a/src/Wallabag/ApiBundle/Controller/DeveloperController.php
+++ b/src/Wallabag/ApiBundle/Controller/DeveloperController.php
@@ -19,7 +19,7 @@ class DeveloperController extends Controller
*/
public function indexAction()
{
- $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findAll();
+ $clients = $this->getDoctrine()->getRepository('WallabagApiBundle:Client')->findByUser($this->getUser()->getId());
return $this->render('@WallabagCore/themes/common/Developer/index.html.twig', [
'clients' => $clients,
@@ -38,11 +38,11 @@ class DeveloperController extends Controller
public function createClientAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
- $client = new Client();
+ $client = new Client($this->getUser());
$clientForm = $this->createForm(ClientType::class, $client);
$clientForm->handleRequest($request);
- if ($clientForm->isValid()) {
+ if ($clientForm->isSubmitted() && $clientForm->isValid()) {
$client->setAllowedGrantTypes(['token', 'authorization_code', 'password', 'refresh_token']);
$em->persist($client);
$em->flush();
@@ -75,6 +75,10 @@ class DeveloperController extends Controller
*/
public function deleteClientAction(Client $client)
{
+ if (null === $this->getUser() || $client->getUser()->getId() != $this->getUser()->getId()) {
+ throw $this->createAccessDeniedException('You can not access this client.');
+ }
+
$em = $this->getDoctrine()->getManager();
$em->remove($client);
$em->flush();
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
index 24fa7b3b..2c2ec0c1 100644
--- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -10,6 +10,8 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
+use Wallabag\CoreBundle\Event\EntrySavedEvent;
+use Wallabag\CoreBundle\Event\EntryDeletedEvent;
class EntryRestController extends WallabagRestController
{
@@ -148,6 +150,28 @@ class EntryRestController extends WallabagRestController
return (new JsonResponse())->setJson($json);
}
+ /**
+ * Retrieve a single entry as a predefined format.
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return Response
+ */
+ public function getEntryExportAction(Entry $entry, Request $request)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ return $this->get('wallabag_core.helper.entries_export')
+ ->setEntries($entry)
+ ->updateTitle('entry')
+ ->exportAs($request->attributes->get('_format'));
+ }
+
/**
* Create an entry.
*
@@ -200,9 +224,11 @@ class EntryRestController extends WallabagRestController
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
-
$em->flush();
+ // entry saved, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+
$json = $this->get('serializer')->serialize($entry, 'json');
return (new JsonResponse())->setJson($json);
@@ -259,6 +285,51 @@ class EntryRestController extends WallabagRestController
return (new JsonResponse())->setJson($json);
}
+ /**
+ * Reload an entry.
+ * An empty response with HTTP Status 304 will be send if we weren't able to update the content (because it hasn't changed or we got an error).
+ *
+ * @ApiDoc(
+ * requirements={
+ * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
+ * }
+ * )
+ *
+ * @return JsonResponse
+ */
+ public function patchEntriesReloadAction(Entry $entry)
+ {
+ $this->validateAuthentication();
+ $this->validateUserAccess($entry->getUser()->getId());
+
+ try {
+ $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
+ } catch (\Exception $e) {
+ $this->get('logger')->error('Error while saving an entry', [
+ 'exception' => $e,
+ 'entry' => $entry,
+ ]);
+
+ return new JsonResponse([], 304);
+ }
+
+ // if refreshing entry failed, don't save it
+ if ($this->getParameter('wallabag_core.fetching_error_message') === $entry->getContent()) {
+ return new JsonResponse([], 304);
+ }
+
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($entry);
+ $em->flush();
+
+ // entry saved, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+
+ $json = $this->get('serializer')->serialize($entry, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
/**
* Delete **permanently** an entry.
*
@@ -279,6 +350,9 @@ class EntryRestController extends WallabagRestController
$em->remove($entry);
$em->flush();
+ // entry deleted, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
+
$json = $this->get('serializer')->serialize($entry, 'json');
return (new JsonResponse())->setJson($json);
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php
index 4e7ddc66..bc6d4e64 100644
--- a/src/Wallabag/ApiBundle/Controller/TagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php
@@ -131,22 +131,6 @@ class TagRestController extends WallabagRestController
return (new JsonResponse())->setJson($json);
}
- /**
- * Retrieve version number.
- *
- * @ApiDoc()
- *
- * @return JsonResponse
- */
- public function getVersionAction()
- {
- $version = $this->container->getParameter('wallabag_core.version');
-
- $json = $this->get('serializer')->serialize($version, 'json');
-
- return (new JsonResponse())->setJson($json);
- }
-
/**
* Remove orphan tag in case no entries are associated to it.
*
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
index e927a890..b1e08ca4 100644
--- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
@@ -3,11 +3,27 @@
namespace Wallabag\ApiBundle\Controller;
use FOS\RestBundle\Controller\FOSRestController;
+use Nelmio\ApiDocBundle\Annotation\ApiDoc;
+use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
-use Wallabag\CoreBundle\Entity\Entry;
class WallabagRestController extends FOSRestController
{
+ /**
+ * Retrieve version number.
+ *
+ * @ApiDoc()
+ *
+ * @return JsonResponse
+ */
+ public function getVersionAction()
+ {
+ $version = $this->container->getParameter('wallabag_core.version');
+ $json = $this->get('serializer')->serialize($version, 'json');
+
+ return (new JsonResponse())->setJson($json);
+ }
+
protected function validateAuthentication()
{
if (false === $this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
diff --git a/src/Wallabag/ApiBundle/Entity/Client.php b/src/Wallabag/ApiBundle/Entity/Client.php
index f7898ac8..9ed9f980 100644
--- a/src/Wallabag/ApiBundle/Entity/Client.php
+++ b/src/Wallabag/ApiBundle/Entity/Client.php
@@ -4,6 +4,7 @@ namespace Wallabag\ApiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\OAuthServerBundle\Entity\Client as BaseClient;
+use Wallabag\UserBundle\Entity\User;
/**
* @ORM\Table("oauth2_clients")
@@ -21,7 +22,7 @@ class Client extends BaseClient
/**
* @var string
*
- * @ORM\Column(name="name", type="text", nullable=true)
+ * @ORM\Column(name="name", type="text", nullable=false)
*/
protected $name;
@@ -35,9 +36,15 @@ class Client extends BaseClient
*/
protected $accessTokens;
- public function __construct()
+ /**
+ * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="clients")
+ */
+ private $user;
+
+ public function __construct(User $user)
{
parent::__construct();
+ $this->user = $user;
}
/**
@@ -63,4 +70,12 @@ class Client extends BaseClient
return $this;
}
+
+ /**
+ * @return User
+ */
+ public function getUser()
+ {
+ return $this->user;
+ }
}
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index c1af9e02..57d37f4b 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -1,9 +1,19 @@
-entries:
+entry:
type: rest
- resource: "WallabagApiBundle:EntryRest"
+ resource: "WallabagApiBundle:EntryRest"
name_prefix: api_
-tags:
+tag:
type: rest
- resource: "WallabagApiBundle:TagRest"
+ resource: "WallabagApiBundle:TagRest"
+ name_prefix: api_
+
+annotation:
+ type: rest
+ resource: "WallabagApiBundle:AnnotationRest"
+ name_prefix: api_
+
+misc:
+ type: rest
+ resource: "WallabagApiBundle:WallabagRest"
name_prefix: api_
diff --git a/src/Wallabag/CoreBundle/Command/ExportCommand.php b/src/Wallabag/CoreBundle/Command/ExportCommand.php
new file mode 100644
index 00000000..e3d3b399
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Command/ExportCommand.php
@@ -0,0 +1,77 @@
+setName('wallabag:export')
+ ->setDescription('Export all entries for an user')
+ ->setHelp('This command helps you to export all entries for an user')
+ ->addArgument(
+ 'username',
+ InputArgument::REQUIRED,
+ 'User from which to export entries'
+ )
+ ->addArgument(
+ 'filepath',
+ InputArgument::OPTIONAL,
+ 'Path of the exported file'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ try {
+ $user = $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($input->getArgument('username'));
+ } catch (NoResultException $e) {
+ $output->writeln(sprintf('User "%s" not found.', $input->getArgument('username')));
+
+ return 1;
+ }
+
+ $entries = $this->getDoctrine()
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->getBuilderForAllByUser($user->getId())
+ ->getQuery()
+ ->getResult();
+
+ $output->write(sprintf('Exporting %d entrie(s) for user « %s »... ', count($entries), $user->getUserName()));
+
+ $filePath = $input->getArgument('filepath');
+
+ if (!$filePath) {
+ $filePath = $this->getContainer()->getParameter('kernel.root_dir').'/../'.sprintf('%s-export.json', $user->getUsername());
+ }
+
+ try {
+ $data = $this->getContainer()->get('wallabag_core.helper.entries_export')
+ ->setEntries($entries)
+ ->updateTitle('All')
+ ->exportJsonData();
+ file_put_contents($filePath, $data);
+ } catch (\InvalidArgumentException $e) {
+ $output->writeln(sprintf('Error: "%s"', $e->getMessage()));
+
+ return 1;
+ }
+
+ $output->writeln('Done.');
+
+ return 0;
+ }
+
+ private function getDoctrine()
+ {
+ return $this->getContainer()->get('doctrine');
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index 2daf2dd8..f0738b91 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -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('Installing Wallabag...');
+ $output->writeln('Installing wallabag...');
$output->writeln('');
$this
@@ -65,7 +65,7 @@ class InstallCommand extends ContainerAwareCommand
->setupConfig()
;
- $output->writeln('Wallabag has been successfully installed.');
+ $output->writeln('wallabag has been successfully installed.');
$output->writeln('Just execute `php bin/console server:run --env=prod` for using wallabag: http://localhost:8000');
}
@@ -78,7 +78,7 @@ class InstallCommand extends ContainerAwareCommand
// testing if database driver exists
$fulfilled = true;
- $label = 'PDO Driver';
+ $label = 'PDO Driver (%s)';
$status = 'OK!';
$help = '';
@@ -88,7 +88,7 @@ class InstallCommand extends ContainerAwareCommand
$help = 'Database driver "'.$this->getContainer()->getParameter('database_driver').'" is not installed.';
}
- $rows[] = [$label, $status, $help];
+ $rows[] = [sprintf($label, $this->getContainer()->getParameter('database_driver')), $status, $help];
// testing if connection to the database can be etablished
$label = 'Database connection';
@@ -96,7 +96,8 @@ class InstallCommand extends ContainerAwareCommand
$help = '';
try {
- $doctrineManager->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')) {
@@ -108,12 +109,25 @@ class InstallCommand extends ContainerAwareCommand
$rows[] = [$label, $status, $help];
- // testing if PostgreSQL > 9.1
- $label = 'SGBD version';
+ // check MySQL & PostgreSQL version
+ $label = 'Database version';
$status = 'OK!';
$help = '';
- if ('postgresql' === $doctrineManager->getConnection()->getSchemaManager()->getDatabasePlatform()->getName()) {
+ // now check if MySQL isn't too old to handle utf8mb4
+ if ($conn->isConnected() && 'mysql' === $conn->getDatabasePlatform()->getName()) {
+ $version = $conn->query('select version()')->fetchColumn();
+ $minimalVersion = '5.5.4';
+
+ if (false === version_compare($version, $minimalVersion, '>')) {
+ $fulfilled = false;
+ $status = 'ERROR!';
+ $help = 'Your MySQL version ('.$version.') is too old, consider upgrading ('.$minimalVersion.'+).';
+ }
+ }
+
+ // testing if PostgreSQL > 9.1
+ if ($conn->isConnected() && 'postgresql' === $conn->getDatabasePlatform()->getName()) {
// return version should be like "PostgreSQL 9.5.4 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.38), 64-bit"
$version = $doctrineManager->getConnection()->query('SELECT version();')->fetchColumn();
@@ -152,7 +166,7 @@ class InstallCommand extends ContainerAwareCommand
throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.');
}
- $this->defaultOutput->writeln('Success! Your system can run Wallabag properly.');
+ $this->defaultOutput->writeln('Success! Your system can run wallabag properly.');
$this->defaultOutput->writeln('');
@@ -298,6 +312,16 @@ class InstallCommand extends ContainerAwareCommand
'value' => 'http://diasporapod.com',
'section' => 'entry',
],
+ [
+ 'name' => 'share_unmark',
+ 'value' => '1',
+ 'section' => 'entry',
+ ],
+ [
+ 'name' => 'unmark_url',
+ 'value' => 'https://unmark.it',
+ 'section' => 'entry',
+ ],
[
'name' => 'share_shaarli',
'value' => '1',
@@ -375,7 +399,7 @@ class InstallCommand extends ContainerAwareCommand
],
[
'name' => 'wallabag_url',
- 'value' => 'http://v2.wallabag.org',
+ 'value' => '',
'section' => 'misc',
],
[
@@ -403,6 +427,16 @@ class InstallCommand extends ContainerAwareCommand
'value' => 'wallabag',
'section' => 'misc',
],
+ [
+ 'name' => 'download_images_enabled',
+ 'value' => '0',
+ 'section' => 'misc',
+ ],
+ [
+ 'name' => 'restricted_access',
+ 'value' => '0',
+ 'section' => 'entry',
+ ],
];
foreach ($settings as $setting) {
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php
index 46fb9503..907bf78e 100644
--- a/src/Wallabag/CoreBundle/Controller/ConfigController.php
+++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php
@@ -7,6 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Wallabag\CoreBundle\Entity\Config;
use Wallabag\CoreBundle\Entity\TaggingRule;
use Wallabag\CoreBundle\Form\Type\ConfigType;
@@ -34,7 +35,7 @@ class ConfigController extends Controller
$configForm = $this->createForm(ConfigType::class, $config, ['action' => $this->generateUrl('config')]);
$configForm->handleRequest($request);
- if ($configForm->isValid()) {
+ if ($configForm->isSubmitted() && $configForm->isValid()) {
$em->persist($config);
$em->flush();
@@ -56,7 +57,7 @@ class ConfigController extends Controller
$pwdForm = $this->createForm(ChangePasswordType::class, null, ['action' => $this->generateUrl('config').'#set4']);
$pwdForm->handleRequest($request);
- if ($pwdForm->isValid()) {
+ if ($pwdForm->isSubmitted() && $pwdForm->isValid()) {
if ($this->get('craue_config')->get('demo_mode_enabled') && $this->get('craue_config')->get('demo_mode_username') === $user->getUsername()) {
$message = 'flashes.config.notice.password_not_updated_demo';
} else {
@@ -78,7 +79,7 @@ class ConfigController extends Controller
]);
$userForm->handleRequest($request);
- if ($userForm->isValid()) {
+ if ($userForm->isSubmitted() && $userForm->isValid()) {
$userManager->updateUser($user, true);
$this->get('session')->getFlashBag()->add(
@@ -93,7 +94,7 @@ class ConfigController extends Controller
$rssForm = $this->createForm(RssType::class, $config, ['action' => $this->generateUrl('config').'#set2']);
$rssForm->handleRequest($request);
- if ($rssForm->isValid()) {
+ if ($rssForm->isSubmitted() && $rssForm->isValid()) {
$em->persist($config);
$em->flush();
@@ -124,7 +125,7 @@ class ConfigController extends Controller
$newTaggingRule = $this->createForm(TaggingRuleType::class, $taggingRule, ['action' => $action]);
$newTaggingRule->handleRequest($request);
- if ($newTaggingRule->isValid()) {
+ if ($newTaggingRule->isSubmitted() && $newTaggingRule->isValid()) {
$taggingRule->setConfig($config);
$em->persist($taggingRule);
$em->flush();
@@ -150,6 +151,10 @@ class ConfigController extends Controller
'token' => $config->getRssToken(),
],
'twofactor_auth' => $this->getParameter('twofactor_auth'),
+ 'wallabag_url' => $this->get('craue_config')->get('wallabag_url'),
+ 'enabled_users' => $this->getDoctrine()
+ ->getRepository('WallabagUserBundle:User')
+ ->getSumEnabledUsers(),
]);
}
@@ -222,6 +227,78 @@ 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)
+ {
+ 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.
*
@@ -253,4 +330,58 @@ class ConfigController extends Controller
return $config;
}
+
+ /**
+ * Delete account for current user.
+ *
+ * @Route("/account/delete", name="delete_account")
+ *
+ * @param Request $request
+ *
+ * @throws AccessDeniedHttpException
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse
+ */
+ public function deleteAccountAction(Request $request)
+ {
+ $enabledUsers = $this->getDoctrine()
+ ->getRepository('WallabagUserBundle:User')
+ ->getSumEnabledUsers();
+
+ if ($enabledUsers <= 1) {
+ throw new AccessDeniedHttpException();
+ }
+
+ $user = $this->getUser();
+
+ // logout current user
+ $this->get('security.token_storage')->setToken(null);
+ $request->getSession()->invalidate();
+
+ $em = $this->get('fos_user.user_manager');
+ $em->deleteUser($user);
+
+ return $this->redirect($this->generateUrl('fos_user_security_login'));
+ }
+
+ /**
+ * Switch view mode for current user.
+ *
+ * @Route("/config/view-mode", name="switch_view_mode")
+ *
+ * @param Request $request
+ *
+ * @return \Symfony\Component\HttpFoundation\RedirectResponse
+ */
+ public function changeViewModeAction(Request $request)
+ {
+ $user = $this->getUser();
+ $user->getConfig()->setListMode(!$user->getConfig()->getListMode());
+
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($user);
+ $em->flush();
+
+ return $this->redirect($request->headers->get('referer'));
+ }
}
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php
index 97bb3d12..f7398e69 100644
--- a/src/Wallabag/CoreBundle/Controller/EntryController.php
+++ b/src/Wallabag/CoreBundle/Controller/EntryController.php
@@ -13,9 +13,44 @@ use Wallabag\CoreBundle\Form\Type\EntryFilterType;
use Wallabag\CoreBundle\Form\Type\EditEntryType;
use Wallabag\CoreBundle\Form\Type\NewEntryType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
+use Wallabag\CoreBundle\Event\EntrySavedEvent;
+use Wallabag\CoreBundle\Event\EntryDeletedEvent;
+use Wallabag\CoreBundle\Form\Type\SearchEntryType;
class EntryController extends Controller
{
+ /**
+ * @param Request $request
+ * @param int $page
+ *
+ * @Route("/search/{page}", name="search", defaults={"page" = 1})
+ *
+ * Default parameter for page is hardcoded (in duplication of the defaults from the Route)
+ * because this controller is also called inside the layout template without any page as argument
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function searchFormAction(Request $request, $page = 1, $currentRoute = null)
+ {
+ // fallback to retrieve currentRoute from query parameter instead of injected one (when using inside a template)
+ if (null === $currentRoute && $request->query->has('currentRoute')) {
+ $currentRoute = $request->query->get('currentRoute');
+ }
+
+ $form = $this->createForm(SearchEntryType::class);
+
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ return $this->showEntries('search', $request, $page);
+ }
+
+ return $this->render('WallabagCoreBundle:Entry:search_form.html.twig', [
+ 'form' => $form->createView(),
+ 'currentRoute' => $currentRoute,
+ ]);
+ }
+
/**
* Fetch content and update entry.
* In case it fails, entry will return to avod loosing the data.
@@ -63,7 +98,7 @@ class EntryController extends Controller
$form->handleRequest($request);
- if ($form->isValid()) {
+ if ($form->isSubmitted() && $form->isValid()) {
$existingEntry = $this->checkIfEntryAlreadyExists($entry);
if (false !== $existingEntry) {
@@ -81,6 +116,9 @@ class EntryController extends Controller
$em->persist($entry);
$em->flush();
+ // entry saved, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+
return $this->redirect($this->generateUrl('homepage'));
}
@@ -107,6 +145,9 @@ class EntryController extends Controller
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
$em->flush();
+
+ // entry saved, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
}
return $this->redirect($this->generateUrl('homepage'));
@@ -140,7 +181,7 @@ class EntryController extends Controller
$form->handleRequest($request);
- if ($form->isValid()) {
+ if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
$em->flush();
@@ -236,8 +277,14 @@ class EntryController extends Controller
private function showEntries($type, Request $request, $page)
{
$repository = $this->get('wallabag_core.entry_repository');
+ $searchTerm = (isset($request->get('search_entry')['term']) ? $request->get('search_entry')['term'] : '');
+ $currentRoute = (!is_null($request->query->get('currentRoute')) ? $request->query->get('currentRoute') : '');
switch ($type) {
+ case 'search':
+ $qb = $repository->getBuilderForSearchByUser($this->getUser()->getId(), $searchTerm, $currentRoute);
+
+ break;
case 'untagged':
$qb = $repository->getBuilderForUntaggedByUser($this->getUser()->getId());
@@ -272,7 +319,7 @@ class EntryController extends Controller
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $qb);
}
- $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
+ $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
$entries = $this->get('wallabag_core.helper.prepare_pager_for_entries')
->prepare($pagerAdapter, $page);
@@ -286,11 +333,11 @@ class EntryController extends Controller
}
return $this->render(
- 'WallabagCoreBundle:Entry:entries.html.twig',
- [
+ 'WallabagCoreBundle:Entry:entries.html.twig', [
'form' => $form->createView(),
'entries' => $entries,
'currentPage' => $page,
+ 'searchTerm' => $searchTerm,
]
);
}
@@ -343,6 +390,9 @@ class EntryController extends Controller
$em->persist($entry);
$em->flush();
+ // entry saved, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+
return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()]));
}
@@ -431,6 +481,9 @@ class EntryController extends Controller
UrlGeneratorInterface::ABSOLUTE_PATH
);
+ // entry deleted, dispatch event about it!
+ $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
+
$em = $this->getDoctrine()->getManager();
$em->remove($entry);
$em->flush();
@@ -486,8 +539,8 @@ class EntryController extends Controller
{
$this->checkUserAction($entry);
- if (null === $entry->getUuid()) {
- $entry->generateUuid();
+ if (null === $entry->getUid()) {
+ $entry->generateUid();
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
@@ -495,7 +548,7 @@ class EntryController extends Controller
}
return $this->redirect($this->generateUrl('share_entry', [
- 'uuid' => $entry->getUuid(),
+ 'uid' => $entry->getUid(),
]));
}
@@ -512,7 +565,7 @@ class EntryController extends Controller
{
$this->checkUserAction($entry);
- $entry->cleanUuid();
+ $entry->cleanUid();
$em = $this->getDoctrine()->getManager();
$em->persist($entry);
@@ -528,7 +581,7 @@ class EntryController extends Controller
*
* @param Entry $entry
*
- * @Route("/share/{uuid}", requirements={"uuid" = ".+"}, name="share_entry")
+ * @Route("/share/{uid}", requirements={"uid" = ".+"}, name="share_entry")
* @Cache(maxage="25200", smaxage="25200", public=true)
*
* @return \Symfony\Component\HttpFoundation\Response
diff --git a/src/Wallabag/CoreBundle/Controller/ExportController.php b/src/Wallabag/CoreBundle/Controller/ExportController.php
index 79653cfe..abc3336a 100644
--- a/src/Wallabag/CoreBundle/Controller/ExportController.php
+++ b/src/Wallabag/CoreBundle/Controller/ExportController.php
@@ -48,7 +48,7 @@ class ExportController extends Controller
*
* @Route("/export/{category}.{format}", name="export_entries", requirements={
* "format": "epub|mobi|pdf|json|xml|txt|csv",
- * "category": "all|unread|starred|archive|tag_entries|untagged"
+ * "category": "all|unread|starred|archive|tag_entries|untagged|search"
* })
*
* @return \Symfony\Component\HttpFoundation\Response
diff --git a/src/Wallabag/CoreBundle/Controller/RssController.php b/src/Wallabag/CoreBundle/Controller/RssController.php
index 38e3b5a0..92f18707 100644
--- a/src/Wallabag/CoreBundle/Controller/RssController.php
+++ b/src/Wallabag/CoreBundle/Controller/RssController.php
@@ -3,12 +3,15 @@
namespace Wallabag\CoreBundle\Controller;
use Pagerfanta\Adapter\DoctrineORMAdapter;
+use Pagerfanta\Exception\OutOfRangeCurrentPageException;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\UserBundle\Entity\User;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class RssController extends Controller
{
@@ -20,9 +23,9 @@ class RssController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showUnreadAction(User $user)
+ public function showUnreadAction(Request $request, User $user)
{
- return $this->showEntries('unread', $user);
+ return $this->showEntries('unread', $user, $request->query->get('page', 1));
}
/**
@@ -33,9 +36,9 @@ class RssController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showArchiveAction(User $user)
+ public function showArchiveAction(Request $request, User $user)
{
- return $this->showEntries('archive', $user);
+ return $this->showEntries('archive', $user, $request->query->get('page', 1));
}
/**
@@ -46,9 +49,9 @@ class RssController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function showStarredAction(User $user)
+ public function showStarredAction(Request $request, User $user)
{
- return $this->showEntries('starred', $user);
+ return $this->showEntries('starred', $user, $request->query->get('page', 1));
}
/**
@@ -57,10 +60,11 @@ class RssController extends Controller
*
* @param string $type Entries type: unread, starred or archive
* @param User $user
+ * @param int $page
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- private function showEntries($type, User $user)
+ private function showEntries($type, User $user, $page = 1)
{
$repository = $this->getDoctrine()->getRepository('WallabagCoreBundle:Entry');
@@ -81,14 +85,32 @@ class RssController extends Controller
throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
}
- $pagerAdapter = new DoctrineORMAdapter($qb->getQuery());
+ $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
$entries = new Pagerfanta($pagerAdapter);
$perPage = $user->getConfig()->getRssLimit() ?: $this->getParameter('wallabag_core.rss_limit');
$entries->setMaxPerPage($perPage);
+ $url = $this->generateUrl(
+ $type.'_rss',
+ [
+ 'username' => $user->getUsername(),
+ 'token' => $user->getConfig()->getRssToken(),
+ ],
+ UrlGeneratorInterface::ABSOLUTE_URL
+ );
+
+ try {
+ $entries->setCurrentPage((int) $page);
+ } catch (OutOfRangeCurrentPageException $e) {
+ if ($page > 1) {
+ return $this->redirect($url.'?page='.$entries->getNbPages(), 302);
+ }
+ }
+
return $this->render('@WallabagCore/themes/common/Entry/entries.xml.twig', [
'type' => $type,
+ 'url' => $url,
'entries' => $entries,
]);
}
diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php
index 707f3bbe..8a093289 100644
--- a/src/Wallabag/CoreBundle/Controller/TagController.php
+++ b/src/Wallabag/CoreBundle/Controller/TagController.php
@@ -27,7 +27,7 @@ class TagController extends Controller
$form = $this->createForm(NewTagType::class, new Tag());
$form->handleRequest($request);
- if ($form->isValid()) {
+ if ($form->isSubmitted() && $form->isValid()) {
$this->get('wallabag_core.content_proxy')->assignTagsToEntry(
$entry,
$form->get('label')->getData()
@@ -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,
];
}
@@ -143,7 +143,7 @@ class TagController extends Controller
'form' => null,
'entries' => $entries,
'currentPage' => $page,
- 'tag' => $tag->getLabel(),
+ 'tag' => $tag->getSlug(),
]);
}
}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php
index 921c739f..3d4d5def 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php
@@ -21,6 +21,8 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
$adminConfig->setReadingSpeed(1);
$adminConfig->setLanguage('en');
$adminConfig->setPocketConsumerKey('xxxxx');
+ $adminConfig->setActionMarkAsRead(0);
+ $adminConfig->setListMode(0);
$manager->persist($adminConfig);
@@ -32,6 +34,8 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
$bobConfig->setReadingSpeed(1);
$bobConfig->setLanguage('fr');
$bobConfig->setPocketConsumerKey(null);
+ $bobConfig->setActionMarkAsRead(1);
+ $bobConfig->setListMode(1);
$manager->persist($bobConfig);
@@ -43,6 +47,8 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
$emptyConfig->setReadingSpeed(1);
$emptyConfig->setLanguage('en');
$emptyConfig->setPocketConsumerKey(null);
+ $emptyConfig->setActionMarkAsRead(0);
+ $emptyConfig->setListMode(0);
$manager->persist($emptyConfig);
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
index a5e1be65..a723656e 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadSettingData.php
@@ -35,6 +35,16 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface
'value' => 'http://diasporapod.com',
'section' => 'entry',
],
+ [
+ 'name' => 'share_unmark',
+ 'value' => '1',
+ 'section' => 'entry',
+ ],
+ [
+ 'name' => 'unmark_url',
+ 'value' => 'https://unmark.it',
+ 'section' => 'entry',
+ ],
[
'name' => 'share_shaarli',
'value' => '1',
@@ -140,6 +150,16 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface
'value' => 'wallabag',
'section' => 'misc',
],
+ [
+ 'name' => 'download_images_enabled',
+ 'value' => '0',
+ 'section' => 'misc',
+ ],
+ [
+ 'name' => 'restricted_access',
+ 'value' => '0',
+ 'section' => 'entry',
+ ],
];
foreach ($settings as $setting) {
@@ -158,6 +178,6 @@ class LoadSettingData extends AbstractFixture implements OrderedFixtureInterface
*/
public function getOrder()
{
- return 50;
+ return 29;
}
}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
index 09e99f36..6de561e0 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php
@@ -15,7 +15,7 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface
public function load(ObjectManager $manager)
{
$tag1 = new Tag();
- $tag1->setLabel('foo');
+ $tag1->setLabel('foo bar');
$manager->persist($tag1);
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
index 3a3da024..006a18c3 100644
--- a/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
+++ b/src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
@@ -41,6 +41,12 @@ class Configuration implements ConfigurationInterface
->end()
->scalarNode('fetching_error_message')
->end()
+ ->scalarNode('action_mark_as_read')
+ ->defaultValue(1)
+ ->end()
+ ->scalarNode('list_mode')
+ ->defaultValue(1)
+ ->end()
->end()
;
diff --git a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
index b4992d54..aa9ee339 100644
--- a/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
+++ b/src/Wallabag/CoreBundle/DependencyInjection/WallabagCoreExtension.php
@@ -23,6 +23,8 @@ class WallabagCoreExtension extends Extension
$container->setParameter('wallabag_core.version', $config['version']);
$container->setParameter('wallabag_core.paypal_url', $config['paypal_url']);
$container->setParameter('wallabag_core.cache_lifetime', $config['cache_lifetime']);
+ $container->setParameter('wallabag_core.action_mark_as_read', $config['action_mark_as_read']);
+ $container->setParameter('wallabag_core.list_mode', $config['list_mode']);
$container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php
index 69393ac9..b902ae2c 100644
--- a/src/Wallabag/CoreBundle/Entity/Config.php
+++ b/src/Wallabag/CoreBundle/Entity/Config.php
@@ -16,6 +16,9 @@ use Wallabag\UserBundle\Entity\User;
*/
class Config
{
+ const REDIRECT_TO_HOMEPAGE = 0;
+ const REDIRECT_TO_CURRENT_PAGE = 1;
+
/**
* @var int
*
@@ -87,6 +90,20 @@ class Config
*/
private $pocketConsumerKey;
+ /**
+ * @var int
+ *
+ * @ORM\Column(name="action_mark_as_read", type="integer", nullable=true, options={"default" = 0})
+ */
+ private $actionMarkAsRead;
+
+ /**
+ * @var int
+ *
+ * @ORM\Column(name="list_mode", type="integer", nullable=true)
+ */
+ private $listMode;
+
/**
* @ORM\OneToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="config")
*/
@@ -309,6 +326,46 @@ class Config
return $this->pocketConsumerKey;
}
+ /**
+ * @return int
+ */
+ public function getActionMarkAsRead()
+ {
+ return $this->actionMarkAsRead;
+ }
+
+ /**
+ * @param int $actionMarkAsRead
+ *
+ * @return Config
+ */
+ public function setActionMarkAsRead($actionMarkAsRead)
+ {
+ $this->actionMarkAsRead = $actionMarkAsRead;
+
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getListMode()
+ {
+ return $this->listMode;
+ }
+
+ /**
+ * @param int $listMode
+ *
+ * @return Config
+ */
+ public function setListMode($listMode)
+ {
+ $this->listMode = $listMode;
+
+ return $this;
+ }
+
/**
* @param TaggingRule $rule
*
diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php
index f2da3f4d..7276b437 100644
--- a/src/Wallabag/CoreBundle/Entity/Entry.php
+++ b/src/Wallabag/CoreBundle/Entity/Entry.php
@@ -19,7 +19,14 @@ 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"},
+ * indexes={
+ * @ORM\Index(name="created_at", columns={"created_at"}),
+ * @ORM\Index(name="uid", columns={"uid"})
+ * }
+ * )
* @ORM\HasLifecycleCallbacks()
* @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
*/
@@ -40,11 +47,11 @@ class Entry
/**
* @var string
*
- * @ORM\Column(name="uuid", type="text", nullable=true)
+ * @ORM\Column(name="uid", type="string", length=23, nullable=true)
*
* @Groups({"entries_for_user", "export_all"})
*/
- private $uuid;
+ private $uid;
/**
* @var string
@@ -176,6 +183,15 @@ class Entry
*/
private $isPublic;
+ /**
+ * @var string
+ *
+ * @ORM\Column(name="http_status", type="string", length=3, nullable=true)
+ *
+ * @Groups({"entries_for_user", "export_all"})
+ */
+ private $httpStatus;
+
/**
* @Exclude
*
@@ -190,10 +206,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")
* }
* )
*/
@@ -636,33 +652,53 @@ class Entry
/**
* @return string
*/
- public function getUuid()
+ public function getUid()
{
- return $this->uuid;
+ return $this->uid;
}
/**
- * @param string $uuid
+ * @param string $uid
*
* @return Entry
*/
- public function setUuid($uuid)
+ public function setUid($uid)
{
- $this->uuid = $uuid;
+ $this->uid = $uid;
return $this;
}
- public function generateUuid()
+ public function generateUid()
{
- if (null === $this->uuid) {
+ if (null === $this->uid) {
// @see http://blog.kevingomez.fr/til/2015/07/26/why-is-uniqid-slow/ for true parameter
- $this->uuid = uniqid('', true);
+ $this->uid = uniqid('', true);
}
}
- public function cleanUuid()
+ public function cleanUid()
+ {
+ $this->uid = null;
+ }
+
+ /**
+ * @return int
+ */
+ public function getHttpStatus()
+ {
+ return $this->httpStatus;
+ }
+
+ /**
+ * @param int $httpStatus
+ *
+ * @return Entry
+ */
+ public function setHttpStatus($httpStatus)
{
- $this->uuid = null;
+ $this->httpStatus = $httpStatus;
+
+ return $this;
}
}
diff --git a/src/Wallabag/CoreBundle/Entity/TaggingRule.php b/src/Wallabag/CoreBundle/Entity/TaggingRule.php
index 28914cc1..72651b19 100644
--- a/src/Wallabag/CoreBundle/Entity/TaggingRule.php
+++ b/src/Wallabag/CoreBundle/Entity/TaggingRule.php
@@ -28,6 +28,7 @@ class TaggingRule
* @var string
*
* @Assert\NotBlank()
+ * @Assert\Length(max=255)
* @RulerZAssert\ValidRule(
* allowed_variables={"title", "url", "isArchived", "isStared", "content", "language", "mimetype", "readingTime", "domainName"},
* allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches"}
diff --git a/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php
new file mode 100644
index 00000000..e9061d04
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Event/EntryDeletedEvent.php
@@ -0,0 +1,26 @@
+entry = $entry;
+ }
+
+ public function getEntry()
+ {
+ return $this->entry;
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php
new file mode 100644
index 00000000..5fdb5221
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Event/EntrySavedEvent.php
@@ -0,0 +1,26 @@
+entry = $entry;
+ }
+
+ public function getEntry()
+ {
+ return $this->entry;
+ }
+}
diff --git a/src/Wallabag/CoreBundle/EventListener/LocaleListener.php b/src/Wallabag/CoreBundle/Event/Listener/LocaleListener.php
similarity index 96%
rename from src/Wallabag/CoreBundle/EventListener/LocaleListener.php
rename to src/Wallabag/CoreBundle/Event/Listener/LocaleListener.php
index a1c7e5ab..b435d99e 100644
--- a/src/Wallabag/CoreBundle/EventListener/LocaleListener.php
+++ b/src/Wallabag/CoreBundle/Event/Listener/LocaleListener.php
@@ -1,6 +1,6 @@
em = $em;
+ $this->downloadImages = $downloadImages;
+ $this->enabled = $enabled;
+ $this->logger = $logger;
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return [
+ EntrySavedEvent::NAME => 'onEntrySaved',
+ EntryDeletedEvent::NAME => 'onEntryDeleted',
+ ];
+ }
+
+ /**
+ * Download images and updated the data into the entry.
+ *
+ * @param EntrySavedEvent $event
+ */
+ public function onEntrySaved(EntrySavedEvent $event)
+ {
+ if (!$this->enabled) {
+ $this->logger->debug('DownloadImagesSubscriber: disabled.');
+
+ return;
+ }
+
+ $entry = $event->getEntry();
+
+ $html = $this->downloadImages($entry);
+ if (false !== $html) {
+ $this->logger->debug('DownloadImagesSubscriber: updated html.');
+
+ $entry->setContent($html);
+ }
+
+ // update preview picture
+ $previewPicture = $this->downloadPreviewImage($entry);
+ if (false !== $previewPicture) {
+ $this->logger->debug('DownloadImagesSubscriber: update preview picture.');
+
+ $entry->setPreviewPicture($previewPicture);
+ }
+
+ $this->em->persist($entry);
+ $this->em->flush();
+ }
+
+ /**
+ * Remove images related to the entry.
+ *
+ * @param EntryDeletedEvent $event
+ */
+ public function onEntryDeleted(EntryDeletedEvent $event)
+ {
+ if (!$this->enabled) {
+ $this->logger->debug('DownloadImagesSubscriber: disabled.');
+
+ return;
+ }
+
+ $this->downloadImages->removeImages($event->getEntry()->getId());
+ }
+
+ /**
+ * Download all images from the html.
+ *
+ * @todo If we want to add async download, it should be done in that method
+ *
+ * @param Entry $entry
+ *
+ * @return string|false False in case of async
+ */
+ private function downloadImages(Entry $entry)
+ {
+ return $this->downloadImages->processHtml(
+ $entry->getId(),
+ $entry->getContent(),
+ $entry->getUrl()
+ );
+ }
+
+ /**
+ * Download the preview picture.
+ *
+ * @todo If we want to add async download, it should be done in that method
+ *
+ * @param Entry $entry
+ *
+ * @return string|false False in case of async
+ */
+ private function downloadPreviewImage(Entry $entry)
+ {
+ return $this->downloadImages->processSingleImage(
+ $entry->getId(),
+ $entry->getPreviewPicture(),
+ $entry->getUrl()
+ );
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php
new file mode 100644
index 00000000..3b4c4cf9
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Event/Subscriber/SQLiteCascadeDeleteSubscriber.php
@@ -0,0 +1,70 @@
+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();
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Subscriber/TablePrefixSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriber.php
similarity index 91%
rename from src/Wallabag/CoreBundle/Subscriber/TablePrefixSubscriber.php
rename to src/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriber.php
index 0379ad6a..711c3bf8 100644
--- a/src/Wallabag/CoreBundle/Subscriber/TablePrefixSubscriber.php
+++ b/src/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriber.php
@@ -1,6 +1,6 @@
setTableName($this->prefix.$classMetadata->getTableName());
+ $classMetadata->setPrimaryTable(['name' => $this->prefix.$classMetadata->getTableName()]);
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY && isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])) {
diff --git a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php
index 0bac2874..7e3b9dd4 100644
--- a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php
+++ b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php
@@ -7,6 +7,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
+use Wallabag\CoreBundle\Entity\Config;
class ConfigType extends AbstractType
{
@@ -48,6 +49,13 @@ class ConfigType extends AbstractType
'config.form_settings.reading_speed.400_word' => '2',
],
])
+ ->add('action_mark_as_read', ChoiceType::class, [
+ 'label' => 'config.form_settings.action_mark_as_read.label',
+ 'choices' => [
+ 'config.form_settings.action_mark_as_read.redirect_homepage' => Config::REDIRECT_TO_HOMEPAGE,
+ 'config.form_settings.action_mark_as_read.redirect_current_page' => Config::REDIRECT_TO_CURRENT_PAGE,
+ ],
+ ])
->add('language', ChoiceType::class, [
'choices' => array_flip($this->languages),
'label' => 'config.form_settings.language_label',
diff --git a/src/Wallabag/CoreBundle/Form/Type/EntryFilterType.php b/src/Wallabag/CoreBundle/Form/Type/EntryFilterType.php
index a3e36fdd..ee66c728 100644
--- a/src/Wallabag/CoreBundle/Form/Type/EntryFilterType.php
+++ b/src/Wallabag/CoreBundle/Form/Type/EntryFilterType.php
@@ -11,6 +11,7 @@ use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\CheckboxFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\ChoiceFilterType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@@ -89,12 +90,27 @@ class EntryFilterType extends AbstractType
if (strlen($value) <= 2 || empty($value)) {
return;
}
- $expression = $filterQuery->getExpr()->like($field, $filterQuery->getExpr()->literal('%'.$value.'%'));
+ $expression = $filterQuery->getExpr()->like($field, $filterQuery->getExpr()->lower($filterQuery->getExpr()->literal('%'.$value.'%')));
return $filterQuery->createCondition($expression);
},
'label' => 'entry.filters.domain_label',
])
+ ->add('httpStatus', TextFilterType::class, [
+ 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) {
+ $value = $values['value'];
+ if (false === array_key_exists($value, Response::$statusTexts)) {
+ return;
+ }
+
+ $paramName = sprintf('%s', str_replace('.', '_', $field));
+ $expression = $filterQuery->getExpr()->eq($field, ':'.$paramName);
+ $parameters = array($paramName => $value);
+
+ return $filterQuery->createCondition($expression, $parameters);
+ },
+ 'label' => 'entry.filters.http_status_label',
+ ])
->add('isArchived', CheckboxFilterType::class, [
'label' => 'entry.filters.archived_label',
])
diff --git a/src/Wallabag/CoreBundle/Form/Type/NewTagType.php b/src/Wallabag/CoreBundle/Form/Type/NewTagType.php
index 3db4105f..e830ade4 100644
--- a/src/Wallabag/CoreBundle/Form/Type/NewTagType.php
+++ b/src/Wallabag/CoreBundle/Form/Type/NewTagType.php
@@ -3,6 +3,7 @@
namespace Wallabag\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -12,7 +13,15 @@ class NewTagType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
- ->add('label', TextType::class, ['required' => true])
+ ->add('label', TextType::class, [
+ 'required' => true,
+ 'attr' => [
+ 'placeholder' => 'tag.new.placeholder',
+ ],
+ ])
+ ->add('add', SubmitType::class, [
+ 'label' => 'tag.new.add',
+ ])
;
}
diff --git a/src/Wallabag/CoreBundle/Form/Type/SearchEntryType.php b/src/Wallabag/CoreBundle/Form/Type/SearchEntryType.php
new file mode 100644
index 00000000..b56cae8e
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Form/Type/SearchEntryType.php
@@ -0,0 +1,29 @@
+setMethod('GET')
+ ->add('term', TextType::class, [
+ 'required' => true,
+ 'label' => 'entry.new.form_search.term_label',
+ ])
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $resolver->setDefaults([
+ 'csrf_protection' => false,
+ ]);
+ }
+}
diff --git a/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
new file mode 100644
index 00000000..6d4129e8
--- /dev/null
+++ b/src/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilder.php
@@ -0,0 +1,68 @@
+grabyConfigBuilder = $grabyConfigBuilder;
+ $this->credentials = $credentials;
+ }
+
+ /**
+ * Builds the SiteConfig for a host.
+ *
+ * @param string $host The "www." prefix is ignored
+ *
+ * @return SiteConfig
+ *
+ * @throws OutOfRangeException If there is no config for $host
+ */
+ public function buildForHost($host)
+ {
+ // required by credentials below
+ $host = strtolower($host);
+ if (substr($host, 0, 4) == 'www.') {
+ $host = substr($host, 4);
+ }
+
+ $config = $this->grabyConfigBuilder->buildForHost($host);
+ $parameters = [
+ 'host' => $host,
+ 'requiresLogin' => $config->requires_login ?: false,
+ 'loginUri' => $config->login_uri ?: null,
+ 'usernameField' => $config->login_username_field ?: null,
+ 'passwordField' => $config->login_password_field ?: null,
+ 'extraFields' => is_array($config->login_extra_fields) ? $config->login_extra_fields : [],
+ 'notLoggedInXpath' => $config->not_logged_in_xpath ?: null,
+ ];
+
+ if (isset($this->credentials[$host])) {
+ $parameters['username'] = $this->credentials[$host]['username'];
+ $parameters['password'] = $this->credentials[$host]['password'];
+ }
+
+ return new SiteConfig($parameters);
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Helper/ContentProxy.php b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
index bbd5db5d..f222dd88 100644
--- a/src/Wallabag/CoreBundle/Helper/ContentProxy.php
+++ b/src/Wallabag/CoreBundle/Helper/ContentProxy.php
@@ -3,7 +3,7 @@
namespace Wallabag\CoreBundle\Helper;
use Graby\Graby;
-use Psr\Log\LoggerInterface as Logger;
+use Psr\Log\LoggerInterface;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\CoreBundle\Tools\Utils;
@@ -21,14 +21,16 @@ class ContentProxy
protected $logger;
protected $tagRepository;
protected $mimeGuesser;
+ protected $fetchingErrorMessage;
- public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, Logger $logger)
+ public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, LoggerInterface $logger, $fetchingErrorMessage)
{
$this->graby = $graby;
$this->tagger = $tagger;
$this->logger = $logger;
$this->tagRepository = $tagRepository;
$this->mimeGuesser = new MimeTypeExtensionGuesser();
+ $this->fetchingErrorMessage = $fetchingErrorMessage;
}
/**
@@ -48,7 +50,13 @@ class ContentProxy
{
// do we have to fetch the content or the provided one is ok?
if (empty($content) || false === $this->validateContent($content)) {
- $content = $this->graby->fetchContent($url);
+ $fetchedContent = $this->graby->fetchContent($url);
+
+ // when content is imported, we have information in $content
+ // in case fetching content goes bad, we'll keep the imported information instead of overriding them
+ if (empty($content) || $fetchedContent['html'] !== $this->fetchingErrorMessage) {
+ $content = $fetchedContent;
+ }
}
$title = $content['title'];
@@ -58,7 +66,7 @@ class ContentProxy
$html = $content['html'];
if (false === $html) {
- $html = 'Unable to retrieve readable content.
';
+ $html = $this->fetchingErrorMessage;
if (isset($content['open_graph']['og_description'])) {
$html .= 'But we found a short description:
';
@@ -69,8 +77,10 @@ class ContentProxy
$entry->setUrl($content['url'] ?: $url);
$entry->setTitle($title);
$entry->setContent($html);
- $entry->setLanguage($content['language']);
- $entry->setMimetype($content['content_type']);
+ $entry->setHttpStatus(isset($content['status']) ? $content['status'] : '');
+
+ $entry->setLanguage(isset($content['language']) ? $content['language'] : '');
+ $entry->setMimetype(isset($content['content_type']) ? $content['content_type'] : '');
$entry->setReadingTime(Utils::getReadingTime($html));
$domainName = parse_url($entry->getUrl(), PHP_URL_HOST);
@@ -78,12 +88,12 @@ class ContentProxy
$entry->setDomainName($domainName);
}
- if (isset($content['open_graph']['og_image'])) {
+ if (isset($content['open_graph']['og_image']) && $content['open_graph']['og_image']) {
$entry->setPreviewPicture($content['open_graph']['og_image']);
}
// if content is an image define as a preview too
- if (in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
+ if (isset($content['content_type']) && in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
$entry->setPreviewPicture($content['url']);
}
diff --git a/src/Wallabag/CoreBundle/Helper/DownloadImages.php b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
new file mode 100644
index 00000000..c83f9618
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Helper/DownloadImages.php
@@ -0,0 +1,233 @@
+client = $client;
+ $this->baseFolder = $baseFolder;
+ $this->wallabagUrl = rtrim($wallabagUrl, '/');
+ $this->logger = $logger;
+ $this->mimeGuesser = new MimeTypeExtensionGuesser();
+
+ $this->setFolder();
+ }
+
+ /**
+ * Setup base folder where all images are going to be saved.
+ */
+ private function setFolder()
+ {
+ // if folder doesn't exist, attempt to create one and store the folder name in property $folder
+ if (!file_exists($this->baseFolder)) {
+ mkdir($this->baseFolder, 0755, true);
+ }
+ }
+
+ /**
+ * Process the html and extract image from it, save them to local and return the updated html.
+ *
+ * @param int $entryId ID of the entry
+ * @param string $html
+ * @param string $url Used as a base path for relative image and folder
+ *
+ * @return string
+ */
+ public function processHtml($entryId, $html, $url)
+ {
+ $crawler = new Crawler($html);
+ $result = $crawler
+ ->filterXpath('//img')
+ ->extract(array('src'));
+
+ $relativePath = $this->getRelativePath($entryId);
+
+ // download and save the image to the folder
+ foreach ($result as $image) {
+ $imagePath = $this->processSingleImage($entryId, $image, $url, $relativePath);
+
+ if (false === $imagePath) {
+ continue;
+ }
+
+ $html = str_replace($image, $imagePath, $html);
+ }
+
+ return $html;
+ }
+
+ /**
+ * Process a single image:
+ * - retrieve it
+ * - re-saved it (for security reason)
+ * - return the new local path.
+ *
+ * @param int $entryId ID of the entry
+ * @param string $imagePath Path to the image to retrieve
+ * @param string $url Url from where the image were found
+ * @param string $relativePath Relative local path to saved the image
+ *
+ * @return string Relative url to access the image from the web
+ */
+ public function processSingleImage($entryId, $imagePath, $url, $relativePath = null)
+ {
+ if (null === $relativePath) {
+ $relativePath = $this->getRelativePath($entryId);
+ }
+
+ $this->logger->debug('DownloadImages: working on image: '.$imagePath);
+
+ $folderPath = $this->baseFolder.'/'.$relativePath;
+
+ // build image path
+ $absolutePath = $this->getAbsoluteLink($url, $imagePath);
+ if (false === $absolutePath) {
+ $this->logger->error('DownloadImages: Can not determine the absolute path for that image, skipping.');
+
+ return false;
+ }
+
+ try {
+ $res = $this->client->get($absolutePath);
+ } catch (\Exception $e) {
+ $this->logger->error('DownloadImages: Can not retrieve image, skipping.', ['exception' => $e]);
+
+ return false;
+ }
+
+ $ext = $this->mimeGuesser->guess($res->getHeader('content-type'));
+ $this->logger->debug('DownloadImages: Checking extension', ['ext' => $ext, 'header' => $res->getHeader('content-type')]);
+ if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
+ $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping '.$imagePath);
+
+ return false;
+ }
+ $hashImage = hash('crc32', $absolutePath);
+ $localPath = $folderPath.'/'.$hashImage.'.'.$ext;
+
+ try {
+ $im = imagecreatefromstring($res->getBody());
+ } catch (\Exception $e) {
+ $im = false;
+ }
+
+ if (false === $im) {
+ $this->logger->error('DownloadImages: Error while regenerating image', ['path' => $localPath]);
+
+ return false;
+ }
+
+ switch ($ext) {
+ case 'gif':
+ imagegif($im, $localPath);
+ $this->logger->debug('DownloadImages: Re-creating gif');
+ break;
+ case 'jpeg':
+ case 'jpg':
+ imagejpeg($im, $localPath, self::REGENERATE_PICTURES_QUALITY);
+ $this->logger->debug('DownloadImages: Re-creating jpg');
+ break;
+ case 'png':
+ imagepng($im, $localPath, ceil(self::REGENERATE_PICTURES_QUALITY / 100 * 9));
+ $this->logger->debug('DownloadImages: Re-creating png');
+ }
+
+ imagedestroy($im);
+
+ return $this->wallabagUrl.'/assets/images/'.$relativePath.'/'.$hashImage.'.'.$ext;
+ }
+
+ /**
+ * Remove all images for the given entry id.
+ *
+ * @param int $entryId ID of the entry
+ */
+ public function removeImages($entryId)
+ {
+ $relativePath = $this->getRelativePath($entryId);
+ $folderPath = $this->baseFolder.'/'.$relativePath;
+
+ $finder = new Finder();
+ $finder
+ ->files()
+ ->ignoreDotFiles(true)
+ ->in($folderPath);
+
+ foreach ($finder as $file) {
+ @unlink($file->getRealPath());
+ }
+
+ @rmdir($folderPath);
+ }
+
+ /**
+ * Generate the folder where we are going to save images based on the entry url.
+ *
+ * @param int $entryId ID of the entry
+ *
+ * @return string
+ */
+ private function getRelativePath($entryId)
+ {
+ $hashId = hash('crc32', $entryId);
+ $relativePath = $hashId[0].'/'.$hashId[1].'/'.$hashId;
+ $folderPath = $this->baseFolder.'/'.$relativePath;
+
+ if (!file_exists($folderPath)) {
+ mkdir($folderPath, 0777, true);
+ }
+
+ $this->logger->debug('DownloadImages: Folder used for that Entry id', ['folder' => $folderPath, 'entryId' => $entryId]);
+
+ return $relativePath;
+ }
+
+ /**
+ * Make an $url absolute based on the $base.
+ *
+ * @see Graby->makeAbsoluteStr
+ *
+ * @param string $base Base url
+ * @param string $url Url to make it absolute
+ *
+ * @return false|string
+ */
+ private function getAbsoluteLink($base, $url)
+ {
+ if (preg_match('!^https?://!i', $url)) {
+ // already absolute
+ return $url;
+ }
+
+ $base = new \SimplePie_IRI($base);
+
+ // remove '//' in URL path (causes URLs not to resolve properly)
+ if (isset($base->ipath)) {
+ $base->ipath = preg_replace('!//+!', '/', $base->ipath);
+ }
+
+ if ($absolute = \SimplePie_IRI::absolutize($base, $url)) {
+ return $absolute->get_uri();
+ }
+
+ $this->logger->error('DownloadImages: Can not make an absolute link', ['base' => $base, 'url' => $url]);
+
+ return false;
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Helper/EntriesExport.php b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
index 4bf292a4..93c01fcb 100644
--- a/src/Wallabag/CoreBundle/Helper/EntriesExport.php
+++ b/src/Wallabag/CoreBundle/Helper/EntriesExport.php
@@ -89,6 +89,11 @@ class EntriesExport
throw new \InvalidArgumentException(sprintf('The format "%s" is not yet supported.', $format));
}
+ public function exportJsonData()
+ {
+ return $this->prepareSerializingContent('json');
+ }
+
/**
* Use PHPePub to dump a .epub file.
*
diff --git a/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
new file mode 100644
index 00000000..8891887b
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Helper/HttpClientFactory.php
@@ -0,0 +1,54 @@
+authenticatorSubscriber = $authenticatorSubscriber;
+ $this->cookieJar = $cookieJar;
+ $this->restrictedAccess = $restrictedAccess;
+ }
+
+ /**
+ * @return \GuzzleHttp\Client|null
+ */
+ public function buildHttpClient()
+ {
+ if (0 === (int) $this->restrictedAccess) {
+ return null;
+ }
+
+ // we clear the cookie to avoid websites who use cookies for analytics
+ $this->cookieJar->clear();
+ // need to set the (shared) cookie jar
+ $client = new Client(['handler' => new SafeCurlHandler(), 'defaults' => ['cookies' => $this->cookieJar]]);
+ $client->getEmitter()->attach($this->authenticatorSubscriber);
+
+ return $client;
+ }
+}
diff --git a/src/Wallabag/CoreBundle/Helper/Redirect.php b/src/Wallabag/CoreBundle/Helper/Redirect.php
index c14c79d1..f78b7fe0 100644
--- a/src/Wallabag/CoreBundle/Helper/Redirect.php
+++ b/src/Wallabag/CoreBundle/Helper/Redirect.php
@@ -3,6 +3,8 @@
namespace Wallabag\CoreBundle\Helper;
use Symfony\Component\Routing\Router;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
+use Wallabag\CoreBundle\Entity\Config;
/**
* Manage redirections to avoid redirecting to empty routes.
@@ -10,10 +12,12 @@ use Symfony\Component\Routing\Router;
class Redirect
{
private $router;
+ private $tokenStorage;
- public function __construct(Router $router)
+ public function __construct(Router $router, TokenStorageInterface $tokenStorage)
{
$this->router = $router;
+ $this->tokenStorage = $tokenStorage;
}
/**
@@ -24,6 +28,16 @@ class Redirect
*/
public function to($url, $fallback = '')
{
+ $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
+
+ if (null === $user || !is_object($user)) {
+ return $url;
+ }
+
+ if (Config::REDIRECT_TO_HOMEPAGE === $user->getConfig()->getActionMarkAsRead()) {
+ return $this->router->generate('homepage');
+ }
+
if (null !== $url) {
return $url;
}
diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
index 4f03ae0f..b9532fa2 100644
--- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php
@@ -20,8 +20,7 @@ class EntryRepository extends EntityRepository
private function getBuilderByUser($userId)
{
return $this->createQueryBuilder('e')
- ->leftJoin('e.user', 'u')
- ->andWhere('u.id = :userId')->setParameter('userId', $userId)
+ ->andWhere('e.user = :userId')->setParameter('userId', $userId)
->orderBy('e.createdAt', 'desc')
;
}
@@ -85,6 +84,36 @@ class EntryRepository extends EntityRepository
;
}
+ /**
+ * Retrieves entries filtered with a search term for a user.
+ *
+ * @param int $userId
+ * @param string $term
+ * @param strint $currentRoute
+ *
+ * @return QueryBuilder
+ */
+ public function getBuilderForSearchByUser($userId, $term, $currentRoute)
+ {
+ $qb = $this
+ ->getBuilderByUser($userId);
+
+ if ('starred' === $currentRoute) {
+ $qb->andWhere('e.isStarred = true');
+ } elseif ('unread' === $currentRoute) {
+ $qb->andWhere('e.isArchived = false');
+ } elseif ('archive' === $currentRoute) {
+ $qb->andWhere('e.isArchived = true');
+ }
+
+ $qb
+ ->andWhere('e.content LIKE :term OR e.title LIKE :term')->setParameter('term', '%'.$term.'%')
+ ->leftJoin('e.tags', 't')
+ ->groupBy('e.id');
+
+ return $qb;
+ }
+
/**
* Retrieves untagged entries for a user.
*
@@ -96,9 +125,7 @@ class EntryRepository extends EntityRepository
{
return $this
->getBuilderByUser($userId)
- ->leftJoin('e.tags', 't')
- ->groupBy('e.id')
- ->having('count(t.id) = 0');
+ ->andWhere('size(e.tags) = 0');
}
/**
@@ -144,7 +171,7 @@ class EntryRepository extends EntityRepository
$qb->orderBy('e.updatedAt', $order);
}
- $pagerAdapter = new DoctrineORMAdapter($qb);
+ $pagerAdapter = new DoctrineORMAdapter($qb, true, false);
return new Pagerfanta($pagerAdapter);
}
@@ -329,4 +356,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();
+ }
}
diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php
index e76878d4..2182df25 100644
--- a/src/Wallabag/CoreBundle/Repository/TagRepository.php
+++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php
@@ -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,21 @@ 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')
+ ->orderBy('t.slug')
->getQuery()
->getArrayResult();
+
+ $tags = [];
+ foreach ($ids as $id) {
+ $tags[] = $this->find($id);
+ }
+
+ return $tags;
}
/**
diff --git a/src/Wallabag/CoreBundle/Resources/config/parameters.yml b/src/Wallabag/CoreBundle/Resources/config/parameters.yml
index 6068e84c..4948f385 100644
--- a/src/Wallabag/CoreBundle/Resources/config/parameters.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/parameters.yml
@@ -1,8 +1,9 @@
parameters:
addons_url:
- firefox: https://addons.mozilla.org/firefox/addon/wallabag-v2/
- chrome: https://chrome.google.com/webstore/detail/wallabagit/peehlcgckcnclnjlndmoddifcicdnabm
+ firefox: https://addons.mozilla.org/firefox/addon/wallabagger/
+ chrome: https://chrome.google.com/webstore/detail/wallabagger/gbmgphmejlcoihgedabhgjdkcahacjlj
+ opera: https://addons.opera.com/en/extensions/details/wallabagger/?display=en
f_droid: https://f-droid.org/app/fr.gaulupeau.apps.InThePoche
google_play: https://play.google.com/store/apps/details?id=fr.gaulupeau.apps.InThePoche
- ios: https://itunes.apple.com/app/wallabag/id828331015?mt=8
+ ios: https://itunes.apple.com/app/wallabag-2/id1170800946?mt=8
windows: https://www.microsoft.com/store/apps/wallabag/9nblggh11646
diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml
index ed66d2be..fadd5e49 100644
--- a/src/Wallabag/CoreBundle/Resources/config/services.yml
+++ b/src/Wallabag/CoreBundle/Resources/config/services.yml
@@ -30,7 +30,7 @@ services:
- "@doctrine"
wallabag_core.subscriber.table_prefix:
- class: Wallabag\CoreBundle\Subscriber\TablePrefixSubscriber
+ class: Wallabag\CoreBundle\Event\Subscriber\TablePrefixSubscriber
arguments:
- "%database_table_prefix%"
tags:
@@ -41,11 +41,44 @@ services:
arguments:
-
error_message: '%wallabag_core.fetching_error_message%'
+ - "@wallabag_core.guzzle.http_client"
+ - "@wallabag_core.graby.config_builder"
calls:
- [ setLogger, [ "@logger" ] ]
tags:
- { name: monolog.logger, channel: graby }
+ wallabag_core.graby.config_builder:
+ class: Graby\SiteConfig\ConfigBuilder
+ arguments:
+ - {}
+ - "@logger"
+
+ wallabag_core.guzzle.http_client:
+ class: GuzzleHttp\ClientInterface
+ factory: ["@wallabag_core.guzzle.http_client_factory", buildHttpClient]
+
+ wallabag_core.guzzle_authenticator.config_builder:
+ class: Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder
+ arguments:
+ - "@wallabag_core.graby.config_builder"
+ - "%sites_credentials%"
+
+ # service alias override
+ bd_guzzle_site_authenticator.site_config_builder:
+ alias: wallabag_core.guzzle_authenticator.config_builder
+
+ wallabag_core.guzzle.http_client_factory:
+ class: Wallabag\CoreBundle\Helper\HttpClientFactory
+ arguments:
+ - "@bd_guzzle_site_authenticator.authenticator_subscriber"
+ - "@wallabag_core.guzzle.cookie_jar"
+ - '@=service(''craue_config'').get(''restricted_access'')'
+
+ wallabag_core.guzzle.cookie_jar:
+ class: GuzzleHttp\Cookie\FileCookieJar
+ arguments: ["%kernel.cache_dir%/cookiejar.json"]
+
wallabag_core.content_proxy:
class: Wallabag\CoreBundle\Helper\ContentProxy
arguments:
@@ -53,6 +86,7 @@ services:
- "@wallabag_core.rule_based_tagger"
- "@wallabag_core.tag_repository"
- "@logger"
+ - '%wallabag_core.fetching_error_message%'
wallabag_core.rule_based_tagger:
class: Wallabag\CoreBundle\Helper\RuleBasedTagger
@@ -94,6 +128,7 @@ services:
class: Wallabag\CoreBundle\Helper\Redirect
arguments:
- "@router"
+ - "@security.token_storage"
wallabag_core.helper.prepare_pager_for_entries:
class: Wallabag\CoreBundle\Helper\PreparePagerForEntries
@@ -109,9 +144,38 @@ services:
host: '%redis_host%'
port: '%redis_port%'
path: '%redis_path%'
+ password: '%redis_password%'
wallabag_core.exception_controller:
class: Wallabag\CoreBundle\Controller\ExceptionController
arguments:
- '@twig'
- '%kernel.debug%'
+
+ wallabag_core.subscriber.sqlite_cascade_delete:
+ class: Wallabag\CoreBundle\Event\Subscriber\SQLiteCascadeDeleteSubscriber
+ arguments:
+ - "@doctrine"
+ tags:
+ - { name: doctrine.event_subscriber }
+
+ wallabag_core.subscriber.download_images:
+ class: Wallabag\CoreBundle\Event\Subscriber\DownloadImagesSubscriber
+ arguments:
+ - "@doctrine.orm.default_entity_manager"
+ - "@wallabag_core.entry.download_images"
+ - '@=service(''craue_config'').get(''download_images_enabled'')'
+ - "@logger"
+ tags:
+ - { name: kernel.event_subscriber }
+
+ wallabag_core.entry.download_images:
+ class: Wallabag\CoreBundle\Helper\DownloadImages
+ arguments:
+ - "@wallabag_core.entry.download_images.client"
+ - "%kernel.root_dir%/../web/assets/images"
+ - '@=service(''craue_config'').get(''wallabag_url'')'
+ - "@logger"
+
+ wallabag_core.entry.download_images.client:
+ class: GuzzleHttp\Client
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
index a1bee173..34d4021c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml
@@ -70,7 +70,12 @@ config:
# 200_word: 'I read ~200 words per minute'
# 300_word: 'I read ~300 words per minute'
# 400_word: 'I read ~400 words per minute'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: Brugers nøgle til Pocket for at importere materialer
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'Emailadresse'
# twoFactorAuthentication_label: 'Two factor authentication'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Gammel adgangskode'
@@ -145,15 +162,16 @@ entry:
# archived: 'Archived entries'
# filtered: 'Filtered entries'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
# number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
reading_time: 'estimeret læsetid'
reading_time_minutes: 'estimeret læsetid: %readingTime% min'
- reading_time_less_one_minute: 'estimeret læsetid: < 1 min'
+ reading_time_less_one_minute: 'estimeret læsetid: < 1 min'
# number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Marker som læst'
toogle_as_star: 'Skift favoritstatus'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Har et vist billede'
preview_picture_help: 'Forhåndsvis billede'
language_label: 'Sprog'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Læsetid i minutter'
from: 'fra'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
# page_title: 'Edit an entry'
# title_label: 'Title'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'How-to'
# page_description: 'There are several ways to save an article:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Browserudvidelser'
mobile_apps: 'Apps'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Standardudvidelse til Firefox'
chrome: 'Chrome-udvidelse'
+ opera: 'Opera-udvidelse'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
# windows: 'on the Microsoft Store'
bookmarklet:
description: 'Træk dette link til din bogmærkeliste:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
# page_title: 'Quickstart'
@@ -329,6 +381,9 @@ tag:
list:
# number_on_the_page: '{0} There is no tag.|{1} There is one tag.|]1,Inf[ There are %count% tags.'
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
# page_title: 'Import'
@@ -362,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
# page_title: 'Import > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
# page_title: 'Developer'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'Emailadresse'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'RSS-oplysninger opdateret'
# tagging_rules_updated: 'Tagging rules updated'
# 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%'
@@ -496,3 +557,8 @@ flashes:
notice:
# client_created: 'New client created.'
# client_deleted: 'Client deleted'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
index c9625d06..eb3644f6 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml
@@ -70,7 +70,12 @@ config:
200_word: 'Ich lese ~200 Wörter pro Minute'
300_word: 'Ich lese ~300 Wörter pro Minute'
400_word: 'Ich lese ~400 Wörter pro Minute'
+ action_mark_as_read:
+ label: 'Wohin soll nach dem Gelesenmarkieren eines Artikels weitergeleitet werden?'
+ redirect_homepage: 'Zur Homepage'
+ redirect_current_page: 'Zur aktuellen Seite'
pocket_consumer_key_label: Consumer-Key für Pocket, um Inhalte zu importieren
+ android_configuration: Konfiguriere deine Android Application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'E-Mail-Adresse'
twoFactorAuthentication_label: 'Zwei-Faktor-Authentifizierung'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ title: Lösche mein Konto (a.k.a Gefahrenzone)
+ description: Wenn du dein Konto löschst, werden ALL deine Artikel, ALL deine Tags, ALL deine Anmerkungen und dein Konto dauerhaft gelöscht (kann NICHT RÃCKGÃNGIG gemacht werden). Du wirst anschlieÃend ausgeloggt.
+ confirm: Bist du wirklich sicher? (DIES KANN NICHT RÃCKGÃNGIG GEMACHT WERDEN)
+ button: Lösche mein Konto
+ reset:
+ title: Zurücksetzen (a.k.a Gefahrenzone)
+ description: Beim Nutzen der folgenden Schaltflächenhast du die Möglichkeit, einige Informationen von deinem Konto zu entfernen. Sei dir bewusst, dass dies NICHT RÃCKGÃNGIG zu machen ist.
+ annotations: Entferne ALLE Annotationen
+ tags: Entferne ALLE Tags
+ entries: Entferne ALLE Einträge
+ confirm: Bist du wirklich sicher? (DIES KANN NICHT RÃCKGÃNGIG GEMACHT WERDEN)
form_password:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Altes Kennwort'
@@ -145,15 +162,16 @@ entry:
archived: 'Archivierte Einträge'
filtered: 'Gefilterte Einträge'
filtered_tags: 'Gefiltert nach Tags:'
+ # filtered_search: 'Filtered by search:'
untagged: 'Nicht getaggte Einträge'
list:
number_on_the_page: '{0} Es gibt keine Einträge.|{1} Es gibt einen Eintrag.|]1,Inf[ Es gibt %count% Einträge.'
reading_time: 'geschätzte Lesezeit'
reading_time_minutes: 'geschätzte Lesezeit: %readingTime% min'
- reading_time_less_one_minute: 'geschätzte Lesezeit: < 1 min'
+ reading_time_less_one_minute: 'geschätzte Lesezeit: < 1 min'
number_of_tags: '{1}und ein anderer Tag|]1,Inf[und %count% andere Tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'Original'
toogle_as_read: 'Gelesen-Status ändern'
toogle_as_star: 'Favoriten-Status ändern'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Vorschaubild vorhanden'
preview_picture_help: 'Vorschaubild'
language_label: 'Sprache'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Lesezeit in Minuten'
from: 'von'
@@ -209,6 +228,8 @@ entry:
placeholder: 'https://website.de'
form_new:
url_label: URL
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Eintrag bearbeiten'
title_label: 'Titel'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'How-To'
page_description: 'Es gibt mehrere Möglichkeiten, einen Artikel zu speichern:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Browser-Erweiterungen'
mobile_apps: 'Apps'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Firefox-Erweiterung'
chrome: 'Chrome-Erweiterung'
+ opera: 'Opera-Erweiterung'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'im Microsoft-Store'
bookmarklet:
description: 'Ziehe diesen Link in deine Lesezeichenleiste:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Schnelleinstieg'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} Es gibt keine Tags.|{1} Es gibt einen Tag.|]1,Inf[ Es gibt %count% Tags.'
see_untagged_entries: 'Zeige nicht getaggte Einträge'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Importieren'
@@ -362,6 +417,7 @@ import:
how_to: 'Bitte wähle deinen Readability Export aus und klicke den unteren Button für das Hochladen und Importieren dessen.'
worker:
enabled: "Der Import erfolgt asynchron. Sobald der Import gestartet ist, wird diese Aufgabe extern abgearbeitet. Der aktuelle Service dafür ist:"
+ download_images_warning: "Du hast das Herunterladen von Bildern für deine Artikel aktiviert. Verbunden mit dem klassischen Import kann es ewig dauern fortzufahren (oder sogar fehlschlagen). Wir empfehlen den asynchronen Import zu aktivieren, um Fehler zu vermeiden."
firefox:
page_title: 'Aus Firefox importieren'
description: "Dieser Import wird all deine Lesezeichen aus Firefox importieren. Gehe zu deinen Lesezeichen (Strg+Shift+O), dann auf \"Importen und Sichern\", wähle \"Sichernâ¦\". Du erhälst eine .json Datei."
@@ -374,6 +430,10 @@ import:
page_title: 'Aus Instapaper importieren'
description: 'Dieser Import wird all deine Instapaper Artikel importieren. Auf der Einstellungsseite (https://www.instapaper.com/user) klickst du auf "Download .CSV Datei" in dem Abschnitt "Export". Eine CSV Datei wird heruntergeladen (z.B. "instapaper-export.csv").'
how_to: "Bitte wähle deine Instapaper Sicherungsdatei aus und klicke den nachfolgenden Button zum Importieren."
+ pinboard:
+ page_title: "Aus Pinboard importieren"
+ description: 'Dieser Import wird all deine Pinboard Artikel importieren. Auf der Seite Backup (https://pinboard.in/settings/backup) klickst du auf "JSON" in dem Abschnitt "Lesezeichen". Eine JSON Datei wird dann heruntergeladen (z.B. "pinboard_export").'
+ how_to: 'Bitte wähle deinen Pinboard Export aus und klicke den nachfolgenden Button zum Importieren.'
developer:
page_title: 'Entwickler'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'E-Mail-Adresse'
enabled_label: 'Aktiviert'
- locked_label: 'Gesperrt'
last_login_label: 'Letzter Login'
twofactor_label: Zwei-Faktor-Authentifizierung
save: Speichern
@@ -453,7 +512,7 @@ user:
back_to_list: Zurück zur Liste
error:
- # page_title: An error occurred
+ page_title: Ein Fehler ist aufgetreten
flashes:
config:
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'RSS-Informationen aktualisiert'
tagging_rules_updated: 'Tagging-Regeln aktualisiert'
tagging_rules_deleted: 'Tagging-Regel gelöscht'
- user_added: 'Benutzer "%username%" erstellt'
rss_token_updated: 'RSS-Token aktualisiert'
+ annotations_reset: Anmerkungen zurücksetzen
+ tags_reset: Tags zurücksetzen
+ entries_reset: Einträge zurücksetzen
entry:
notice:
entry_already_saved: 'Eintrag bereits am %date% gespeichert'
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: 'Neuer Client erstellt.'
client_deleted: 'Client gelöscht'
+ user:
+ notice:
+ added: 'Benutzer "%username%" hinzugefügt'
+ updated: 'Benutzer "%username%" aktualisiert'
+ deleted: 'Benutzer "%username%" gelöscht'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
index 139cdc24..2626523a 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml
@@ -70,7 +70,12 @@ config:
200_word: 'I read ~200 words per minute'
300_word: 'I read ~300 words per minute'
400_word: 'I read ~400 words per minute'
+ action_mark_as_read:
+ label: 'Where do you want to be redirected after mark an article as read?'
+ redirect_homepage: 'To the homepage'
+ redirect_current_page: 'To the current page'
pocket_consumer_key_label: Consumer key for Pocket to import contents
+ android_configuration: Configure your Android application
help_theme: "wallabag is customizable. You can choose your prefered theme here."
help_items_per_page: "You can change the number of articles displayed on each page."
help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'Email'
twoFactorAuthentication_label: 'Two factor authentication'
help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ 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? (THIS CAN'T BE UNDONE)
+ button: Delete my account
+ reset:
+ title: Reset area (a.k.a danger zone)
+ description: By hitting buttons below you'll have ability to remove some information 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 sure? (THIS CAN'T BE UNDONE)
form_password:
description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Current password'
@@ -145,15 +162,16 @@ entry:
archived: 'Archived entries'
filtered: 'Filtered entries'
filtered_tags: 'Filtered by tags:'
+ filtered_search: 'Filtered by search:'
untagged: 'Untagged entries'
list:
number_on_the_page: '{0} There are no entries.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
reading_time: 'estimated reading time'
reading_time_minutes: 'estimated reading time: %readingTime% min'
- reading_time_less_one_minute: 'estimated reading time: < 1 min'
+ reading_time_less_one_minute: 'estimated reading time: < 1 min'
number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Toggle mark as read'
toogle_as_star: 'Toggle starred'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Has a preview picture'
preview_picture_help: 'Preview picture'
language_label: 'Language'
+ http_status_label: 'HTTP status'
reading_time:
label: 'Reading time in minutes'
from: 'from'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ placeholder: 'What are you looking for?'
edit:
page_title: 'Edit an entry'
title_label: 'Title'
@@ -251,6 +272,9 @@ about:
howto:
page_title: 'How to'
+ tab_menu:
+ add_link: "Add a link"
+ shortcuts: "Use shortcuts"
page_description: 'There are several ways to save an article:'
top_menu:
browser_addons: 'Browser addons'
@@ -259,8 +283,9 @@ howto:
form:
description: 'Thanks to this form'
browser_addons:
- firefox: 'Standard Firefox Add-On'
- chrome: 'Chrome Extension'
+ firefox: 'Firefox addon'
+ chrome: 'Chrome addon'
+ opera: 'Opera addon'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'on the Microsoft Store'
bookmarklet:
description: 'Drag & drop this link to your bookmarks bar:'
+ shortcuts:
+ page_description: Here are the shortcuts available in wallabag.
+ shortcut: Shortcut
+ action: Action
+ all_pages_title: Shortcuts available in all pages
+ go_unread: Go to unread
+ go_starred: Go to starred
+ go_archive: Go to archive
+ go_all: Go to all entries
+ go_tags: Go to tags
+ go_config: Go to config
+ go_import: Go to import
+ go_developers: Go to developers
+ go_howto: Go to howto (this page!)
+ go_logout: Logout
+ list_title: Shortcuts available in listing pages
+ search: Display the search form
+ article_title: Shortcuts available in entry view
+ open_original: Open original URL of the entry
+ toggle_favorite: Toggle star status for the entry
+ toggle_archive: Toggle read status for the entry
+ delete: Delete the entry
+ material_title: Shortcuts available with Material theme only
+ add_link: Add a new link
+ hide_form: Hide the current form (search or new link)
+ arrows_navigation: Navigate through articles
+ open_article: Display the selected entry
quickstart:
page_title: 'Quickstart'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} There are no tags.|{1} There is one tag.|]1,Inf[ There are %count% tags.'
see_untagged_entries: 'See untagged entries'
+ new:
+ add: 'Add'
+ placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Import'
@@ -362,6 +417,7 @@ import:
how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'Import > Firefox'
description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
page_title: 'Import > Instapaper'
description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ page_title: "Import > Pinboard"
+ description: 'This importer will import all your Pinboard articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
page_title: 'Developer'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'Email'
enabled_label: 'Enabled'
- locked_label: 'Locked'
last_login_label: 'Last login'
twofactor_label: Two factor authentication
save: Save
@@ -466,6 +525,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%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
index 70e64bec..d45f8bf5 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml
@@ -70,7 +70,12 @@ config:
200_word: 'Leo ~200 palabras por minuto'
300_word: 'Leo ~300 palabras por minuto'
400_word: 'Leo ~400 palabras por minuto'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
# pocket_consumer_key_label: Consumer key for Pocket to import contents
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'Direccion e-mail'
twoFactorAuthentication_label: 'Autentificación de dos factores'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Contraseña actual'
@@ -145,15 +162,16 @@ entry:
archived: 'ArtÃculos archivados'
filtered: 'ArtÃculos filtrados'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} No hay artÃculos.|{1} Hay un artÃculo.|]1,Inf[ Hay %count% artÃculos.'
reading_time: 'tiempo estimado de lectura'
reading_time_minutes: 'tiempo estimado de lectura: %readingTime% min'
- reading_time_less_one_minute: 'tiempo estimado de lectura: < 1 min'
+ reading_time_less_one_minute: 'tiempo estimado de lectura: < 1 min'
#Â number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Marcar como leÃdo/ no leÃdo'
toogle_as_star: 'Marcar como favorito/ no favorito'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Hay una foto'
preview_picture_help: 'Foto de preview'
language_label: 'Idioma'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Duración de lectura en minutos'
from: 'de'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Editar un artÃculo'
title_label: 'TÃtulo'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'Ayuda'
page_description: 'Hay muchas maneras para guardar un artÃculo:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Extensiones de navigador'
mobile_apps: 'Aplicaciones para smartphone'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Extensión Firefox'
chrome: 'Extensión Chrome'
+ opera: 'Extensión Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'por la tienda de Microsoft'
bookmarklet:
description: 'Desplazar y soltar este link en la barra de marcadores :'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Comienzo rápido'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} No hay ninguna etiqueta.|{1} Hay una etiqueta.|]1,Inf[ Hay %count% etiquetas.'
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Importar'
@@ -362,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'Importar > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
page_title: 'Importar > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ page_title: "Importar > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
page_title: 'Promotor'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'Email'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'La configuración de los feeds RSS ha sido actualizada'
tagging_rules_updated: 'Regla de etiquetado borrada'
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%'
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: 'Nuevo cliente creado.'
client_deleted: 'Cliente suprimido'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
index 75359901..36a7cd80 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml
@@ -70,7 +70,12 @@ config:
200_word: 'Ù
٠تÙرÛبا٠۲۰۰ ÙاÚ٠را در دÙÛÙÙ Ù
ÛâØ®ÙاÙÙ
'
300_word: 'Ù
٠تÙرÛبا٠۳۰۰ ÙاÚ٠را در دÙÛÙÙ Ù
ÛâØ®ÙاÙÙ
'
400_word: 'Ù
٠تÙرÛبا٠۴۰۰ ÙاÚ٠را در دÙÛÙÙ Ù
ÛâØ®ÙاÙÙ
'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: Ú©ÙÛد Ú©Ø§Ø±Ø¨Ø±Û Pocket Ø¨Ø±Ø§Û Ø¯Ø±ÙÙâرÛØ²Û Ù
طاÙب
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'ÙشاÙÛ Ø§ÛÙ
ÛÙ'
twoFactorAuthentication_label: 'تأÛÛد Û²Ù
رØÙÙâاÛ'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'رÙ
ز ÙدÛÙ
Û'
@@ -145,15 +162,16 @@ entry:
archived: 'Ù
ÙاÙÙâÙØ§Û Ø¨Ø§ÛگاÙÛâشدÙ'
filtered: 'Ù
ÙاÙÙâÙØ§Û ÙÛÙترشدÙ'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} ÙÛج Ù
ÙاÙÙâØ§Û ÙÛست.|{1} ÛÚ© Ù
ÙاÙÙ Ùست.|]1,Inf[ %count% Ù
ÙاÙÙ Ùست.'
reading_time: 'زÙ
ا٠تخÙ
ÛÙÛ Ø¨Ø±Ø§Û Ø®ÙاÙدÙ'
reading_time_minutes: 'زÙ
ا٠تخÙ
ÛÙÛ Ø¨Ø±Ø§Û Ø®ÙاÙدÙ: %readingTime% min'
- reading_time_less_one_minute: 'زÙ
ا٠تخÙ
ÛÙÛ Ø¨Ø±Ø§Û Ø®ÙاÙدÙ: < 1 min'
+ reading_time_less_one_minute: 'زÙ
ا٠تخÙ
ÛÙÛ Ø¨Ø±Ø§Û Ø®ÙاÙدÙ: < 1 min'
#Â number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Ø®ÙاÙدÙâشدÙ/Ø®ÙاÙدÙâÙشدÙ'
toogle_as_star: 'برگزÛدÙ/ÙابرگزÛدÙ'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Ø¯Ø§Ø±Ø§Û Ø¹Ú©Ø³ Ù¾ÛØ´âÙÙ
اÛØ´'
preview_picture_help: 'Ù¾ÛØ´âÙÙ
اÛØ´ عکس'
language_label: 'زباÙ'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'زÙ
ا٠خÙاÙد٠ب٠دÙÛÙÙ'
from: 'از'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: ÙشاÙÛ
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'ÙÛراÛØ´ Ù
ÙاÙÙ'
title_label: 'عÙÙاÙ'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'Ø®ÙدآÙ
Ùز'
page_description: 'راÙâÙØ§Û Ø²ÛØ§Ø¯Û Ø¨Ø±Ø§Û Ø°Ø®ÛرÙÙ Ù
ÙاÙÙâÙا Ùست:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'اÙزÙÙÙ Ø¨Ø±Ø§Û Ù
رÙرگرÙا'
mobile_apps: 'برÙاÙ
ÙâÙØ§Û Ù
ÙباÛÙ'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'اÙزÙÙÙÙ ÙاÛرÙاکس'
chrome: 'اÙزÙÙÙ٠کرÙÙ
'
+ # opera: 'Opera addon'
mobile_apps:
android:
via_f_droid: 'از را٠F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'از را٠Microsoft Store'
bookmarklet:
description: 'اÛÙ Ù¾ÛÙÙد را ب٠ÙÙار بÙÚ©âÙ
ارک Ù
رÙرگرتا٠بکشÛد:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Quickstart'
@@ -279,6 +331,7 @@ quickstart:
paragraph_2: 'اداÙ
٠دÙÛد!'
configure:
title: 'برÙاÙ
٠را تÙظÛÙ
Ú©ÙÛد'
+ # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
language: 'زبا٠٠ÙÙ
Ø§Û Ø¨Ø±ÙاÙ
٠را تغÛÛر دÙÛد'
rss: 'Ø®Ùراک آر-اس-اس را Ùعا٠کÙÛد'
tagging_rules: 'ÙاÙÙÙâÙØ§Û Ø¨Ø±ÚسبâÚ¯Ø°Ø§Ø±Û Ø®Ùدکار Ù
ÙاÙÙâÙاÛتا٠را تعرÛÙ Ú©ÙÛد'
@@ -328,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} ÙÛÚ Ø¨Ø±ÚØ³Ø¨Û ÙÛست.|{1} ÛÚ© برÚسب Ùست.|]1,Inf[ %count% برÚسب Ùست.'
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'درÙÙâرÛزÛ'
@@ -361,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'درÙÙâرÛØ²Û > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -373,6 +430,10 @@ import:
page_title: 'درÙÙâرÛØ²Û > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
# page_title: 'Developer'
@@ -443,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'ÙشاÙÛ Ø§ÛÙ
ÛÙ'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -464,8 +524,10 @@ flashes:
rss_updated: 'اطÙاعات آر-اس-اس بÙâرÙز شد'
tagging_rules_updated: 'برÚسبâÚ¯Ø°Ø§Ø±Û Ø®Ùدکار بÙâرÙز شد'
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% ذخÛر٠شد٠بÙد'
@@ -495,3 +557,8 @@ flashes:
notice:
# client_created: 'New client created.'
# client_deleted: 'Client deleted'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
index f2c9d8db..6dd449ba 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml
@@ -46,7 +46,7 @@ footer:
social: "Social"
powered_by: "propulsé par"
about: "Ã propos"
- stats: Depuis le %user_creation% vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
+ stats: Depuis le %user_creation%, vous avez lu %nb_archives% articles. Ce qui fait %per_day% par jour !
config:
page_title: "Configuration"
@@ -70,7 +70,12 @@ config:
200_word: "Je lis environ 200 mots par minute"
300_word: "Je lis environ 300 mots par minute"
400_word: "Je lis environ 400 mots par minute"
+ action_mark_as_read:
+ label: 'Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?'
+ redirect_homepage: "Ã la page d'accueil"
+ redirect_current_page: 'Ã la page courante'
pocket_consumer_key_label: Clé dâauthentification Pocket pour importer les données
+ android_configuration: Configurez votre application Android
help_theme: "L'affichage de wallabag est personnalisable. C'est ici que vous choisissez le thème que vous préférez."
help_items_per_page: "Vous pouvez définir le nombre d'articles affichés sur chaque page."
help_reading_speed: "wallabag calcule une durée de lecture pour chaque article. Vous pouvez définir ici, grâce à cette liste déroulante, si vous lisez plus ou moins vite. wallabag recalculera la durée de lecture de chaque article."
@@ -94,6 +99,18 @@ config:
email_label: "Adresse courriel"
twoFactorAuthentication_label: "Double authentification"
help_twoFactorAuthentication: "Si vous activez 2FA, à chaque tentative de connexion à wallabag, vous recevrez un code par email."
+ 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)
+ 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:
description: "Vous pouvez changer ici votre mot de passe. Le mot de passe doit contenir au moins 8 caractères."
old_password_label: "Mot de passe actuel"
@@ -128,7 +145,7 @@ config:
domainName: "Le nom de domaine de lâarticle"
operator_description:
label: "Opérateur"
- less_than: "Moins queâ¦..."
+ less_than: "Moins queâ¦"
strictly_less_than: "Strictement moins queâ¦"
greater_than: "Plus queâ¦"
strictly_greater_than: "Strictement plus queâ¦"
@@ -145,15 +162,16 @@ entry:
archived: "Articles lus"
filtered: "Articles filtrés"
filtered_tags: "Articles filtrés par tags :"
+ filtered_search: 'Articles filtrés par recherche :'
untagged: "Article sans tag"
list:
- number_on_the_page: "{0} Il nây a pas dâarticles.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
+ number_on_the_page: "{0} Il nây a pas dâarticle.|{1} Il y a un article.|]1,Inf[ Il y a %count% articles."
reading_time: "durée de lecture"
reading_time_minutes: "durée de lecture: %readingTime% min"
- reading_time_less_one_minute: "durée de lecture: < 1 min"
+ reading_time_less_one_minute: "durée de lecture: < 1 min"
number_of_tags: "{1}et un autre tag|]1,Inf[et %count% autres tags"
reading_time_minutes_short: "%readingTime% min"
- reading_time_less_one_minute_short: "< 1 min"
+ reading_time_less_one_minute_short: "< 1 min"
original_article: "original"
toogle_as_read: "Marquer comme lu/non lu"
toogle_as_star: "Marquer comme favori"
@@ -168,6 +186,7 @@ entry:
preview_picture_label: "A une photo"
preview_picture_help: "Photo"
language_label: "Langue"
+ http_status_label: 'Statut HTTP'
reading_time:
label: "Durée de lecture en minutes"
from: "de"
@@ -209,6 +228,8 @@ entry:
placeholder: "http://website.com"
form_new:
url_label: "Adresse"
+ search:
+ placeholder: "Que recherchez-vous ?"
edit:
page_title: "Ãditer un article"
title_label: "Titre"
@@ -251,6 +272,9 @@ about:
howto:
page_title: "Aide"
+ tab_menu:
+ add_link: "Ajouter un lien"
+ shortcuts: "Utiliser les raccourcis"
page_description: "Il y a plusieurs façon dâenregistrer un article :"
top_menu:
browser_addons: "Extensions de navigateur"
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: "Extension Firefox"
chrome: "Extension Chrome"
+ opera: "Extension Opera"
mobile_apps:
android:
via_f_droid: "via F-Droid"
@@ -269,6 +294,33 @@ howto:
windows: "sur Microsoft Store"
bookmarklet:
description: "Glissez et déposez ce lien dans votre barre de favoris :"
+ shortcuts:
+ page_description: Voici les raccourcis disponibles dans wallabag.
+ shortcut: Raccourci
+ action: Action
+ all_pages_title: Raccourcis disponibles dans toutes les pages
+ go_unread: Afficher les articles non lus
+ go_starred: Afficher les articles favoris
+ go_archive: Afficher les articles lus
+ go_all: Afficher tous les articles
+ go_tags: Afficher les tags
+ go_config: Aller à la configuration
+ go_import: Aller aux imports
+ go_developers: Aller à la section Développeurs
+ go_howto: Afficher l'aide (cette page !)
+ go_logout: Se déconnecter
+ list_title: Raccourcis disponibles dans les pages de liste
+ search: Afficher le formulaire de recherche
+ article_title: Raccourcis disponibles quand on affiche un article
+ open_original: Ouvrir l'URL originale de l'article
+ toggle_favorite: Changer le statut Favori de l'article
+ toggle_archive: Changer le status Lu de l'article
+ delete: Supprimer l'article
+ material_title: Raccourcis disponibles avec le thème Material uniquement
+ add_link: Ajouter un nouvel article
+ hide_form: Masquer le formulaire courant (recherche ou nouvel article)
+ arrows_navigation: Naviguer à travers les articles
+ open_article: Afficher l'article sélectionné
quickstart:
page_title: "Pour bien débuter"
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: "{0} Il nây a pas de tag.|{1} Il y a un tag.|]1,Inf[ Il y a %count% tags."
see_untagged_entries: "Voir les articles sans tag"
+ new:
+ add: 'Ajouter'
+ placeholder: 'Vous pouvez ajouter plusieurs tags, séparés par une virgule.'
import:
page_title: "Importer"
@@ -362,9 +417,10 @@ import:
how_to: "Choisissez le fichier de votre export Readability et cliquez sur le bouton ci-dessous pour lâimporter."
worker:
enabled: "Les imports sont asynchrones. Une fois lâimport commencé un worker externe traitera les messages un par un. Le service activé est :"
+ download_images_warning: "Vous avez configuré le téléchagement des images pour vos articles. Combiné à l'import classique, cette opération peut être très très longue (voire échouer). Nous vous conseillons vivement d'activer les imports asynchrones."
firefox:
page_title: "Import > Firefox"
- description: "Cet outil va vous permettre dâimporter tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde... ». Vous allez récupérer un fichier .json.
"
+ description: "Cet outil va vous permettre dâimporter tous vos marques-pages de Firefox. Ouvrez le panneau des marques-pages (Ctrl+Maj+O), puis dans « Importation et sauvegarde », choisissez « Sauvegarde⦠». Vous allez récupérer un fichier .json. "
how_to: "Choisissez le fichier de sauvegarde de vos marques-page et cliquez sur le bouton pour lâimporter. Soyez avertis que le processus peut prendre un temps assez long car tous les articles doivent être récupérés en ligne."
chrome:
page_title: "Import > Chrome"
@@ -374,6 +430,10 @@ import:
page_title: "Import > Instapaper"
description: "Sur la page des paramètres (https://www.instapaper.com/user), cliquez sur « Download .CSV file » dans la section « Export ». Un fichier CSV sera téléchargé (« instapaper-export.csv »)."
how_to: "Choisissez le fichier de votre export Instapaper et cliquez sur le bouton ci-dessous pour lâimporter."
+ pinboard:
+ page_title: "Import > Pinboard"
+ description: "Sur la page « Backup » (https://pinboard.in/settings/backup), cliquez sur « JSON » dans la section « Bookmarks ». Un fichier json (sans extension) sera téléchargé (« pinboard_export »)."
+ how_to: "Choisissez le fichier de votre export Pinboard et cliquez sur le bouton ci-dessous pour lâimporter."
developer:
page_title: "Développeur"
@@ -444,7 +504,6 @@ user:
plain_password_label: "Mot de passe en clair"
email_label: "Adresse courriel"
enabled_label: "Activé"
- locked_label: "Bloqué"
last_login_label: "Dernière connexion"
twofactor_label: "Double authentification"
save: "Sauvegarder"
@@ -465,8 +524,10 @@ flashes:
rss_updated: "La configuration des flux RSS a bien été mise à jour"
tagging_rules_updated: "Règles mises à jour"
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à sauvegardé le %date%"
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: "Nouveau client %name% créé"
client_deleted: "Client %name% supprimé"
+ user:
+ notice:
+ added: 'Utilisateur "%username%" ajouté'
+ updated: 'Utilisateur "%username%" mis à jour'
+ deleted: 'Utilisateur "%username%" supprimé'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
index b7d066ab..4298d1f7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml
@@ -70,7 +70,12 @@ config:
200_word: 'Leggo ~200 parole al minuto'
300_word: 'Leggo ~300 parole al minuto'
400_word: 'Leggo ~400 parole al minuto'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: Consumer key per Pocket per importare i contenuti
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'E-mail'
twoFactorAuthentication_label: 'Two factor authentication'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Password corrente'
@@ -145,15 +162,16 @@ entry:
archived: 'Contenuti archiviati'
filtered: 'Contenuti filtrati'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
number_on_the_page: "{0} Non ci sono contenuti.|{1} C'è un contenuto.|]1,Inf[ Ci sono %count% contenuti."
reading_time: 'tempo di lettura stimato'
reading_time_minutes: 'tempo di lettura stimato: %readingTime% min'
- reading_time_less_one_minute: 'tempo di lettura stimato: < 1 min'
+ reading_time_less_one_minute: 'tempo di lettura stimato: < 1 min'
#Â number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'originale'
toogle_as_read: 'Segna come da leggere'
toogle_as_star: 'Segna come non preferito'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: "Ha un'immagine di anteprima"
preview_picture_help: 'Immagine di anteprima'
language_label: 'Lingua'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Tempo di lettura in minuti'
from: 'da'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Modifica voce'
title_label: 'Titolo'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'How to'
page_description: 'Ci sono diversi modi per salvare un contenuto:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'tramite addons del Browser'
mobile_apps: 'tramite app Mobile'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Add-On di Firefox'
chrome: 'Estensione di Chrome'
+ opera: 'Estensione di Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'sullo store di Microsoft'
bookmarklet:
description: 'Trascinando e rilasciando questo link sulla barra dei bookmark del tuo browser:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Introduzione'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: "{0} Non ci sono tag.|{1} C'è un tag.|]1,Inf[ ci sono %count% tag."
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Importa'
@@ -362,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'Importa da > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
page_title: 'Importa da > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ page_title: "Importa da > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
page_title: 'Sviluppatori'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'E-mail'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'Informazioni RSS aggiornate'
tagging_rules_updated: 'Regole di tagging aggiornate'
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%'
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: 'Nuovo client creato.'
client_deleted: 'Client eliminato'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
index 16ef1e5d..85310cd7 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml
@@ -25,13 +25,13 @@ menu:
internal_settings: 'Configuracion interna'
import: 'Importar'
howto: 'Ajuda'
- developer: 'Desvolopador'
+ developer: 'Desvolopaire'
logout: 'Desconnexion'
about: 'A prepaus'
search: 'Cercar'
save_link: 'Enregistrar un novèl article'
back_to_unread: 'Tornar als articles pas legits'
- # users_management: 'Users management'
+ users_management: 'Gestion dels utilizaires'
top:
add_new_entry: 'Enregistrar un novèl article'
search: 'Cercar'
@@ -46,7 +46,7 @@ footer:
social: 'Social'
powered_by: 'propulsat per'
about: 'A prepaus'
- # stats: Since %user_creation% you read %nb_archives% articles. That is about %per_day% a day!
+ stats: "Dempuèi %user_creation% avètz legit %nb_archives% articles. Es a l'entorn de %per_day% per jorn !"
config:
page_title: 'Configuracion'
@@ -70,7 +70,12 @@ config:
200_word: "Legissi a l'entorn de 200 mots per minuta"
300_word: "Legissi a l'entorn de 300 mots per minuta"
400_word: "Legissi a l'entorn de 400 mots per minuta"
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: Clau d'autentificacion Pocket per importar las donadas
+ android_configuration: Configuratz vòstra aplicacion Android
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'Adreça de corrièl'
twoFactorAuthentication_label: 'Dobla autentificacion'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ title: Suprimir mon compte (Mèfi zòna perilhosa)
+ description: Se confirmatz la supression de vòstre compte, TOTES vòstres articles, TOTAS vòstras etiquetas, TOTAS vòstras anotacions e vòstre compte serà n suprimits per totjorn. E aquò es IRREVERSIBLE. Puèi seretz desconnectat.
+ confirm: Sètz vertadièrament segur ? (ES IRREVERSIBLE)
+ button: Suprimir mon compte
+ reset:
+ title: Zòna de reïnicializacion (Mèfi zòna perilhosa)
+ description: En clicant sul boton çai-jos auretz la possibilitat de levar qualques informacions de vòstre compte. Mèfi que totas aquelas accions son IRREVERSIBLAS.
+ annotations: Levar TOTAS las anotacions
+ tags: Levar TOTAS las etiquetas
+ entries: Levar TOTES los articles
+ confirm: Sètz vertadièrament segur ? (ES IRREVERSIBLE)
form_password:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Senhal actual'
@@ -103,7 +120,7 @@ config:
if_label: 'se'
then_tag_as_label: 'alara atribuir las etiquetas'
delete_rule_label: 'suprimir'
- # edit_rule_label: 'edit'
+ edit_rule_label: 'modificar'
rule_label: 'Règla'
tags_label: 'Etiquetas'
faq:
@@ -145,15 +162,16 @@ entry:
archived: 'Articles legits'
filtered: 'Articles filtrats'
filtered_tags: 'Filtats per etiquetas:'
+ # filtered_search: 'Filtered by search:'
untagged: 'Articles sens etiqueta'
list:
number_on_the_page: "{0} I a pas cap d'article.|{1} I a un article.|]1,Inf[ I a %count% articles."
reading_time: 'durada de lectura'
reading_time_minutes: 'durada de lectura : %readingTime% min'
- reading_time_less_one_minute: 'durada de lectura : < 1 min'
+ reading_time_less_one_minute: 'durada de lectura : < 1 min'
number_of_tags: '{1}e una autra etiqueta|]1,Inf[e %count% autras etiquetas'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Marcar coma legit/pas legit'
toogle_as_star: 'Marcar coma favorit'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'A una fotò'
preview_picture_help: 'Fotò'
language_label: 'Lenga'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Durada de lectura en minutas'
from: 'de'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Modificar un article'
title_label: 'TÃtol'
@@ -216,7 +237,7 @@ entry:
is_public_label: 'Public'
save_label: 'Enregistrar'
public:
- # shared_by_wallabag: "This article has been shared by wallabag"
+ shared_by_wallabag: "Aqueste article es estat partejat per wallabag"
about:
page_title: 'A prepaus'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'Ajuda'
page_description: "I a mai d'un biais d'enregistrar un article :"
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Extensions de navigator'
mobile_apps: 'Aplicacions mobil'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Extension Firefox'
chrome: 'Extension Chrome'
+ opera: 'Extension Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,17 +294,44 @@ howto:
windows: 'sus Microsoft Store'
bookmarklet:
description: 'Lisatz-depausatz aqueste ligam dins vòstra barra de favorits :'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Per ben començar'
- # more: 'Moreâ¦'
+ more: 'Maiâ¦'
intro:
title: 'Benvenguda sus wallabag !'
paragraph_1: "Anem vos guidar per far lo torn de la proprietat e vos presentar unas fonccionalitats que vos poirián interessar per vos apropriar aquesta aisina."
paragraph_2: 'Seguètz-nos '
configure:
- title: "Configuratz l'aplicacio"
- # description: 'In order to have an application which suits you, have a look into the configuration of wallabag.'
+ title: "Configuratz l'aplicacion"
+ description: "Per fin d'aver una aplicacion que vos va ben, anatz veire la configuracion de wallabag."
language: "Cambiatz la lenga e l'estil de l'aplicacion"
rss: 'Activatz los fluxes RSS'
tagging_rules: 'Escrivètz de règlas per classar automaticament vòstres articles'
@@ -293,7 +345,7 @@ quickstart:
import: 'Configurar los impòrt'
first_steps:
title: 'Primièrs passes'
- # description: "Now wallabag is well configured, it's time to archive the web. You can click on the top right sign + to add a link."
+ description: "Ara wallabag es ben configurat, es lo moment d'archivar lo web. Podètz clicar sul signe + a man drecha amont per ajustar un ligam."
new_article: 'Ajustatz vòstre primièr article'
unread_articles: 'E racaptatz-lo !'
migrate:
@@ -305,14 +357,14 @@ quickstart:
readability: 'Migrar dempuèi Readability'
instapaper: 'Migrar dempuèi Instapaper'
developer:
- title: 'Pels desvolopadors'
- # description: 'We also thought to the developers: Docker, API, translations, etc.'
+ title: 'Pels desvolopaires'
+ description: 'Avèm tanben pensat als desvolopaires : Docker, API, traduccions, etc.'
create_application: 'Crear vòstra aplicacion tèrça'
- # use_docker: 'Use Docker to install wallabag'
+ use_docker: 'Utilizar Docker per installar wallabag'
docs:
title: 'Documentacion complèta'
- # description: "There are so much features in wallabag. Don't hesitate to read the manual to know them and to learn how to use them."
- annotate: 'Anotatar vòstre article'
+ description: "I a un fum de fonccionalitats dins wallabag. Esitetz pas a legir lo manual per las conéisser e aprendre a las utilizar."
+ annotate: 'Anotar vòstre article'
export: 'Convertissètz vòstres articles en ePub o en PDF'
search_filters: "Aprenètz a utilizar lo motor de recèrca e los filtres per retrobar l'article que vos interèssa"
fetching_errors: "Qué far se mon article es pas recuperat coma cal ?"
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: "{0} I a pas cap d'etiquetas.|{1} I a una etiqueta.|]1,Inf[ I a %count% etiquetas."
see_untagged_entries: "Afichar las entradas sens pas cap d'etiquetas"
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Importar'
@@ -362,6 +417,7 @@ import:
how_to: "Mercés de seleccionar vòstre Readability fichièr e de clicar sul boton dejós per lo telecargar e l'importar."
worker:
enabled: "L'importacion se fa de manièra asincròna. Un còp l'importacion lançada, una aisina externa s'ocuparà dels messatges un per un. Lo servici actual es : "
+ download_images_warning: "Avètz activat lo telecargament de los imatges de vòstres articles. Combinat amb l'importacion classica, aquò pòt tardar un long moment (o benlèu fracassar). Recomandem fòrtament l'activacion de l'importacion asincròna per evitar las errors."
firefox:
page_title: 'Importar > Firefox'
description: "Aquesta aisina importarà totas vòstres favorits de Firefox. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
page_title: 'Importar > Instapaper'
description: "Aquesta aisina importarà totas vòstres articles d'Instapaper. Sus la pagina de paramètres (https://www.instapaper.com/user), clicatz sus \"Download .CSV file\" dins la seccion \"Export\". Un fichièr CSV serà telecargat (aital \"instapaper-export.csv\")."
how_to: "Mercés de causir vòstre fichièr Instapaper e de clicar sul boton dejós per lo telecargar e l'importar"
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
page_title: 'Desvolopaire'
@@ -397,7 +457,7 @@ developer:
warn_message_2: "Se suprimissètz un client, totas las aplicacions que l'emplegan foncionarà n pas mai amb vòstre compte wallabag."
action: 'Suprimir aqueste client'
client:
- page_title: 'Desvlopador > Novèl client'
+ page_title: 'Desvolopaire > Novèl client'
page_description: "Anatz crear un novèl client. Mercés de cumplir l'url de redireccion cap a vòstra aplicacion."
form:
name_label: "Nom del client"
@@ -405,7 +465,7 @@ developer:
save_label: 'Crear un novèl client'
action_back: 'Retorn'
client_parameter:
- page_title: 'Desvolopador > Los paramètres de vòstre client'
+ page_title: 'Desvolopaire > Los paramètres de vòstre client'
page_description: 'Vaquà los paramètres de vòstre client'
field_name: 'Nom del client'
field_id: 'ID Client'
@@ -413,7 +473,7 @@ developer:
back: 'Retour'
read_howto: 'Legir "cossà crear ma primièra aplicacion"'
howto:
- page_title: 'Desvolopador > Cossà crear ma primièra aplicacion'
+ page_title: 'Desvolopaire > Cossà crear ma primièra aplicacion'
description:
paragraph_1: "Las comandas seguentas utilizan la bibliotèca HTTPie. Asseguratz-vos que siasqueòu installadas abans de l'utilizar."
paragraph_2: "Vos cal un geton per escambiar entre vòstra aplicacion e l'API de wallabar."
@@ -426,34 +486,33 @@ developer:
back: 'Retorn'
user:
- # page_title: Users management
- # new_user: Create a new user
- # edit_user: Edit an existing user
- # description: "Here you can manage all users (create, edit and delete)"
- # list:
- # actions: Actions
- # edit_action: Edit
- # yes: Yes
- # no: No
- # create_new_one: Create a new user
+ page_title: 'Gestion dels utilizaires'
+ new_user: 'Crear un novèl utilizaire'
+ edit_user: 'Modificar un utilizaire existent'
+ description: "Aquà podètz gerir totes los utilizaires (crear, modificar e suprimir)"
+ list:
+ actions: 'Accions'
+ edit_action: 'Modificar'
+ yes: 'Ãc'
+ no: 'Non'
+ create_new_one: 'Crear un novèl utilizaire'
form:
username_label: "Nom d'utilizaire"
- # name_label: 'Name'
+ name_label: 'Nom'
password_label: 'Senhal'
repeat_new_password_label: 'Confirmatz vòstre novèl senhal'
plain_password_label: 'Senhal en clar'
email_label: 'Adreça de corrièl'
- # enabled_label: 'Enabled'
- # locked_label: 'Locked'
- # last_login_label: 'Last login'
- # twofactor_label: Two factor authentication
- # save: Save
- # delete: Delete
- # delete_confirm: Are you sure?
- # back_to_list: Back to list
+ enabled_label: 'Actiu'
+ last_login_label: 'Darrièra connexion'
+ twofactor_label: 'Autentificacion doble-factor'
+ save: 'Enregistrar'
+ delete: 'Suprimir'
+ delete_confirm: 'Sètz segur ?'
+ back_to_list: 'Tornar a la lista'
error:
- # page_title: An error occurred
+ page_title: Una error s'es produsida
flashes:
config:
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'La configuracion dels fluxes RSS es ben estada mesa a jorn'
tagging_rules_updated: 'Règlas misa a jorn'
tagging_rules_deleted: 'Règla suprimida'
- user_added: 'Utilizaire "%username%" apondut'
rss_token_updated: 'Geton RSS mes a jorn'
+ annotations_reset: Anotacions levadas
+ tags_reset: Etiquetas levadas
+ entries_reset: Articles levats
entry:
notice:
entry_already_saved: 'Article ja salvargardat lo %date%'
@@ -477,12 +538,12 @@ flashes:
entry_reloaded_failed: "L'article es estat cargat de nòu mai la recuperacion del contengut a fracassat"
entry_archived: 'Article marcat coma legit'
entry_unarchived: 'Article marcat coma pas legit'
- entry_starred: 'Article apondut dins los favorits'
+ entry_starred: 'Article ajustat dins los favorits'
entry_unstarred: 'Article quitat dels favorits'
entry_deleted: 'Article suprimit'
tag:
notice:
- tag_added: 'Etiqueta aponduda'
+ tag_added: 'Etiqueta ajustada'
import:
notice:
failed: "L'importacion a fracassat, mercés de tornar ensajar"
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: 'Novèl client creat'
client_deleted: 'Client suprimit'
+ user:
+ notice:
+ added: 'Utilizaire "%username%" ajustat'
+ updated: 'Utilizaire "%username%" mes a jorn'
+ deleted: 'Utilizaire "%username%" suprimit'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
index 73250cc0..35120edc 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml
@@ -61,7 +61,7 @@ config:
save: 'Zapisz'
form_settings:
theme_label: 'Temat'
- items_per_page_label: 'IloÅÄ elementóŠna stronie'
+ items_per_page_label: 'IloÅÄ elementów na stronie'
language_label: 'JÄzyk'
reading_speed:
label: 'PrÄdkoÅÄ czytania'
@@ -70,12 +70,17 @@ config:
200_word: 'Czytam ~200 sÅów na minutÄ'
300_word: 'Czytam ~300 sÅów na minutÄ'
400_word: 'Czytam ~400 sÅów na minutÄ'
+ action_mark_as_read:
+ label: 'Gdzie zostaniesz przekierowany po oznaczeniu artukuÅy jako przeczytanego'
+ redirect_homepage: 'do strony gÅównej'
+ redirect_current_page: 'do bieżÄ
cej strony'
pocket_consumer_key_label: 'Klucz klienta Pocket do importu zawartoÅci'
- # help_theme: "wallabag is customizable. You can choose your prefered theme here."
- # help_items_per_page: "You can change the number of articles displayed on each page."
- # help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
- # help_language: "You can change the language of wallabag interface."
- # help_pocket_consumer_key: "Required for Pocket import. You can create it in your Pocket account."
+ android_configuration: Skonfiguruj swojÄ
androidowÄ
aplikacjÄ
+ help_theme: "Dopasuj wallabag do swoich potrzeb. Tutaj możesz wybraÄ preferowany przez ciebie motyw."
+ help_items_per_page: "Możesz zmieniÄ iloÅÄ artykuÅów wyÅwietlanych na każdej stronie."
+ help_reading_speed: "wallabag oblicza czas czytania każdego artykuÅu. DziÄki tej liÅcie możesz okreÅliÄ swoje tempo. Wallabag przeliczy ponownie czas potrzebny, na przeczytanie każdego z artykuÅów."
+ help_language: "Możesz zmieniÄ jÄzyk interfejsu wallabag."
+ help_pocket_consumer_key: "Wymagane dla importu z Pocket. Możesz go stworzyÄ na swoim koncie Pocket."
form_rss:
description: 'KanaÅy RSS prowadzone przez wallabag pozwalajÄ
Ci na czytanie twoich zapisanych artykuÅów w twoium ulubionym czytniku RSS. Musisz najpierw wynegenerowaÄ tokena.â'
token_label: 'Token RSS'
@@ -93,9 +98,21 @@ config:
name_label: 'Nazwa'
email_label: 'Adres email'
twoFactorAuthentication_label: 'Autoryzacja dwuetapowa'
- # help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ help_twoFactorAuthentication: "Jeżeli wÅÄ
czysz autoryzacjÄ dwuetapowÄ
. Za każdym razem, kiedy bÄdziesz chciaÅ siÄ zalogowaÄ, dostaniesz kod na swój e-mail."
+ delete:
+ title: UsuÅ moje konto (niebezpieczna strefa !)
+ 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 (niebezpieczna strefa)
+ description: Poniższe przyciski pozwalajÄ
usunÄ
Ä pewne informacje z twojego konta. Uważaj te operacje sÄ
NIEODWRACALNE.
+ annotations: UsuÅ WSZYSTKIE adnotacje
+ tags: UsuÅ WSZYSTKIE tagi
+ entries: usuÅ WSZYTSTKIE wpisy
+ confirm: JesteÅ pewien? (tej operacji NIE MOÅ»NA cofnÄ
Ä)
form_password:
- # description: "You can change your password here. Your new password should by at least 8 characters long."
+ description: "Tutaj możesz zmieniÄ swoje hasÅo. Twoje nowe hasÅo powinno mieÄ conajmniej 8 znaków."
old_password_label: 'Stare hasÅo'
new_password_label: 'Nowe hasÅo'
repeat_new_password_label: 'Powtórz nowe hasÅo'
@@ -145,15 +162,16 @@ entry:
archived: 'Zarchiwizowane wpisy'
filtered: 'Odfiltrowane wpisy'
filtered_tags: 'Filtrowane po tagach:'
+ filtered_search: 'Filtrowanie po wyszukiwaniu:'
untagged: 'Odtaguj wpisy'
list:
number_on_the_page: '{0} Nie ma wpisów.|{1} Jest jeden wpis.|]1,Inf[ SÄ
%count% wpisy.'
reading_time: 'szacunkowy czas czytania'
reading_time_minutes: 'szacunkowy czas czytania: %readingTime% min'
- reading_time_less_one_minute: 'szacunkowy czas czytania: < 1 min'
+ reading_time_less_one_minute: 'szacunkowy czas czytania: < 1 min'
number_of_tags: '{1} i inny tag|]1,Inf[i %count% innych tagów'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'oryginaÅ'
toogle_as_read: 'Oznacz jako przeczytane'
toogle_as_star: 'Oznacz jako ulubione'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Posiada podglÄ
d obrazu'
preview_picture_help: 'PodglÄ
d obrazu'
language_label: 'JÄzyk'
+ http_status_label: 'Status HTTP'
reading_time:
label: 'Czas czytania w minutach'
from: 'od'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ placeholder: 'Czego szukasz?'
edit:
page_title: 'Edytuj wpis'
title_label: 'TytuÅ'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'Howto'
page_description: 'Sposoby zapisania artykuÅu:'
+ tab_menu:
+ add_link: "Dodaj link"
+ shortcuts: "Użyj skrótów"
top_menu:
browser_addons: 'Wtyczki dla przeglÄ
darki'
mobile_apps: 'Aplikacje mobilne'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Standardowe rozszerzenie dla Firefox'
chrome: 'Rozszerzenie dla Chrome'
+ opera: 'Rozszerzenie dla Opera'
mobile_apps:
android:
via_f_droid: 'w F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'w Microsoft Store'
bookmarklet:
description: 'PrzeciÄ
gnij i upuÅÄ ten link na swój pasek zakÅadek'
+ shortcuts:
+ page_description: Tutaj znajdujÄ
siÄ skróty dostÄpne w wallabag.
+ shortcut: Skrót
+ action: Akcja
+ all_pages_title: Skróty dostÄpne na wszystkich stronach
+ go_unread: Idź do nieprzeczytanych
+ go_starred: Idź do oznaczonych gwiazdkÄ
+ go_archive: Idź do archiwum
+ go_all: Idź do wszystkich wpisów
+ go_tags: Idź do tagów
+ go_config: Idź do konfiguracji
+ go_import: Idź do importu
+ go_developers: Idź do deweloperów
+ go_howto: Idź do howto (tej strony!)
+ go_logout: Wyloguj
+ list_title: Skróty dostÄpne w spisie stron
+ search: Pokaż formularz wyszukiwania
+ article_title: Skróty dostÄpne w widoku artykuÅu
+ open_original: Otwórz oryginalny adres URL wpisu
+ toggle_favorite: Oznacz wpis gwiazdkÄ
+ toggle_archive: Oznacz wpis jako przeczytany
+ delete: UsuÅ wpis
+ material_title: Skróty dostÄpne wyÅÄ
cznie w motywie Material
+ add_link: Dodaj nowy link
+ hide_form: Ukryj obecny formularz (wyszukiwania lub nowego linku)
+ arrows_navigation: Nawiguj pomiÄdzy artykuÅami
+ open_article: WyÅwietl zaznaczony wpis
quickstart:
page_title: 'Szybki start'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} Nie ma tagów.|{1} Jest jeden tag.|]1,Inf[ SÄ
%count% tagi.'
see_untagged_entries: 'Zobacz nieotagowane wpisy'
+ new:
+ add: 'Dodaj'
+ placeholder: 'Możesz dodaÄ kilka tagów, oddzielajÄ
c je przecinkami.'
import:
page_title: 'Import'
@@ -362,6 +417,7 @@ import:
how_to: 'Wybierz swój plik eksportu z Readability i kliknij poniższy przycisk, aby go zaÅadowaÄ.'
worker:
enabled: "Import jest wykonywany asynchronicznie. Od momentu rozpoczÄcia importu, zewnÄtrzna usÅuga może zajmowaÄ siÄ na raz tylko jednym zadaniem. BieżÄ
cÄ
usÅugÄ
jest:"
+ download_images_warning: "WÅÄ
czyÅeÅ pobieranie obrazów dla swoich artykuÅów. W poÅÄ
czeniu z klasycznym importem, może to zajÄ
Ä dużo czasu (lub zakoÅczyÄ siÄ niepowodzeniem).Zdecydowanie zalecamy wÅÄ
czenie asynchronicznego importu, w celu unikniÄcia bÅÄdów."
firefox:
page_title: 'Import > Firefox'
description: "Ten importer zaimportuje wszystkie twoje zakÅadki z Firefoksa. Idź do twoich zakÅadek (Ctrl+Shift+O), nastÄpnie w \"Import i kopie zapasowe\", wybierz \"Utwórz kopiÄ zapasowÄ
...\". Uzyskasz plik .json."
@@ -374,6 +430,10 @@ import:
page_title: 'Import > Instapaper'
description: 'Ten importer, zaimportuje wszystkie twoje artykuÅy z Instapaper. W ustawieniach (https://www.instapaper.com/user), kliknij na "Download .CSV file" w sekcji "Export". Otrzymasz plik CSV.'
how_to: 'Wybierz swój plik eksportu z Instapaper i kliknij poniższy przycisk, aby go zaÅadowaÄ.'
+ pinboard:
+ page_title: "Import > Pinboard"
+ description: 'Ten importer, zaimportuje wszystkie twoje artykuÅy z Pinboard. W ustawieniach kopii zapasowej (https://pinboard.in/settings/backup), kliknij na "JSON" w sekcji "Bookmarks". Otrzymasz plik "pinboard_export".'
+ how_to: 'Wybierz swój plik eksportu z Pinboard i kliknij poniższy przycisk, aby go zaÅadowaÄ.'
developer:
page_title: 'Deweloper'
@@ -444,7 +504,6 @@ user:
plain_password_label: 'Jawne hasÅo'
email_label: 'Adres email'
enabled_label: 'WÅÄ
czony'
- locked_label: 'Zablokowany'
last_login_label: 'Ostatnie logowanie'
twofactor_label: Autoryzacja dwuetapowa
save: Zapisz
@@ -453,7 +512,7 @@ user:
back_to_list: Powrót do listy
error:
- # page_title: An error occurred
+ page_title: WystÄ
piÅ bÅÄ
d
flashes:
config:
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'Informacje RSS zaktualizowane'
tagging_rules_updated: 'ReguÅy tagowania zaktualizowane'
tagging_rules_deleted: 'ReguÅa tagowania usuniÄta'
- user_added: 'Użytkownik "%username%" dodany'
rss_token_updated: 'Token kanaÅu RSS zaktualizowany'
+ annotations_reset: Zresetuj adnotacje
+ tags_reset: Zresetuj tagi
+ entries_reset: Zresetuj wpisy
entry:
notice:
entry_already_saved: 'Wpis już zostaŠdodany %date%'
@@ -496,3 +557,8 @@ flashes:
notice:
client_created: 'Nowy klient utworzony.'
client_deleted: 'Klient usuniÄty'
+ user:
+ notice:
+ added: 'Użytkownik "%username%" dodany'
+ updated: 'Użytkownik "%username%" zaktualizowany'
+ deleted: 'Użytkownik "%username%" usuniÄty'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
index a375ac7b..c4ace37c 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml
@@ -70,7 +70,12 @@ config:
200_word: 'Posso ler ~200 palavras por minuto'
300_word: 'Posso ler ~300 palavras por minuto'
400_word: 'Posso ler ~400 palavras por minuto'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: 'Chave do consumidor do Pocket para importar conteúdo'
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'E-mail'
twoFactorAuthentication_label: 'Autenticação de dois passos'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Senha atual'
@@ -145,15 +162,16 @@ entry:
archived: 'Entradas arquivadas'
filtered: 'Entradas filtradas'
filtered_tags: 'Filtrar por tags:'
+ # filtered_search: 'Filtered by search:'
untagged: 'Entradas sem tags'
list:
number_on_the_page: '{0} Não existem entradas.|{1} Existe uma entrada.|]1,Inf[ Existem %count% entradas.'
reading_time: 'tempo estimado de leitura'
reading_time_minutes: 'tempo estimado de leitura: %readingTime% min'
- reading_time_less_one_minute: 'tempo estimado de leitura: < 1 min'
+ reading_time_less_one_minute: 'tempo estimado de leitura: < 1 min'
number_of_tags: '{1}e uma outra tag|]1,Inf[e %count% outras tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'Marcar como lido'
toogle_as_star: 'Marcar como destacado'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Possui uma imagem de preview'
preview_picture_help: 'Imagem de preview'
language_label: 'Idioma'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Tempo de leitura em minutos'
from: 'de'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Editar uma entrada'
title_label: 'TÃtulo'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'How to'
page_description: 'Existem diferentes formas de salvar um artigo:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Extensões de navegadores'
mobile_apps: "App's móveis"
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Extensão padrão do Firefox'
chrome: 'Extensão do Chrome'
+ opera: 'Extensão do Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'na Microsoft Store'
bookmarklet:
description: 'Arraste e solve este link na sua barra de favoritos:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Começo Rápido'
@@ -329,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} Não existem tags.|{1} Uma tag.|]1,Inf[ Existem %count% tags.'
see_untagged_entries: 'Ver entradas sem tags'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'Importar'
@@ -362,6 +417,7 @@ import:
how_to: 'Por favor, selecione sua exportação do Readability e clique no botão abaixo para importá-la.'
worker:
enabled: "A importação é feita assÃncronamente. Uma vez que a tarefa de importação é iniciada, um trabalho externo pode executar tarefas uma por vez. O serviço atual é:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'Importar > Firefox'
description: "Com este importador você importa todos os favoritos de seu Firefox. Somente vá até seus favoritos (Ctrl+Maj+O), e em \"Importar e Backup\" e escolha \"Backup...\". Você terá então um arquivo .json."
@@ -374,6 +430,10 @@ import:
page_title: 'Importar > Instapaper'
description: 'Este importador pode importar todos os artigos do seu Instapaper. Nas página de configurações (https://www.instapaper.com/user), clique em "Download .CSV file" na seção "Export". Um arquivo CSV será baixado (algo como "instapaper-export.csv").'
how_to: 'Por favor, selecione sua exportação do seu Instapaper e clique no botão abaixo para importá-la.'
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
page_title: 'Desenvolvedor'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'E-mail'
enabled_label: 'Habilitado'
- locked_label: 'Travado'
last_login_label: 'Ãltimo login'
twofactor_label: 'Autenticação de dois passos'
save: 'Salvar'
@@ -452,17 +511,23 @@ user:
delete_confirm: 'Tem certeza?'
back_to_list: 'Voltar para a lista'
+error:
+ # page_title: An error occurred
+
flashes:
config:
notice:
config_saved: 'Configiração salva.'
password_updated: 'Senha atualizada'
password_not_updated_demo: 'Em modo de demonstração, você não pode alterar a senha deste usuário.'
- user_updated: 'Informação atualizada'
+ # user_updated: 'Information updated'
rss_updated: 'Informação de RSS atualizada'
tagging_rules_updated: 'Regras de tags atualizadas'
tagging_rules_deleted: 'Regra de tag apagada'
rss_token_updated: 'Token RSS atualizado'
+ # annotations_reset: Annotations reset
+ # tags_reset: Tags reset
+ # entries_reset: Entries reset
entry:
notice:
entry_already_saved: 'Entrada já foi salva em %date%'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
index 7d8fcea3..928e5c27 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml
@@ -70,7 +70,12 @@ config:
# 200_word: 'I read ~200 words per minute'
# 300_word: 'I read ~300 words per minute'
# 400_word: 'I read ~400 words per minute'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
pocket_consumer_key_label: Cheie consumator pentru importarea contentului din Pocket
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'E-mail'
# twoFactorAuthentication_label: 'Two factor authentication'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Parola veche'
@@ -145,15 +162,16 @@ entry:
# archived: 'Archived entries'
# filtered: 'Filtered entries'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
# number_on_the_page: '{0} There is no entry.|{1} There is one entry.|]1,Inf[ There are %count% entries.'
reading_time: 'timp estimat de citire'
reading_time_minutes: 'timp estimat de citire: %readingTime% min'
- reading_time_less_one_minute: 'timp estimat de citire: < 1 min'
+ reading_time_less_one_minute: 'timp estimat de citire: < 1 min'
# number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'original'
toogle_as_read: 'ComutÄ marcat ca citit'
toogle_as_star: 'ComutÄ marcat ca favorit'
@@ -168,6 +186,7 @@ entry:
preview_picture_label: 'Are o imagine de previzualizare'
preview_picture_help: 'Previzualizare imagine'
language_label: 'LimbÄ'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Timp de citire în minute'
from: 'de la'
@@ -209,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
# page_title: 'Edit an entry'
# title_label: 'Title'
@@ -252,6 +273,9 @@ about:
howto:
page_title: 'Cum sÄ'
# page_description: 'There are several ways to save an article:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Add-On-uri de Browser'
mobile_apps: 'AplicaÈii mobile'
@@ -261,6 +285,7 @@ howto:
browser_addons:
firefox: 'Add-On standard de Firefox'
chrome: 'Extensie Chrome'
+ opera: 'Extensie Opera'
mobile_apps:
android:
via_f_droid: 'prin F-Droid'
@@ -269,6 +294,33 @@ howto:
windows: 'prin Microsoft Store'
bookmarklet:
description: 'Drag & drop acest link în bara de bookmark-uri:'
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
# page_title: 'Quickstart'
@@ -329,6 +381,9 @@ tag:
list:
# number_on_the_page: '{0} There is no tag.|{1} There is one tag.|]1,Inf[ There are %count% tags.'
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
# page_title: 'Import'
@@ -362,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
# firefox:
# page_title: 'Import > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -374,6 +430,10 @@ import:
# page_title: 'Import > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
# page_title: 'Developer'
@@ -444,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'E-mail'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -465,8 +524,10 @@ flashes:
rss_updated: 'InformaÈie RSS actualizatÄ'
# tagging_rules_updated: 'Tagging rules updated'
# 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%'
@@ -496,3 +557,8 @@ flashes:
notice:
# client_created: 'New client created.'
# client_deleted: 'Client deleted'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
index 357aa2ae..d6cea974 100644
--- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
+++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml
@@ -70,7 +70,12 @@ config:
# 200_word: 'I read ~200 words per minute'
# 300_word: 'I read ~300 words per minute'
# 400_word: 'I read ~400 words per minute'
+ action_mark_as_read:
+ # label: 'Where do you to be redirected after mark an article as read?'
+ # redirect_homepage: 'To the homepage'
+ # redirect_current_page: 'To the current page'
# pocket_consumer_key_label: Consumer key for Pocket to import contents
+ # android_configuration: Configure your Android application
# help_theme: "wallabag is customizable. You can choose your prefered theme here."
# help_items_per_page: "You can change the number of articles displayed on each page."
# help_reading_speed: "wallabag calculates a reading time for each article. You can define here, thanks to this list, if you are a fast or a slow reader. wallabag will recalculate the reading time for each article."
@@ -94,6 +99,18 @@ config:
email_label: 'E-posta'
twoFactorAuthentication_label: 'Ä°ki adımlı doÄrulama'
# help_twoFactorAuthentication: "If you enable 2FA, each time you want to login to wallabag, you'll receive a code by email."
+ delete:
+ # 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? (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:
# description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Eski Åifre'
@@ -103,6 +120,7 @@ config:
# if_label: 'if'
# then_tag_as_label: 'then tag as'
# delete_rule_label: 'delete'
+ # edit_rule_label: 'edit'
rule_label: 'Kural'
tags_label: 'Etiketler'
faq:
@@ -144,15 +162,16 @@ entry:
# archived: 'Archived entries'
# filtered: 'Filtered entries'
# filtered_tags: 'Filtered by tags:'
+ # filtered_search: 'Filtered by search:'
# untagged: 'Untagged entries'
list:
number_on_the_page: '{0} Herhangi bir makale yok.|{1} Burada bir adet makale var.|]1,Inf[ Burada %count% adet makale var.'
reading_time: 'tahmini okuma süresi'
reading_time_minutes: 'tahmini okuma süresi: %readingTime% min'
- reading_time_less_one_minute: 'tahmini okuma süresi: < 1 min'
+ reading_time_less_one_minute: 'tahmini okuma süresi: < 1 min'
# number_of_tags: '{1}and one other tag|]1,Inf[and %count% other tags'
reading_time_minutes_short: '%readingTime% min'
- reading_time_less_one_minute_short: '< 1 min'
+ reading_time_less_one_minute_short: '< 1 min'
original_article: 'orijinal'
toogle_as_read: 'Okundu/okunmadı olarak iÅaretle'
toogle_as_star: 'Favorilere ekle/çıkar'
@@ -167,6 +186,7 @@ entry:
preview_picture_label: 'Resim önizlemesi varsa'
preview_picture_help: 'Resim önizlemesi'
language_label: 'Dil'
+ # http_status_label: 'HTTP status'
reading_time:
label: 'Dakika cinsinden okuma süresi'
from: 'baÅlangıç'
@@ -208,6 +228,8 @@ entry:
placeholder: 'http://website.com'
form_new:
url_label: Url
+ search:
+ # placeholder: 'What are you looking for?'
edit:
page_title: 'Makaleyi düzenle'
title_label: 'BaÅlık'
@@ -251,6 +273,9 @@ about:
howto:
page_title: 'Yardım'
# page_description: 'There are several ways to save an article:'
+ tab_menu:
+ # add_link: "Add a link"
+ # shortcuts: "Use shortcuts"
top_menu:
browser_addons: 'Tarayıcı eklentileri'
mobile_apps: 'Mobil uygulamalar'
@@ -260,6 +285,7 @@ howto:
browser_addons:
firefox: 'Standart Firefox Eklentisi'
chrome: 'Chrome Eklentisi'
+ opera: 'Opera Eklentisi'
mobile_apps:
android:
# via_f_droid: 'via F-Droid'
@@ -268,6 +294,33 @@ howto:
# windows: 'on the Microsoft Store'
bookmarklet:
description: "Bu baÄlantı ile yer imlerinizi sürükleyip bırakarak wallabag'e ekleyebilirsiniz:"
+ shortcuts:
+ # page_description: Here are the shortcuts available in wallabag.
+ # shortcut: Shortcut
+ # action: Action
+ # all_pages_title: Shortcuts available in all pages
+ # go_unread: Go to unread
+ # go_starred: Go to starred
+ # go_archive: Go to archive
+ # go_all: Go to all entries
+ # go_tags: Go to tags
+ # go_config: Go to config
+ # go_import: Go to import
+ # go_developers: Go to developers
+ # go_howto: Go to howto (this page!)
+ # go_logout: Logout
+ # list_title: Shortcuts available in listing pages
+ # search: Display the search form
+ # article_title: Shortcuts available in entry view
+ # open_original: Open original URL of the entry
+ # toggle_favorite: Toggle star status for the entry
+ # toggle_archive: Toggle read status for the entry
+ # delete: Delete the entry
+ # material_title: Shortcuts available with Material theme only
+ # add_link: Add a new link
+ # hide_form: Hide the current form (search or new link)
+ # arrows_navigation: Navigate through articles
+ # open_article: Display the selected entry
quickstart:
page_title: 'Hızlı baÅlangıç'
@@ -328,6 +381,9 @@ tag:
list:
number_on_the_page: '{0} Herhangi bir etiket yok.|{1} Burada bir adet etiket var.|]1,Inf[ Burada %count% adet etiket var.'
# see_untagged_entries: 'See untagged entries'
+ new:
+ # add: 'Add'
+ # placeholder: 'You can add several tags, separated by a comma.'
import:
page_title: 'İçe Aktar'
@@ -361,6 +417,7 @@ import:
# how_to: 'Please select your Readability export and click on the below button to upload and import it.'
worker:
# enabled: "Import is made asynchronously. Once the import task is started, an external worker will handle jobs one at a time. The current service is:"
+ # download_images_warning: "You enabled downloading images for your articles. Combined with classic import it can take ages to proceed (or maybe failed). We strongly recommend to enable asynchronous import to avoid errors."
firefox:
page_title: 'İçe Aktar > Firefox'
# description: "This importer will import all your Firefox bookmarks. Just go to your bookmarks (Ctrl+Maj+O), then into \"Import and backup\", choose \"Backup...\". You will obtain a .json file."
@@ -373,6 +430,10 @@ import:
page_title: 'İçe Aktar > Instapaper'
# description: 'This importer will import all your Instapaper articles. On the settings (https://www.instapaper.com/user) page, click on "Download .CSV file" in the "Export" section. A CSV file will be downloaded (like "instapaper-export.csv").'
# how_to: 'Please select your Instapaper export and click on the below button to upload and import it.'
+ pinboard:
+ # page_title: "Import > Pinboard"
+ # description: 'This importer will import all your Instapaper articles. On the backup (https://pinboard.in/settings/backup) page, click on "JSON" in the "Bookmarks" section. A JSON file will be downloaded (like "pinboard_export").'
+ # how_to: 'Please select your Pinboard export and click on the below button to upload and import it.'
developer:
# page_title: 'Developer'
@@ -443,7 +504,6 @@ user:
plain_password_label: '????'
email_label: 'E-posta'
# enabled_label: 'Enabled'
- # locked_label: 'Locked'
# last_login_label: 'Last login'
# twofactor_label: Two factor authentication
# save: Save
@@ -464,8 +524,10 @@ flashes:
rss_updated: 'RSS bilgiler güncellendi'
tagging_rules_updated: 'Tagging rules updated'
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%'
@@ -495,3 +557,8 @@ flashes:
notice:
# client_created: 'New client created.'
# client_deleted: 'Client deleted'
+ user:
+ notice:
+ # added: 'User "%username%" added'
+ # updated: 'User "%username%" updated'
+ # deleted: 'User "%username%" deleted'
diff --git a/src/Wallabag/CoreBundle/Resources/views/base.html.twig b/src/Wallabag/CoreBundle/Resources/views/base.html.twig
index a1a9a136..289458d4 100644
--- a/src/Wallabag/CoreBundle/Resources/views/base.html.twig
+++ b/src/Wallabag/CoreBundle/Resources/views/base.html.twig
@@ -41,6 +41,8 @@
{% block css %}
{% endblock %}
{% block scripts %}
+
+
{% endblock %}
{% block title %}{% endblock %} â wallabag
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 98b0e119..3548f590 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
@@ -45,6 +45,14 @@
+
+