Merge branch 'master' into feat_referer_to_session_redirect

This commit is contained in:
Michael Ciociola 2023-08-06 20:14:44 +00:00 committed by GitHub
commit ced2ea4015
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
362 changed files with 8665 additions and 6104 deletions

View file

@ -45,3 +45,17 @@ Note : If you have large portions of text, use [Github's Gist service](https://g
## You want to fix a bug or to add a feature
Please fork wallabag and work with **the master branch**.
## Run Tests and PHP formatter
All pull requests need to pass the tests and the code needs match the style guide.
To run the tests locally run:
- when testing using Docker: `docker-compose run --rm php make test`
- otherwise: `make test`
To run the PHP formatter:
- when testing using Docker: `docker-compose run --rm php bin/php-cs-fixer fix`
- otherwise: `php bin/php-cs-fixer fix`

View file

@ -22,15 +22,10 @@ updates:
- j0k3r
- tcitworld
- Kdecherf
labels:
- Ready for review
ignore:
- dependency-name: doctrine/doctrine-migrations-bundle
- dependency-name: lcobucci/jwt
versions:
- "> 1.3.2"
- dependency-name: friendsofsymfony/user-bundle
versions:
- "> 2.0.2"
- ">= 4.2.0"
- package-ecosystem: github-actions
directory: "/"
schedule:

View file

@ -49,3 +49,6 @@ jobs:
- name: "Run TwigCS"
run: "php bin/twigcs --severity=error --display=blocking --reporter checkstyle app/ src/ | cs2pr"
- name: "Run ergebnis/composer-normalize"
run: "composer normalize --dry-run --no-check-lock"

View file

@ -32,6 +32,7 @@ jobs:
- "7.4"
- "8.0"
- "8.1"
- "8.2"
database:
- "sqlite"
- "mysql"
@ -79,3 +80,74 @@ jobs:
- name: "Run PHPUnit"
run: "php bin/simple-phpunit -v"
phpunit_no_prefix:
name: "PHP ${{ matrix.php }} using ${{ matrix.database }} without prefix"
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:
- "sqlite"
- "mysql"
- "pgsql"
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: "Remove database prefix"
run: |
pip install --user yq
yq -Y --in-place '.parameters.database_table_prefix = ""' app/config/parameters.yml.dist
- name: "Setup MySQL"
if: "${{ matrix.database == 'mysql' }}"
run: |
sudo systemctl start mysql.service
sudo mysql -u root -proot -h 127.0.0.1 -e "CREATE DATABASE wallabag_test"
- name: "Setup PostgreSQL"
if: "${{ matrix.database == 'pgsql' }}"
run: |
sudo systemctl start postgresql
sudo -u postgres psql -d template1 -c "CREATE USER wallabag WITH PASSWORD 'wallabagrocks' CREATEDB"
createdb -h localhost -p 5432 -U wallabag wallabag_test
pg_isready -d wallabag_test -h localhost -p 5432 -U wallabag
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
composer-options: "--optimize-autoloader --prefer-dist"
- name: "Prepare database"
run: "make prepare DB=${{ matrix.database }}"
- name: "Prepare fixtures"
run: "make fixtures"
- name: "Run PHPUnit"
run: "php bin/simple-phpunit -v"

View file

@ -12,7 +12,7 @@ jobs:
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.5
uses: dependabot/fetch-metadata@v1.6.0
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
- name: Approve and merge minor updates

View file

@ -40,11 +40,5 @@ jobs:
with:
composer-options: "--optimize-autoloader --prefer-dist"
- name: "Validate Core translations"
run: "php bin/console lint:yaml src/Wallabag/CoreBundle/Resources/translations -v"
- name: "Validate CraueConfig translations"
run: "php bin/console lint:yaml app/Resources/CraueConfigBundle/translations -v"
- name: "Validate User translations"
run: "php bin/console lint:yaml src/Wallabag/UserBundle/Resources/translations -v"
- name: "Validate translations"
run: "php bin/console lint:yaml translations -v"

View file

@ -1,5 +1,131 @@
# Changelog
## [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)
### Fixes
* Fix mass action input on dark theme by @simounet https://github.com/wallabag/wallabag/pull/6673
* Fix undefined variable by @nicosomb https://github.com/wallabag/wallabag/pull/6672
* Fix table name in migration by @nicosomb https://github.com/wallabag/wallabag/pull/6653
### Technical stuff
* Add a new build to test when no database table prefix are defined by @j0k3r https://github.com/wallabag/wallabag/pull/6731
* Keep escaped table name while migrating by @Glandos https://github.com/wallabag/wallabag/pull/6710
* Remove twofactor_auth parameter by @nicosomb https://github.com/wallabag/wallabag/pull/6723
* ApiDoc: Add response description to UserRestController by @caspermeijn https://github.com/wallabag/wallabag/pull/6684
* ApiDoc: Add response description to WallabagRestController by @caspermeijn https://github.com/wallabag/wallabag/pull/6102
* Skip migration if the table was already renamed by @gramakri https://github.com/wallabag/wallabag/pull/6678
### Meta
* Document how to run tests and formatter for new contributors by @caspermeijn https://github.com/wallabag/wallabag/pull/6685
* Add link to wallabag ecosystem resources by @nicosomb https://github.com/wallabag/wallabag/pull/6700
## [2.6.1](https://github.com/wallabag/wallabag/tree/2.6.1)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.6.0...2.6.1)
### Fixes
* Do not autoload fixtures by @j0k3r https://github.com/wallabag/wallabag/pull/6648
* Add confirmation alert when deleting articles from list view by @nicosomb https://github.com/wallabag/wallabag/pull/6644
## [2.6.0](https://github.com/wallabag/wallabag/tree/2.6.0)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.5.4...2.6.0)
### Features
* Add tag deletion from tags list by @nicosomb https://github.com/wallabag/wallabag/pull/5861
* Add support of mass action to tag entries by @kdecherf https://github.com/wallabag/wallabag/pull/5838
* Mass action interface by @Simounet https://github.com/wallabag/wallabag/pull/6547
* Empty space on the top bar used for more add url toggle clickable target by @Simounet https://github.com/wallabag/wallabag/pull/6612
* Add new setting to show / hide articles thumbnails by @nicosomb https://github.com/wallabag/wallabag/pull/6609
### Fixes
* Add prefix for tag slugs by @kdecherf https://github.com/wallabag/wallabag/pull/6226
* Fix open all external links in new tab in Config by @wyntonfranklin https://github.com/wallabag/wallabag/pull/6256
* Fix dark theme for pre HTML tags by @Simounet https://github.com/wallabag/wallabag/pull/6495
* Fix dark mode top bar contrast by @Simounet https://github.com/wallabag/wallabag/pull/6510
* Dark mode contrast improved by @Simounet https://github.com/wallabag/wallabag/pull/6512
* Fix dark mode URL add input color by @Simounet https://github.com/wallabag/wallabag/pull/6525
* Fix round reading time in export by @mart-e https://github.com/wallabag/wallabag/pull/6545
* Fix images downloading with numeric HTML entity by @Simounet https://github.com/wallabag/wallabag/pull/6563
* Fix DownloadImages not following redirections by @Simounet https://github.com/wallabag/wallabag/pull/6562
* Fix auto dark theme detection flickering by @Simounet https://github.com/wallabag/wallabag/pull/6584
* Fix RSS feed_route not set by @Simounet https://github.com/wallabag/wallabag/pull/6606
* Add flash message when we try to add too much tags by @nicosomb https://github.com/wallabag/wallabag/pull/6607
* Changed default value for domain_name parameter by @nicosomb https://github.com/wallabag/wallabag/pull/6616
* Improved tags display by @Simounet https://github.com/wallabag/wallabag/pull/6613
* Fix mousetrap enter issue by @Simounet https://github.com/wallabag/wallabag/pull/6624
* Fix duplicate tags creation when assigning search results to tag by @nicosomb https://github.com/wallabag/wallabag/pull/6629
### Meta
* Removed Carrot & Scuttle share by @nicosomb https://github.com/wallabag/wallabag/pull/6047
* Remove old, not so maintained and buggy baggy theme by @nicosomb https://github.com/wallabag/wallabag/pull/4332
* Remove Scrutinizer badge by @j0k3r https://github.com/wallabag/wallabag/pull/6179
* Add mention to unofficial linux client by @imhemish https://github.com/wallabag/wallabag/pull/6203
### Technical stuff
* Remove SensioDistributionBundle by @yguedidi https://github.com/wallabag/wallabag/pull/5761
* Back to latest composer version by @yguedidi https://github.com/wallabag/wallabag/pull/5810
* Clean composer.lock after SensioDistributionBundle removal by @yguedidi https://github.com/wallabag/wallabag/pull/5839
* Remove transitive dependencies by @yguedidi https://github.com/wallabag/wallabag/pull/5784
* Register missed commands by @yguedidi https://github.com/wallabag/wallabag/pull/5928
* Extend right FOSRestBundle controller class by @yguedidi https://github.com/wallabag/wallabag/pull/5929
* Remove PHP-CS-Fixer deprecations by @yguedidi https://github.com/wallabag/wallabag/pull/5914
* Upgrade FOSUserBundle to 2.1 by @yguedidi https://github.com/wallabag/wallabag/pull/5782
* Add TwigCS by @yguedidi https://github.com/wallabag/wallabag/pull/5759
* Use FQCN as service name by @yguedidi https://github.com/wallabag/wallabag/pull/5748
* Migrate to new template reference notation by @yguedidi https://github.com/wallabag/wallabag/pull/5758
* Migrate from old colon notation to FQCN by @yguedidi https://github.com/wallabag/wallabag/pull/5943
* Use autowiring by @yguedidi https://github.com/wallabag/wallabag/pull/5946
* Use FQCN to fetch services by @yguedidi https://github.com/wallabag/wallabag/pull/5951
* Run tests without memory limit by @yguedidi https://github.com/wallabag/wallabag/pull/5953
* Import used classes by @yguedidi https://github.com/wallabag/wallabag/pull/5952
* Rework command tests by @yguedidi https://github.com/wallabag/wallabag/pull/5954
* Switch to Swagger for api documentation by @caspermeijn https://github.com/wallabag/wallabag/pull/6062
* Remove some deprecation by @j0k3r https://github.com/wallabag/wallabag/pull/6085
* Remove deprecated options from FOSRest by @j0k3r https://github.com/wallabag/wallabag/pull/6095
* Remove LiipThemeBundle by @j0k3r https://github.com/wallabag/wallabag/pull/6097
* Upgrade PHPStan and move to level 2 with baseline by @j0k3r https://github.com/wallabag/wallabag/pull/6098
* Upgrade to Symfony 4.4 by @j0k3r https://github.com/wallabag/wallabag/pull/6099
* Update to FOSUserBundle 3.1 by @j0k3r https://github.com/wallabag/wallabag/pull/6136
* Update to scheb/2fa-bundle by @j0k3r https://github.com/wallabag/wallabag/pull/6144
* Upgrade to Twig 3 by @j0k3r https://github.com/wallabag/wallabag/pull/6151
* Move translations files to /translations by @j0k3r https://github.com/wallabag/wallabag/pull/6153
* Fix EventDispatcher & events by @j0k3r https://github.com/wallabag/wallabag/pull/6154
* Replace SwiftMailer by Symfony Mailer by @j0k3r https://github.com/wallabag/wallabag/pull/6150
* Remove ContainerAwareCommand from commands by @j0k3r https://github.com/wallabag/wallabag/pull/6152
* Update all Doctrine deps by @j0k3r https://github.com/wallabag/wallabag/pull/6143
* Update PagerFanta by @j0k3r https://github.com/wallabag/wallabag/pull/6145
* Move to controller as a service by @j0k3r https://github.com/wallabag/wallabag/pull/6159
* Add RabbitMQConsumerTotalProxy to lazy RabbitMQ services for messages by @j0k3r https://github.com/wallabag/wallabag/pull/6166
* Properly handle json_array type removal by @j0k3r https://github.com/wallabag/wallabag/pull/6171
* Fix database_path in Docker env by @j0k3r https://github.com/wallabag/wallabag/pull/6174
* Docker: database_table_prefix may be configured from environment by @fcatt https://github.com/wallabag/wallabag/pull/6196
* Update annotations to OpenApi 3 by @caspermeijn https://github.com/wallabag/wallabag/pull/6182
* Fix public folder for Symfony 4+ by @kdecherf https://github.com/wallabag/wallabag/pull/6217
* Fix API allowed_registration by @caspermeijn https://github.com/wallabag/wallabag/pull/6315
* Enable PHP 8.2 in CI by @j0k3r https://github.com/wallabag/wallabag/pull/6469
* Fix/build stylelint error by @Simounet https://github.com/wallabag/wallabag/pull/6586
## [2.5.4](https://github.com/wallabag/wallabag/tree/2.5.4)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.5.3...2.5.4)
### Security fixes
* Fix adding tag to entries from other people by @j0k3r in https://github.com/wallabag/wallabag/pull/6290
* Fix XSS on username on share page by @j0k3r in https://github.com/wallabag/wallabag/pull/6288
* Fix CSRF on user deletion by @j0k3r in https://github.com/wallabag/wallabag/pull/6289
### Meta
* Fix release script by @j0k3r in https://github.com/wallabag/wallabag/pull/6275
## [2.5.3](https://github.com/wallabag/wallabag/tree/2.5.3)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.5.2...2.5.3)
### Security fixes
* Fix GHSA-qwx8-mxxx-mg96 https://github.com/wallabag/wallabag/commit/0f7460dbab9e29f4f7d2944aca20210f828b6abb by @Kdecherf, thanks to @bAuh0lz
* Fix GHSA-mrqx-mjc4-vfh3 https://github.com/wallabag/wallabag/commit/5ac6b6bff9e2e3a87fd88c2904ff3c6aac40722e by @Kdecherf, thanks to @bAuh0lz
### Meta
* Update deps before 2.5.3 by @j0k3r in https://github.com/wallabag/wallabag/pull/6241
## [2.5.2](https://github.com/wallabag/wallabag/tree/2.5.2)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.5.1...2.5.2)

View file

@ -40,7 +40,7 @@ ifdef DB
endif
-php bin/console doctrine:database:drop --force --env=test
php bin/console doctrine:database:create --env=test
php bin/console doctrine:migrations:migrate --no-interaction --env=test
php bin/console doctrine:migrations:migrate --no-interaction --env=test -vv
fixtures: ## Load fixtures into database
php bin/console doctrine:fixtures:load --no-interaction --env=test

View file

@ -1,7 +1,6 @@
# wallabag
![CI](https://github.com/wallabag/wallabag/workflows/CI/badge.svg)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/wallabag/wallabag/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/wallabag/wallabag/?branch=master)
[![Gitter](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/wallabag/wallabag)
[![Donation Status](https://img.shields.io/liberapay/goal/wallabag.svg?logo=liberapay)](https://liberapay.com/wallabag/donate)
[![Translation status](https://hosted.weblate.org/widgets/wallabag/-/svg-badge.svg)](https://hosted.weblate.org/engage/wallabag/?utm_source=widget)
@ -18,6 +17,8 @@ You can install it on your own server, or you can create an account on [wallabag
* Android app: [wallabag/android-app](https://github.com/wallabag/android-app)
* iOS app: [wallabag/ios-app](https://github.com/wallabag/ios-app)
* Browser extension: [wallabag/wallabagger](https://github.com/wallabag/wallabagger)
* GNOME (Linux) app: [read-it-later](https://gitlab.gnome.org/World/read-it-later) (not maintained by this project)
* All resources about wallabag ecosystem are listed here: https://github.com/wallabag/wallabag/wiki/wallabag-ecosystem
## Documentation

View file

@ -17,9 +17,8 @@ During this documentation, we assume the release is `$LAST_WALLABAG_RELEASE` (li
#### Create a new release on GitHub
- [Create the new release on GitHub](https://github.com/wallabag/wallabag/releases/new) by targetting the `master` branch or any appropriate branch (for instance backports).
- Update nginx config to change the redirect rule for `https://wllbg.org/latest-v2-package` & `http://wllbg.org/latest-v2` (they both redirect to the asset of the GitHub release)
- Update [website](https://github.com/wallabag/website) to change MD5 sum and create the release blog post (based on the changelog).
- Update Dockerfile https://github.com/wallabag/docker (and create a new tag)
- Update wallabag.org website (downloads, MD5 sum, releases and new blog post)
- Put the next patch version suffixed with `-dev` in `app/config/wallabag.yml` (`wallabag_core.version`)
- Drink a :beer:!

View file

@ -13,7 +13,6 @@ class AppKernel extends Kernel
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new FOS\RestBundle\FOSRestBundle(),
@ -35,6 +34,7 @@ class AppKernel extends Kernel
new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(),
new Http\HttplugBundle\HttplugBundle(),
new Sentry\SentryBundle\SentryBundle(),
new Twig\Extra\TwigExtraBundle\TwigExtraBundle(),
// wallabag bundles
new Wallabag\CoreBundle\WallabagCoreBundle(),

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20160401000000 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf($schema->hasTable($this->getTable('entry')), 'Database already initialized');
@ -164,7 +164,7 @@ SQL
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql("DROP TABLE {$this->getTable('craue_config_setting')}");
$this->addSql("DROP TABLE {$this->getTable('tagging_rule')}");

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20160410190541 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -24,14 +24,14 @@ class Version20160410190541 extends WallabagMigration
$sharePublic = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_public'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_public'");
if (false === $sharePublic) {
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('share_public', '1', 'entry')");
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$entryTable->dropColumn('uid');

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20160812120952 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
$this->skipIf($clientsTable->hasColumn('name'), 'It seems that you already played this migration.');
@ -31,7 +31,7 @@ class Version20160812120952 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));

View file

@ -10,12 +10,12 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20160911214952 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$redis = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_redis'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_redis'");
if (false === $redis) {
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('import_with_redis', 0, 'import')");
@ -24,7 +24,7 @@ class Version20160911214952 extends WallabagMigration
$rabbitmq = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_rabbitmq'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_rabbitmq'");
if (false === $rabbitmq) {
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('import_with_rabbitmq', 0, 'import')");
@ -33,7 +33,7 @@ class Version20160911214952 extends WallabagMigration
$this->skipIf(false !== $rabbitmq && false !== $redis, 'It seems that you already played this migration.');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_redis';");
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'import_with_rabbitmq';");

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20160916201049 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
@ -20,7 +20,7 @@ class Version20160916201049 extends WallabagMigration
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'pocket_consumer_key';");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
$configTable->dropColumn('pocket_consumer_key');

View file

@ -11,7 +11,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161001072726 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
@ -24,9 +24,8 @@ class Version20161001072726 extends WallabagMigration
WHERE TABLE_NAME = '" . $this->getTable('entry_tag', WallabagMigration::UN_ESCAPED_TABLE) . "' AND CONSTRAINT_NAME LIKE 'FK_%'
AND TABLE_SCHEMA = '" . $this->connection->getDatabase() . "'"
);
$query->execute();
foreach ($query->fetchAll() as $fk) {
foreach ($query->fetchAllAssociative() as $fk) {
$this->addSql('ALTER TABLE ' . $this->getTable('entry_tag') . ' DROP FOREIGN KEY ' . $fk['CONSTRAINT_NAME']);
}
break;
@ -42,9 +41,8 @@ class Version20161001072726 extends WallabagMigration
AND conrelid::regclass::text = '" . $this->getTable('entry_tag', WallabagMigration::UN_ESCAPED_TABLE) . "'
AND n.nspname = 'public';"
);
$query->execute();
foreach ($query->fetchAll() as $fk) {
foreach ($query->fetchAllAssociative() as $fk) {
$this->addSql('ALTER TABLE ' . $this->getTable('entry_tag') . ' DROP CONSTRAINT ' . $fk['conname']);
}
break;
@ -65,9 +63,8 @@ class Version20161001072726 extends WallabagMigration
AND COLUMN_NAME = 'entry_id'
AND TABLE_SCHEMA = '" . $this->connection->getDatabase() . "'"
);
$query->execute();
foreach ($query->fetchAll() as $fk) {
foreach ($query->fetchAllAssociative() as $fk) {
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' DROP FOREIGN KEY ' . $fk['CONSTRAINT_NAME']);
}
break;
@ -84,9 +81,8 @@ class Version20161001072726 extends WallabagMigration
AND n.nspname = 'public'
AND pg_get_constraintdef(c.oid) LIKE '%entry_id%';"
);
$query->execute();
foreach ($query->fetchAll() as $fk) {
foreach ($query->fetchAllAssociative() as $fk) {
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' DROP CONSTRAINT ' . $fk['conname']);
}
break;
@ -95,7 +91,7 @@ class Version20161001072726 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('annotation') . ' ADD CONSTRAINT FK_annotation_entry FOREIGN KEY (entry_id) REFERENCES ' . $this->getTable('entry') . ' (id) ON DELETE CASCADE');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
throw new SkipMigrationException('Too complex ...');
}

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161022134138 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
@ -38,7 +38,7 @@ class Version20161022134138 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('user') . ' CHANGE `name` `name` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');

View file

@ -12,7 +12,7 @@ class Version20161024212538 extends WallabagMigration
{
private $constraintName = 'IDX_user_oauth_client';
public function up(Schema $schema)
public function up(Schema $schema): void
{
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
@ -29,7 +29,7 @@ class Version20161024212538 extends WallabagMigration
);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$clientsTable = $schema->getTable($this->getTable('oauth2_clients'));

View file

@ -10,19 +10,19 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161031132655 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$images = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_images_enabled'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_images_enabled'");
$this->skipIf(false !== $images, 'It seems that you already played this migration.');
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('download_images_enabled', 0, 'misc')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_images_enabled';");
}

View file

@ -12,7 +12,7 @@ class Version20161104073720 extends WallabagMigration
{
private $indexName = 'IDX_entry_created_at';
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf($entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
@ -20,7 +20,7 @@ class Version20161104073720 extends WallabagMigration
$entryTable->addIndex(['created_at'], $this->indexName);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(false === $entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161106113822 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
@ -22,7 +22,7 @@ class Version20161106113822 extends WallabagMigration
]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));

View file

@ -10,12 +10,12 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161117071626 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$share = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_unmark'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_unmark'");
if (false === $share) {
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('share_unmark', 0, 'entry')");
@ -24,7 +24,7 @@ class Version20161117071626 extends WallabagMigration
$unmark = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'unmark_url'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'unmark_url'");
if (false === $unmark) {
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')");
@ -33,7 +33,7 @@ class Version20161117071626 extends WallabagMigration
$this->skipIf(false !== $share && false !== $unmark, 'It seems that you already played this migration.');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_unmark';");
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'unmark_url';");

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161118134328 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -22,7 +22,7 @@ class Version20161118134328 extends WallabagMigration
]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,19 +10,19 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161122144743 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$access = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'restricted_access'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'restricted_access'");
$this->skipIf(false !== $access, 'It seems that you already played this migration.');
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('restricted_access', 0, 'entry')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'restricted_access';");
}

View file

@ -18,7 +18,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161122203647 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));
@ -28,7 +28,7 @@ class Version20161122203647 extends WallabagMigration
$userTable->dropColumn('credentials_expired');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161128084725 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
$this->skipIf($configTable->hasColumn('list_mode'), 'It seems that you already played this migration.');
@ -18,7 +18,7 @@ class Version20161128084725 extends WallabagMigration
$configTable->addColumn('list_mode', 'integer', ['notnull' => false]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
$configTable->dropColumn('list_mode');

View file

@ -16,7 +16,7 @@ class Version20161128131503 extends WallabagMigration
'expires_at' => 'datetime',
];
public function up(Schema $schema)
public function up(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));
@ -26,7 +26,7 @@ class Version20161128131503 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$userTable = $schema->getTable($this->getTable('user'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20161214094402 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -32,7 +32,7 @@ class Version20161214094402 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -12,7 +12,7 @@ class Version20161214094403 extends WallabagMigration
{
private $indexName = 'IDX_entry_uid';
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf($entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
@ -20,7 +20,7 @@ class Version20161214094403 extends WallabagMigration
$entryTable->addIndex(['uid'], $this->indexName);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(false === $entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');

View file

@ -13,7 +13,7 @@ class Version20170127093841 extends WallabagMigration
private $indexStarredName = 'IDX_entry_starred';
private $indexArchivedName = 'IDX_entry_archived';
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf($entryTable->hasIndex($this->indexStarredName) && $entryTable->hasIndex($this->indexArchivedName), 'It seems that you already played this migration.');
@ -22,7 +22,7 @@ class Version20170127093841 extends WallabagMigration
$entryTable->addIndex(['is_archived'], $this->indexArchivedName);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(false === $entryTable->hasIndex($this->indexStarredName) && false === $entryTable->hasIndex($this->indexArchivedName), 'It seems that you already played this migration.');

View file

@ -10,12 +10,12 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170327194233 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$scuttle = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_scuttle'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_scuttle'");
$this->skipIf(false !== $scuttle, 'It seems that you already played this migration.');
@ -23,7 +23,7 @@ class Version20170327194233 extends WallabagMigration
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('scuttle_url', 'http://scuttle.org', 'entry')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'share_scuttle';");
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'scuttle_url';");

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170405182620 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -27,7 +27,7 @@ class Version20170405182620 extends WallabagMigration
]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170407200919 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(!$entryTable->hasColumn('is_public'), 'It seems that you already played this migration.');
@ -18,7 +18,7 @@ class Version20170407200919 extends WallabagMigration
$entryTable->dropColumn('is_public');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf($entryTable->hasColumn('is_public'), 'It seems that you already played this migration.');

View file

@ -10,17 +10,17 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170420134133 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_pictures';");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$downloadPictures = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_pictures'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'download_pictures'");
$this->skipIf(false !== $downloadPictures, 'It seems that you already played this migration.');

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170501115751 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf($schema->hasTable($this->getTable('site_credential')), 'It seems that you already played this migration.');
@ -31,7 +31,7 @@ class Version20170501115751 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$schema->dropTable($this->getTable('site_credential'));
}

View file

@ -17,7 +17,7 @@ class Version20170510082609 extends WallabagMigration
'email_canonical',
];
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
@ -26,7 +26,7 @@ class Version20170510082609 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170511115400 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -21,7 +21,7 @@ class Version20170511115400 extends WallabagMigration
]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -11,7 +11,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170511211659 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
switch ($this->connection->getDatabasePlatform()->getName()) {
case 'sqlite':
@ -62,7 +62,7 @@ EOD
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$tableName = $this->getTable('annotation');

View file

@ -10,19 +10,19 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170602075214 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$apiUserRegistration = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'api_user_registration'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'api_user_registration'");
$this->skipIf(false !== $apiUserRegistration, 'It seems that you already played this migration.');
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('api_user_registration', '0', 'api')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'api_user_registration';");
}

View file

@ -11,19 +11,21 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170606155640 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf(!$schema->hasTable($this->getTable('craue_config_setting')), 'Table already renamed');
$apiUserRegistration = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'wallabag_url'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'wallabag_url'");
$this->skipIf(false === $apiUserRegistration, 'It seems that you already played this migration.');
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'wallabag_url'");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('wallabag_url', 'wallabag.me', 'misc')");
}

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170719231144 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
@ -21,13 +21,12 @@ class Version20170719231144 extends WallabagMigration
GROUP BY LOWER(label)
HAVING COUNT(*) > 1'
);
$dupTags->execute();
foreach ($dupTags->fetchAll() as $duplicates) {
foreach ($dupTags->fetchAllAssociative() as $duplicates) {
$label = $duplicates['lower_label'];
// Retrieve all duplicate tags for a given tag
$tags = $this->connection->executeQuery('
$tags = $this->connection->query('
SELECT id
FROM ' . $this->getTable('tag') . '
WHERE LOWER(label) = :label
@ -41,7 +40,7 @@ class Version20170719231144 extends WallabagMigration
$newId = null;
$ids = [];
foreach ($tags->fetchAll() as $tag) {
foreach ($tags->fetchAllAssociative() as $tag) {
// Ignore the first tag as we use it as the new reference tag
if ($first) {
$first = false;
@ -86,7 +85,7 @@ class Version20170719231144 extends WallabagMigration
);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
throw new SkipMigrationException('Too complex ...');
}

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20170824113337 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -21,7 +21,7 @@ class Version20170824113337 extends WallabagMigration
]);
}
public function postUp(Schema $schema)
public function postUp(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(!$entryTable->hasColumn('starred_at'), 'Unable to add starred_at colum');
@ -34,7 +34,7 @@ class Version20170824113337 extends WallabagMigration
);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20171008195606 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
@ -26,7 +26,7 @@ class Version20171008195606 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->skipIf('sqlite' === $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20171105202000 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -21,7 +21,7 @@ class Version20171105202000 extends WallabagMigration
]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,19 +10,19 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20171120163128 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$storeArticleHeaders = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'store_article_headers'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'store_article_headers'");
$this->skipIf(false !== $storeArticleHeaders, 'It seems that you already played this migration.');
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('store_article_headers', '0', 'entry')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'store_article_headers';");
}

View file

@ -10,19 +10,19 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20171125164500 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$shaarliShareOriginUrl = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'shaarli_share_origin_url'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'shaarli_share_origin_url'");
$this->skipIf(false !== $shaarliShareOriginUrl, 'It seems that you already played this migration.');
$this->addSql('INSERT INTO ' . $this->getTable('craue_config_setting') . " (name, value, section) VALUES ('shaarli_share_origin_url', '0', 'entry')");
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->addSql('DELETE FROM ' . $this->getTable('craue_config_setting') . " WHERE name = 'shaarli_share_origin_url';");
}

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20180405182455 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -21,7 +21,7 @@ class Version20180405182455 extends WallabagMigration
]);
}
public function postUp(Schema $schema)
public function postUp(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
$this->skipIf(!$entryTable->hasColumn('archived_at'), 'Unable to add archived_at colum');
@ -34,7 +34,7 @@ class Version20180405182455 extends WallabagMigration
);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20181128203230 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration can only be applied on \'mysql\'.');
@ -25,7 +25,7 @@ class Version20181128203230 extends WallabagMigration
$this->addSql('ALTER TABLE ' . $this->getTable('craue_config_setting') . ' CHANGE `value` `value` varchar(191)');
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration can only be applied on \'mysql\'.');

View file

@ -118,13 +118,13 @@ final class Version20190129120000 extends WallabagMigration
],
];
public function up(Schema $schema)
public function up(Schema $schema): void
{
foreach ($this->settings as $setting) {
$settingEnabled = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = '" . $setting['name'] . "'");
->fetchOne('SELECT * FROM ' . $this->getTable('craue_config_setting') . " WHERE name = '" . $setting['name'] . "'");
if (false !== $settingEnabled) {
continue;
@ -134,7 +134,7 @@ final class Version20190129120000 extends WallabagMigration
}
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$this->skipIf(true, 'These settings are required and should not be removed.');
}

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20190401105353 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -24,7 +24,7 @@ class Version20190401105353 extends WallabagMigration
$entryTable->addIndex(['user_id', 'hashed_url'], 'hashed_url_user_id', [], ['lengths' => [null, 40]]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -10,7 +10,7 @@ use Wallabag\CoreBundle\Doctrine\WallabagMigration;
*/
class Version20190601125843 extends WallabagMigration
{
public function up(Schema $schema)
public function up(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));
@ -31,7 +31,7 @@ class Version20190601125843 extends WallabagMigration
$entryTable->addIndex(['user_id', 'hashed_given_url'], 'hashed_given_url_user_id', [], ['lengths' => [null, 40]]);
}
public function down(Schema $schema)
public function down(Schema $schema): void
{
$entryTable = $schema->getTable($this->getTable('entry'));

View file

@ -48,7 +48,7 @@ final class Version20190826204730 extends WallabagMigration
$previous_rule = $this->container
->get('doctrine.orm.default_entity_manager')
->getConnection()
->fetchArray('SELECT * FROM ' . $this->getTable('ignore_origin_instance_rule') . " WHERE rule = '" . $entity['rule'] . "'");
->fetchOne('SELECT * FROM ' . $this->getTable('ignore_origin_instance_rule') . " WHERE rule = '" . $entity['rule'] . "'");
if (false === $previous_rule) {
$this->addSql('INSERT INTO ' . $this->getTable('ignore_origin_instance_rule') . " (rule) VALUES ('" . $entity['rule'] . "');");

View file

@ -0,0 +1,62 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
/**
* Remove the deprecated (and removed in DBAL v3) `json_array` type.
*/
final class Version20221221092957 extends WallabagMigration
{
public function up(Schema $schema): void
{
$userTable = $this->getTable('user');
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)
, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, googleAuthenticatorSecret VARCHAR(255) DEFAULT NULL, backupCodes CLOB DEFAULT NULL --(DC2Type:json)
, emailTwoFactor BOOLEAN NOT NULL)');
$this->addSql('INSERT INTO ' . $userTable . ' (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) 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 __temp__wallabag_user');
$this->addSql('DROP TABLE __temp__wallabag_user');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $userTable . ' (username_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
break;
case 'mysql':
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL');
break;
case 'postgresql':
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupcodes TYPE JSON USING backupcodes::json');
break;
}
}
public function down(Schema $schema): void
{
$userTable = $this->getTable('user');
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)
, name CLOB DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, authCode INTEGER DEFAULT NULL, googleAuthenticatorSecret VARCHAR(255) DEFAULT NULL, backupCodes CLOB DEFAULT NULL --(DC2Type:json_array)
, emailTwoFactor BOOLEAN NOT NULL)');
$this->addSql('INSERT INTO ' . $userTable . ' (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) 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 __temp__wallabag_user');
$this->addSql('DROP TABLE __temp__wallabag_user');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E592FC23A8 ON ' . $userTable . ' (username_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5A0D96FBF ON ' . $userTable . ' (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_1D63E7E5C05FB297 ON ' . $userTable . ' (confirmation_token)');
break;
case 'mysql':
$this->addSql('ALTER TABLE ' . $userTable . ' CHANGE backupCodes backupCodes JSON DEFAULT NULL COMMENT \'(DC2Type:json_array)\'');
break;
case 'postgresql':
$this->addSql('ALTER TABLE ' . $userTable . ' ALTER backupCodes TYPE TEXT');
break;
}
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Wallabag\CoreBundle\Doctrine\WallabagMigration;
/**
* Added a new setting to display or not thumbnails.
*/
final class Version20230613121354 extends WallabagMigration
{
public function up(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
$this->skipIf($configTable->hasColumn('display_thumbnails'), 'It seems that you already played this migration.');
$configTable->addColumn('display_thumbnails', 'integer', [
'default' => 1,
'notnull' => false,
]);
}
public function down(Schema $schema): void
{
$configTable = $schema->getTable($this->getTable('config'));
$configTable->dropColumn('display_thumbnails');
}
}

View file

@ -54,7 +54,7 @@
}
a {
border-bottom: 1px dotted $blueAccentColor;
border-bottom: 1px dotted $blue-accent-color;
text-decoration: none;
}
@ -105,14 +105,15 @@
margin: 2.1rem 0 0.68rem;
}
aside {
.entry-info {
.tools {
display: flex;
flex-flow: row wrap;
margin: 8px 5px 5px;
flex-wrap: wrap;
.stats {
margin: 0;
font-size: 0.7em;
margin: 8px 5px 5px;
li {
display: inline-flex;
@ -133,18 +134,21 @@
}
.tags {
float: right;
margin: 5px 15px 10px;
display: flex;
margin: 0;
align-items: center;
gap: 5px;
}
}
.chip {
background-color: #9e9e9e;
padding: 0 15px 0 10px;
margin: auto 2px;
border-radius: 6px;
height: 18px;
line-height: 18px;
display: flex;
margin: 0;
padding: 0;
height: 25px;
line-height: 25px;
align-items: center;
background-color: transparent;
a,
i {
@ -152,15 +156,45 @@
}
i.material-icons {
float: right;
font-size: 16px;
line-height: 18px;
padding-left: 8px;
vertical-align: sub;
}
}
.chip-label {
padding-left: 10px;
padding-right: 5px;
background-color: #9e9e9e;
border-radius: 6px 0 0 6px;
}
.chip-action {
padding: 0 5px;
background-color: #868686;
border-radius: 0 6px 6px 0;
}
.chip-label,
.chip-action {
min-width: 30px;
text-align: center;
}
.chip-label:hover,
.chip-label:active,
.chip-label:focus,
.chip-action:hover,
.chip-action:active,
.chip-action:focus {
background-color: #5e5e5e;
}
}
}
.entry-info {
margin-bottom: 40px;
}
.reader-mode {
width: 70px !important;
transition: width 0.2s ease;
@ -200,3 +234,28 @@
margin: 0;
z-index: 9999;
}
@media only screen and (max-width: 640px) {
.entry-info {
margin-bottom: 20px;
}
#article .entry-info .tools {
margin-left: 0;
margin-right: 0;
}
#article .entry-info .tools .tags {
gap: 10px;
}
#article .entry-info .chip {
height: 32px;
line-height: 32px;
}
#article .entry-info .chip-label,
#article .entry-info .chip-action {
min-width: 40px;
}
}

