Compare commits

..

3 Commits

Author SHA1 Message Date
357ce8f7c3 test 2023-08-24 15:14:05 +02:00
e185e03c6e Add new build 2023-07-28 15:48:14 +02:00
2c688daf2a Fix installer when database not exists 2023-07-28 15:37:33 +02:00
106 changed files with 2816 additions and 7283 deletions

View File

@ -5,7 +5,7 @@ on:
push:
branches:
- master
- "2.**"
- 2.*
permissions:
contents: read
@ -17,12 +17,12 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
- name: "Install Node"
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version-file: ".nvmrc"
node-version: "16"
- name: "Install dependencies with Yarn"
run: "yarn install"

View File

@ -5,7 +5,7 @@ on:
push:
branches:
- master
- "2.**"
- 2.*
permissions:
contents: read
@ -17,7 +17,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

View File

@ -5,7 +5,7 @@ on:
push:
branches:
- master
- "2.**"
- 2.*
env:
PGPASSWORD: wallabagrocks
@ -40,7 +40,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
with:
fetch-depth: 2
@ -106,7 +106,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
with:
fetch-depth: 2
@ -151,3 +151,58 @@ jobs:
- name: "Run PHPUnit"
run: "php bin/simple-phpunit -v"
phpunit_no_database:
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without DB created"
runs-on: "ubuntu-20.04"
services:
rabbitmq:
image: rabbitmq:3-alpine
ports:
- 5672:5672
redis:
image: redis:6-alpine
ports:
- 6379:6379
strategy:
fail-fast: true
matrix:
php:
- "8.2"
database:
- "mysql"
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
with:
fetch-depth: 2
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php }}"
coverage: none
tools: pecl
extensions: json, pdo, pdo_mysql, pdo_sqlite, pdo_pgsql, curl, imagick, pgsql, gd, tidy
ini-values: "date.timezone=Europe/Paris"
- name: "Setup MySQL"
if: "${{ matrix.database == 'mysql' }}"
run: |
sudo systemctl start mysql.service
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
composer-options: "--optimize-autoloader --prefer-dist"
- name: "Install wallabag"
run: "php bin/console wallabag:install --env=test"
- name: "Prepare fixtures"
run: "make fixtures"
- name: "Run PHPUnit"
run: "php bin/simple-phpunit -v"

View File

@ -5,7 +5,7 @@ on:
push:
branches:
- master
- "2.**"
- 2.*
permissions:
contents: read
@ -22,7 +22,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

View File

@ -16,7 +16,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v3"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"

1
.gitignore vendored
View File

@ -15,7 +15,6 @@
.php-cs-fixer.cache
.phpunit.result.cache
phpunit.xml
docker-compose.override.yml
# Parameters
/app/config/parameters.yml

2
.nvmrc
View File

@ -1 +1 @@
20
16

View File

@ -1,87 +1,5 @@
# Changelog
## [2.6.8](https://github.com/wallabag/wallabag/tree/2.6.8)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.7...2.6.8)
### Fixes
* Update deps & Node 20 by @j0k3r in https://github.com/wallabag/wallabag/pull/7134
* Fix dark mode disabled url 2.6 by @Simounet in https://github.com/wallabag/wallabag/pull/7133
* Make database dependent commands lazy by @yguedidi in https://github.com/wallabag/wallabag/pull/7142
* Fix docker setup by @yguedidi in https://github.com/wallabag/wallabag/pull/7141
* Remove session-based redirection by @yguedidi in https://github.com/wallabag/wallabag/pull/7140
## [2.6.7](https://github.com/wallabag/wallabag/tree/2.6.7)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.6...2.6.7)
### Security fix
* A user can disable her 2FA unintentionally by @kdecherf in https://github.com/wallabag/wallabag/commit/0cfdddc2eb0aee5ffb69bf499d377d75655ba157
### Fixes
* Fix deprecated null tag parameter by @Simounet in https://github.com/wallabag/wallabag/pull/6985
* Full clickable card on mass action by @Simounet in https://github.com/wallabag/wallabag/pull/6991
* Add tag form submit button always displayed by @Simounet in https://github.com/wallabag/wallabag/pull/6986
## [2.6.6](https://github.com/wallabag/wallabag/tree/2.6.6)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.5...2.6.6)
### Security fix
* Force secure cookie on HTTPS connection by @j0k3r in https://github.com/wallabag/wallabag/pull/6924
### Fixes
* Fix checkboxes pointer events issue by @Simounet in https://github.com/wallabag/wallabag/pull/6897
* Add Google mailer by @j0k3r in https://github.com/wallabag/wallabag/pull/6899
* Improve performance on homepage by @Simounet in https://github.com/wallabag/wallabag/pull/6909
* Mass action layout improved by @Simounet in https://github.com/wallabag/wallabag/pull/6912
## [2.6.5](https://github.com/wallabag/wallabag/tree/2.6.5)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.4...2.6.5)
### Fixes
* "Fix checkboxes pointer-events disabled" by @Simounet https://github.com/wallabag/wallabag/pull/6874
* "Fix nav input styles" by @Simounet https://github.com/wallabag/wallabag/pull/6877
* "Change domain status filters html types" by @Simounet https://github.com/wallabag/wallabag/pull/6888
## [2.6.4](https://github.com/wallabag/wallabag/tree/2.6.4)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.3...2.6.4)
### Fixes
* Fix API token generation by @nicosomb https://github.com/wallabag/wallabag/pull/6869
* Fix checkboxes which were broken by @nicosomb https://github.com/wallabag/wallabag/pull/6864
## [2.6.3](https://github.com/wallabag/wallabag/tree/2.6.3)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.2...2.6.3)
### Security fixes
* Replace GET way to POST way to reset data user by @nicosomb https://github.com/wallabag/wallabag/commit/78b0b55c40511e1f22d5bbb4897aa10fca68441c
* Replace GET way to POST way to delete API client by @nicosomb https://github.com/wallabag/wallabag/commit/ffcc5c9062fcc8cd922d7d6d65edbe5efae96806
### Improvement
* Add confirmation before reload entry by @nicosomb https://github.com/wallabag/wallabag/pull/6778
* Remove external dependencies on howto page by @viktoriussuwandi https://github.com/wallabag/wallabag/pull/6775
### Fixes
* Use Session instead of Referrer for Redirection by @Spoons https://github.com/wallabag/wallabag/pull/6119
* Reduce risk of collision for #content by @kdecherf https://github.com/wallabag/wallabag/pull/6829
* Update dependencies to fix vulnerabilities by @nicosomb https://github.com/wallabag/wallabag/pull/6783
* Fix failing randomly test by @nicosomb https://github.com/wallabag/wallabag/pull/6763
### Technical stuff
* Add check if git is installed by @nicosomb https://github.com/wallabag/wallabag/pull/6788
* Replace kernel.root_dir by kernel.project_dir by @yguedidi https://github.com/wallabag/wallabag/pull/6809
* Split symfony/symfony by @yguedidi https://github.com/wallabag/wallabag/pull/6817
* Make Crawler::extract get an array by @yguedidi https://github.com/wallabag/wallabag/pull/6812
* Use PSR-17 and PSR-18 by @yguedidi https://github.com/wallabag/wallabag/pull/6816
* Replace Client by KernelBrowser by @yguedidi https://github.com/wallabag/wallabag/pull/6813
* Replace Debug component by ErrorHandler component by @yguedidi https://github.com/wallabag/wallabag/pull/6810
* Make ImportController extends AbstractController by @yguedidi https://github.com/wallabag/wallabag/pull/6808
* Use Twig instead of templating by @yguedidi https://github.com/wallabag/wallabag/pull/6797
* Identify platforms by their class by @yguedidi https://github.com/wallabag/wallabag/pull/6799
* Move from transchoice to trans by @yguedidi https://github.com/wallabag/wallabag/pull/6800
* Replace GetResponseEvent by RequestEvent by @yguedidi https://github.com/wallabag/wallabag/pull/6811
* Ensure the kernel is shut down before calling createClient by @yguedidi https://github.com/wallabag/wallabag/pull/6803
* Ignore docker-compose.override.yml by @yguedidi https://github.com/wallabag/wallabag/pull/6814
* Add composer normalizer by @nicosomb https://github.com/wallabag/wallabag/pull/6762
## [2.6.2](https://github.com/wallabag/wallabag/tree/2.6.2)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.1...2.6.2)

View File

@ -62,6 +62,11 @@ class AppKernel extends Kernel
return $bundles;
}
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__) . '/var/cache/' . $this->getEnvironment();
@ -74,7 +79,7 @@ class AppKernel extends Kernel
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getProjectDir() . '/app/config/config_' . $this->getEnvironment() . '.yml');
$loader->load($this->getRootDir() . '/config/config_' . $this->getEnvironment() . '.yml');
$loader->load(function ($container) {
if ($container->getParameter('use_webpack_dev_server')) {

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -17,10 +14,8 @@ class Version20160401000000 extends WallabagMigration
{
$this->skipIf($schema->hasTable($this->getTable('entry')), 'Database already initialized');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$sql = <<<SQL
CREATE TABLE {$this->getTable('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 {$this->getTable('craue_config_setting')} (name);
@ -63,7 +58,7 @@ SQL
}
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$sql = <<<SQL
CREATE TABLE {$this->getTable('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 {$this->getTable('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;
@ -96,7 +91,7 @@ SQL
$this->addSql($query);
}
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$sql = <<<SQL
CREATE TABLE {$this->getTable('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 {$this->getTable('craue_config_setting')} (name);

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -16,7 +15,7 @@ class Version20160812120952 extends WallabagMigration
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
$this->skipIf($clientsTable->hasColumn('name'), 'It seems that you already played this migration.');
if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
if ('sqlite' === $this->connection->getDatabasePlatform()->getName()) {
// Can't use $clientsTable->addColumn('name', 'blob');
// because of the error:
// SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL
@ -36,7 +35,7 @@ class Version20160812120952 extends WallabagMigration
{
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
if ('sqlite' === $this->connection->getDatabasePlatform()->getName()) {
$databaseTablePrefix = $this->container->getParameter('database_table_prefix');
$this->addSql('DROP INDEX IDX_635D765EA76ED395');
$this->addSql('CREATE TEMPORARY TABLE __temp__' . $databaseTablePrefix . 'oauth2_clients AS SELECT id, random_id, redirect_uris, secret, allowed_grant_types FROM ' . $databaseTablePrefix . 'oauth2_clients');

View File

@ -3,9 +3,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\SkipMigrationException;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -16,13 +13,11 @@ class Version20161001072726 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
$this->skipIf($platform instanceof SqlitePlatform, 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
// remove all FK from entry_tag
switch (true) {
case $platform instanceof MySQLPlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'mysql':
$query = $this->connection->query("
SELECT CONSTRAINT_NAME
FROM information_schema.key_column_usage
@ -34,7 +29,7 @@ class Version20161001072726 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('entry_tag') . ' DROP FOREIGN KEY ' . $fk['CONSTRAINT_NAME']);
}
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
// http://dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
$query = $this->connection->query("
SELECT conrelid::regclass AS table_from
@ -58,8 +53,8 @@ class Version20161001072726 extends WallabagMigration
// remove entry FK from annotation
switch (true) {
case $platform instanceof MySQLPlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'mysql':
$query = $this->connection->query("
SELECT CONSTRAINT_NAME
FROM information_schema.key_column_usage
@ -73,7 +68,7 @@ class Version20161001072726 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' DROP FOREIGN KEY ' . $fk['CONSTRAINT_NAME']);
}
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
// http://dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
$query = $this->connection->query("
SELECT conrelid::regclass AS table_from

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -13,7 +12,7 @@ class Version20161022134138 extends WallabagMigration
{
public function up(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
$this->addSql('ALTER DATABASE `' . $this->connection->getParams()['dbname'] . '` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;');
@ -41,7 +40,7 @@ class Version20161022134138 extends WallabagMigration
public function down(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
$this->addSql('ALTER DATABASE `' . $this->connection->getParams()['dbname'] . '` CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;');

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -38,7 +37,7 @@ class Version20161024212538 extends WallabagMigration
$clientsTable->dropColumn('user_id', 'integer');
if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
if ('sqlite' !== $this->connection->getDatabasePlatform()->getName()) {
$clientsTable->removeForeignKey($this->constraintName);
}
}

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -19,20 +16,18 @@ class Version20161214094402 extends WallabagMigration
$this->skipIf($entryTable->hasColumn('uid'), 'It seems that you already played this migration.');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
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 $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' CHANGE uuid uid VARCHAR(23)');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' RENAME uuid TO uid');
}
}
@ -43,16 +38,14 @@ class Version20161214094402 extends WallabagMigration
$this->skipIf($entryTable->hasColumn('uuid'), 'It seems that you already played this migration.');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
throw new SkipMigrationException('Too complex ...');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' CHANGE uid uuid VARCHAR(23)');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' RENAME uid TO uuid');
}
}

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -26,7 +25,7 @@ class Version20170501115751 extends WallabagMigration
$table->setPrimaryKey(['id']);
$table->addForeignKeyConstraint($this->getTable('user'), ['user_id'], ['id'], [], 'fk_user');
if ($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform) {
if ('postgresql' === $this->connection->getDatabasePlatform()->getName()) {
$schema->dropSequence('site_credential_id_seq');
$schema->createSequence('site_credential_id_seq');
}

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -20,7 +19,7 @@ class Version20170510082609 extends WallabagMigration
public function up(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
foreach ($this->fields as $field) {
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' CHANGE ' . $field . ' ' . $field . ' VARCHAR(180) NOT NULL;');
@ -29,7 +28,7 @@ class Version20170510082609 extends WallabagMigration
public function down(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
foreach ($this->fields as $field) {
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' CHANGE ' . $field . ' ' . $field . ' VARCHAR(255) NOT NULL;');

View File

@ -3,9 +3,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\SkipMigrationException;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -16,10 +13,8 @@ class Version20170511211659 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$annotationTableName = $this->getTable('annotation', true);
$userTableName = $this->getTable('user', true);
$entryTableName = $this->getTable('entry', true);
@ -58,10 +53,10 @@ EOD
);
$this->addSql('DROP TABLE __temp__wallabag_annotation');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' MODIFY quote TEXT NOT NULL');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' ALTER COLUMN quote TYPE TEXT');
break;
}
@ -71,16 +66,14 @@ EOD
{
$tableName = $this->getTable('annotation');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
throw new SkipMigrationException('Too complex ...');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $tableName . ' MODIFY quote VARCHAR(255) NOT NULL');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $tableName . ' ALTER COLUMN quote TYPE VARCHAR(255)');
break;
}

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -13,7 +12,7 @@ class Version20170719231144 extends WallabagMigration
{
public function up(Schema $schema): void
{
$this->skipIf($this->connection->getDatabasePlatform() instanceof SqlitePlatform, 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
// Find tags which need to be merged
$dupTags = $this->connection->query('

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,16 +12,14 @@ class Version20171008195606 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
$this->skipIf($platform instanceof SqlitePlatform, 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
switch (true) {
case $platform instanceof MySQLPlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'mysql':
$this->addSql('UPDATE ' . $this->getTable('entry') . ' SET reading_time = 0 WHERE reading_time IS NULL;');
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' CHANGE reading_time reading_time INT(11) NOT NULL;');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('UPDATE ' . $this->getTable('entry') . ' SET reading_time = 0 WHERE reading_time IS NULL;');
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' ALTER COLUMN reading_time SET NOT NULL;');
break;
@ -33,15 +28,13 @@ class Version20171008195606 extends WallabagMigration
public function down(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
$this->skipIf($platform instanceof SqlitePlatform, 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
switch (true) {
case $platform instanceof MySQLPlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' CHANGE reading_time reading_time INT(11);');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' ALTER COLUMN reading_time DROP NOT NULL;');
break;
}

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -13,7 +12,7 @@ class Version20181128203230 extends WallabagMigration
{
public function up(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration can only be applied on \'mysql\'.');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration can only be applied on \'mysql\'.');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' CHANGE `token` `token` varchar(191) NOT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' CHANGE `scope` `scope` varchar(191)');
@ -28,7 +27,7 @@ class Version20181128203230 extends WallabagMigration
public function down(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration can only be applied on \'mysql\'.');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration can only be applied on \'mysql\'.');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' CHANGE `token` `token` varchar(255) NOT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' CHANGE `scope` `scope` varchar(255)');

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,10 +12,8 @@ final class Version20181202073750 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX UNIQ_1D63E7E5C05FB297');
$this->addSql('DROP INDEX UNIQ_1D63E7E5A0D96FBF');
$this->addSql('DROP INDEX UNIQ_1D63E7E592FC23A8');
@ -33,13 +28,13 @@ final class Version20181202073750 extends WallabagMigration
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $this->getTable('user', true) . ' (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $this->getTable('user', true) . ' (username_canonical)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD googleAuthenticatorSecret VARCHAR(191) DEFAULT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' CHANGE twoFactorAuthentication emailTwoFactor BOOLEAN NOT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP trusted');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD backupCodes LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD googleAuthenticatorSecret VARCHAR(191) DEFAULT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' RENAME COLUMN twofactorauthentication TO emailTwoFactor');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP trusted');
@ -50,10 +45,8 @@ final class Version20181202073750 extends WallabagMigration
public function down(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX UNIQ_1D63E7E592FC23A8');
$this->addSql('DROP INDEX UNIQ_1D63E7E5A0D96FBF');
$this->addSql('DROP INDEX UNIQ_1D63E7E5C05FB297');
@ -66,13 +59,13 @@ final class Version20181202073750 extends WallabagMigration
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON "' . $this->getTable('user', true) . '" (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON "' . $this->getTable('user', true) . '" (confirmation_token)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` DROP googleAuthenticatorSecret');
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` CHANGE emailtwofactor twoFactorAuthentication BOOLEAN NOT NULL');
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` ADD trusted TEXT DEFAULT NULL');
$this->addSql('ALTER TABLE `' . $this->getTable('user') . '` DROP backupCodes');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' DROP googleAuthenticatorSecret');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' RENAME COLUMN emailTwoFactor TO twofactorauthentication');
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' ADD trusted TEXT DEFAULT NULL');

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,10 +12,8 @@ final class Version20190425115043 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX UNIQ_87E64C53A76ED395');
$this->addSql('CREATE TEMPORARY TABLE __temp__' . $this->getTable('config', true) . ' AS SELECT id, user_id, theme, items_per_page, language, rss_token, rss_limit, reading_speed, pocket_consumer_key, action_mark_as_read, list_mode FROM ' . $this->getTable('config', true));
$this->addSql('DROP TABLE ' . $this->getTable('config', true));
@ -27,11 +22,11 @@ final class Version20190425115043 extends WallabagMigration
$this->addSql('DROP TABLE __temp__' . $this->getTable('config', true));
$this->addSql('CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON ' . $this->getTable('config', true) . ' (user_id)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' CHANGE rss_token feed_token VARCHAR(255) DEFAULT NULL');
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' CHANGE rss_limit feed_limit INT DEFAULT NULL');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' RENAME COLUMN rss_token TO feed_token');
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' RENAME COLUMN rss_limit TO feed_limit');
break;
@ -40,10 +35,8 @@ final class Version20190425115043 extends WallabagMigration
public function down(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX UNIQ_87E64C53A76ED395');
$this->addSql('CREATE TEMPORARY TABLE __temp__' . $this->getTable('config', true) . ' AS SELECT id, user_id, theme, items_per_page, language, feed_token, feed_limit, reading_speed, pocket_consumer_key, action_mark_as_read, list_mode FROM "' . $this->getTable('config', true) . '"');
$this->addSql('DROP TABLE "' . $this->getTable('config', true) . '"');
@ -52,11 +45,11 @@ final class Version20190425115043 extends WallabagMigration
$this->addSql('DROP TABLE __temp__' . $this->getTable('config', true));
$this->addSql('CREATE UNIQUE INDEX UNIQ_87E64C53A76ED395 ON "' . $this->getTable('config', true) . '" (user_id)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' CHANGE feed_token rss_token');
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' CHANGE feed_limit rss_limit');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' RENAME COLUMN feed_token TO rss_token');
$this->addSql('ALTER TABLE ' . $this->getTable('config') . ' RENAME COLUMN feed_limit TO rss_limit');
break;

View File

@ -3,9 +3,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\SkipMigrationException;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -20,10 +17,8 @@ final class Version20190510141130 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX IDX_368A4209A76ED395');
$this->addSql('DROP INDEX IDX_368A420919EB6921');
$this->addSql('DROP INDEX UNIQ_368A42095F37A13B');
@ -65,7 +60,7 @@ final class Version20190510141130 extends WallabagMigration
$this->addSql('CREATE INDEX IDX_EE52E3FAA76ED395 ON ' . $this->getTable('oauth2_auth_codes', true) . ' (user_id)');
$this->addSql('CREATE INDEX IDX_EE52E3FA19EB6921 ON ' . $this->getTable('oauth2_auth_codes', true) . ' (client_id)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' DROP FOREIGN KEY FK_368A4209A76ED395');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' ADD CONSTRAINT FK_368A4209A76ED395 FOREIGN KEY (user_id) REFERENCES ' . $this->getTable('user') . ' (id) ON DELETE CASCADE');
@ -80,7 +75,7 @@ final class Version20190510141130 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_auth_codes') . ' DROP FOREIGN KEY FK_EE52E3FAA76ED395');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_auth_codes') . ' ADD CONSTRAINT FK_EE52E3FAA76ED395 FOREIGN KEY (user_id) REFERENCES ' . $this->getTable('user') . ' (id) ON DELETE CASCADE');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' DROP CONSTRAINT FK_368A4209A76ED395');
$this->addSql('ALTER TABLE ' . $this->getTable('oauth2_access_tokens') . ' ADD CONSTRAINT FK_368A4209A76ED395 FOREIGN KEY (user_id) REFERENCES ' . $this->getTable('user') . ' (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,7 +14,7 @@ final class Version20190511165128 extends WallabagMigration
{
public function up(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
$this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
$this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
@ -23,7 +22,7 @@ final class Version20190511165128 extends WallabagMigration
public function down(Schema $schema): void
{
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof MySQLPlatform, 'This migration only apply to MySQL');
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
$this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) 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;');

View File

@ -2,7 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,7 +14,7 @@ final class Version20190619093534 extends WallabagMigration
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof SqlitePlatform, 'Migration can only be executed safely on \'sqlite\'.');
$this->skipIf('sqlite' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'sqlite\'.');
$this->addSql('UPDATE ' . $this->getTable('entry', true) . ' SET reading_time = 0 WHERE reading_time IS NULL;');
@ -43,7 +42,7 @@ final class Version20190619093534 extends WallabagMigration
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->skipIf(!$this->connection->getDatabasePlatform() instanceof SqlitePlatform, 'Migration can only be executed safely on \'sqlite\'.');
$this->skipIf('sqlite' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'sqlite\'.');
$this->addSql('DROP INDEX IDX_F4D18282A76ED395');
$this->addSql('DROP INDEX created_at');

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -21,10 +18,8 @@ final class Version20190806130304 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX uid');
$this->addSql('DROP INDEX created_at');
$this->addSql('DROP INDEX hashed_url_user_id');
@ -49,7 +44,7 @@ final class Version20190806130304 extends WallabagMigration
$this->addSql('CREATE INDEX tag_label ON ' . $this->getTable('tag', true) . ' (label)');
$this->addSql('CREATE INDEX config_feed_token ON ' . $this->getTable('config', true) . ' (feed_token)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' MODIFY language VARCHAR(20) DEFAULT NULL');
$this->addSql('CREATE INDEX user_language ON ' . $this->getTable('entry') . ' (language, user_id)');
$this->addSql('CREATE INDEX user_archived ON ' . $this->getTable('entry') . ' (user_id, is_archived, archived_at)');
@ -58,7 +53,7 @@ final class Version20190806130304 extends WallabagMigration
$this->addSql('CREATE INDEX tag_label ON ' . $this->getTable('tag') . ' (label (255))');
$this->addSql('CREATE INDEX config_feed_token ON ' . $this->getTable('config') . ' (feed_token (255))');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' ALTER language TYPE VARCHAR(20)');
$this->addSql('CREATE INDEX user_language ON ' . $this->getTable('entry') . ' (language, user_id)');
$this->addSql('CREATE INDEX user_archived ON ' . $this->getTable('entry') . ' (user_id, is_archived, archived_at)');
@ -72,10 +67,8 @@ final class Version20190806130304 extends WallabagMigration
public function down(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('DROP INDEX IDX_F4D18282A76ED395');
$this->addSql('DROP INDEX created_at');
$this->addSql('DROP INDEX uid');
@ -100,7 +93,7 @@ final class Version20190806130304 extends WallabagMigration
$this->addSql('CREATE INDEX hashed_url_user_id ON ' . $this->getTable('entry', true) . ' (user_id, hashed_url)');
$this->addSql('CREATE INDEX hashed_given_url_user_id ON ' . $this->getTable('entry', true) . ' (user_id, hashed_given_url)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' MODIFY language LONGTEXT DEFAULT NULL');
$this->addSql('DROP INDEX user_language ON ' . $this->getTable('entry'));
$this->addSql('DROP INDEX user_archived ON ' . $this->getTable('entry'));
@ -109,7 +102,7 @@ final class Version20190806130304 extends WallabagMigration
$this->addSql('DROP INDEX tag_label ON ' . $this->getTable('tag'));
$this->addSql('DROP INDEX config_feed_token ON ' . $this->getTable('config'));
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('entry') . ' ALTER language TYPE TEXT');
$this->addSql('DROP INDEX user_language ON ' . $this->getTable('entry'));
$this->addSql('DROP INDEX user_archived ON ' . $this->getTable('entry'));

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -15,16 +12,14 @@ final class Version20190808124957 extends WallabagMigration
{
public function up(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('ALTER TABLE ' . $this->getTable('craue_config_setting', true) . ' RENAME TO ' . $this->getTable('internal_setting', true));
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('craue_config_setting') . ' RENAME ' . $this->getTable('internal_setting'));
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('craue_config_setting') . ' RENAME TO ' . $this->getTable('internal_setting'));
break;
}
@ -32,16 +27,14 @@ final class Version20190808124957 extends WallabagMigration
public function down(Schema $schema): void
{
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('ALTER TABLE ' . $this->getTable('internal_setting', true) . ' RENAME TO ' . $this->getTable('craue_config_setting', true));
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $this->getTable('internal_setting') . ' RENAME ' . $this->getTable('craue_config_setting'));
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $this->getTable('internal_setting') . ' RENAME TO ' . $this->getTable('craue_config_setting'));
break;
}

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -24,7 +23,7 @@ final class Version20190826204730 extends WallabagMigration
$userTable->setPrimaryKey(['id']);
$userTable->addForeignKeyConstraint($this->getTable('config'), ['config_id'], ['id'], [], 'fk_config');
if ($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform) {
if ('postgresql' === $this->connection->getDatabasePlatform()->getName()) {
$schema->dropSequence('ignore_origin_user_rule_id_seq');
$schema->createSequence('ignore_origin_user_rule_id_seq');
}
@ -36,7 +35,7 @@ final class Version20190826204730 extends WallabagMigration
$instanceTable->addColumn('rule', 'string', ['length' => 255]);
$instanceTable->setPrimaryKey(['id']);
if ($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform) {
if ('postgresql' === $this->connection->getDatabasePlatform()->getName()) {
$schema->dropSequence('ignore_origin_instance_rule_id_seq');
$schema->createSequence('ignore_origin_instance_rule_id_seq');
}

View File

@ -2,9 +2,6 @@
namespace Application\Migrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
@ -16,10 +13,8 @@ final class Version20221221092957 extends WallabagMigration
public function up(Schema $schema): void
{
$userTable = $this->getTable('user');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('CREATE TEMPORARY TABLE __temp__wallabag_user AS SELECT id, username, username_canonical, email, email_canonical, enabled, password, last_login, password_requested_at, name, created_at, updated_at, authCode, emailTwoFactor, salt, confirmation_token, roles, googleAuthenticatorSecret, backupCodes FROM ' . $userTable);
$this->addSql('DROP TABLE ' . $userTable);
$this->addSql('CREATE TABLE ' . $userTable . ' (id INTEGER PRIMARY KEY AUTOINCREMENT 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) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
@ -31,10 +26,10 @@ final class Version20221221092957 extends WallabagMigration
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupcodes TYPE JSON USING backupcodes::json');
break;
}
@ -43,10 +38,8 @@ final class Version20221221092957 extends WallabagMigration
public function down(Schema $schema): void
{
$userTable = $this->getTable('user');
$platform = $this->connection->getDatabasePlatform();
switch (true) {
case $platform instanceof SqlitePlatform:
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
$this->addSql('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, googleAuthenticatorSecret, backupCodes, emailTwoFactor FROM ' . $userTable);
$this->addSql('DROP TABLE ' . $userTable);
$this->addSql('CREATE TABLE ' . $userTable . ' (id INTEGER PRIMARY KEY AUTOINCREMENT 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) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login DATETIME DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at DATETIME DEFAULT NULL, roles CLOB NOT NULL --(DC2Type:array)
@ -58,10 +51,10 @@ final class Version20221221092957 extends WallabagMigration
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
break;
case $platform instanceof MySQLPlatform:
case 'mysql':
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
break;
case $platform instanceof PostgreSQLPlatform:
case 'postgresql':
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupCodes TYPE TEXT');
break;
}

View File

@ -235,12 +235,6 @@
z-index: 9999;
}
.tags-add-form {
display: flex;
align-items: center;
gap: 20px;
}
@media only screen and (max-width: 640px) {
.entry-info {
margin-bottom: 20px;
@ -264,12 +258,4 @@
#article .entry-info .chip-action {
min-width: 40px;
}
.tags-add-form {
display: block;
}
.tags-add-form-submit {
margin-top: 10px;
}
}

View File

@ -3,7 +3,7 @@
========================================================================== */
main {
div#content {
#content {
padding: 0 0.5rem;
}
}

View File

@ -85,7 +85,6 @@
background-color: #2f2f2f;
}
.mass-action-tags .mass-action-tags-input.mass-action-tags-input,
.side-nav li:not(.logo) > a:hover,
.side-nav .collapsible-header:hover,
.side-nav.fixed .collapsible-header:hover {
@ -132,10 +131,6 @@
color: #abb2bf;
}
input[type="url"]:not(.browser-default):disabled {
color: #9e9e9e;
}
.input-field.nav-panel-add.disabled,
.input-field.nav-panel-add.disabled input {
background-color: transparent;

View File

@ -14,53 +14,44 @@
}
.mass-action {
margin: 20px 5px 10px 20px;
margin: 10px 5px 10px 20px;
}
.mass-action-group {
display: flex;
padding: 3px;
align-items: center;
gap: 30px;
gap: 10px;
}
.mass-action-button {
height: 36px;
line-height: 36px;
padding: 0 0.7rem;
height: 24px;
line-height: 24px;
padding: 0 0.5rem;
i {
font-size: 1rem;
}
}
.mass-action-button--tags {
border-radius: 2px 0 0 2px;
}
.card-stacked .entry-checkbox {
.entry-checkbox {
margin: 10px 15px 10px 5px;
}
.card .entry-checkbox {
position: absolute;
display: flex;
padding: 10px;
inset: 0;
justify-content: flex-end;
align-items: start;
background-color: rgb(0 172 193 / 20%);
cursor: pointer;
z-index: 10;
.card & {
float: right;
margin-right: 0;
padding: 10px;
}
}
.entries .entry-checkbox-input,
.mass-action .entry-checkbox-input {
position: relative;
left: 0;
width: 20px;
min-height: 25px;
height: 100%;
vertical-align: middle;
opacity: initial;
cursor: pointer;
z-index: 10;
}
@ -73,19 +64,11 @@
.mass-action-tags {
display: flex;
margin-top: 10px;
align-items: center;
gap: 10px;
.mass-action-tags-input.mass-action-tags-input {
.mass-action-tags-input {
margin: 0;
padding: 0 5px;
height: 34px;
background: white;
border-bottom: 3px solid #c5ebef;
}
.mass-action-tags-input.mass-action-tags-input.mass-action-tags-input:focus {
border-bottom: 3px solid $blue-accent-color;
box-shadow: none;
}
}
@ -105,16 +88,13 @@
.results {
display: flex;
margin-bottom: 10px;
padding: 1rem 1rem 0;
flex-wrap: wrap;
justify-content: space-between;
}
.nb-results {
display: inline-flex;
margin-bottom: 20px;
gap: 30px;
.nb-results {
display: inline-flex;
}
}
.results-item {
@ -193,38 +173,9 @@ footer {
}
@media screen and (min-width: 993px) {
.results {
margin-bottom: 0;
}
.nb-results {
margin-bottom: 0;
gap: 0;
}
.mass-action-button {
height: 24px;
line-height: 24px;
padding: 0 0.5rem;
}
.mass-action-group {
gap: 10px;
}
.mass-action-tags {
margin-top: 0;
margin-left: 7px;
flex-wrap: initial;
}
.mass-action {
display: flex;
margin-top: 10px;
align-items: center;
.mass-action-tags-input.mass-action-tags-input {
height: 21px;
}
gap: 30px;
}
}

View File

@ -21,7 +21,7 @@
}
@media screen and (min-width: 993px) {
.entry main div#content {
.entry #content {
padding-left: 70px;
}
}

View File

@ -70,7 +70,6 @@ nav {
.input-field input {
display: block;
font-size: 1.2rem;
line-height: inherit;
height: 3rem;
}
@ -80,17 +79,6 @@ nav {
box-shadow: none;
color: #444;
}
/* materializecss override */
.input-field.input-field input {
margin-bottom: 0;
border-bottom: none;
}
.input-field.input-field input:focus {
border-bottom: none;
box-shadow: initial;
}
}
.nav-panel-top {

View File

@ -15,13 +15,6 @@ div.settings div.file-field {
}
}
/* override materializecss pointer-event disabled on checkboxes */
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked,
.input-field label {
pointer-events: initial;
}
.input-field label.active {
font-size: 1rem;
}

View File

@ -23,13 +23,14 @@ framework:
csrf_protection: ~
validation:
enable_annotations: true
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: session.handler.native_file
save_path: "%kernel.project_dir%/var/sessions/%kernel.environment%"
cookie_secure: auto
fragments: ~
http_method_override: true
assets: ~
@ -42,6 +43,7 @@ twig:
strict_variables: "%kernel.debug%"
form_themes:
- "@LexikFormFilter/Form/form_div_layout.html.twig"
exception_controller: Wallabag\CoreBundle\Controller\ExceptionController:showAction
globals:
registration_enabled: '%fosuser_registration%'

View File

@ -12,7 +12,7 @@ services:
autoconfigure: true
public: true
bind:
$projectDir: '%kernel.project_dir%'
$rootDir: '%kernel.root_dir%'
$debug: '%kernel.debug%'
$defaultLocale: '%kernel.default_locale%'
$wallabagUrl: '%domain_name%'
@ -268,23 +268,9 @@ services:
arguments:
$baseFolder: "%kernel.project_dir%/web/assets/images"
Wallabag\CoreBundle\Command\CleanDownloadedImagesCommand:
tags:
- { name: console.command, command: 'wallabag:clean-downloaded-images' }
Wallabag\CoreBundle\Command\CleanDuplicatesCommand:
tags:
- { name: console.command, command: 'wallabag:clean-duplicates' }
Wallabag\CoreBundle\Command\ExportCommand:
arguments:
$projectDir: '%kernel.project_dir%'
tags:
- { name: console.command, command: 'wallabag:export' }
Wallabag\CoreBundle\Command\GenerateUrlHashesCommand:
tags:
- { name: console.command, command: 'wallabag:generate-hashed-urls' }
Wallabag\CoreBundle\Command\InstallCommand:
arguments:
@ -293,26 +279,6 @@ services:
$defaultSettings: '%wallabag_core.default_internal_settings%'
$defaultIgnoreOriginInstanceRules: '%wallabag_core.default_ignore_origin_instance_rules%'
Wallabag\CoreBundle\Command\ListUserCommand:
tags:
- { name: console.command, command: 'wallabag:user:list' }
Wallabag\CoreBundle\Command\ReloadEntryCommand:
tags:
- { name: console.command, command: 'wallabag:entry:reload' }
Wallabag\CoreBundle\Command\ShowUserCommand:
tags:
- { name: console.command, command: 'wallabag:user:show' }
Wallabag\CoreBundle\Command\TagAllCommand:
tags:
- { name: console.command, command: 'wallabag:tag:all' }
Wallabag\ImportBundle\Command\ImportCommand:
tags:
- { name: console.command, command: 'wallabag:import' }
wallabag_core.entry.download_images.client:
alias: 'httplug.client.wallabag_core.entry.download_images'

View File

@ -1,5 +1,5 @@
wallabag_core:
version: 2.6.8
version: 2.6.2
paypal_url: "https://liberapay.com/wallabag/donate"
languages:
en: 'English'

View File

@ -2,16 +2,16 @@ const path = require('path');
const webpack = require('webpack');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const projectDir = path.resolve(__dirname, '../../../');
const rootDir = path.resolve(__dirname, '../../../');
module.exports = {
entry: {
material: path.join(projectDir, './app/Resources/static/themes/material/index.js'),
public: path.join(projectDir, './app/Resources/static/themes/_global/share.js'),
material: path.join(rootDir, './app/Resources/static/themes/material/index.js'),
public: path.join(rootDir, './app/Resources/static/themes/_global/share.js'),
},
output: {
filename: '[name].js',
path: path.resolve(projectDir, 'web/wallassets'),
path: path.resolve(rootDir, 'web/wallassets'),
publicPath: '',
},
plugins: [
@ -31,7 +31,7 @@ module.exports = {
],
resolve: {
alias: {
jquery: path.join(projectDir, 'node_modules/jquery/dist/jquery.js'),
jquery: path.join(rootDir, 'node_modules/jquery/dist/jquery.js'),
},
},
};

View File

@ -3,7 +3,7 @@
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\Debug\Debug;
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
// read https://symfony.com/doc/current/setup.html#checking-symfony-application-configuration-and-setup

View File

@ -86,6 +86,7 @@
"kphoen/rulerz": "^0.21",
"kphoen/rulerz-bundle": "~0.13",
"laminas/laminas-code": "^4.7",
"laminas/laminas-diactoros": "^2.3",
"lcobucci/jwt": "~4.1.5",
"lexik/form-filter-bundle": "^7.0",
"mgargano/simplehtmldom": "~1.5",
@ -115,35 +116,13 @@
"scheb/2fa-qr-code": "^5.13",
"scheb/2fa-trusted-device": "^5.13",
"sensio/framework-extra-bundle": "^6.2",
"sentry/sentry-symfony": "4.10.0",
"sentry/sentry-symfony": "4.9.2",
"stof/doctrine-extensions-bundle": "^1.2",
"symfony/asset": "^4.4",
"symfony/config": "^4.4",
"symfony/console": "^4.4",
"symfony/debug": "^4.4",
"symfony/dependency-injection": "^4.4",
"symfony/doctrine-bridge": "^4.4",
"symfony/dom-crawler": "^4.4",
"symfony/error-handler": "^4.4",
"symfony/event-dispatcher": "^4.4",
"symfony/finder": "^4.4",
"symfony/form": "^4.4",
"symfony/framework-bundle": "^4.4",
"symfony/google-mailer": "^4.4",
"symfony/http-foundation": "^4.4",
"symfony/http-kernel": "^4.4",
"symfony/mailer": "^4.4",
"symfony/mime": "^4.4",
"symfony/dom-crawler": "^4.0",
"symfony/mailer": "^4.0",
"symfony/monolog-bundle": "^3.1",
"symfony/options-resolver": "^4.4",
"symfony/proxy-manager-bridge": "^4.4",
"symfony/routing": "^4.4",
"symfony/security-bundle": "^4.4",
"symfony/security-core": "^4.4",
"symfony/security-http": "^4.4",
"symfony/templating": "^4.4",
"symfony/twig-bundle": "^4.4",
"symfony/validator": "^4.4",
"symfony/symfony": "^4.0",
"tecnickcom/tcpdf": "^6.3.0",
"twig/extra-bundle": "^3.4",
"twig/string-extra": "^3.4",
@ -166,14 +145,8 @@
"phpstan/phpstan-doctrine": "^1.3",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-symfony": "^1.2",
"symfony/browser-kit": "^4.4",
"symfony/css-selector": "^4.4",
"symfony/debug-bundle": "^4.4",
"symfony/maker-bundle": "^1.18",
"symfony/phpunit-bridge": "^6.0",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4",
"symfony/web-server-bundle": "^4.4"
"symfony/phpunit-bridge": "~6.0"
},
"suggest": {
"ext-imagick": "To keep GIF animation when downloading image is enabled"
@ -192,7 +165,10 @@
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
"config": {
"allow-plugins": {
@ -210,11 +186,7 @@
"incenteev-parameters": {
"file": "app/config/parameters.yml"
},
"public-dir": "web",
"symfony": {
"allow-contrib": true,
"require": "4.4.*"
}
"public-dir": "web"
},
"scripts": {
"post-install-cmd": [

5870
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
FROM php:8.1-fpm AS rootless
ARG DEBIAN_FRONTEND=noninteractive
ARG NODE_VERSION=20
ARG NODE_VERSION=16
RUN apt-get update \
&& apt-get install -y \
@ -33,7 +33,8 @@ RUN apt-get update && apt-get install -y \
zlib1g-dev \
git \
build-essential \
nodejs
nodejs \
npm
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp
RUN docker-php-ext-install -j "$(nproc)" \
bcmath \

View File

@ -6,7 +6,7 @@ parameters:
database_name: ${DATABASE_NAME:-symfony}
database_user: ${DATABASE_USER:-root}
database_password: ${DATABASE_PASSWORD:-~}
database_path: '${DATABASE_PATH:-"%kernel.project_dir%/data/db/wallabag.sqlite"}'
database_path: '${DATABASE_PATH:-"%kernel.root_dir%/data/db/wallabag.sqlite"}'
database_table_prefix: ${DATABASE_TABLE_PREFIX:-wallabag_}
database_socket: null
database_charset: ${DATABASE_CHARSET:-utf8}

View File

@ -1,13 +1,13 @@
{
"name": "wallabag",
"version": "2.6.0",
"version": "2.5.0",
"description": "wallabag is a self hostable application for saving web pages",
"private": true,
"directories": {
"doc": "docs"
},
"engines": {
"node": ">=20"
"node": ">=16"
},
"repository": {
"type": "git",
@ -17,22 +17,17 @@
{
"name": "Nicolas Lœuillet",
"email": "nicolas@loeuillet.org",
"homepage": "https://nicolas.loeuillet.org",
"homepage": "http://www.cdetc.fr",
"role": "Developer"
},
{
"name": "Thomas Citharel",
"homepage": "https://tcit.fr",
"homepage": "http://tcit.fr",
"role": "Developer"
},
{
"name": "Jérémy Benoist",
"homepage": "https://www.j0k3r.net",
"role": "Developer"
},
{
"name": "Kevin Decherf",
"homepage": "https://kdecherf.com/",
"homepage": "http://www.j0k3r.net",
"role": "Developer"
}
],
@ -41,30 +36,30 @@
"url": "https://github.com/wallabag/wallabag/issues"
},
"devDependencies": {
"@babel/core": "^7.22.10",
"@babel/eslint-parser": "^7.22.10",
"@babel/preset-env": "^7.22.10",
"autoprefixer": "^10.4.15",
"@babel/core": "^7.22.9",
"@babel/eslint-parser": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"autoprefixer": "^10.4.14",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"eslint": "^8.47.0",
"eslint": "^8.45.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-import": "^2.27.5",
"eslint-webpack-plugin": "^4.0.1",
"file-loader": "^6.2.0",
"lato-font": "^3.0.0",
"mini-css-extract-plugin": "^2.7.6",
"node-sass": "^9.0.0",
"postcss": "^8.4.28",
"postcss": "^8.4.27",
"postcss-loader": "^7.3.3",
"postcss-scss": "^4.0.7",
"sass": "^1.66.1",
"postcss-scss": "^4.0.6",
"sass": "^1.64.1",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"stylelint": "^15.10.3",
"stylelint": "^15.10.2",
"stylelint-config-standard": "^34.0.0",
"stylelint-config-standard-scss": "^10.0.0",
"stylelint-scss": "^5.1.0",
"stylelint-scss": "^5.0.1",
"stylelint-webpack-plugin": "^4.1.1",
"terser-webpack-plugin": "^5.3.9",
"url-loader": "^4.1.1",
@ -84,7 +79,7 @@
"jquery.cookie": "^1.4.1",
"jr-qrcode": "^1.0.7",
"material-design-icons-iconfont": "^6.7.0",
"materialize-css": "^0.100.2",
"materialize-css": "^0.98.1",
"mathjax": "^3.2.2",
"mousetrap": "^1.6.0",
"ptsans-npm-webfont": "^0.0.4",

View File

@ -45,6 +45,11 @@ parameters:
count: 1
path: tests/Wallabag/CoreBundle/Controller/FeedControllerTest.php
-
message: "#^Call to method generate\\(\\) on an unknown class PHPUnit_Framework_MockObject_MockObject\\.$#"
count: 2
path: tests/Wallabag/CoreBundle/Helper/RedirectTest.php
-
message: "#^Property Tests\\\\Wallabag\\\\CoreBundle\\\\Helper\\\\RedirectTest\\:\\:\\$routerMock has unknown class PHPUnit_Framework_MockObject_MockObject as its type\\.$#"
count: 1
@ -57,5 +62,5 @@ parameters:
-
message: "#^Method FOS\\\\UserBundle\\\\Model\\\\UserManagerInterface\\:\\:updateUser()#"
count: 6
count: 7
path: src/Wallabag/CoreBundle/Controller/ConfigController.php

View File

@ -7,9 +7,3 @@ if [ ! -f composer.phar ]; then
else
COMPOSER_COMMAND='./composer.phar'
fi
# Check for git
command -v git >/dev/null 2>&1 ||
{ echo >&2 "git is not installed. We can't install wallabag";
exit 1
}

View File

@ -7,9 +7,7 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Wallabag\AnnotationBundle\Entity\Annotation;
use Wallabag\CoreBundle\DataFixtures\EntryFixtures;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\UserBundle\DataFixtures\UserFixtures;
use Wallabag\UserBundle\Entity\User;
class AnnotationFixtures extends Fixture implements DependentFixtureInterface
{
@ -18,8 +16,8 @@ class AnnotationFixtures extends Fixture implements DependentFixtureInterface
*/
public function load(ObjectManager $manager)
{
$annotation1 = new Annotation($this->getReference('admin-user', User::class));
$annotation1->setEntry($this->getReference('entry1', Entry::class));
$annotation1 = new Annotation($this->getReference('admin-user'));
$annotation1->setEntry($this->getReference('entry1'));
$annotation1->setText('This is my annotation /o/');
$annotation1->setQuote('content');
@ -27,8 +25,8 @@ class AnnotationFixtures extends Fixture implements DependentFixtureInterface
$this->addReference('annotation1', $annotation1);
$annotation2 = new Annotation($this->getReference('admin-user', User::class));
$annotation2->setEntry($this->getReference('entry2', Entry::class));
$annotation2 = new Annotation($this->getReference('admin-user'));
$annotation2->setEntry($this->getReference('entry2'));
$annotation2->setText('This is my 2nd annotation /o/');
$annotation2->setQuote('content');
@ -36,8 +34,8 @@ class AnnotationFixtures extends Fixture implements DependentFixtureInterface
$this->addReference('annotation2', $annotation2);
$annotation3 = new Annotation($this->getReference('bob-user', User::class));
$annotation3->setEntry($this->getReference('entry3', Entry::class));
$annotation3 = new Annotation($this->getReference('bob-user'));
$annotation3->setEntry($this->getReference('entry3'));
$annotation3->setText('This is my first annotation !');
$annotation3->setQuote('content');

View File

@ -69,16 +69,12 @@ class DeveloperController extends AbstractController
/**
* Remove a client.
*
* @Route("/developer/client/delete/{id}", requirements={"id" = "\d+"}, name="developer_delete_client", methods={"POST"})
* @Route("/developer/client/delete/{id}", requirements={"id" = "\d+"}, name="developer_delete_client")
*
* @return RedirectResponse
*/
public function deleteClientAction(Request $request, Client $client, EntityManagerInterface $entityManager, TranslatorInterface $translator)
public function deleteClientAction(Client $client, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
if (!$this->isCsrfTokenValid('delete-client', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
if (null === $this->getUser() || $client->getUser()->getId() !== $this->getUser()->getId()) {
throw $this->createAccessDeniedException('You can not access this client.');
}
@ -103,9 +99,6 @@ class DeveloperController extends AbstractController
*/
public function howtoFirstAppAction()
{
return $this->render('@WallabagCore/Developer/howto_app.html.twig',
[
'wallabag_url' => $this->getParameter('domain_name'),
]);
return $this->render('@WallabagCore/Developer/howto_app.html.twig');
}
}

View File

@ -4,9 +4,6 @@ namespace Wallabag\CoreBundle\Command;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
@ -141,7 +138,7 @@ class InstallCommand extends Command
$help = '';
// now check if MySQL isn't too old to handle utf8mb4
if ($conn->isConnected() && $conn->getDatabasePlatform() instanceof MySQLPlatform) {
if ($conn->isConnected() && 'mysql' === $conn->getDatabasePlatform()->getName()) {
$version = $conn->query('select version()')->fetchOne();
$minimalVersion = '5.5.4';
@ -153,7 +150,7 @@ class InstallCommand extends Command
}
// testing if PostgreSQL > 9.1
if ($conn->isConnected() && $conn->getDatabasePlatform() instanceof PostgreSQLPlatform) {
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 = $conn->query('SELECT version();')->fetchOne();
@ -375,26 +372,27 @@ class InstallCommand extends Command
private function isDatabasePresent()
{
$connection = $this->entityManager->getConnection();
$databaseName = $connection->getDatabase();
try {
$schemaManager = $connection->getSchemaManager();
$databaseName = $connection->getDatabase();
} catch (\Exception $exception) {
// mysql & sqlite
if (false !== strpos($exception->getMessage(), sprintf("Unknown database '%s'", $databaseName))) {
if (false !== strpos($exception->getMessage(), 'Unknown database')) {
return false;
}
// pgsql
if (false !== strpos($exception->getMessage(), sprintf('database "%s" does not exist', $databaseName))) {
if (false !== strpos($exception->getMessage(), 'does not exist')) {
return false;
}
throw $exception;
}
$schemaManager = $connection->getSchemaManager();
// custom verification for sqlite, since `getListDatabasesSQL` doesn't work for sqlite
if ($connection->getDatabasePlatform() instanceof SqlitePlatform) {
if ('sqlite' === $schemaManager->getDatabasePlatform()->getName()) {
$params = $connection->getParams();
if (isset($params['path']) && file_exists($params['path'])) {

View File

@ -32,7 +32,6 @@ use Wallabag\CoreBundle\Form\Type\IgnoreOriginUserRuleType;
use Wallabag\CoreBundle\Form\Type\TaggingRuleImportType;
use Wallabag\CoreBundle\Form\Type\TaggingRuleType;
use Wallabag\CoreBundle\Form\Type\UserInformationType;
use Wallabag\CoreBundle\Helper\Redirect;
use Wallabag\CoreBundle\Repository\ConfigRepository;
use Wallabag\CoreBundle\Repository\EntryRepository;
use Wallabag\CoreBundle\Repository\IgnoreOriginUserRuleRepository;
@ -49,9 +48,8 @@ class ConfigController extends AbstractController
private TagRepository $tagRepository;
private AnnotationRepository $annotationRepository;
private ConfigRepository $configRepository;
private Redirect $redirectHelper;
public function __construct(EntityManagerInterface $entityManager, UserManagerInterface $userManager, EntryRepository $entryRepository, TagRepository $tagRepository, AnnotationRepository $annotationRepository, ConfigRepository $configRepository, Redirect $redirectHelper)
public function __construct(EntityManagerInterface $entityManager, UserManagerInterface $userManager, EntryRepository $entryRepository, TagRepository $tagRepository, AnnotationRepository $annotationRepository, ConfigRepository $configRepository)
{
$this->entityManager = $entityManager;
$this->userManager = $userManager;
@ -59,7 +57,6 @@ class ConfigController extends AbstractController
$this->tagRepository = $tagRepository;
$this->annotationRepository = $annotationRepository;
$this->configRepository = $configRepository;
$this->redirectHelper = $redirectHelper;
}
/**
@ -257,14 +254,10 @@ class ConfigController extends AbstractController
/**
* Disable 2FA using email.
*
* @Route("/config/otp/email/disable", name="disable_otp_email", methods={"POST"})
* @Route("/config/otp/email/disable", name="disable_otp_email")
*/
public function disableOtpEmailAction(Request $request)
public function disableOtpEmailAction()
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
$user = $this->getUser();
$user->setEmailTwoFactor(false);
@ -281,14 +274,10 @@ class ConfigController extends AbstractController
/**
* Enable 2FA using email.
*
* @Route("/config/otp/email", name="config_otp_email", methods={"POST"})
* @Route("/config/otp/email", name="config_otp_email")
*/
public function otpEmailAction(Request $request)
public function otpEmailAction()
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
$user = $this->getUser();
$user->setGoogleAuthenticatorSecret(null);
@ -308,14 +297,10 @@ class ConfigController extends AbstractController
/**
* Disable 2FA using OTP app.
*
* @Route("/config/otp/app/disable", name="disable_otp_app", methods={"POST"})
* @Route("/config/otp/app/disable", name="disable_otp_app")
*/
public function disableOtpAppAction(Request $request)
public function disableOtpAppAction()
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
$user = $this->getUser();
$user->setGoogleAuthenticatorSecret('');
@ -334,14 +319,10 @@ class ConfigController extends AbstractController
/**
* Enable 2FA using OTP app, user will need to confirm the generated code from the app.
*
* @Route("/config/otp/app", name="config_otp_app", methods={"POST"})
* @Route("/config/otp/app", name="config_otp_app")
*/
public function otpAppAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator)
public function otpAppAction(GoogleAuthenticatorInterface $googleAuthenticator)
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
$user = $this->getUser();
$secret = $googleAuthenticator->generateSecret();
@ -376,10 +357,8 @@ class ConfigController extends AbstractController
* Cancelling 2FA using OTP app.
*
* @Route("/config/otp/app/cancel", name="config_otp_app_cancel")
*
* XXX: commented until we rewrite 2fa with a real two-steps activation
*/
/*public function otpAppCancelAction()
public function otpAppCancelAction()
{
$user = $this->getUser();
$user->setGoogleAuthenticatorSecret(null);
@ -388,19 +367,15 @@ class ConfigController extends AbstractController
$this->userManager->updateUser($user, true);
return $this->redirect($this->generateUrl('config') . '#set3');
}*/
}
/**
* Validate OTP code.
*
* @Route("/config/otp/app/check", name="config_otp_app_check", methods={"POST"})
* @Route("/config/otp/app/check", name="config_otp_app_check")
*/
public function otpAppCheckAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator)
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
$isValid = $googleAuthenticator->checkCode(
$this->getUser(),
$request->get('_auth_code')
@ -420,12 +395,7 @@ class ConfigController extends AbstractController
'scheb_two_factor.code_invalid'
);
$this->addFlash(
'notice',
'scheb_two_factor.code_invalid'
);
return $this->redirect($this->generateUrl('config') . '#set3');
return $this->redirect($this->generateUrl('config_otp_app'));
}
/**
@ -553,16 +523,12 @@ class ConfigController extends AbstractController
/**
* Remove all annotations OR tags OR entries for the current user.
*
* @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset", methods={"POST"})
* @Route("/reset/{type}", requirements={"id" = "annotations|tags|entries"}, name="config_reset")
*
* @return RedirectResponse
*/
public function resetAction(Request $request, string $type, AnnotationRepository $annotationRepository, EntryRepository $entryRepository)
public function resetAction(string $type, AnnotationRepository $annotationRepository, EntryRepository $entryRepository)
{
if (!$this->isCsrfTokenValid('reset-area', $request->request->get('token'))) {
throw $this->createAccessDeniedException('Bad CSRF token.');
}
switch ($type) {
case 'annotations':
$annotationRepository->removeAllByUserId($this->getUser()->getId());
@ -649,9 +615,7 @@ class ConfigController extends AbstractController
$this->entityManager->persist($user);
$this->entityManager->flush();
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'));
return $this->redirect($redirectUrl);
return $this->redirect($request->headers->get('referer'));
}
/**

View File

@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
@ -127,7 +128,7 @@ class EntryController extends AbstractController
$this->entityManager->flush();
}
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'));
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'));
return $this->redirect($redirectUrl);
}
@ -450,7 +451,7 @@ class EntryController extends AbstractController
$message
);
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'));
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'));
return $this->redirect($redirectUrl);
}
@ -480,7 +481,7 @@ class EntryController extends AbstractController
$message
);
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'));
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'));
return $this->redirect($redirectUrl);
}
@ -500,7 +501,8 @@ class EntryController extends AbstractController
// to avoid redirecting to the deleted entry. Ugh.
$url = $this->generateUrl(
'view',
['id' => $entry->getId()]
['id' => $entry->getId()],
UrlGeneratorInterface::ABSOLUTE_PATH
);
// entry deleted, dispatch event about it!
@ -515,8 +517,8 @@ class EntryController extends AbstractController
);
// don't redirect user to the deleted entry (check that the referer doesn't end with the same url)
$prev = $request->query->get('redirect', '');
$to = (1 !== preg_match('#' . $url . '$#i', $prev) ? $prev : null);
$referer = $request->headers->get('referer');
$to = (1 !== preg_match('#' . $url . '$#i', $referer) ? $referer : null);
$redirectUrl = $this->redirectHelper->to($to);
@ -671,6 +673,9 @@ class EntryController extends AbstractController
}
}
$nbEntriesUntagged = $this->entryRepository
->countUntaggedEntriesByUser($this->getUser()->getId());
return $this->render(
'@WallabagCore/Entry/entries.html.twig', [
'form' => $form->createView(),
@ -678,6 +683,7 @@ class EntryController extends AbstractController
'currentPage' => $page,
'searchTerm' => $searchTerm,
'isFiltered' => $form->isSubmitted(),
'nbEntriesUntagged' => $nbEntriesUntagged,
]
);
}

View File

@ -0,0 +1,40 @@
<?php
namespace Wallabag\CoreBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
use Symfony\Component\HttpFoundation\Request;
/**
* This controller allow us to customize the error template.
* The only modified line from the parent template is for "WallabagCoreBundle".
*/
class ExceptionController extends BaseExceptionController
{
protected function findTemplate(Request $request, $format, $code, $showException)
{
$name = $showException ? 'exception' : 'error';
if ($showException && 'html' === $format) {
$name = 'exception_full';
}
// For error pages, try to find a template for the specific HTTP status code and format
if (!$showException) {
$template = sprintf('@WallabagCore/Exception/%s.%s.twig', $name, $format);
if ($this->templateExists($template)) {
return $template;
}
}
// try to find a template for the given format
$template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format);
if ($this->templateExists($template)) {
return $template;
}
// default to a generic HTML exception
$request->setRequestFormat('html');
return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
}
}

View File

@ -45,7 +45,7 @@ class TagController extends AbstractController
$form = $this->createForm(NewTagType::class, new Tag());
$form->handleRequest($request);
$tags = $form->get('label')->getData() ?? '';
$tags = $form->get('label')->getData();
$tagsExploded = explode(',', $tags);
// avoid too much tag to be added
@ -104,7 +104,7 @@ class TagController extends AbstractController
$this->entityManager->flush();
}
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'), true);
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'), '', true);
return $this->redirect($redirectUrl);
}
@ -185,7 +185,7 @@ class TagController extends AbstractController
$form = $this->createForm(RenameTagType::class, new Tag());
$form->handleRequest($request);
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'), true);
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'), '', true);
if ($form->isSubmitted() && $form->isValid()) {
$newTag = new Tag();
@ -257,7 +257,7 @@ class TagController extends AbstractController
$this->entityManager->flush();
}
return $this->redirect($this->redirectHelper->to($request->query->get('redirect'), true));
return $this->redirect($this->redirectHelper->to($request->headers->get('referer'), '', true));
}
/**
@ -279,7 +279,8 @@ class TagController extends AbstractController
$this->entityManager->remove($tag);
$this->entityManager->flush();
}
$redirectUrl = $this->redirectHelper->to($request->query->get('redirect'), true);
$redirectUrl = $this->redirectHelper->to($request->headers->get('referer'), '', true);
return $this->redirect($redirectUrl);
}

View File

@ -7,7 +7,6 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Wallabag\CoreBundle\Entity\Config;
use Wallabag\UserBundle\DataFixtures\UserFixtures;
use Wallabag\UserBundle\Entity\User;
class ConfigFixtures extends Fixture implements DependentFixtureInterface
{
@ -16,7 +15,7 @@ class ConfigFixtures extends Fixture implements DependentFixtureInterface
*/
public function load(ObjectManager $manager): void
{
$adminConfig = new Config($this->getReference('admin-user', User::class));
$adminConfig = new Config($this->getReference('admin-user'));
$adminConfig->setItemsPerPage(30);
$adminConfig->setReadingSpeed(200);
@ -30,7 +29,7 @@ class ConfigFixtures extends Fixture implements DependentFixtureInterface
$this->addReference('admin-config', $adminConfig);
$bobConfig = new Config($this->getReference('bob-user', User::class));
$bobConfig = new Config($this->getReference('bob-user'));
$bobConfig->setItemsPerPage(10);
$bobConfig->setReadingSpeed(200);
$bobConfig->setLanguage('fr');
@ -43,7 +42,7 @@ class ConfigFixtures extends Fixture implements DependentFixtureInterface
$this->addReference('bob-config', $bobConfig);
$emptyConfig = new Config($this->getReference('empty-user', User::class));
$emptyConfig = new Config($this->getReference('empty-user'));
$emptyConfig->setItemsPerPage(10);
$emptyConfig->setReadingSpeed(100);
$emptyConfig->setLanguage('en');

View File

@ -6,9 +6,7 @@ use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\UserBundle\DataFixtures\UserFixtures;
use Wallabag\UserBundle\Entity\User;
class EntryFixtures extends Fixture implements DependentFixtureInterface
{
@ -89,7 +87,7 @@ class EntryFixtures extends Fixture implements DependentFixtureInterface
];
foreach ($entries as $reference => $item) {
$entry = new Entry($this->getReference($item['user'], User::class));
$entry = new Entry($this->getReference($item['user']));
$entry->setUrl($item['url']);
$entry->setReadingTime($item['reading_time']);
$entry->setDomainName($item['domain']);
@ -100,7 +98,7 @@ class EntryFixtures extends Fixture implements DependentFixtureInterface
if (isset($item['tags'])) {
foreach ($item['tags'] as $tag) {
$entry->addTag($this->getReference($tag, Tag::class));
$entry->addTag($this->getReference($tag));
}
}

View File

@ -7,7 +7,6 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Wallabag\CoreBundle\Entity\IgnoreOriginUserRule;
use Wallabag\UserBundle\DataFixtures\UserFixtures;
use Wallabag\UserBundle\Entity\User;
class IgnoreOriginUserRuleFixtures extends Fixture implements DependentFixtureInterface
{
@ -18,7 +17,7 @@ class IgnoreOriginUserRuleFixtures extends Fixture implements DependentFixtureIn
{
$rule = new IgnoreOriginUserRule();
$rule->setRule('host = "example.fr"');
$rule->setConfig($this->getReference('admin-user', User::class)->getConfig());
$rule->setConfig($this->getReference('admin-user')->getConfig());
$manager->persist($rule);

View File

@ -10,7 +10,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
use Wallabag\CoreBundle\Entity\SiteCredential;
use Wallabag\CoreBundle\Helper\CryptoProxy;
use Wallabag\UserBundle\DataFixtures\UserFixtures;
use Wallabag\UserBundle\Entity\User;
class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface, ContainerAwareInterface
{
@ -29,14 +28,14 @@ class SiteCredentialFixtures extends Fixture implements DependentFixtureInterfac
*/
public function load(ObjectManager $manager): void
{
$credential = new SiteCredential($this->getReference('admin-user', User::class));
$credential = new SiteCredential($this->getReference('admin-user'));
$credential->setHost('.super.com');
$credential->setUsername($this->container->get(CryptoProxy::class)->crypt('.super'));
$credential->setPassword($this->container->get(CryptoProxy::class)->crypt('bar'));
$manager->persist($credential);
$credential = new SiteCredential($this->getReference('admin-user', User::class));
$credential = new SiteCredential($this->getReference('admin-user'));
$credential->setHost('paywall.example.com');
$credential->setUsername($this->container->get(CryptoProxy::class)->crypt('paywall.example'));
$credential->setPassword($this->container->get(CryptoProxy::class)->crypt('bar'));

View File

@ -5,7 +5,6 @@ namespace Wallabag\CoreBundle\DataFixtures;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Wallabag\CoreBundle\Entity\Config;
use Wallabag\CoreBundle\Entity\TaggingRule;
class TaggingRuleFixtures extends Fixture implements DependentFixtureInterface
@ -18,14 +17,14 @@ class TaggingRuleFixtures extends Fixture implements DependentFixtureInterface
$tr1 = new TaggingRule();
$tr1->setRule('content matches "spurs"');
$tr1->setTags(['sport']);
$tr1->setConfig($this->getReference('admin-config', Config::class));
$tr1->setConfig($this->getReference('admin-config'));
$manager->persist($tr1);
$tr2 = new TaggingRule();
$tr2->setRule('content matches "basket"');
$tr2->setTags(['sport']);
$tr2->setConfig($this->getReference('admin-config', Config::class));
$tr2->setConfig($this->getReference('admin-config'));
$manager->persist($tr2);
@ -33,28 +32,28 @@ class TaggingRuleFixtures extends Fixture implements DependentFixtureInterface
$tr3->setRule('title matches "wallabag"');
$tr3->setTags(['wallabag']);
$tr3->setConfig($this->getReference('admin-config', Config::class));
$tr3->setConfig($this->getReference('admin-config'));
$manager->persist($tr3);
$tr4 = new TaggingRule();
$tr4->setRule('content notmatches "basket"');
$tr4->setTags(['foot']);
$tr4->setConfig($this->getReference('admin-config', Config::class));
$tr4->setConfig($this->getReference('admin-config'));
$manager->persist($tr4);
$tr5 = new TaggingRule();
$tr5->setRule('readingTime <= 5');
$tr5->setTags(['shortread']);
$tr5->setConfig($this->getReference('empty-config', Config::class));
$tr5->setConfig($this->getReference('empty-config'));
$manager->persist($tr5);
$tr6 = new TaggingRule();
$tr6->setRule('readingTime > 5');
$tr6->setTags(['longread']);
$tr6->setConfig($this->getReference('empty-config', Config::class));
$tr6->setConfig($this->getReference('empty-config'));
$manager->persist($tr6);

View File

@ -2,7 +2,6 @@
namespace Wallabag\CoreBundle\Doctrine;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@ -50,7 +49,7 @@ abstract class WallabagMigration extends AbstractMigration implements ContainerA
}
// escape table name is handled using " on postgresql
if ($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform) {
if ('postgresql' === $this->connection->getDatabasePlatform()->getName()) {
return '"' . $table . '"';
}

View File

@ -3,7 +3,7 @@
namespace Wallabag\CoreBundle\Event\Listener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
@ -18,7 +18,7 @@ class LocaleListener implements EventSubscriberInterface
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event)
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {

View File

@ -6,7 +6,6 @@ use Lexik\Bundle\FormFilterBundle\Filter\FilterOperands;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\CheckboxFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\ChoiceFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\DateRangeFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\NumberFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\NumberRangeFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Form\Type\TextFilterType;
use Lexik\Bundle\FormFilterBundle\Filter\Query\QueryInterface;
@ -103,13 +102,10 @@ class EntryFilterType extends AbstractType
return $filterQuery->createCondition($expression);
},
'label' => 'entry.filters.domain_label',
'attr' => [
'autocapitalize' => 'off',
],
])
->add('httpStatus', NumberFilterType::class, [
->add('httpStatus', TextFilterType::class, [
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) {
$value = (int) $values['value'];
$value = $values['value'];
if (false === \array_key_exists($value, Response::$statusTexts)) {
return false;
}
@ -121,11 +117,6 @@ class EntryFilterType extends AbstractType
return $filterQuery->createCondition($expression, $parameters);
},
'label' => 'entry.filters.http_status_label',
'html5' => true,
'attr' => [
'min' => 100,
'max' => 527,
],
])
->add('isArchived', CheckboxFilterType::class, [
'label' => 'entry.filters.archived_label',

View File

@ -4,6 +4,7 @@ namespace Wallabag\CoreBundle\Form\Type;
use FOS\UserBundle\Form\Type\RegistrationFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
@ -22,6 +23,15 @@ class UserInformationType extends AbstractType
->add('email', EmailType::class, [
'label' => 'config.form_user.email_label',
])
->add('emailTwoFactor', CheckboxType::class, [
'required' => false,
'label' => 'config.form_user.emailTwoFactor_label',
])
->add('googleTwoFactor', CheckboxType::class, [
'required' => false,
'label' => 'config.form_user.googleTwoFactor_label',
'mapped' => false,
])
->add('save', SubmitType::class, [
'label' => 'config.form.save',
])

View File

@ -9,11 +9,10 @@ use Http\Client\Common\HttpMethodsClient;
use Http\Client\Common\Plugin\ErrorPlugin;
use Http\Client\Common\Plugin\RedirectPlugin;
use Http\Client\Common\PluginClient;
use Http\Discovery\Psr17FactoryDiscovery;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Http\Client\HttpClient;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Message\MessageFactory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\Finder\Finder;
@ -29,9 +28,9 @@ class DownloadImages
private $mimeTypes;
private $wallabagUrl;
public function __construct(ClientInterface $client, $baseFolder, $wallabagUrl, LoggerInterface $logger, RequestFactoryInterface $requestFactory = null, StreamFactoryInterface $streamFactory = null)
public function __construct(HttpClient $client, $baseFolder, $wallabagUrl, LoggerInterface $logger, MessageFactory $messageFactory = null)
{
$this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin(), new RedirectPlugin()]), $requestFactory ?: Psr17FactoryDiscovery::findRequestFactory(), $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory());
$this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin(), new RedirectPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find());
$this->baseFolder = $baseFolder;
$this->wallabagUrl = rtrim($wallabagUrl, '/');
$this->logger = $logger;

View File

@ -2,7 +2,6 @@
namespace Wallabag\CoreBundle\Helper;
use GuzzleHttp\Psr7\Uri;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Wallabag\CoreBundle\Entity\Config;
@ -24,23 +23,16 @@ class Redirect
/**
* @param string $url URL to redirect
* @param string $fallback Fallback URL if $url is null
* @param bool $ignoreActionMarkAsRead Ignore configured action when mark as read
*
* @return string
*/
public function to($url, $ignoreActionMarkAsRead = false)
public function to($url, $fallback = '', $ignoreActionMarkAsRead = false)
{
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (!$user instanceof User) {
if (null === $url) {
return $this->router->generate('homepage');
}
if (!Uri::isAbsolutePathReference(new Uri($url))) {
return $this->router->generate('homepage');
}
return $url;
}
@ -49,14 +41,14 @@ class Redirect
return $this->router->generate('homepage');
}
if (null === $url) {
if (null !== $url) {
return $url;
}
if ('' === $fallback) {
return $this->router->generate('homepage');
}
if (!Uri::isAbsolutePathReference(new Uri($url))) {
return $this->router->generate('homepage');
}
return $url;
return $fallback;
}
}

View File

@ -37,20 +37,6 @@ class EntryRepository extends ServiceEntityRepository
;
}
/**
* Retrieves all entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForAllByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
;
}
/**
* Retrieves unread entries for a user.
*
@ -66,21 +52,6 @@ class EntryRepository extends ServiceEntityRepository
;
}
/**
* Retrieves unread entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForUnreadByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isArchived = false')
;
}
/**
* Retrieves entries with the same domain.
*
@ -123,21 +94,6 @@ class EntryRepository extends ServiceEntityRepository
;
}
/**
* Retrieves read entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForArchiveByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isArchived = true')
;
}
/**
* Retrieves starred entries for a user.
*
@ -153,21 +109,6 @@ class EntryRepository extends ServiceEntityRepository
;
}
/**
* Retrieves starred entries count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForStarredByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->andWhere('e.isStarred = true')
;
}
/**
* Retrieves entries filtered with a search term for a user.
*
@ -226,21 +167,6 @@ class EntryRepository extends ServiceEntityRepository
;
}
/**
* Retrieve entries with annotations count for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getCountBuilderForAnnotationsByUser($userId)
{
return $this
->getQueryBuilderByUser($userId)
->innerJoin('e.annotations', 'a')
;
}
/**
* Retrieve untagged entries for a user.
*
@ -637,23 +563,6 @@ class EntryRepository extends ServiceEntityRepository
return $qb->getQuery()->getArrayResult();
}
/**
* @param int $userId
*
* @return array
*/
public function findEmptyEntriesIdByUserId($userId = null)
{
$qb = $this->createQueryBuilder('e')
->select('e.id');
if (null !== $userId) {
$qb->where('e.user = :userid AND e.content IS NULL')->setParameter(':userid', $userId);
}
return $qb->getQuery()->getArrayResult();
}
/**
* Find all entries by url and owner.
*

View File

@ -209,66 +209,38 @@
{{ form_widget(form.user.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }}
<br/>
<br/>
<div class="row">
<h5>{{ 'config.otp.page_title'|trans }}</h5>
<p>{{ 'config.form_user.two_factor_description'|trans }}</p>
<table>
<thead>
<tr>
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
<td><a href="{{ path('config_otp_email') }}" class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_email'|trans }}</a> {% if app.user.isEmailTwoFactor %}<a href="{{ path('disable_otp_email') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
</tr>
<tr>
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
<td><a href="{{ path('config_otp_app') }}" class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}">{{ 'config.form_user.two_factor.action_app'|trans }}</a> {% if app.user.isGoogleTwoFactor %}<a href="{{ path('disable_otp_app') }}" class="waves-effect waves-light btn red">Disable</a>{% endif %}</td>
</tr>
</tbody>
</table>
</div>
{{ form_widget(form.user._token) }}
{{ form_end(form.user) }}
<br/>
<br/>
<div class="row">
<h5>{{ 'config.otp.page_title'|trans }}</h5>
<p>{{ 'config.form_user.two_factor_description'|trans }}</p>
<table>
<thead>
<tr>
<th>{{ 'config.form_user.two_factor.table_method'|trans }}</th>
<th>{{ 'config.form_user.two_factor.table_state'|trans }}</th>
<th>{{ 'config.form_user.two_factor.table_action'|trans }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ 'config.form_user.two_factor.emailTwoFactor_label'|trans }}</td>
<td>{% if app.user.isEmailTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
<td>
<form action="{{ path('config_otp_email') }}" method="post" name="config_otp_email">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<button class="waves-effect waves-light btn{% if app.user.isEmailTwoFactor %} disabled{% endif %}" type="submit">{{ 'config.form_user.two_factor.action_email'|trans }}</button>
</form>
{% if app.user.isEmailTwoFactor %}
<form action="{{ path('disable_otp_email') }}" method="post" name="disable_otp_email">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<button class="waves-effect waves-light btn red" type="submit">Disable</button>
</form>
{% endif %}
</td>
</tr>
<tr>
<td>{{ 'config.form_user.two_factor.googleTwoFactor_label'|trans }}</td>
<td>{% if app.user.isGoogleTwoFactor %}<b>{{ 'config.form_user.two_factor.state_enabled'|trans }}</b>{% else %}{{ 'config.form_user.two_factor.state_disabled'|trans }}{% endif %}</td>
<td>
<form action="{{ path('config_otp_app') }}" method="post" name="config_otp_app">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<button class="waves-effect waves-light btn{% if app.user.isGoogleTwoFactor %} disabled{% endif %}" type="submit">{{ 'config.form_user.two_factor.action_app'|trans }}</button>
</form>
{% if app.user.isGoogleTwoFactor %}
<form action="{{ path('disable_otp_app') }}" method="post" name="disable_otp_app">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<button class="waves-effect waves-light btn red" type="submit">Disable</button>
</form>
{% endif %}
</td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
<div id="set4" class="col s12">
@ -580,34 +552,18 @@
<div class="row">
<h5>{{ 'config.reset.title'|trans }}</h5>
<p>{{ 'config.reset.description'|trans }}</p>
<p>
<form action="{{ path('config_reset', {type: 'annotations'}) }}" method="post" onsubmit="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" name="reset-annotations">
<input type="hidden" name="token" value="{{ csrf_token('reset-area') }}" />
<button class="waves-effect waves-light btn red" type="submit">{{ 'config.reset.annotations'|trans }}</button>
</form>
</p>
<p>
<form action="{{ path('config_reset', {type: 'tags'}) }}" method="post" onsubmit="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" name="reset-tags">
<input type="hidden" name="token" value="{{ csrf_token('reset-area') }}" />
<button class="waves-effect waves-light btn red" type="submit">{{ 'config.reset.tags'|trans }}</button>
</form>
</p>
<p>
<form action="{{ path('config_reset', {type: 'archived'}) }}" method="post" onsubmit="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" name="reset-archived">
<input type="hidden" name="token" value="{{ csrf_token('reset-area') }}" />
<button class="waves-effect waves-light btn red" type="submit">{{ 'config.reset.archived'|trans }}</button>
</form>
</p>
<p>
<form action="{{ path('config_reset', {type: 'entries'}) }}" method="post" onsubmit="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" name="reset-entries">
<input type="hidden" name="token" value="{{ csrf_token('reset-area') }}" />
<button class="waves-effect waves-light btn red" type="submit">{{ 'config.reset.entries'|trans }}</button>
</form>
</p>
<a href="{{ path('config_reset', {type: 'annotations'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.annotations'|trans }}
</a>
<a href="{{ path('config_reset', {type: 'tags'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.tags'|trans }}
</a>
<a href="{{ path('config_reset', {type: 'archived'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.archived'|trans }}
</a>
<a href="{{ path('config_reset', {type: 'entries'}) }}" onclick="return confirm('{{ 'config.reset.confirm'|trans|escape('js') }}')" class="waves-effect waves-light btn red">
{{ 'config.reset.entries'|trans }}
</a>
</div>
{% if enabled_users > 1 %}

View File

@ -40,7 +40,6 @@
{% endfor %}
<form class="form" action="{{ path("config_otp_app_check") }}" method="post">
<input type="hidden" name="token" value="{{ csrf_token('otp') }}" />
<div class="card-content">
<div class="row">
<div class="input-field col s12">
@ -50,6 +49,9 @@
</div>
</div>
<div class="card-action">
<a href="{{ path('config_otp_app_cancel') }}" class="waves-effect waves-light grey btn">
{{ 'config.otp.app.cancel'|trans }}
</a>
<button class="btn waves-effect waves-light" type="submit" name="send">
{{ 'config.otp.app.enable'|trans }}
<i class="material-icons right">send</i>

View File

@ -2,6 +2,11 @@
{% block title %}{{ 'developer.howto.page_title'|trans }}{% endblock %}
{% block css %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/themes/prism-dark.min.css') }}">
{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
@ -13,7 +18,7 @@
<p>{{ 'developer.howto.description.paragraph_3'|trans({'%link%': path('developer_create_client')})|raw }}</p>
<p>{{ 'developer.howto.description.paragraph_4'|trans }}</p>
<p>
<pre><code class="language-bash">http POST {{ wallabag_url }}/oauth/v2/token \
<pre><code class="language-bash">http POST https://app.wallabag.it/oauth/v2/token \
grant_type=password \
client_id=12_5um6nz50ceg4088c0840wwc0kgg44g00kk84og044ggkscso0k \
client_secret=3qd12zpeaxes8cwg8c0404g888co4wo8kc4gcw0occww8cgw4k \
@ -42,7 +47,7 @@ X-Powered-By: PHP/5.5.9-1ubuntu4.13
</p>
<p>{{ 'developer.howto.description.paragraph_6'|trans }}</p>
<p>
<pre><code class="language-bash">http GET {{ wallabag_url }}/api/entries.json \
<pre><code class="language-bash">http GET https://app.wallabag.it/api/entries.json \
"Authorization:Bearer ZWFjNjA3ZWMwYWVmYzRkYTBlMmQ3NTllYmVhOGJiZDE0ZTg1NjE4MjczOTVlNzM0ZTRlMWQ0MmRlMmYwNTk5Mw"</code></pre>
</p>
<p>{{ 'developer.howto.description.paragraph_7'|trans }}</p>
@ -53,4 +58,6 @@ X-Powered-By: PHP/5.5.9-1ubuntu4.13
</div>
</div>
</div>
<script src="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/prism.min.js') }}"></script>
<script src="{{ asset('https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/components/prism-bash.min.js') }}"></script>
{% endblock %}

View File

@ -57,11 +57,9 @@
<p>{{ 'developer.remove.warn_message_1'|trans({'%name%': client.name}) }}</p>
<p>{{ 'developer.remove.warn_message_2'|trans({'%name%': client.name}) }}</p>
<form action="{{ path('developer_delete_client', {id: client.id}) }}" method="post" name="delete-client">
<input type="hidden" name="token" value="{{ csrf_token('delete-client') }}" />
<button class="waves-effect waves-light btn red" type="submit">{{ 'developer.remove.action'|trans({'%name%': client.name}) }}</button>
</form>
<p>
<a class="waves-effect waves-light red btn" href="{{ path('developer_delete_client', {'id': client.id}) }}">{{ 'developer.remove.action'|trans({'%name%': client.name}) }}</a>
</p>
</div>
</li>
{% endfor %}

View File

@ -1,3 +1,3 @@
<label class="entry-checkbox">
<div class="entry-checkbox">
<input type="checkbox" class="entry-checkbox-input" data-js="entry-checkbox" name="entry-checkbox[]" value="{{ entry.id }}" />
</label>
</div>

View File

@ -7,20 +7,18 @@
</div>
</div>
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
<ul class="tools right">
<li>
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', {'id': entry.id, redirect: current_path}) }}" data-action="same_domain" data-entry-id="{{ entry.id }}"><i class="material-icons">language</i></a>
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', {'id': entry.id}) }}" data-action="same_domain" data-entry-id="{{ entry.id }}"><i class="material-icons">language</i></a>
</li>
<li>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" data-action="archived" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', {'id': entry.id}) }}" data-action="archived" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
</li>
<li>
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" data-action="star" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', {'id': entry.id}) }}" data-action="star" data-entry-id="{{ entry.id }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
</li>
<li>
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" data-action-confirm="{{ 'entry.confirm.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}" data-action="delete" data-entry-id="{{ entry.id }}"><i class="material-icons">delete</i></a>
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" data-action-confirm="{{ 'entry.confirm.delete'|trans }}" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id}) }}" data-action="delete" data-entry-id="{{ entry.id }}"><i class="material-icons">delete</i></a>
</li>
</ul>
</div>

View File

@ -9,15 +9,12 @@
</div>
{% endif %}
{% include "@WallabagCore/Entry/Card/_content.html.twig" with {'entry': entry, 'withMetadata': true, 'subClass': 'metadata'} only %}
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
<ul class="tools-list hide-on-small-only">
<li>
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">language</i></a>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">delete</i></a>
<a title="{{ 'entry.list.show_same_domain'|trans }}" class="tool grey-text" href="{{ path('same_domain', {'id': entry.id}) }}"><i class="material-icons">language</i></a>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', {'id': entry.id}) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>
<a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool grey-text" href="{{ path('star_entry', {'id': entry.id}) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_border{% else %}star{% endif %}</i></a>
<a title="{{ 'entry.list.delete'|trans }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" class="tool grey-text delete" href="{{ path('delete_entry', {'id': entry.id}) }}"><i class="material-icons">delete</i></a>
</li>
</ul>
</div>

View File

@ -1,7 +1,7 @@
<div class="card entry-card{% if currentRoute in routes and entry.isArchived %} archived{% endif %}">
{% include "@WallabagCore/Entry/Card/_mass_checkbox.html.twig" with {'entry': entry} only %}
<div class="card-body">
<div class="{% if app.user.config.displayThumbnails %}card-image{% endif %} waves-effect waves-block waves-light">
{% include "@WallabagCore/Entry/Card/_mass_checkbox.html.twig" with {'entry': entry} only %}
<ul class="card-entry-labels">
{% for tag in entry.tags|slice(0, 3) %}
<li title="{{ tag.label }}"><a href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a></li>

View File

@ -4,8 +4,7 @@
<li class="chip">
<a class="chip-label" href="{{ path('tag_entries', {'slug': tag.slug}) }}">{{ tag.label }}</a>
{% if withRemove is defined and withRemove == true %}
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
<a class="chip-action" href="{{ path('remove_tag', {'entry': entryId, 'tag': tag.id, redirect: current_path}) }}" onclick="return confirm('{{ 'entry.confirm.delete_tag'|trans|escape('js') }}')">
<a class="chip-action" href="{{ path('remove_tag', {'entry': entryId, 'tag': tag.id}) }}" onclick="return confirm('{{ 'entry.confirm.delete_tag'|trans|escape('js') }}')">
<i class="material-icons vertical-align-middle">delete</i>
</a>
{% endif %}

View File

@ -19,19 +19,18 @@
{% endblock %}
{% block content %}
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
{% set list_mode = app.user.config.listMode %}
{% set entries_with_archived_class_routes = ['tag_entries', 'search', 'all'] %}
{% set current_route = app.request.attributes.get('_route') %}
{% if current_route == 'homepage' %}
{% set current_route = 'unread' %}
{% endif %}
<form name="form_mass_action" action="{{ path('mass_action', {redirect: current_path}) }}" method="post">
<form name="form_mass_action" action="{{ path('mass_action') }}" method="post">
<div class="results">
<div class="nb-results">
{{ 'entry.list.number_on_the_page'|trans({'%count%': entries.count}) }}
{{ 'entry.list.number_on_the_page'|transchoice(entries.count) }}
{% if entries.count > 0 %}
<a class="results-item" href="{{ path('switch_view_mode', {redirect: current_path}) }}"><i class="material-icons">{% if list_mode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
<a class="results-item" href="{{ path('switch_view_mode') }}"><i class="material-icons">{% if list_mode == 0 %}view_list{% else %}view_module{% endif %}</i></a>
{% endif %}
{% if entries.count > 0 %}
<label for="mass-action-inputs-displayed" class="mass-action-toggle results-item tooltipped" data-position="right" data-delay="50" data-tooltip="{{ 'entry.list.toggle_mass_action'|trans }}"><i class="material-icons">library_add_check</i></label>
@ -40,7 +39,7 @@
{% include "@WallabagCore/Entry/_feed_link.html.twig" %}
{% endif %}
</div>
{% if current_route == 'search' %}<div><a href="{{ path('tag_this_search', {'filter': searchTerm, 'currentRoute': app.request.get('currentRoute'), redirect: current_path}) }}" title="{{ 'entry.list.assign_search_tag'|trans }}">{{ 'entry.list.assign_search_tag'|trans }}</a></div>{% endif %}
{% if current_route == 'search' %}<div><a href="{{ path('tag_this_search', {'filter': searchTerm, 'currentRoute': app.request.get('currentRoute')}) }}" title="{{ 'entry.list.assign_search_tag'|trans }}">{{ 'entry.list.assign_search_tag'|trans }}</a></div>{% endif %}
{% if entries.getNbPages > 1 %}
{{ pagerfanta(entries, 'default_wallabag') }}
{% endif %}
@ -54,11 +53,13 @@
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-read" title="{{ 'entry.list.toogle_as_read'|trans }}"><i class="material-icons">done</i></button>
<button class="mass-action-button btn cyan darken-1" type="submit" name="toggle-star" title="{{ 'entry.list.toogle_as_star'|trans }}" ><i class="material-icons">star</i></button>
<button class="mass-action-button btn cyan darken-1" type="submit" name="delete" onclick="return confirm('{{ 'entry.confirm.delete_entries'|trans|escape('js') }}')" title="{{ 'entry.list.delete'|trans }}"><i class="material-icons">delete</i></button>
<label for="mass-action-tags-displayed" class="mass-action-button btn cyan darken-1" type="button" title="{{ 'entry.list.add_tags'|trans }}"><i class="material-icons">label</i></label>
</div>
<input id="mass-action-tags-displayed" class="toggle-checkbox" type="checkbox" />
<div class="mass-action-tags">
<button class="btn cyan darken-1 mass-action-button mass-action-button--tags" type="submit" name="tag" title="{{ 'entry.list.add_tags'|trans }}"><i class="material-icons">label</i></button>
<input type="text" class="mass-action-tags-input" name="tags" placeholder="{{ 'entry.list.mass_action_tags_input_placeholder'|trans }}" />
<button class="btn cyan darken-1" type="submit" name="tag">{{ 'entry.list.add_tags'|trans }}</button>
</div>
</div>
@ -117,9 +118,9 @@
<h4 class="center">{{ 'entry.filters.title'|trans }}</h4>
<div class="row">
{% if current_route != 'untagged' %}
{% if current_route != 'untagged' and nbEntriesUntagged != 0 %}
<div class="col s12 center-align">
<a href="{{ path('untagged') }}">{{ 'tag.list.see_untagged_entries'|trans }}</a>
<a href="{{ path('untagged') }}">{{ 'tag.list.see_untagged_entries'|trans }} ({{ nbEntriesUntagged }})</a>
</div>
{% endif %}

View File

@ -4,8 +4,6 @@
{% block body_class %}entry{% endblock %}
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
{% block menu %}
<div class="progress">
<div class="determinate"></div>
@ -26,12 +24,12 @@
</ul>
<ul class="right">
<li>
<a class="waves-effect" title="{{ 'entry.view.left_menu.set_as_read'|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead">
<a class="waves-effect" title="{{ 'entry.view.left_menu.set_as_read'|trans }}" href="{{ path('archive_entry', {'id': entry.id}) }}" id="markAsRead">
<i class="material-icons small">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i>
</a>
</li>
<li>
<a class="waves-effect" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav">
<a class="waves-effect" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id}) }}" id="setFav">
<i class="material-icons small">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i>
</a>
</li>
@ -56,7 +54,7 @@
</li>
<li class="bold">
<a class="waves-effect collapsible-header" onclick="return confirm('{{ 'entry.confirm.reload'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" href="{{ path('reload_entry', {'id': entry.id}) }}" id="reload">
<a class="waves-effect collapsible-header" title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" href="{{ path('reload_entry', {'id': entry.id}) }}" id="reload">
<i class="material-icons small">refresh</i>
<span>{{ 'entry.view.left_menu.re_fetch_content'|trans }}</span>
</a>
@ -69,7 +67,7 @@
{% endif %}
<li class="bold hide-on-med-and-down">
<a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}" id="markAsRead">
<a class="waves-effect collapsible-header markasread" title="{{ mark_as_read_label|trans }}" href="{{ path('archive_entry', {'id': entry.id}) }}" id="markAsRead">
<i class="material-icons small">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i>
<span>{{ mark_as_read_label|trans }}</span>
</a>
@ -77,14 +75,14 @@
</li>
<li class="bold hide-on-med-and-down">
<a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}" id="setFav">
<a class="waves-effect collapsible-header favorite" title="{{ 'entry.view.left_menu.set_as_starred'|trans }}" href="{{ path('star_entry', {'id': entry.id}) }}" id="setFav">
<i class="material-icons spall">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i>
<span>{{ 'entry.view.left_menu.set_as_starred'|trans }}</span>
</a>
<div class="collapsible-body"></div>
</li>
<li class="bold border-bottom">
<a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}">
<a class="waves-effect collapsible-header delete" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" title="{{ 'entry.view.left_menu.delete'|trans }}" href="{{ path('delete_entry', {'id': entry.id}) }}">
<i class="material-icons small">delete</i>
<span>{{ 'entry.view.left_menu.delete'|trans }}</span>
</a>
@ -271,7 +269,7 @@
{% if entry.annotations|length %}
<li>
<i class="material-icons grey-text">comment</i>
{{ 'entry.view.annotations_on_the_entry'|trans({'%count%': entry.annotations|length}) }}
{{ 'entry.view.annotations_on_the_entry'|transchoice(entry.annotations|length) }}
</li>
{% endif %}
{% if entry.originUrl is not empty %}
@ -300,9 +298,9 @@
<i class="material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating" href="{{ path('archive_entry', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a></li>
<li><a class="btn-floating" href="{{ path('star_entry', {'id': entry.id, redirect: current_path}) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i></a></li>
<li><a class="btn-floating" href="{{ path('delete_entry', {'id': entry.id, redirect: current_path}) }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')"><i class="material-icons">delete</i></a></li>
<li><a class="btn-floating" href="{{ path('archive_entry', {'id': entry.id}) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a></li>
<li><a class="btn-floating" href="{{ path('star_entry', {'id': entry.id}) }}"><i class="material-icons">{% if entry.isStarred == 0 %}star_outline{% else %}star{% endif %}</i></a></li>
<li><a class="btn-floating" href="{{ path('delete_entry', {'id': entry.id}) }}" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')"><i class="material-icons">delete</i></a></li>
</ul>
</div>
</div>

View File

@ -1,4 +1,4 @@
<form class="tags-add-form" name="tag" method="post" action="{{ path('new_tag', {'entry': entry.id}) }}">
<form name="tag" method="post" action="{{ path('new_tag', {'entry': entry.id}) }}">
{% if form_errors(form) %}
<span class="black-text">{{ form_errors(form) }}</span>
{% endif %}
@ -9,6 +9,6 @@
{{ form_widget(form.label, {'attr': {'autocomplete': 'off'}}) }}
{{ form_widget(form.add, {'attr': {'class': 'btn waves-effect waves-light tags-add-form-submit'}}) }}
{{ form_widget(form.add, {'attr': {'class': 'btn waves-effect waves-light hide-on-large-only'}}) }}
{{ form_widget(form._token) }}
</form>

View File

@ -3,10 +3,8 @@
{% block title %}{{ 'tag.page_title'|trans }}{% endblock %}
{% block content %}
{% set current_path = path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) %}
<div class="results clearfix">
{{ 'tag.list.number_on_the_page'|trans({'%count%': tags|length}) }}
{{ 'tag.list.number_on_the_page'|transchoice(tags|length) }}
</div>
<div class="row">
@ -20,7 +18,7 @@
{{ tag.label }}&nbsp;({{ tag.nbEntries }})
</a>
{% if renameForms is defined and renameForms[tag.id] is defined %}
<form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug, redirect: current_path}) }}" method="POST">
<form class="card-tag-form hidden" data-handle="tag-rename-form" action="{{ path('tag_rename', {'slug': tag.slug}) }}" method="POST">
{{ form_widget(renameForms[tag.id].label, {'attr': {'value': tag.label}}) }}
{{ form_rest(renameForms[tag.id]) }}
</form>
@ -28,7 +26,7 @@
<i class="material-icons">mode_edit</i>
</a>
{% endif %}
<a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug, redirect: current_path}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')">
<a id="delete-{{ tag.slug }}" href="{{ path('tag_delete', {'slug': tag.slug}) }}" class="card-tag-icon card-tag-delete" onclick="return confirm('{{ 'tag.confirm.delete'|trans({'%name%': tag.label})|escape('js') }}')">
<i class="material-icons">delete</i>
</a>
{% if app.user.config.feedToken %}

View File

@ -168,7 +168,7 @@
<div class="container">
<div class="row">
<div class="col m12 l8">
<p class="footer-text">
<p class="footer-text" title="{{ display_stats()|raw|striptags }}">
{{ display_stats() }}
</p>
</div>

View File

@ -19,16 +19,16 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
private $tagRepository;
private $lifeTime;
private $translator;
private $projectDir;
private $rootDir;
public function __construct(EntryRepository $entryRepository, TagRepository $tagRepository, TokenStorageInterface $tokenStorage, $lifeTime, TranslatorInterface $translator, string $projectDir)
public function __construct(EntryRepository $entryRepository, TagRepository $tagRepository, TokenStorageInterface $tokenStorage, $lifeTime, TranslatorInterface $translator, string $rootDir)
{
$this->entryRepository = $entryRepository;
$this->tagRepository = $tagRepository;
$this->tokenStorage = $tokenStorage;
$this->lifeTime = $lifeTime;
$this->translator = $translator;
$this->projectDir = $projectDir;
$this->rootDir = $rootDir;
}
public function getGlobals(): array
@ -88,32 +88,35 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
switch ($type) {
case 'starred':
$qb = $this->entryRepository->getCountBuilderForStarredByUser($user->getId());
$qb = $this->entryRepository->getBuilderForStarredByUser($user->getId());
break;
case 'archive':
$qb = $this->entryRepository->getCountBuilderForArchiveByUser($user->getId());
$qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId());
break;
case 'unread':
$qb = $this->entryRepository->getCountBuilderForUnreadByUser($user->getId());
$qb = $this->entryRepository->getBuilderForUnreadByUser($user->getId());
break;
case 'annotated':
$qb = $this->entryRepository->getCountBuilderForAnnotationsByUser($user->getId());
$qb = $this->entryRepository->getBuilderForAnnotationsByUser($user->getId());
break;
case 'all':
$qb = $this->entryRepository->getCountBuilderForAllByUser($user->getId());
$qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
break;
default:
throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
}
// THANKS to PostgreSQL we CAN'T make a DEAD SIMPLE count(e.id)
// ERROR: column "e0_.id" must appear in the GROUP BY clause or be used in an aggregate function
$query = $qb
->select('COUNT(e.id)')
->select('e.id')
->groupBy('e.id')
->getQuery();
$query->useQueryCache(true);
$query->enableResultCache($this->lifeTime);
return $query->getSingleScalarResult();
return \count($query->getArrayResult());
}
/**
@ -145,14 +148,15 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
return 0;
}
$query = $this->entryRepository->getCountBuilderForArchiveByUser($user->getId())
->select('COUNT(e.id)')
$query = $this->entryRepository->getBuilderForArchiveByUser($user->getId())
->select('e.id')
->groupBy('e.id')
->getQuery();
$query->useQueryCache(true);
$query->enableResultCache($this->lifeTime);
$nbArchives = $query->getSingleScalarResult();
$nbArchives = \count($query->getArrayResult());
$interval = $user->getCreatedAt()->diff(new \DateTime('now'));
$nbDays = (int) $interval->format('%a') ?: 1;
@ -170,7 +174,7 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface
public function assetFileExists($name)
{
return file_exists(realpath($this->projectDir . '/web/' . $name));
return file_exists(realpath($this->rootDir . '/../web/' . $name));
}
public function themeClass()

View File

@ -4,13 +4,13 @@ namespace Wallabag\ImportBundle\Controller;
use Craue\ConfigBundle\Util\Config;
use Predis\Client;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Wallabag\ImportBundle\Consumer\RabbitMQConsumerTotalProxy;
use Wallabag\ImportBundle\Import\ImportChain;
class ImportController extends AbstractController
class ImportController extends Controller
{
private RabbitMQConsumerTotalProxy $rabbitMQConsumerTotalProxy;

View File

@ -6,11 +6,10 @@ use Http\Client\Common\HttpMethodsClient;
use Http\Client\Common\Plugin\ErrorPlugin;
use Http\Client\Common\PluginClient;
use Http\Client\Exception\RequestException;
use Http\Discovery\Psr17FactoryDiscovery;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Http\Client\HttpClient;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Message\MessageFactory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Wallabag\CoreBundle\Entity\Entry;
class PocketImport extends AbstractImport
@ -153,9 +152,9 @@ class PocketImport extends AbstractImport
/**
* Set the Http client.
*/
public function setClient(ClientInterface $client, RequestFactoryInterface $requestFactory = null, StreamFactoryInterface $streamFactory = null)
public function setClient(HttpClient $client, MessageFactory $messageFactory = null)
{
$this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $requestFactory ?: Psr17FactoryDiscovery::findRequestFactory(), $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory());
$this->client = new HttpMethodsClient(new PluginClient($client, [new ErrorPlugin()]), $messageFactory ?: MessageFactoryDiscovery::find());
}
/**

View File

@ -5,7 +5,7 @@ namespace Tests\Wallabag\AnnotationBundle;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManager;
use FOS\UserBundle\Security\LoginManager;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
@ -14,7 +14,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
abstract class WallabagAnnotationTestCase extends WebTestCase
{
/**
* @var KernelBrowser
* @var Client
*/
protected $client = null;
@ -42,7 +42,7 @@ abstract class WallabagAnnotationTestCase extends WebTestCase
}
/**
* @return KernelBrowser
* @return Client
*/
protected function createAuthorizedClient()
{

View File

@ -104,16 +104,20 @@ class DeveloperControllerTest extends WallabagCoreTestCase
$this->assertStringContainsString('no_client', $client->getResponse()->getContent());
$this->logInAs('bob');
$client->request('POST', '/developer/client/delete/' . $adminApiClient->getId());
$client->request('GET', '/developer/client/delete/' . $adminApiClient->getId());
$this->assertSame(403, $client->getResponse()->getStatusCode());
// Try to remove the admin's client with the good user
$this->logInAs('admin');
$crawler = $client->request('GET', '/developer');
$form = $crawler->filter('form[name=delete-client]')->form();
$link = $crawler
->filter('div[class=collapsible-body] p a')
->eq(0)
->link()
;
$client->submit($form);
$client->click($link);
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertNull(

View File

@ -6,7 +6,7 @@ use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManager;
use FOS\UserBundle\Security\LoginManager;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
@ -16,7 +16,7 @@ use Wallabag\UserBundle\Entity\User;
abstract class WallabagApiTestCase extends WebTestCase
{
/**
* @var KernelBrowser
* @var Client
*/
protected $client = null;
@ -32,7 +32,7 @@ abstract class WallabagApiTestCase extends WebTestCase
}
/**
* @return KernelBrowser
* @return Client
*/
protected function createAuthorizedClient()
{

View File

@ -929,8 +929,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
$form = $crawler->filter('form[name=reset-annotations]')->form();
$client->submit($form);
$crawler = $client->click($crawler->selectLink('config.reset.annotations')->link());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.annotations_reset', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
@ -946,8 +945,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
$form = $crawler->filter('form[name=reset-tags]')->form();
$client->submit($form);
$crawler = $client->click($crawler->selectLink('config.reset.tags')->link());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.tags_reset', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
@ -963,8 +961,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
$form = $crawler->filter('form[name=reset-entries]')->form();
$client->submit($form);
$crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.entries_reset', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
@ -1030,8 +1027,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
$form = $crawler->filter('form[name=reset-archived]')->form();
$client->submit($form);
$crawler = $client->click($crawler->selectLink('config.reset.archived')->link());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.archived_reset', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
@ -1090,8 +1086,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode());
$form = $crawler->filter('form[name=reset-entries]')->form();
$client->submit($form);
$crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.entries_reset', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
@ -1174,13 +1169,14 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/config');
$form = $crawler->filter('form[name=config_otp_email]')->form();
$client->submit($form);
$crawler = $client->request('GET', '/config/otp/email');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.otp_enabled', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.config.notice.otp_enabled', $alert[0]);
// restore user
$em = $this->getEntityManager();
@ -1200,23 +1196,14 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->logInAs('admin');
$client = $this->getTestClient();
$em = $this->getEntityManager();
$user = $em
->getRepository(User::class)
->findOneByUsername('admin');
$user->setEmailTwoFactor(true);
$em->persist($user);
$em->flush();
$crawler = $client->request('GET', '/config');
$form = $crawler->filter('form[name=disable_otp_email]')->form();
$client->submit($form);
$crawler = $client->request('GET', '/config/otp/email/disable');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.otp_disabled', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.config.notice.otp_disabled', $alert[0]);
// restore user
$em = $this->getEntityManager();
@ -1232,10 +1219,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/config');
$form = $crawler->filter('form[name=config_otp_app]')->form();
$client->submit($form);
$crawler = $client->request('GET', '/config/otp/app');
$this->assertSame(200, $client->getResponse()->getStatusCode());
@ -1254,28 +1238,49 @@ class ConfigControllerTest extends WallabagCoreTestCase
$em->flush();
}
public function testUserDisable2faGoogle()
public function testUserEnable2faGoogleCancel()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/config/otp/app');
$this->assertSame(200, $client->getResponse()->getStatusCode());
// restore user
$em = $this->getEntityManager();
$user = $em
->getRepository(User::class)
->findOneByUsername('admin');
$user->setGoogleAuthenticatorSecret('Google2FA');
$em->persist($user);
$em->flush();
$this->assertTrue($user->isGoogleTwoFactor());
$this->assertGreaterThan(0, $user->getBackupCodes());
$crawler = $client->request('GET', '/config');
$form = $crawler->filter('form[name=disable_otp_app]')->form();
$client->submit($form);
$crawler = $client->request('GET', '/config/otp/app/cancel');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('flashes.config.notice.otp_disabled', $client->getContainer()->get(SessionInterface::class)->getFlashBag()->get('notice')[0]);
$user = $em
->getRepository(User::class)
->findOneByUsername('admin');
$this->assertFalse($user->isGoogleTwoFactor());
$this->assertEmpty($user->getBackupCodes());
}
public function testUserDisable2faGoogle()
{
$this->logInAs('admin');
$client = $this->getTestClient();
$crawler = $client->request('GET', '/config/otp/app/disable');
$this->assertSame(302, $client->getResponse()->getStatusCode());
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
$this->assertStringContainsString('flashes.config.notice.otp_disabled', $alert[0]);
// restore user
$em = $this->getEntityManager();

View File

@ -1302,10 +1302,8 @@ class EntryControllerTest extends WallabagCoreTestCase
$this->getEntityManager()->flush();
$crawler = $client->request('GET', '/view/' . $entry->getId());
$link = $crawler->filter('a[id="markAsRead"]')->link();
$client->click($link);
$client->request('GET', '/view/' . $entry->getId());
$client->request('GET', '/archive/' . $entry->getId());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertStringContainsString('/view/' . $entry->getId(), $client->getResponse()->headers->get('location'));
@ -1656,9 +1654,9 @@ class EntryControllerTest extends WallabagCoreTestCase
// As long as the deletion link of a tag is following
// a link to the tag view, we take the second one to retrieve
// the deletion link of the first tag
$link = $crawler->filter('body div#article div.tools ul.tags li.chip a')->extract(['href'])[1];
$link = $crawler->filter('body div#article div.tools ul.tags li.chip a')->extract('href')[1];
$this->assertStringStartsWith(sprintf('/remove-tag/%s/%s', $entry->getId(), $tag->getId()), $link);
$this->assertSame(sprintf('/remove-tag/%s/%s', $entry->getId(), $tag->getId()), $link);
}
public function testRandom()

View File

@ -4,7 +4,7 @@ namespace Tests\Wallabag\CoreBundle\Controller;
use Craue\ConfigBundle\Util\Config;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Client;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Wallabag\CoreBundle\Entity\SiteCredential;
@ -139,7 +139,7 @@ class SiteCredentialControllerTest extends WallabagCoreTestCase
$this->assertStringContainsString('flashes.site_credential.notice.deleted', $crawler->filter('body')->extract(['_text'])[0]);
}
private function createSiteCredential(KernelBrowser $client)
private function createSiteCredential(Client $client)
{
$credential = new SiteCredential($this->getLoggedInUser());
$credential->setHost('google.io');

View File

@ -123,11 +123,9 @@ class TagControllerTest extends WallabagCoreTestCase
$this->getEntityManager()->clear();
// We make a first request to set an history and test redirection after tag deletion
$crawler = $client->request('GET', '/view/' . $entry->getId());
$entryUri = $client->getRequest()->getRequestUri();
$link = $crawler->filter('a[href^="/remove-tag/' . $entry->getId() . '/' . $tag->getId() . '"]')->link();
$client->click($link);
$client->request('GET', '/view/' . $entry->getId());
$entryUri = $client->getRequest()->getUri();
$client->request('GET', '/remove-tag/' . $entry->getId() . '/' . $tag->getId());
$this->assertSame(302, $client->getResponse()->getStatusCode());
$this->assertSame($entryUri, $client->getResponse()->getTargetUrl());

View File

@ -7,7 +7,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Wallabag\CoreBundle\Event\Listener\LocaleListener;
@ -82,6 +82,6 @@ class LocaleListenerTest extends TestCase
->disableOriginalConstructor()
->getMock();
return new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
}
}

View File

@ -33,7 +33,7 @@ class RedirectTest extends TestCase
$this->routerMock->expects($this->any())
->method('generate')
->with('homepage')
->willReturn('/');
->willReturn('homepage');
$this->user = new User();
$this->user->setName('youpi');
@ -59,11 +59,18 @@ class RedirectTest extends TestCase
$this->redirect = new Redirect($this->routerMock, $tokenStorage);
}
public function testRedirectToNull()
public function testRedirectToNullWithFallback()
{
$redirectUrl = $this->redirect->to(null, 'fallback');
$this->assertSame('fallback', $redirectUrl);
}
public function testRedirectToNullWithoutFallback()
{
$redirectUrl = $this->redirect->to(null);
$this->assertSame('/', $redirectUrl);
$this->assertSame($this->routerMock->generate('homepage'), $redirectUrl);
}
public function testRedirectToValidUrl()
@ -73,13 +80,6 @@ class RedirectTest extends TestCase
$this->assertSame('/unread/list', $redirectUrl);
}
public function testRedirectToAbsoluteUrl()
{
$redirectUrl = $this->redirect->to('https://www.google.com/');
$this->assertSame('/', $redirectUrl);
}
public function testWithNotLoggedUser()
{
$redirect = new Redirect($this->routerMock, new TokenStorage());
@ -94,24 +94,24 @@ class RedirectTest extends TestCase
$redirectUrl = $this->redirect->to('/unread/list');
$this->assertSame('/', $redirectUrl);
$this->assertSame($this->routerMock->generate('homepage'), $redirectUrl);
}
public function testUserForRedirectWithIgnoreActionMarkAsRead()
{
$this->user->getConfig()->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE);
$redirectUrl = $this->redirect->to('/unread/list', true);
$redirectUrl = $this->redirect->to('/unread/list', '', true);
$this->assertSame('/unread/list', $redirectUrl);
}
public function testUserForRedirectNullWithIgnoreActionMarkAsRead()
public function testUserForRedirectNullWithFallbackWithIgnoreActionMarkAsRead()
{
$this->user->getConfig()->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE);
$redirectUrl = $this->redirect->to(null, true);
$redirectUrl = $this->redirect->to(null, 'fallback', true);
$this->assertSame('/', $redirectUrl);
$this->assertSame('fallback', $redirectUrl);
}
}

View File

@ -3,8 +3,8 @@
namespace Tests\Wallabag\CoreBundle;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Console\Input\ArrayInput;
@ -16,14 +16,12 @@ use Wallabag\UserBundle\Entity\User;
abstract class WallabagCoreTestCase extends WebTestCase
{
/**
* @var KernelBrowser|null
* @var Client|null
*/
private $client = null;
protected function setUp(): void
{
static::ensureKernelShutdown();
parent::setUp();
$this->client = static::createClient();
@ -31,8 +29,6 @@ abstract class WallabagCoreTestCase extends WebTestCase
public function getNewClient()
{
static::ensureKernelShutdown();
return $this->client = static::createClient();
}
@ -41,7 +37,7 @@ abstract class WallabagCoreTestCase extends WebTestCase
return $this->client;
}
public function resetDatabase(KernelBrowser $client)
public function resetDatabase(Client $client)
{
$application = new Application($client->getKernel());
$application->setAutoExit(false);

View File

@ -74,7 +74,7 @@ class ManageControllerTest extends WallabagCoreTestCase
$client = $this->getTestClient();
$crawler = $client->request('GET', '/users/' . $this->getLoggedInUserId() . '/edit');
$disabled = $crawler->selectButton('user.form.delete')->extract(['disabled']);
$disabled = $crawler->selectButton('user.form.delete')->extract('disabled');
$this->assertSame('disabled', $disabled[0]);
}

View File

@ -320,7 +320,6 @@ entry:
delete: Are you sure you want to remove that article?
delete_tag: Are you sure you want to remove that tag from that article?
delete_entries: Are you sure you want to remove these articles?
reload: Are you sure you want to reload that article?
metadata:
reading_time: Estimated reading time
reading_time_minutes_short: '%readingTime% min'

View File

@ -551,7 +551,6 @@ entry:
delete: Stvarno želiš ukloniti taj članak?
delete_tag: Stvarno želiš ukloniti tu oznaku za taj članak?
delete_entries: Stvarno želiš ukloniti ove članke?
reload: Stvarno želiš ponovo učitati taj članak?
edit:
title_label: Naslov
url_label: Url

View File

@ -336,7 +336,6 @@ entry:
delete: Czy jesteś pewien, że chcesz usunąć ten artykuł?
delete_tag: Czy jesteś pewien, że chcesz usunąć ten tag z tego artykułu?
delete_entries: Czy na pewno chcesz usunąć te artykuły?
reload: Czy na pewno chcesz ponownie załadować ten artykuł?
metadata:
reading_time: Szacowany czas czytania
reading_time_minutes_short: '%readingTime% min'

Some files were not shown because too many files have changed in this diff Show More