View file

@ -73,7 +73,7 @@ main {
.card-entry-labels-hidden li {
display: inline-block;
background-color: $blueAccentColor;
background-color: $blue-accent-color;
margin: 0 5px;
padding: 5px 12px;
border-radius: 3px;
@ -85,10 +85,6 @@ main {
white-space: nowrap;
}
.card-content .estimatedTime {
margin-bottom: 10px;
}
.card-action {
padding: 10px 10px 10px 15px;
@ -160,7 +156,7 @@ a.original:not(.waves-effect) {
.card-tag-labels li {
margin: 10px 10px 10px auto;
padding: 5px 12px 5px 16px !important;
background-color: $blueAccentColor;
background-color: $blue-accent-color;
border-radius: 3px;
color: #fff;
cursor: default;
@ -251,7 +247,7 @@ a.original:not(.waves-effect) {
}
.chip {
background-color: $blueAccentColor;
background-color: $blue-accent-color;
padding: 0 7px;
margin: auto 1px;
border-radius: 6px;
@ -315,10 +311,19 @@ a.original:not(.waves-effect) {
color: #fff !important;
}
.settings .div_tabs {
.settings .tabs-container {
padding-bottom: 15px;
}
.settings .settings-checkbox-col {
padding: 0;
}
.settings .settings-checkbox-label {
margin-bottom: 20px;
height: 3rem;
}
.entries-row {
display: grid;
margin: 0.4rem 0 0;

View file

@ -1,6 +1,8 @@
.dark-theme {
body,
main #content,
body {
background-color: #101010;
}
#article,
.card,
.card-panel,
@ -10,13 +12,11 @@
.collapsible-header,
.collection,
.dropdown-content,
.nav-panel-add,
.nav-panel-search,
.side-nav,
.side-nav .collapsible-body,
.side-nav.fixed .collapsible-body,
.tabs {
background-color: #121212;
background-color: #131716;
}
table.striped > tbody > tr:nth-child(2n+1),
@ -50,7 +50,7 @@
background-color: #272727;
}
main #content,
#content,
#article article,
#article article h1,
#article article h2,
@ -59,7 +59,8 @@
#article article h5,
#article article h6,
.dropdown-content li > a,
.results a,
.nav-panels .input-field input:focus,
.results-item,
.side-nav li > a,
.side-nav li > a > i.material-icons {
color: #dfdfdf;
@ -67,18 +68,19 @@
.cyan,
.cyan.darken-1,
.cyan.darken-2 {
.cyan.darken-2,
.nav-panel-add,
.nav-panel-search {
background-color: #1d1d1d !important;
}
.grey-text.text-darken-4 {
.grey-text.text-darken-4,
.nav-panel-item .add,
.nav-panel-item .search,
.nav-panels .close {
color: #dfdfdf !important;
}
#article .chip {
background-color: #373737;
}
.side-nav li.active {
background-color: #2f2f2f;
}
@ -120,11 +122,20 @@
}
.hljs,
#article pre.hljs {
#article pre {
color: #abb2bf;
background-color: #282c34;
}
nav input {
color: #abb2bf;
}
.input-field.nav-panel-add.disabled,
.input-field.nav-panel-add.disabled input {
background-color: transparent;
}
@media only screen and (min-width: 992px) {
#article {
background-color: #101010;

View file

@ -2,40 +2,73 @@
* Entries
* ========================================================================== */
.mass-buttons {
margin: 10px 5px 10px 20px;
.mass-action-toggle {
display: inline-flex;
background-color: transparent;
border: none;
cursor: pointer;
#selectAll {
position: relative;
opacity: initial;
left: 0;
}
span {
padding: 3px;
}
button {
i {
font-size: 15px;
}
height: 24px;
line-height: 24px;
padding: 0 0.5rem;
margin-right: 0.75rem;
&:focus {
background-color: transparent;
}
}
.card-stacked {
input[type="checkbox"] {
position: relative;
opacity: initial;
left: 0;
}
.mass-action {
margin: 10px 5px 10px 20px;
}
.entry-checkbox {
margin-right: 10px;
.mass-action-group {
display: flex;
padding: 3px;
gap: 10px;
}
.mass-action-button {
height: 24px;
line-height: 24px;
padding: 0 0.5rem;
i {
font-size: 1rem;
}
}
.entry-checkbox {
margin: 10px 15px 10px 5px;
.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;
z-index: 10;
}
.toggle-checkbox:not(:checked) + .mass-action,
.toggle-checkbox:not(:checked) + .mass-action-tags,
.toggle-checkbox:not(:checked) ~ .entries .entry-checkbox,
.toggle-checkbox:checked ~ .entries .card-preview {
display: none;
}
.mass-action-tags {
display: flex;
align-items: center;
gap: 10px;
.mass-action-tags-input {
margin: 0;
}
}
@ -62,10 +95,10 @@
.nb-results {
display: inline-flex;
}
}
a {
color: #444;
}
.results-item {
color: #444;
}
.pagination {
@ -138,3 +171,11 @@ footer {
margin-bottom: 10px;
}
}
@media screen and (min-width: 993px) {
.mass-action {
display: flex;
align-items: center;
gap: 30px;
}
}

View file

@ -21,12 +21,13 @@
word-wrap: normal;
white-space: nowrap;
direction: ltr;
user-select: none;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
text-rendering: optimizelegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;

View file

@ -19,7 +19,7 @@ body {
}
a {
color: $blueAccentColor;
color: $blue-accent-color;
}
main,

View file

@ -10,7 +10,7 @@
@media only screen and (min-width: 992px) {
nav,
body:not(.entry):not(.login) main,
.index main,
footer {
padding-left: 240px;
}

View file

@ -131,11 +131,11 @@ nav {
margin: 0 1%;
}
#button_filters {
.button-filters {
display: none;
}
#button_export {
.button-export {
display: none;
}
@ -161,6 +161,16 @@ nav {
}
@media (min-width: 993px) {
.toggle-add-url-container {
flex-grow: 1;
}
.toggle-add-url {
display: flex;
width: 100%;
justify-content: end;
}
.button-collapse {
display: none;
}

View file

@ -18,20 +18,16 @@
/* Hide useless blocks */
body > header,
#article_toolbar,
#links,
#sort,
body > footer,
.top_link,
div.tools,
.entry-tools,
header div,
.messages,
.entry + .results,
#slide-out,
.left-bar,
.progress,
.hide-on-large-only,
#article > aside,
#article .mbm a {
.entry-info,
.title-edit {
display: none !important;
}
@ -39,7 +35,7 @@
padding-left: 0 !important;
}
#article {
.article {
margin: inherit !important;
}

View file

@ -45,6 +45,6 @@
font-weight: bold;
}
span.numberItems {
.items-number {
float: right;
}

View file

@ -2,4 +2,4 @@
Variables
========================================================================== */
$blueAccentColor: #00acc1;
$blue-accent-color: #00acc1;

View file

@ -19,7 +19,7 @@ import './css/index.scss';
const mobileMaxWidth = 993;
function darkTheme() {
(function darkTheme() {
const rootEl = document.querySelector('html');
const themeDom = {
darkClass: 'dark-theme',
@ -87,35 +87,42 @@ function darkTheme() {
return true;
},
};
const addDarkThemeListeners = () => {
$(document).ready(() => {
const lightThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="light"]');
[...lightThemeButtons].map((lightThemeButton) => {
lightThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.removeClass(rootEl);
themeCookie.setCookie(false);
});
return true;
});
const darkThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="dark"]');
[...darkThemeButtons].map((darkThemeButton) => {
darkThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.addClass(rootEl);
themeCookie.setCookie(true);
});
return true;
});
const autoThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="auto"]');
[...autoThemeButtons].map((autoThemeButton) => {
autoThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeCookie.removeCookie();
preferedColorScheme.choose();
});
return true;
});
});
};
preferedColorScheme.init();
const lightThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="light"]');
[...lightThemeButtons].map((lightThemeButton) => {
lightThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.removeClass(rootEl);
themeCookie.setCookie(false);
});
return true;
});
const darkThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="dark"]');
[...darkThemeButtons].map((darkThemeButton) => {
darkThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeDom.addClass(rootEl);
themeCookie.setCookie(true);
});
return true;
});
const autoThemeButtons = document.querySelectorAll('.js-theme-toggle[data-theme="auto"]');
[...autoThemeButtons].map((autoThemeButton) => {
autoThemeButton.addEventListener('click', (e) => {
e.preventDefault();
themeCookie.removeCookie();
preferedColorScheme.choose();
});
return true;
});
}
addDarkThemeListeners();
}());
const stickyNav = () => {
const nav = $('.js-entry-nav-top');
@ -150,7 +157,6 @@ const articleScroll = () => {
$(document).ready(() => {
// sideNav
$('.button-collapse').sideNav();
darkTheme();
$('select').material_select();
$('.collapsible').collapsible({
accordion: false,

View file

@ -80,6 +80,13 @@ $(document).ready(() => {
});
Mousetrap.bind('enter', () => {
window.location.href = window.location.origin + $(card).find('span.card-title a').attr('href');
if (typeof card !== 'object') {
return;
}
const url = $(card).find('.card-title a').attr('href');
if (typeof url === 'string' && url.length > 0) {
window.location.href = window.location.origin + url;
}
});
});

View file

@ -14,6 +14,7 @@ framework:
translator:
enabled: true
fallback: "%locale%"
default_path: '%kernel.project_dir%/translations'
secret: "%secret%"
router:
resource: "%kernel.project_dir%/app/config/routing.yml"
@ -33,6 +34,8 @@ framework:
fragments: ~
http_method_override: true
assets: ~
mailer:
dsn: "%mailer_dsn%"
# Twig Configuration
twig:
@ -56,6 +59,8 @@ doctrine:
charset: "%database_charset%"
path: "%database_path%"
unix_socket: "%database_socket%"
types:
json_array: Wallabag\CoreBundle\Doctrine\JsonArrayType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
@ -72,22 +77,14 @@ stof_doctrine_extensions:
sluggable: true
doctrine_migrations:
dir_name: "%kernel.project_dir%/app/DoctrineMigrations"
namespace: Application\Migrations
table_name: migration_versions
name: Application Migrations
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
username: "%mailer_user%"
password: "%mailer_password%"
host: "%mailer_host%"
port: "%mailer_port%"
encryption: "%mailer_encryption%"
auth_mode: "%mailer_auth_mode%"
spool:
type: memory
migrations_paths:
'Application\Migrations': "%kernel.project_dir%/app/DoctrineMigrations"
storage:
table_storage:
table_name: 'migration_versions'
version_column_name: 'version'
version_column_length: 192
executed_at_column_name: 'executed_at'
fos_rest:
param_fetcher_listener: true
@ -133,12 +130,13 @@ nelmio_api_doc:
title: wallabag API documentation
description: This is the API documentation of wallabag
version: 2.x
securityDefinitions:
Bearer:
type: apiKey
description: 'Value: Bearer {jwt}'
name: Authorization
in: header
components:
securitySchemes:
Bearer:
type: apiKey
description: 'Value: Bearer {jwt}'
name: Authorization
in: header
security:
- Bearer: []
@ -179,8 +177,10 @@ fos_user:
confirmation:
enabled: "%fosuser_confirmation%"
from_email:
address: "%from_email%"
sender_name: wallabag
address: "%from_email%"
sender_name: wallabag
service:
mailer: Wallabag\UserBundle\Mailer\UserMailer
fos_oauth_server:
db_driver: orm
@ -201,15 +201,15 @@ scheb_two_factor:
lifetime: 2592000
backup_codes:
enabled: "%twofactor_auth%"
enabled: true
google:
enabled: "%twofactor_auth%"
enabled: true
issuer: "%server_name%"
template: "@WallabagUser/Authentication/form.html.twig"
email:
enabled: "%twofactor_auth%"
enabled: true
sender_email: "%twofactor_sender%"
digits: 6
template: "@WallabagUser/Authentication/form.html.twig"

View file

@ -8,6 +8,10 @@ framework:
profiler:
only_exceptions: false
mailer:
# see https://mailcatcher.me/
dsn: smtp://127.0.0.1:1025
web_profiler:
toolbar: true
intercept_redirects: false
@ -35,12 +39,6 @@ monolog:
VERBOSITY_DEBUG: DEBUG
channels: [doctrine]
swiftmailer:
# see https://mailcatcher.me/
transport: smtp
host: 'localhost'
port: 1025
# If you want to use cache for queries used in WallabagExtension
# Uncomment the following lines
#doctrine:

View file

@ -11,16 +11,13 @@ framework:
collect: false
translator:
enabled: false
mailer:
dsn: 'null://null'
web_profiler:
toolbar: false
intercept_redirects: false
swiftmailer:
# to be able to read emails sent
spool:
type: file
doctrine:
dbal:
driver: "%test_database_driver%"

View file

@ -23,16 +23,10 @@ parameters:
# with PostgreSQL and SQLite, you must set "utf8"
database_charset: utf8mb4
domain_name: https://your-wallabag-url-instance.com
domain_name: https://your-wallabag-instance.wallabag.org
server_name: "Your wallabag instance"
mailer_transport: smtp
mailer_user: ~
mailer_password: ~
mailer_host: 127.0.0.1
mailer_port: false
mailer_encryption: ~
mailer_auth_mode: ~
mailer_dsn: smtp://127.0.0.1
locale: en
@ -40,7 +34,6 @@ parameters:
secret: CHANGE_ME_TO_SOMETHING_SECRET_AND_RANDOM
# two factor stuff
twofactor_auth: true
twofactor_sender: no-reply@wallabag.org
# fosuser stuff

View file

@ -7,7 +7,7 @@ _profiler:
prefix: /_profiler
_errors:
resource: "@TwigBundle/Resources/config/routing/errors.xml"
resource: '@TwigBundle/Resources/config/routing/errors.xml'
prefix: /_error
_main:

View file

@ -34,12 +34,10 @@ security:
provider: fos_userbundle
login_firewall:
logout_on_user_change: true
pattern: ^/login$
anonymous: ~
secured_area:
logout_on_user_change: true
pattern: ^/
form_login:
provider: fos_userbundle

View file

@ -33,7 +33,7 @@ services:
Wallabag\AnnotationBundle\:
resource: '../../src/Wallabag/AnnotationBundle/*'
exclude: '../../src/Wallabag/AnnotationBundle/{Controller,Entity}'
exclude: '../../src/Wallabag/AnnotationBundle/{Controller,Entity,DataFixtures}'
Wallabag\ApiBundle\:
resource: '../../src/Wallabag/ApiBundle/*'
@ -41,7 +41,80 @@ services:
Wallabag\CoreBundle\:
resource: '../../src/Wallabag/CoreBundle/*'
exclude: ['../../src/Wallabag/CoreBundle/{Controller,Entity}', '../../src/Wallabag/CoreBundle/Event/*Event.php']
exclude: ['../../src/Wallabag/CoreBundle/{Controller,Entity,DataFixtures}', '../../src/Wallabag/CoreBundle/Event/*Event.php']
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
Wallabag\AnnotationBundle\Controller\:
resource: '../../src/Wallabag/AnnotationBundle/Controller/'
tags: ['controller.service_arguments']
Wallabag\ApiBundle\Controller\:
resource: '../../src/Wallabag/ApiBundle/Controller/'
tags: ['controller.service_arguments']
Wallabag\CoreBundle\Controller\:
resource: '../../src/Wallabag/CoreBundle/Controller/'
tags: ['controller.service_arguments']
Wallabag\ImportBundle\Controller\:
resource: '../../src/Wallabag/ImportBundle/Controller/'
tags: ['controller.service_arguments']
Wallabag\UserBundle\Controller\:
resource: '../../src/Wallabag/UserBundle/Controller/'
tags: ['controller.service_arguments']
# inject alias service into controllers
Wallabag\ImportBundle\Controller\ChromeController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_chrome_producer'
$redisProducer: '@wallabag_import.producer.redis.chrome'
Wallabag\ImportBundle\Controller\DeliciousController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_delicious_producer'
$redisProducer: '@wallabag_import.producer.redis.delicious'
Wallabag\ImportBundle\Controller\ElcuratorController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_elcurator_producer'
$redisProducer: '@wallabag_import.producer.redis.elcurator'
Wallabag\ImportBundle\Controller\FirefoxController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_firefox_producer'
$redisProducer: '@wallabag_import.producer.redis.firefox'
Wallabag\ImportBundle\Controller\InstapaperController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_instapaper_producer'
$redisProducer: '@wallabag_import.producer.redis.instapaper'
Wallabag\ImportBundle\Controller\PinboardController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pinboard_producer'
$redisProducer: '@wallabag_import.producer.redis.pinboard'
Wallabag\ImportBundle\Controller\PocketController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_pocket_producer'
$redisProducer: '@wallabag_import.producer.redis.pocket'
Wallabag\ImportBundle\Controller\ReadabilityController:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_readability_producer'
$redisProducer: '@wallabag_import.producer.redis.readability'
Wallabag\ImportBundle\Controller\WallabagV1Controller:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_wallabag_v1_producer'
$redisProducer: '@wallabag_import.producer.redis.wallabag_v1'
Wallabag\ImportBundle\Controller\WallabagV2Controller:
arguments:
$rabbitMqProducer: '@old_sound_rabbit_mq.import_wallabag_v2_producer'
$redisProducer: '@wallabag_import.producer.redis.wallabag_v2'
Wallabag\ImportBundle\:
resource: '../../src/Wallabag/ImportBundle/*'
@ -49,7 +122,7 @@ services:
Wallabag\UserBundle\:
resource: '../../src/Wallabag/UserBundle/*'
exclude: '../../src/Wallabag/UserBundle/{Controller,Entity}'
exclude: '../../src/Wallabag/UserBundle/{Controller,Entity,DataFixtures}'
Doctrine\DBAL\Connection:
alias: doctrine.dbal.default_connection
@ -96,9 +169,6 @@ services:
FOS\UserBundle\Model\UserManagerInterface:
alias: fos_user.user_manager
Twig_Extensions_Extension_Text:
class: Twig_Extensions_Extension_Text
MatomoTwigExtension\MatomoTwigExtension:
public: false
@ -186,8 +256,6 @@ services:
path: '%redis_path%'
password: '%redis_password%'
Wallabag\CoreBundle\Controller\ExceptionController: ~
Wallabag\CoreBundle\Event\Subscriber\SQLiteCascadeDeleteSubscriber:
tags:
- { name: doctrine.event_subscriber }
@ -200,9 +268,30 @@ services:
arguments:
$baseFolder: "%kernel.project_dir%/web/assets/images"
Wallabag\CoreBundle\Command\ExportCommand:
arguments:
$projectDir: '%kernel.project_dir%'
Wallabag\CoreBundle\Command\InstallCommand:
arguments:
$databaseDriver: '%database_driver%'
$databaseName: '%database_name%'
$defaultSettings: '%wallabag_core.default_internal_settings%'
$defaultIgnoreOriginInstanceRules: '%wallabag_core.default_ignore_origin_instance_rules%'
wallabag_core.entry.download_images.client:
alias: 'httplug.client.wallabag_core.entry.download_images'
Wallabag\UserBundle\Mailer\UserMailer:
arguments:
$parameters:
template:
confirmation: '%fos_user.registration.confirmation.template%'
resetting: '%fos_user.resetting.email.template%'
from_email:
confirmation: '%fos_user.registration.confirmation.from_email%'
resetting: '%fos_user.resetting.email.from_email%'
Wallabag\UserBundle\EventListener\CreateConfigListener:
arguments:
$itemsOnPage: "%wallabag_core.items_on_page%"
@ -211,6 +300,7 @@ services:
$readingSpeed: "%wallabag_core.reading_speed%"
$actionMarkAsRead: "%wallabag_core.action_mark_as_read%"
$listMode: "%wallabag_core.list_mode%"
$displayThumbnails: "%wallabag_core.display_thumbnails%"
Wallabag\UserBundle\EventListener\AuthenticationFailureListener:
tags:
@ -260,3 +350,13 @@ services:
Wallabag\ImportBundle\Import\ChromeImport:
tags:
- { name: wallabag_import.import, alias: chrome }
# to factorize the proximity and bypass translation for prev & next
pagerfanta.view.default_wallabag:
class: Pagerfanta\View\OptionableView
arguments:
- '@pagerfanta.view.twitter_bootstrap'
- { proximity: 1, prev_message: "<", next_message: ">" }
public: false
tags:
- { name: pagerfanta.view, alias: default_wallabag }

View file

@ -5,6 +5,20 @@ services:
autoconfigure: true
public: true
Wallabag\ImportBundle\Consumer\RabbitMQConsumerTotalProxy:
lazy: true
arguments:
$pocketConsumer: '@old_sound_rabbit_mq.import_pocket_consumer'
$readabilityConsumer: '@old_sound_rabbit_mq.import_readability_consumer'
$wallabagV1Consumer: '@old_sound_rabbit_mq.import_wallabag_v1_consumer'
$wallabagV2Consumer: '@old_sound_rabbit_mq.import_wallabag_v2_consumer'
$firefoxConsumer: '@old_sound_rabbit_mq.import_firefox_consumer'
$chromeConsumer: '@old_sound_rabbit_mq.import_chrome_consumer'
$instapaperConsumer: '@old_sound_rabbit_mq.import_instapaper_consumer'
$pinboardConsumer: '@old_sound_rabbit_mq.import_pinboard_consumer'
$deliciousConsumer: '@old_sound_rabbit_mq.import_delicious_consumer'
$elcuratorConsumer: '@old_sound_rabbit_mq.import_elcurator_consumer'
wallabag_import.consumer.amqp.pocket:
class: Wallabag\ImportBundle\Consumer\AMQPEntryConsumer
arguments:

View file

@ -1,6 +1,6 @@
wallabag_core:
version: 2.5.2
paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
version: 2.6.2
paypal_url: "https://liberapay.com/wallabag/donate"
languages:
en: 'English'
fr: 'Français'
@ -30,6 +30,7 @@ wallabag_core:
cache_lifetime: 10
action_mark_as_read: 1
list_mode: 0
display_thumbnails: 1
fetching_error_message_title: 'No title found'
fetching_error_message: |
wallabag can't retrieve contents for this article. Please <a href="https://doc.wallabag.org/en/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.

View file

@ -1,33 +1,38 @@
{
"name": "wallabag/wallabag",
"type": "project",
"description": "open source self hostable read-it-later web application",
"license": "MIT",
"type": "project",
"keywords": [
"poche",
"wallabag",
"read-it-later",
"read it later"
],
"homepage": "https://github.com/wallabag/wallabag",
"license": "MIT",
"authors": [
{
"name": "Nicolas Lœuillet",
"email": "nicolas@loeuillet.org",
"homepage": "http://www.cdetc.fr",
"homepage": "https://nicolas.loeuillet.org",
"role": "Developer"
},
{
"name": "Thomas Citharel",
"homepage": "http://tcit.fr",
"homepage": "https://tcit.fr",
"role": "Developer"
},
{
"name": "Jérémy Benoist",
"homepage": "https://www.j0k3r.net",
"role": "Developer"
},
{
"name": "Kevin Decherf",
"homepage": "https://kdecherf.com/",
"role": "Developer"
}
],
"homepage": "https://github.com/wallabag/wallabag",
"support": {
"email": "hello@wallabag.org",
"issues": "https://github.com/wallabag/wallabag/issues"
@ -51,46 +56,47 @@
"ext-tidy": "*",
"ext-tokenizer": "*",
"ext-xml": "*",
"babdev/pagerfanta-bundle": "^2.5",
"babdev/pagerfanta-bundle": "^3.7",
"bdunogier/guzzle-site-authenticator": "^1.0.0",
"craue/config-bundle": "^2.3.0",
"defuse/php-encryption": "^2.1",
"doctrine/collections": "^1.6",
"doctrine/common": "^2.13",
"doctrine/dbal": "^2.13",
"doctrine/doctrine-bundle": "^1.9",
"doctrine/doctrine-cache-bundle": "^1.3",
"doctrine/doctrine-migrations-bundle": "^1.3",
"doctrine/common": "^3.0",
"doctrine/dbal": "^3.3",
"doctrine/doctrine-bundle": "^2.0",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/event-manager": "^1.1",
"doctrine/migrations": "^1.8",
"doctrine/migrations": "^3.2",
"doctrine/orm": "^2.6",
"doctrine/persistence": "^1.3",
"doctrine/persistence": "^3.0",
"egulias/email-validator": "^3.2",
"enshrined/svg-sanitize": "^0.15.4",
"friendsofsymfony/jsrouting-bundle": "^2.2",
"friendsofsymfony/oauth-server-bundle": "^1.5",
"friendsofsymfony/rest-bundle": "~2.1",
"friendsofsymfony/user-bundle": "2.1.*",
"friendsofsymfony/oauth-server-bundle": "dev-master#dc8ff343363cf794d30eb1a123610d186a43f162",
"friendsofsymfony/rest-bundle": "~3.4",
"friendsofsymfony/user-bundle": "^3.1",
"guzzlehttp/guzzle": "^5.3.1",
"guzzlehttp/psr7": "^1.8",
"guzzlehttp/psr7": "^2.5",
"html2text/html2text": "^4.1",
"incenteev/composer-parameter-handler": "^2.1",
"j0k3r/graby": "^2.0",
"javibravo/simpleue": "^2.0",
"jms/serializer": "^3.17",
"jms/serializer-bundle": "~3.6",
"jms/serializer-bundle": "~5.0",
"kphoen/rulerz": "^0.21",
"kphoen/rulerz-bundle": "~0.13",
"laminas/laminas-code": "^3.4",
"laminas/laminas-diactoros": "^2.3",
"lexik/form-filter-bundle": "^5.0.4",
"laminas/laminas-code": "^4.7",
"lcobucci/jwt": "~4.1.5",
"lexik/form-filter-bundle": "^7.0",
"mgargano/simplehtmldom": "~1.5",
"mnapoli/piwik-twig-extension": "^3.0",
"nelmio/api-doc-bundle": "^3.0",
"nelmio/cors-bundle": "~1.5",
"nelmio/api-doc-bundle": "^4.10",
"nelmio/cors-bundle": "~2.2",
"ocramius/proxy-manager": "^2.1.1",
"pagerfanta/pagerfanta": "^2.4",
"php-amqplib/php-amqplib": "^2.12",
"php-amqplib/rabbitmq-bundle": "^1.14",
"pagerfanta/doctrine-orm-adapter": "^3.7",
"pagerfanta/twig": "^3.7",
"php-amqplib/php-amqplib": "^3.4",
"php-amqplib/rabbitmq-bundle": "^2.11",
"php-http/client-common": "^2.4",
"php-http/discovery": "^1.14",
"php-http/guzzle5-adapter": "^2.0",
@ -102,27 +108,34 @@
"predis/predis": "^2.0.3",
"psr/http-message": "^1.0",
"psr/log": "^1.1",
"scheb/two-factor-bundle": "^4.11.0",
"sensio/framework-extra-bundle": "^5.2",
"sentry/sentry-symfony": "3.5.3",
"scheb/2fa-backup-code": "^5.13",
"scheb/2fa-bundle": "^5.13",
"scheb/2fa-email": "^5.13",
"scheb/2fa-google-authenticator": "^5.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",
"stof/doctrine-extensions-bundle": "^1.2",
"swiftmailer/swiftmailer": "^6.3",
"symfony/dom-crawler": "^4.0",
"symfony/mailer": "^4.0",
"symfony/monolog-bundle": "^3.1",
"symfony/swiftmailer-bundle": "^3.2",
"symfony/proxy-manager-bridge": "^4.4",
"symfony/symfony": "^4.0",
"tecnickcom/tcpdf": "^6.3.0",
"twig/extensions": "^1.5",
"twig/twig": "^2.15",
"twig/extra-bundle": "^3.4",
"twig/string-extra": "^3.4",
"twig/twig": "^3.4.3",
"wallabag/php-mobi": "~1.0",
"wallabag/phpepub": "^4.0.10",
"willdurand/hateoas": "^3.8",
"willdurand/hateoas-bundle": "~2.1"
},
"require-dev": {
"dama/doctrine-test-bundle": "^6.0",
"dama/doctrine-test-bundle": "^7.1",
"doctrine/doctrine-fixtures-bundle": "~3.0",
"friendsofphp/php-cs-fixer": "~2.13",
"ergebnis/composer-normalize": "^2.28",
"friendsofphp/php-cs-fixer": "~3.4",
"friendsoftwig/twigcs": "^6.0",
"m6web/redis-mock": "^5.0",
"php-http/mock-client": "^1.0",
@ -137,24 +150,8 @@
"suggest": {
"ext-imagick": "To keep GIF animation when downloading image is enabled"
},
"scripts": {
"post-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"bin/console cache:clear --no-warmup",
"bin/console assets:install web --symlink --relative"
],
"post-install-cmd": [
"@post-cmd"
],
"post-update-cmd": [
"@post-cmd"
]
},
"extra": {
"incenteev-parameters": {
"file": "app/config/parameters.yml"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Wallabag\\": "src/Wallabag/"
@ -173,15 +170,34 @@
]
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true,
"php-http/discovery": true,
"ergebnis/composer-normalize": true
},
"bin-dir": "bin",
"platform": {
"php": "7.4.29"
},
"sort-packages": true,
"allow-plugins": {
"phpstan/extension-installer": true
}
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
"extra": {
"incenteev-parameters": {
"file": "app/config/parameters.yml"
},
"public-dir": "web"
},
"scripts": {
"post-install-cmd": [
"@post-cmd"
],
"post-update-cmd": [
"@post-cmd"
],
"post-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"bin/console cache:clear --no-warmup",
"bin/console assets:install web --symlink --relative"
]
}
}

4884
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
FROM php:7.4-fpm AS rootless
FROM php:8.1-fpm AS rootless
ARG DEBIAN_FRONTEND=noninteractive
ARG NODE_VERSION=16
@ -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 \
@ -53,7 +54,7 @@ RUN docker-php-ext-install -j "$(nproc)" \
RUN pecl install redis; \
pecl install imagick; \
pecl install xdebug; \
pecl install xdebug-3.1.6; \
docker-php-ext-enable \
redis \
imagick \

View file

@ -6,29 +6,22 @@ parameters:
database_name: ${DATABASE_NAME:-symfony}
database_user: ${DATABASE_USER:-root}
database_password: ${DATABASE_PASSWORD:-~}
database_path: ${DATABASE_PATH:-"%kernel.root_dir%/data/db/wallabag.sqlite"}
database_table_prefix: wallabag_
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}
domain_name: ${DOMAIN_NAME:-https://www.example.com}
server_name: ${SERVER_NAME:-"Your wallabag instance"}
mailer_transport: ${MAILER_TRANSPORT:-smtp}
mailer_user: ${MAILER_USER:-~}
mailer_password: ${MAILER_PASSWORD:-~}
mailer_host: ${MAILER_HOST:-127.0.0.1}
mailer_port: ${MAILER_PORT:-25}
mailer_encryption: ${MAILER_ENCRYPTION:-~}
mailer_auth_mode: ${MAILER_AUTH_MODE:-~}
mailer_dsn: ${MAILER_DSN:-"smtp://127.0.0.1"}
locale: ${LOCALE:-en}
locale: ${LOCALE:-en}
# A secret key that's used to generate certain security-related tokens
secret: ${SECRET:-~}
# two factor stuff
twofactor_auth: ${TWOFACTOR_AUTH:-true}
twofactor_sender: ${TWOFACTOR_SENDER:-no-reply@wallabag.org}
# fosuser stuff

View file

@ -1,6 +1,6 @@
{
"name": "wallabag",
"version": "2.5.0",
"version": "2.6.0",
"description": "wallabag is a self hostable application for saving web pages",
"private": true,
"directories": {
@ -17,17 +17,22 @@
{
"name": "Nicolas Lœuillet",
"email": "nicolas@loeuillet.org",
"homepage": "http://www.cdetc.fr",
"homepage": "https://nicolas.loeuillet.org",
"role": "Developer"
},
{
"name": "Thomas Citharel",
"homepage": "http://tcit.fr",
"homepage": "https://tcit.fr",
"role": "Developer"
},
{
"name": "Jérémy Benoist",
"homepage": "http://www.j0k3r.net",
"homepage": "https://www.j0k3r.net",
"role": "Developer"
},
{
"name": "Kevin Decherf",
"homepage": "https://kdecherf.com/",
"role": "Developer"
}
],
@ -36,49 +41,50 @@
"url": "https://github.com/wallabag/wallabag/issues"
},
"devDependencies": {
"@babel/core": "^7.20.2",
"@babel/eslint-parser": "^7.19.1",
"@babel/preset-env": "^7.20.2",
"autoprefixer": "^10.4.13",
"babel-loader": "^9.1.0",
"css-loader": "^6.7.2",
"eslint": "^8.28.0",
"@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.46.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-webpack-plugin": "^3.2.0",
"eslint-plugin-import": "^2.28.0",
"eslint-webpack-plugin": "^4.0.1",
"file-loader": "^6.2.0",
"lato-font": "^3.0.0",
"mini-css-extract-plugin": "^2.7.0",
"node-sass": "^8.0.0",
"postcss": "^8.4.19",
"postcss-loader": "^7.0.1",
"mini-css-extract-plugin": "^2.7.6",
"node-sass": "^9.0.0",
"postcss": "^8.4.27",
"postcss-loader": "^7.3.3",
"postcss-scss": "^4.0.6",
"sass": "^1.56.1",
"sass-loader": "^13.2.0",
"style-loader": "^3.3.1",
"stylelint": "^14.15.0",
"stylelint-config-standard": "^29.0.0",
"stylelint-scss": "^4.3.0",
"stylelint-webpack-plugin": "^3.3.0",
"terser-webpack-plugin": "^5.3.6",
"sass": "^1.64.1",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"stylelint": "^15.10.2",
"stylelint-config-standard": "^34.0.0",
"stylelint-config-standard-scss": "^10.0.0",
"stylelint-scss": "^5.0.1",
"stylelint-webpack-plugin": "^4.1.1",
"terser-webpack-plugin": "^5.3.9",
"url-loader": "^4.1.1",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.0",
"webpack-dev-server": "^4.11.1",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-manifest-plugin": "^5.0.0",
"webpack-merge": "^5.7.3"
"webpack-merge": "^5.9.0"
},
"dependencies": {
"annotator": "wallabag/annotator#master",
"clipboard": "^2.0.11",
"hammerjs": "^2.0.8",
"highlight.js": "^11.7.0",
"highlight.js": "^11.8.0",
"icomoon-free-npm": "^0.0.0",
"jquery": "^3.6.1",
"jquery": "^3.7.0",
"jquery.cookie": "^1.4.1",
"jr-qrcode": "^1.0.7",
"material-design-icons-iconfont": "^6.7.0",
"materialize-css": "^0.98.1",
"materialize-css": "^0.100.2",
"mathjax": "^3.2.2",
"mousetrap": "^1.6.0",
"ptsans-npm-webfont": "^0.0.4",

View file

@ -1,40 +1,10 @@
parameters:
ignoreErrors:
-
message: "#^Call to an undefined method Psr\\\\Container\\\\ContainerInterface\\:\\:getParameter\\(\\)\\.$#"
count: 2
path: src/Wallabag/ApiBundle/Controller/EntryRestController.php
-
message: "#^Call to an undefined method Psr\\\\Container\\\\ContainerInterface\\:\\:getParameter\\(\\)\\.$#"
count: 1
path: src/Wallabag/ApiBundle/Controller/UserRestController.php
-
message: "#^Call to an undefined method Psr\\\\Container\\\\ContainerInterface\\:\\:getParameter\\(\\)\\.$#"
count: 3
path: src/Wallabag/ApiBundle/Controller/WallabagRestController.php
-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getConnection\\(\\)\\.$#"
count: 5
path: src/Wallabag/CoreBundle/Command/InstallCommand.php
-
message: "#^Call to an undefined method Wallabag\\\\CoreBundle\\\\Entity\\\\RuleInterface\\:\\:getConfig\\(\\)\\.$#"
count: 1
path: src/Wallabag/CoreBundle/Controller/ConfigController.php
-
message: "#^Call to an undefined method Psr\\\\Container\\\\ContainerInterface\\:\\:getParameter\\(\\)\\.$#"
count: 1
path: src/Wallabag/CoreBundle/Controller/StaticController.php
-
message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeDefinition\\:\\:children\\(\\)\\.$#"
count: 1
path: src/Wallabag/CoreBundle/DependencyInjection/Configuration.php
-
message: "#^Call to an undefined method Lexik\\\\Bundle\\\\FormFilterBundle\\\\Filter\\\\Query\\\\QueryInterface\\:\\:getExpressionBuilder\\(\\)\\.$#"
count: 1
@ -45,11 +15,6 @@ parameters:
count: 10
path: src/Wallabag/CoreBundle/Form/Type/EntryFilterType.php
-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getConnection\\(\\)\\.$#"
count: 1
path: src/Wallabag/ImportBundle/Command/ImportCommand.php
-
message: "#^Call to an undefined method Wallabag\\\\ImportBundle\\\\Import\\\\ImportInterface\\:\\:setFilepath\\(\\)\\.$#"
count: 1
@ -70,11 +35,6 @@ parameters:
count: 1
path: src/Wallabag/ImportBundle/Controller/WallabagController.php
-
message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeDefinition\\:\\:children\\(\\)\\.$#"
count: 1
path: src/Wallabag/ImportBundle/DependencyInjection/Configuration.php
-
message: "#^Call to an undefined method Scheb\\\\TwoFactorBundle\\\\Model\\\\Email\\\\TwoFactorInterface\\:\\:getName\\(\\)\\.$#"
count: 2
@ -94,3 +54,13 @@ parameters:
message: "#^Property Tests\\\\Wallabag\\\\CoreBundle\\\\Helper\\\\RedirectTest\\:\\:\\$routerMock has unknown class PHPUnit_Framework_MockObject_MockObject as its type\\.$#"
count: 1
path: tests/Wallabag/CoreBundle/Helper/RedirectTest.php
-
message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch()#"
count: 15
path: src/*
-
message: "#^Method FOS\\\\UserBundle\\\\Model\\\\UserManagerInterface\\:\\:updateUser()#"
count: 7
path: src/Wallabag/CoreBundle/Controller/ConfigController.php

View file

@ -31,7 +31,7 @@
</whitelist>
</filter>
<listeners>
<listener class="\DAMA\DoctrineTestBundle\PHPUnit\PHPUnitListener" />
</listeners>
<extensions>
<extension class="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension" />
</extensions>
</phpunit>

View file

@ -9,7 +9,7 @@ ENV=$4
rm -rf "${TMP_FOLDER:?}"/"$RELEASE_FOLDER"
mkdir "$TMP_FOLDER"/"$RELEASE_FOLDER"
git clone https://github.com/wallabag/wallabag.git "$TMP_FOLDER"/"$RELEASE_FOLDER"/"$VERSION"
git clone https://github.com/wallabag/wallabag.git --single-branch --depth 1 --branch $1 "$TMP_FOLDER"/"$RELEASE_FOLDER"/"$VERSION"
cd "$TMP_FOLDER"/"$RELEASE_FOLDER"/"$VERSION" && SYMFONY_ENV="$ENV" COMPOSER_MEMORY_LIMIT=-1 composer install -n --no-dev
cd "$TMP_FOLDER"/"$RELEASE_FOLDER"/"$VERSION" && php bin/console wallabag:install --env="$ENV" -n
cd "$TMP_FOLDER"/"$RELEASE_FOLDER"/"$VERSION" && php bin/console assets:install --env="$ENV" --symlink --relative

View file

@ -2,20 +2,33 @@
namespace Wallabag\AnnotationBundle\Controller;
use Doctrine\ORM\EntityManagerInterface;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use JMS\Serializer\SerializerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Wallabag\AnnotationBundle\Entity\Annotation;
use Wallabag\AnnotationBundle\Form\EditAnnotationType;
use Wallabag\AnnotationBundle\Form\NewAnnotationType;
use Wallabag\AnnotationBundle\Repository\AnnotationRepository;
use Wallabag\CoreBundle\Entity\Entry;
class WallabagAnnotationController extends AbstractFOSRestController
{
protected EntityManagerInterface $entityManager;
protected SerializerInterface $serializer;
protected FormFactoryInterface $formFactory;
public function __construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, FormFactoryInterface $formFactory)
{
$this->entityManager = $entityManager;
$this->serializer = $serializer;
$this->formFactory = $formFactory;
}
/**
* Retrieve annotations for an entry.
*
@ -25,16 +38,14 @@ class WallabagAnnotationController extends AbstractFOSRestController
*
* @return JsonResponse
*/
public function getAnnotationsAction(Entry $entry)
public function getAnnotationsAction(Entry $entry, AnnotationRepository $annotationRepository)
{
$annotationRows = $this
->getDoctrine()
->getRepository(Annotation::class)
->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId());
$annotationRows = $annotationRepository->findByEntryIdAndUserId($entry->getId(), $this->getUser()->getId());
$total = \count($annotationRows);
$annotations = ['total' => $total, 'rows' => $annotationRows];
$json = $this->get(SerializerInterface::class)->serialize($annotations, 'json');
$json = $this->serializer->serialize($annotations, 'json');
return (new JsonResponse())->setJson($json);
}
@ -52,21 +63,20 @@ class WallabagAnnotationController extends AbstractFOSRestController
{
$data = json_decode($request->getContent(), true);
$em = $this->get('doctrine')->getManager();
$annotation = new Annotation($this->getUser());
$annotation->setEntry($entry);
$form = $this->get(FormFactoryInterface::class)->createNamed('', NewAnnotationType::class, $annotation, [
$form = $this->formFactory->createNamed('', NewAnnotationType::class, $annotation, [
'csrf_protection' => false,
'allow_extra_fields' => true,
]);
$form->submit($data);
if ($form->isValid()) {
$em->persist($annotation);
$em->flush();
$this->entityManager->persist($annotation);
$this->entityManager->flush();
$json = $this->get(SerializerInterface::class)->serialize($annotation, 'json');
$json = $this->serializer->serialize($annotation, 'json');
return JsonResponse::fromJsonString($json);
}
@ -80,31 +90,35 @@ class WallabagAnnotationController extends AbstractFOSRestController
* @see Wallabag\ApiBundle\Controller\WallabagRestController
*
* @Route("/annotations/{annotation}.{_format}", methods={"PUT"}, name="annotations_put_annotation", defaults={"_format": "json"})
* @ParamConverter("annotation", class="Wallabag\AnnotationBundle\Entity\Annotation")
*
* @return JsonResponse
*/
public function putAnnotationAction(Annotation $annotation, Request $request)
public function putAnnotationAction(Request $request, AnnotationRepository $annotationRepository, int $annotation)
{
$data = json_decode($request->getContent(), true);
try {
$annotation = $this->validateAnnotation($annotationRepository, $annotation, $this->getUser()->getId());
$form = $this->get(FormFactoryInterface::class)->createNamed('', EditAnnotationType::class, $annotation, [
'csrf_protection' => false,
'allow_extra_fields' => true,
]);
$form->submit($data);
$data = json_decode($request->getContent(), true, 512, \JSON_THROW_ON_ERROR);
if ($form->isValid()) {
$em = $this->get('doctrine')->getManager();
$em->persist($annotation);
$em->flush();
$form = $this->formFactory->createNamed('', EditAnnotationType::class, $annotation, [
'csrf_protection' => false,
'allow_extra_fields' => true,
]);
$form->submit($data);
$json = $this->get(SerializerInterface::class)->serialize($annotation, 'json');
if ($form->isValid()) {
$this->entityManager->persist($annotation);
$this->entityManager->flush();
return JsonResponse::fromJsonString($json);
$json = $this->serializer->serialize($annotation, 'json');
return JsonResponse::fromJsonString($json);
}
return $form;
} catch (\InvalidArgumentException $e) {
throw new NotFoundHttpException($e);
}
return $form;
}
/**
@ -113,18 +127,33 @@ class WallabagAnnotationController extends AbstractFOSRestController
* @see Wallabag\ApiBundle\Controller\WallabagRestController
*
* @Route("/annotations/{annotation}.{_format}", methods={"DELETE"}, name="annotations_delete_annotation", defaults={"_format": "json"})
* @ParamConverter("annotation", class="Wallabag\AnnotationBundle\Entity\Annotation")
*
* @return JsonResponse
*/
public function deleteAnnotationAction(Annotation $annotation)
public function deleteAnnotationAction(AnnotationRepository $annotationRepository, int $annotation)
{
$em = $this->get('doctrine')->getManager();
$em->remove($annotation);
$em->flush();
try {
$annotation = $this->validateAnnotation($annotationRepository, $annotation, $this->getUser()->getId());
$json = $this->get(SerializerInterface::class)->serialize($annotation, 'json');
$this->entityManager->remove($annotation);
$this->entityManager->flush();
return (new JsonResponse())->setJson($json);
$json = $this->serializer->serialize($annotation, 'json');
return (new JsonResponse())->setJson($json);
} catch (\InvalidArgumentException $e) {
throw new NotFoundHttpException($e);
}
}
private function validateAnnotation(AnnotationRepository $annotationRepository, int $annotationId, int $userId)
{
$annotation = $annotationRepository->findOneByIdAndUserId($annotationId, $userId);
if (null === $annotation) {
throw new NotFoundHttpException();
}
return $annotation;
}
}

View file

@ -34,6 +34,15 @@ class AnnotationFixtures extends Fixture implements DependentFixtureInterface
$this->addReference('annotation2', $annotation2);
$annotation3 = new Annotation($this->getReference('bob-user'));
$annotation3->setEntry($this->getReference('entry3'));
$annotation3->setText('This is my first annotation !');
$annotation3->setQuote('content');
$manager->persist($annotation3);
$this->addReference('annotation3', $annotation3);
$manager->flush();
}

View file

@ -12,9 +12,6 @@ class Configuration implements ConfigurationInterface
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('wallabag_annotation');
return $treeBuilder;
return new TreeBuilder('wallabag_annotation');
}
}

View file

@ -49,6 +49,24 @@ class AnnotationRepository extends ServiceEntityRepository
;
}
/**
* Find annotation by id and user.
*
* @param int $annotationId
* @param int $userId
*
* @return Annotation
*/
public function findOneByIdAndUserId($annotationId, $userId)
{
return $this->createQueryBuilder('a')
->where('a.id = :annotationId')->setParameter('annotationId', $annotationId)
->andWhere('a.user = :userId')->setParameter('userId', $userId)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
/**
* Find annotations for entry id.
*
@ -57,7 +75,7 @@ class AnnotationRepository extends ServiceEntityRepository
*
* @return array
*/
public function findAnnotationsByPageId($entryId, $userId)
public function findByEntryIdAndUserId($entryId, $userId)
{
return $this->createQueryBuilder('a')
->where('a.entry = :entryId')->setParameter('entryId', $entryId)
@ -72,9 +90,9 @@ class AnnotationRepository extends ServiceEntityRepository
*
* @param int $entryId
*
* @return array
* @return Annotation|null
*/
public function findLastAnnotationByPageId($entryId, $userId)
public function findLastAnnotationByUserId($entryId, $userId)
{
return $this->createQueryBuilder('a')
->where('a.entry = :entryId')->setParameter('entryId', $entryId)

View file

@ -3,8 +3,7 @@
namespace Wallabag\ApiBundle\Controller;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
@ -19,15 +18,17 @@ class AnnotationRestController extends WallabagRestController
* @Operation(
* tags={"Annotations"},
* summary="Retrieve annotations for an entry.",
* @SWG\Parameter(
* @OA\Parameter(
* name="entry",
* in="path",
* description="The entry ID",
* required=true,
* pattern="\w+",
* type="integer"
* @OA\Schema(
* type="integer",
* pattern="\w+",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -52,40 +53,48 @@ class AnnotationRestController extends WallabagRestController
* @Operation(
* tags={"Annotations"},
* summary="Creates a new annotation.",
* @SWG\Parameter(
* @OA\Parameter(
* name="entry",
* in="path",
* description="The entry ID",
* required=true,
* pattern="\w+",
* type="integer"
* ),
* @SWG\Parameter(
* name="ranges",
* in="body",
* description="The range array for the annotation",
* required=false,
* pattern="\w+",
* @SWG\Schema(
* type="array",
* @SWG\Items(type="string")
* @OA\Schema(
* type="integer",
* pattern="\w+",
* )
* ),
* @SWG\Parameter(
* name="quote",
* in="body",
* description="The annotated text",
* required=false,
* @SWG\Schema(type="string")
* @OA\RequestBody(
* @OA\JsonContent(
* type="object",
* required={"text"},
* @OA\Property(
* property="ranges",
* type="array",
* description="The range array for the annotation",
* @OA\Items(
* type="string",
* pattern="\w+",
* )
* ),
* @OA\Property(
* property="quote",
* type="array",
* description="The annotated text",
* @OA\Items(
* type="string",
* )
* ),
* @OA\Property(
* property="text",
* type="array",
* description="Content of annotation",
* @OA\Items(
* type="string",
* )
* ),
* )
* ),
* @SWG\Parameter(
* name="text",
* in="body",
* description="Content of annotation",
* required=true,
* @SWG\Schema(type="string")
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -111,26 +120,27 @@ class AnnotationRestController extends WallabagRestController
* @Operation(
* tags={"Annotations"},
* summary="Updates an annotation.",
* @SWG\Parameter(
* @OA\Parameter(
* name="annotation",
* in="path",
* description="The annotation ID",
* required=true,
* pattern="\w+",
* type="string"
* @OA\Schema(
* type="string",
* pattern="\w+",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
* )
*
* @Route("/api/annotations/{annotation}.{_format}", methods={"PUT"}, name="api_put_annotation", defaults={"_format": "json"})
* @ParamConverter("annotation", class="Wallabag\AnnotationBundle\Entity\Annotation")
*
* @return JsonResponse
*/
public function putAnnotationAction(Annotation $annotation, Request $request)
public function putAnnotationAction(int $annotation, Request $request)
{
$this->validateAuthentication();
@ -146,26 +156,27 @@ class AnnotationRestController extends WallabagRestController
* @Operation(
* tags={"Annotations"},
* summary="Removes an annotation.",
* @SWG\Parameter(
* @OA\Parameter(
* name="annotation",
* in="path",
* description="The annotation ID",
* required=true,
* pattern="\w+",
* type="string"
* @OA\Schema(
* type="string",
* pattern="\w+",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
* )
*
* @Route("/api/annotations/{annotation}.{_format}", methods={"DELETE"}, name="api_delete_annotation", defaults={"_format": "json"})
* @ParamConverter("annotation", class="Wallabag\AnnotationBundle\Entity\Annotation")
*
* @return JsonResponse
*/
public function deleteAnnotationAction(Annotation $annotation)
public function deleteAnnotationAction(int $annotation)
{
$this->validateAuthentication();

View file

@ -5,7 +5,7 @@ namespace Wallabag\ApiBundle\Controller;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
@ -17,7 +17,7 @@ class ConfigRestController extends WallabagRestController
* @Operation(
* tags={"Config"},
* summary="Retrieve configuration for current user.",
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -27,11 +27,11 @@ class ConfigRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function getConfigAction()
public function getConfigAction(SerializerInterface $serializer)
{
$this->validateAuthentication();
$json = $this->get(SerializerInterface::class)->serialize(
$json = $serializer->serialize(
$this->getUser()->getConfig(),
'json',
SerializationContext::create()->setGroups(['config_api'])

View file

@ -2,17 +2,18 @@
namespace Wallabag\ApiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Wallabag\ApiBundle\Entity\Client;
use Wallabag\ApiBundle\Form\Type\ClientType;
use Wallabag\ApiBundle\Repository\ClientRepository;
class DeveloperController extends Controller
class DeveloperController extends AbstractController
{
/**
* List all clients and link to create a new one.
@ -21,9 +22,9 @@ class DeveloperController extends Controller
*
* @return Response
*/
public function indexAction()
public function indexAction(ClientRepository $repo)
{
$clients = $this->get('doctrine')->getRepository(Client::class)->findByUser($this->getUser()->getId());
$clients = $repo->findByUser($this->getUser()->getId());
return $this->render('@WallabagCore/Developer/index.html.twig', [
'clients' => $clients,
@ -37,21 +38,20 @@ class DeveloperController extends Controller
*
* @return Response
*/
public function createClientAction(Request $request)
public function createClientAction(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
$em = $this->get('doctrine')->getManager();
$client = new Client($this->getUser());
$clientForm = $this->createForm(ClientType::class, $client);
$clientForm->handleRequest($request);
if ($clientForm->isSubmitted() && $clientForm->isValid()) {
$client->setAllowedGrantTypes(['token', 'authorization_code', 'password', 'refresh_token']);
$em->persist($client);
$em->flush();
$entityManager->persist($client);
$entityManager->flush();
$this->get(SessionInterface::class)->getFlashBag()->add(
$this->addFlash(
'notice',
$this->get(TranslatorInterface::class)->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()])
$translator->trans('flashes.developer.notice.client_created', ['%name%' => $client->getName()])
);
return $this->render('@WallabagCore/Developer/client_parameters.html.twig', [
@ -73,19 +73,18 @@ class DeveloperController extends Controller
*
* @return RedirectResponse
*/
public function deleteClientAction(Client $client)
public function deleteClientAction(Client $client, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
if (null === $this->getUser() || $client->getUser()->getId() !== $this->getUser()->getId()) {
throw $this->createAccessDeniedException('You can not access this client.');
}
$em = $this->get('doctrine')->getManager();
$em->remove($client);
$em->flush();
$entityManager->remove($client);
$entityManager->flush();
$this->get(SessionInterface::class)->getFlashBag()->add(
$this->addFlash(
'notice',
$this->get(TranslatorInterface::class)->trans('flashes.developer.notice.client_deleted', ['%name%' => $client->getName()])
$translator->trans('flashes.developer.notice.client_deleted', ['%name%' => $client->getName()])
);
return $this->redirect($this->generateUrl('developer'));
@ -100,6 +99,9 @@ class DeveloperController extends Controller
*/
public function howtoFirstAppAction()
{
return $this->render('@WallabagCore/Developer/howto_app.html.twig');
return $this->render('@WallabagCore/Developer/howto_app.html.twig',
[
'wallabag_url' => $this->getParameter('domain_name'),
]);
}
}

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,9 @@ namespace Wallabag\ApiBundle\Controller;
use Hateoas\Configuration\Route as HateoasRoute;
use Hateoas\Representation\Factory\PagerfantaFactory;
use Nelmio\ApiDocBundle\Annotation\Operation;
use OpenApi\Annotations as OA;
use Pagerfanta\Doctrine\ORM\QueryAdapter as DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
@ -21,34 +21,34 @@ class SearchRestController extends WallabagRestController
* @Operation(
* tags={"Search"},
* summary="Search all entries by term.",
* @SWG\Parameter(
* @OA\Parameter(
* name="term",
* in="body",
* in="query",
* description="Any query term",
* required=false,
* @SWG\Schema(type="string")
* @OA\Schema(type="string")
* ),
* @SWG\Parameter(
* @OA\Parameter(
* name="page",
* in="body",
* in="query",
* description="what page you want.",
* required=false,
* @SWG\Schema(
* @OA\Schema(
* type="integer",
* default=1
* )
* ),
* @SWG\Parameter(
* @OA\Parameter(
* name="perPage",
* in="body",
* in="query",
* description="results per page.",
* required=false,
* @SWG\Schema(
* @OA\Schema(
* type="integer",
* default=30
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -58,7 +58,7 @@ class SearchRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function getSearchAction(Request $request)
public function getSearchAction(Request $request, EntryRepository $entryRepository)
{
$this->validateAuthentication();
@ -66,12 +66,11 @@ class SearchRestController extends WallabagRestController
$page = (int) $request->query->get('page', 1);
$perPage = (int) $request->query->get('perPage', 30);
$qb = $this->get(EntryRepository::class)
->getBuilderForSearchByUser(
$this->getUser()->getId(),
$term,
null
);
$qb = $entryRepository->getBuilderForSearchByUser(
$this->getUser()->getId(),
$term,
null
);
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
$pager = new Pagerfanta($pagerAdapter);

View file

@ -2,14 +2,15 @@
namespace Wallabag\ApiBundle\Controller;
use JMS\Serializer\SerializerInterface;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Entity\Tag;
use Wallabag\CoreBundle\Repository\EntryRepository;
use Wallabag\CoreBundle\Repository\TagRepository;
class TagRestController extends WallabagRestController
{
@ -19,7 +20,7 @@ class TagRestController extends WallabagRestController
* @Operation(
* tags={"Tags"},
* summary="Retrieve all tags.",
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -29,15 +30,13 @@ class TagRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function getTagsAction()
public function getTagsAction(TagRepository $tagRepository)
{
$this->validateAuthentication();
$tags = $this->get('doctrine')
->getRepository(Tag::class)
->findAllFlatTagsWithNbEntries($this->getUser()->getId());
$tags = $tagRepository->findAllFlatTagsWithNbEntries($this->getUser()->getId());
$json = $this->get(SerializerInterface::class)->serialize($tags, 'json');
$json = $this->serializer->serialize($tags, 'json');
return (new JsonResponse())->setJson($json);
}
@ -48,15 +47,17 @@ class TagRestController extends WallabagRestController
* @Operation(
* tags={"Tags"},
* summary="Permanently remove one tag from every entry by passing the Tag label.",
* @SWG\Parameter(
* @OA\Parameter(
* name="tag",
* in="body",
* in="query",
* description="Tag as a string",
* required=true,
* pattern="\w+",
* @SWG\Schema(type="string")
* @OA\Schema(
* type="string",
* pattern="\w+",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -66,12 +67,12 @@ class TagRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function deleteTagLabelAction(Request $request)
public function deleteTagLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{
$this->validateAuthentication();
$label = $request->get('tag', '');
$tags = $this->get('doctrine')->getRepository(Tag::class)->findByLabelsAndUser([$label], $this->getUser()->getId());
$tags = $tagRepository->findByLabelsAndUser([$label], $this->getUser()->getId());
if (empty($tags)) {
throw $this->createNotFoundException('Tag not found');
@ -79,13 +80,11 @@ class TagRestController extends WallabagRestController
$tag = $tags[0];
$this->get('doctrine')
->getRepository(Entry::class)
->removeTag($this->getUser()->getId(), $tag);
$entryRepository->removeTag($this->getUser()->getId(), $tag);
$this->cleanOrphanTag($tag);
$json = $this->get(SerializerInterface::class)->serialize($tag, 'json');
$json = $this->serializer->serialize($tag, 'json');
return (new JsonResponse())->setJson($json);
}
@ -96,17 +95,17 @@ class TagRestController extends WallabagRestController
* @Operation(
* tags={"Tags"},
* summary="Permanently remove some tags from every entry.",
* @SWG\Parameter(
* @OA\Parameter(
* name="tags",
* in="body",
* in="query",
* description="Tags as strings (comma splitted)",
* required=true,
* @SWG\Schema(
* @OA\Schema(
* type="string",
* example="tag1,tag2",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -116,25 +115,23 @@ class TagRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function deleteTagsLabelAction(Request $request)
public function deleteTagsLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{
$this->validateAuthentication();
$tagsLabels = $request->get('tags', '');
$tags = $this->get('doctrine')->getRepository(Tag::class)->findByLabelsAndUser(explode(',', $tagsLabels), $this->getUser()->getId());
$tags = $tagRepository->findByLabelsAndUser(explode(',', $tagsLabels), $this->getUser()->getId());
if (empty($tags)) {
throw $this->createNotFoundException('Tags not found');
}
$this->get('doctrine')
->getRepository(Entry::class)
->removeTags($this->getUser()->getId(), $tags);
$entryRepository->removeTags($this->getUser()->getId(), $tags);
$this->cleanOrphanTag($tags);
$json = $this->get(SerializerInterface::class)->serialize($tags, 'json');
$json = $this->serializer->serialize($tags, 'json');
return (new JsonResponse())->setJson($json);
}
@ -145,15 +142,17 @@ class TagRestController extends WallabagRestController
* @Operation(
* tags={"Tags"},
* summary="Permanently remove one tag from every entry by passing the Tag ID.",
* @SWG\Parameter(
* @OA\Parameter(
* name="tag",
* in="body",
* in="path",
* description="The tag",
* required=true,
* pattern="\w+",
* @SWG\Schema(type="integer")
* @OA\Schema(
* type="integer",
* pattern="\w+",
* )
* ),
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )
@ -163,23 +162,21 @@ class TagRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function deleteTagAction(Tag $tag)
public function deleteTagAction(Tag $tag, TagRepository $tagRepository, EntryRepository $entryRepository)
{
$this->validateAuthentication();
$tagFromDb = $this->get('doctrine')->getRepository(Tag::class)->findByLabelsAndUser([$tag->getLabel()], $this->getUser()->getId());
$tagFromDb = $tagRepository->findByLabelsAndUser([$tag->getLabel()], $this->getUser()->getId());
if (empty($tagFromDb)) {
throw $this->createNotFoundException('Tag not found');
}
$this->get('doctrine')
->getRepository(Entry::class)
->removeTag($this->getUser()->getId(), $tag);
$entryRepository->removeTag($this->getUser()->getId(), $tag);
$this->cleanOrphanTag($tag);
$json = $this->get(SerializerInterface::class)->serialize($tag, 'json');
$json = $this->serializer->serialize($tag, 'json');
return (new JsonResponse())->setJson($json);
}
@ -195,14 +192,12 @@ class TagRestController extends WallabagRestController
$tags = [$tags];
}
$em = $this->get('doctrine')->getManager();
foreach ($tags as $tag) {
if (0 === \count($tag->getEntries())) {
$em->remove($tag);
$this->entityManager->remove($tag);
}
}
$em->flush();
$this->entityManager->flush();
}
}

View file

@ -5,7 +5,7 @@ namespace Wallabag\ApiBundle\Controller;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerBuilder;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -17,7 +17,7 @@ class TaggingRuleRestController extends WallabagRestController
* @Operation(
* tags={"TaggingRule"},
* summary="Export all tagging rules as a json file.",
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* )

View file

@ -3,18 +3,18 @@
namespace Wallabag\ApiBundle\Controller;
use Craue\ConfigBundle\Util\Config;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManagerInterface;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Translation\TranslatorInterface;
use Wallabag\ApiBundle\Entity\Client;
use Wallabag\UserBundle\Entity\User;
use Wallabag\UserBundle\Form\NewUserType;
@ -27,9 +27,10 @@ class UserRestController extends WallabagRestController
* @Operation(
* tags={"User"},
* summary="Retrieve current logged in user informations.",
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* description="Returned when successful",
* @Model(type=User::class, groups={"user_api"}))
* )
* )
*
@ -50,37 +51,48 @@ class UserRestController extends WallabagRestController
* @Operation(
* tags={"User"},
* summary="Register an user and create a client.",
* @SWG\Parameter(
* name="username",
* in="body",
* description="The user's username",
* required=true,
* @SWG\Schema(type="string")
* @OA\RequestBody(
* @OA\JsonContent(
* type="object",
* required={"username", "password", "email"},
* @OA\Property(
* property="username",
* description="The user's username",
* type="string",
* example="wallabag",
* ),
* @OA\Property(
* property="password",
* description="The user's password",
* type="string",
* example="hidden_value",
* ),
* @OA\Property(
* property="email",
* description="The user's email",
* type="string",
* example="wallabag@wallabag.io",
* ),
* @OA\Property(
* property="client_name",
* description="The client name (to be used by your app)",
* type="string",
* example="Fancy App",
* ),
* )
* ),
* @SWG\Parameter(
* name="password",
* in="body",
* description="The user's password",
* required=true,
* @SWG\Schema(type="string")
* @OA\Response(
* response="201",
* description="Returned when successful",
* @Model(type=User::class, groups={"user_api_with_client"})),
* ),
* @SWG\Parameter(
* name="email",
* in="body",
* description="The user's email",
* required=true,
* @SWG\Schema(type="string")
* @OA\Response(
* response="403",
* description="Server doesn't allow registrations"
* ),
* @SWG\Parameter(
* name="client_name",
* in="body",
* description="The client name (to be used by your app)",
* required=true,
* @SWG\Schema(type="string")
* ),
* @SWG\Response(
* response="200",
* description="Returned when successful"
* @OA\Response(
* response="400",
* description="Request is incorrectly formatted"
* )
* )
*
@ -90,17 +102,16 @@ class UserRestController extends WallabagRestController
*
* @return JsonResponse
*/
public function putUserAction(Request $request)
public function putUserAction(Request $request, Config $craueConfig, UserManagerInterface $userManager, EntityManagerInterface $entityManager, EventDispatcherInterface $eventDispatcher)
{
if (!$this->container->getParameter('fosuser_registration') || !$this->get(Config::class)->get('api_user_registration')) {
$json = $this->get(SerializerInterface::class)->serialize(['error' => "Server doesn't allow registrations"], 'json');
if (!$this->getParameter('fosuser_registration') || !$craueConfig->get('api_user_registration')) {
$json = $this->serializer->serialize(['error' => "Server doesn't allow registrations"], 'json');
return (new JsonResponse())
->setJson($json)
->setStatusCode(JsonResponse::HTTP_FORBIDDEN);
}
$userManager = $this->get(UserManagerInterface::class);
$user = $userManager->createUser();
\assert($user instanceof User);
// user will be disabled BY DEFAULT to avoid spamming account to be enabled
@ -140,7 +151,7 @@ class UserRestController extends WallabagRestController
$errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']);
}
$json = $this->get(SerializerInterface::class)->serialize(['error' => $errors], 'json');
$json = $this->serializer->serialize(['error' => $errors], 'json');
return (new JsonResponse())
->setJson($json)
@ -151,15 +162,14 @@ class UserRestController extends WallabagRestController
$client = new Client($user);
$client->setName($request->request->get('client_name', 'Default client'));
$this->get('doctrine')->getManager()->persist($client);
$entityManager->persist($client);
$user->addClient($client);
$userManager->updateUser($user);
// dispatch a created event so the associated config will be created
$event = new UserEvent($user, $request);
$this->get(EventDispatcherInterface::class)->dispatch(FOSUserEvents::USER_CREATED, $event);
$eventDispatcher->dispatch(new UserEvent($user, $request), FOSUserEvents::USER_CREATED);
return $this->sendUser($user, 'user_api_with_client', JsonResponse::HTTP_CREATED);
}
@ -174,7 +184,7 @@ class UserRestController extends WallabagRestController
*/
private function sendUser(User $user, $group = 'user_api', $status = JsonResponse::HTTP_OK)
{
$json = $this->get(SerializerInterface::class)->serialize(
$json = $this->serializer->serialize(
$user,
'json',
SerializationContext::create()->setGroups([$group])
@ -196,7 +206,7 @@ class UserRestController extends WallabagRestController
{
$translatedErrors = [];
foreach ($errors as $error) {
$translatedErrors[] = $this->get(TranslatorInterface::class)->trans($error);
$translatedErrors[] = $this->translator->trans($error);
}
return $translatedErrors;

View file

@ -2,29 +2,54 @@
namespace Wallabag\ApiBundle\Controller;
use Craue\ConfigBundle\Util\Config;
use Doctrine\ORM\EntityManagerInterface;
use FOS\RestBundle\Controller\AbstractFOSRestController;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Swagger\Annotations as SWG;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Wallabag\ApiBundle\Entity\ApplicationInfo;
use Wallabag\UserBundle\Entity\User;
class WallabagRestController extends AbstractFOSRestController
{
protected EntityManagerInterface $entityManager;
protected SerializerInterface $serializer;
protected AuthorizationCheckerInterface $authorizationChecker;
protected TokenStorageInterface $tokenStorage;
protected TranslatorInterface $translator;
public function __construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, AuthorizationCheckerInterface $authorizationChecker, TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
{
$this->entityManager = $entityManager;
$this->serializer = $serializer;
$this->authorizationChecker = $authorizationChecker;
$this->tokenStorage = $tokenStorage;
$this->translator = $translator;
}
/**
* Retrieve version number.
*
* @Operation(
* tags={"Informations"},
* tags={"Information"},
* summary="Retrieve version number.",
* @SWG\Response(
* @OA\Response(
* response="200",
* description="Returned when successful"
* description="Returned when successful",
* @OA\JsonContent(
* description="Version number of the application.",
* type="string",
* example="2.5.2",
* )
* )
* )
*
@ -36,21 +61,20 @@ class WallabagRestController extends AbstractFOSRestController
*/
public function getVersionAction()
{
$version = $this->container->getParameter('wallabag_core.version');
$json = $this->get(SerializerInterface::class)->serialize($version, 'json');
$version = $this->getParameter('wallabag_core.version');
$json = $this->serializer->serialize($version, 'json');
return (new JsonResponse())->setJson($json);
}
/**
* Retrieve information about the wallabag instance.
*
* @Operation(
* tags={"Informations"},
* summary="Retrieve information about the wallabag instance.",
* @SWG\Response(
* tags={"Information"},
* summary="Retrieve information about the running wallabag application.",
* @OA\Response(
* response="200",
* description="Returned when successful"
* description="Returned when successful",
* @Model(type=ApplicationInfo::class),
* )
* )
*
@ -58,20 +82,19 @@ class WallabagRestController extends AbstractFOSRestController
*
* @return JsonResponse
*/
public function getInfoAction()
public function getInfoAction(Config $craueConfig)
{
$info = [
'appname' => 'wallabag',
'version' => $this->container->getParameter('wallabag_core.version'),
'allowed_registration' => $this->container->getParameter('fosuser_registration'),
];
$info = new ApplicationInfo(
$this->getParameter('wallabag_core.version'),
$this->getParameter('fosuser_registration') && $craueConfig->get('api_user_registration'),
);
return (new JsonResponse())->setJson($this->get(SerializerInterface::class)->serialize($info, 'json'));
return (new JsonResponse())->setJson($this->serializer->serialize($info, 'json'));
}
protected function validateAuthentication()
{
if (false === $this->get(AuthorizationCheckerInterface::class)->isGranted('IS_AUTHENTICATED_FULLY')) {
if (false === $this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) {
throw new AccessDeniedException();
}
}
@ -84,8 +107,9 @@ class WallabagRestController extends AbstractFOSRestController
*/
protected function validateUserAccess($requestUserId)
{
$user = $this->get(TokenStorageInterface::class)->getToken()->getUser();
$user = $this->tokenStorage->getToken()->getUser();
\assert($user instanceof User);
if ($requestUserId !== $user->getId()) {
throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId());
}
@ -104,7 +128,7 @@ class WallabagRestController extends AbstractFOSRestController
$context = new SerializationContext();
$context->setSerializeNull(true);
$json = $this->get(SerializerInterface::class)->serialize($data, 'json', $context);
$json = $this->serializer->serialize($data, 'json', $context);
return (new JsonResponse())->setJson($json);
}

View file

@ -17,9 +17,6 @@ class Configuration implements ConfigurationInterface
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('wallabag_api');
return $treeBuilder;
return new TreeBuilder('wallabag_api');
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Wallabag\ApiBundle\Entity;
use OpenApi\Annotations as OA;
class ApplicationInfo
{
/**
* @var string
* @OA\Property(
* description="Name of the application.",
* type="string",
* example="wallabag",
* )
*/
public $appname;
/**
* @var string
* @OA\Property(
* description="Version number of the application.",
* type="string",
* example="2.5.2",
* )
*/
public $version;
/**
* @var bool
* @OA\Property(
* description="Indicates whether registration is allowed. See PUT /api/user.",
* type="boolean"
* )
*/
public $allowed_registration;
public function __construct($version, $allowed_registration)
{
$this->appname = 'wallabag';
$this->version = $version;
$this->allowed_registration = $allowed_registration;
}
}

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