1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-06-27 16:36:00 +00:00

Merge pull request #8122 from wallabag/modernize-code-base-with-rector

Modernize code base with Rector
This commit is contained in:
Yassine Guedidi 2025-04-07 10:03:12 +02:00 committed by GitHub
commit 63dc69d70f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
150 changed files with 1141 additions and 1858 deletions

View file

@ -1,8 +1,39 @@
<?php <?php
use BabDev\PagerfantaBundle\BabDevPagerfantaBundle;
use Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle;
use Craue\ConfigBundle\CraueConfigBundle;
use DAMA\DoctrineTestBundle\DAMADoctrineTestBundle;
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle;
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
use FOS\JsRoutingBundle\FOSJsRoutingBundle;
use FOS\OAuthServerBundle\FOSOAuthServerBundle;
use FOS\RestBundle\FOSRestBundle;
use FOS\UserBundle\FOSUserBundle;
use JMS\SerializerBundle\JMSSerializerBundle;
use KPhoen\RulerZBundle\KPhoenRulerZBundle;
use Nelmio\ApiDocBundle\NelmioApiDocBundle;
use Nelmio\CorsBundle\NelmioCorsBundle;
use OldSound\RabbitMqBundle\OldSoundRabbitMqBundle;
use Scheb\TwoFactorBundle\SchebTwoFactorBundle;
use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
use Sentry\SentryBundle\SentryBundle;
use Spiriit\Bundle\FormFilterBundle\SpiriitFormFilterBundle;
use Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle;
use Symfony\Bundle\DebugBundle\DebugBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\MakerBundle\MakerBundle;
use Symfony\Bundle\MonologBundle\MonologBundle;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
use Symfony\Bundle\WebProfilerBundle\WebProfilerBundle;
use Symfony\Bundle\WebServerBundle\WebServerBundle;
use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Kernel;
use Symfony\WebpackEncoreBundle\WebpackEncoreBundle;
use Twig\Extra\TwigExtraBundle\TwigExtraBundle;
use Wallabag\Import\ImportCompilerPass; use Wallabag\Import\ImportCompilerPass;
class AppKernel extends Kernel class AppKernel extends Kernel
@ -10,45 +41,45 @@ class AppKernel extends Kernel
public function registerBundles() public function registerBundles()
{ {
$bundles = [ $bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(), new SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(), new TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(), new MonologBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), new DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new SensioFrameworkExtraBundle(),
new FOS\RestBundle\FOSRestBundle(), new FOSRestBundle(),
new FOS\UserBundle\FOSUserBundle(), new FOSUserBundle(),
new JMS\SerializerBundle\JMSSerializerBundle(), new JMSSerializerBundle(),
new Nelmio\ApiDocBundle\NelmioApiDocBundle(), new NelmioApiDocBundle(),
new Nelmio\CorsBundle\NelmioCorsBundle(), new NelmioCorsBundle(),
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), new BazingaHateoasBundle(),
new Spiriit\Bundle\FormFilterBundle\SpiriitFormFilterBundle(), new SpiriitFormFilterBundle(),
new FOS\OAuthServerBundle\FOSOAuthServerBundle(), new FOSOAuthServerBundle(),
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(), new StofDoctrineExtensionsBundle(),
new Scheb\TwoFactorBundle\SchebTwoFactorBundle(), new SchebTwoFactorBundle(),
new KPhoen\RulerZBundle\KPhoenRulerZBundle(), new KPhoenRulerZBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(), new DoctrineMigrationsBundle(),
new Craue\ConfigBundle\CraueConfigBundle(), new CraueConfigBundle(),
new BabDev\PagerfantaBundle\BabDevPagerfantaBundle(), new BabDevPagerfantaBundle(),
new FOS\JsRoutingBundle\FOSJsRoutingBundle(), new FOSJsRoutingBundle(),
new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(), new OldSoundRabbitMqBundle(),
new Sentry\SentryBundle\SentryBundle(), new SentryBundle(),
new Twig\Extra\TwigExtraBundle\TwigExtraBundle(), new TwigExtraBundle(),
new Symfony\WebpackEncoreBundle\WebpackEncoreBundle(), new WebpackEncoreBundle(),
]; ];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); $bundles[] = new DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); $bundles[] = new WebProfilerBundle();
$bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); $bundles[] = new DoctrineFixturesBundle();
if ('test' === $this->getEnvironment()) { if ('test' === $this->getEnvironment()) {
$bundles[] = new DAMA\DoctrineTestBundle\DAMADoctrineTestBundle(); $bundles[] = new DAMADoctrineTestBundle();
} }
if ('dev' === $this->getEnvironment()) { if ('dev' === $this->getEnvironment()) {
$bundles[] = new Symfony\Bundle\MakerBundle\MakerBundle(); $bundles[] = new MakerBundle();
$bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle(); $bundles[] = new WebServerBundle();
} }
} }
@ -69,13 +100,13 @@ class AppKernel extends Kernel
{ {
$loader->load($this->getProjectDir() . '/app/config/config_' . $this->getEnvironment() . '.yml'); $loader->load($this->getProjectDir() . '/app/config/config_' . $this->getEnvironment() . '.yml');
$loader->load(function (ContainerBuilder $container) { $loader->load(function (ContainerBuilder $container): void {
// $container->setParameter('container.autowiring.strict_mode', true); // $container->setParameter('container.autowiring.strict_mode', true);
// $container->setParameter('container.dumper.inline_class_loader', true); // $container->setParameter('container.dumper.inline_class_loader', true);
$container->addObjectResource($this); $container->addObjectResource($this);
}); });
$loader->load(function (ContainerBuilder $container) { $loader->load(function (ContainerBuilder $container): void {
$this->processDatabaseParameters($container); $this->processDatabaseParameters($container);
$this->defineRedisUrlEnvVar($container); $this->defineRedisUrlEnvVar($container);
$this->defineRabbitMqUrlEnvVar($container); $this->defineRabbitMqUrlEnvVar($container);
@ -89,19 +120,12 @@ class AppKernel extends Kernel
private function processDatabaseParameters(ContainerBuilder $container) private function processDatabaseParameters(ContainerBuilder $container)
{ {
switch ($container->getParameter('database_driver')) { $scheme = match ($container->getParameter('database_driver')) {
case 'pdo_mysql': 'pdo_mysql' => 'mysql',
$scheme = 'mysql'; 'pdo_pgsql' => 'pgsql',
break; 'pdo_sqlite' => 'sqlite',
case 'pdo_pgsql': default => throw new RuntimeException('Unsupported database driver: ' . $container->getParameter('database_driver')),
$scheme = 'pgsql'; };
break;
case 'pdo_sqlite':
$scheme = 'sqlite';
break;
default:
throw new RuntimeException('Unsupported database driver: ' . $container->getParameter('database_driver'));
}
$container->setParameter('database_scheme', $scheme); $container->setParameter('database_scheme', $scheme);

View file

@ -37,11 +37,11 @@ $config
'phpstan/phpstan-symfony', 'phpstan/phpstan-symfony',
'psr/http-client', 'psr/http-client',
'psr/http-factory', 'psr/http-factory',
'rector/rector',
'scheb/2fa-trusted-device', 'scheb/2fa-trusted-device',
'shipmonk/composer-dependency-analyser', 'shipmonk/composer-dependency-analyser',
'symfony/asset', 'symfony/asset',
'symfony/css-selector', 'symfony/css-selector',
'symfony/doctrine-bridge',
'symfony/google-mailer', 'symfony/google-mailer',
'symfony/intl', 'symfony/intl',
'symfony/phpunit-bridge', 'symfony/phpunit-bridge',
@ -62,6 +62,9 @@ $config
'symfony/web-profiler-bundle', 'symfony/web-profiler-bundle',
'symfony/web-server-bundle', 'symfony/web-server-bundle',
], [ErrorType::DEV_DEPENDENCY_IN_PROD]) ], [ErrorType::DEV_DEPENDENCY_IN_PROD])
->ignoreErrorsOnPackages([
'gedmo/doctrine-extensions',
], [ErrorType::SHADOW_DEPENDENCY])
; ;
return $config; return $config;

View file

@ -173,6 +173,7 @@
"phpstan/phpstan-phpunit": "^1.4.2", "phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-symfony": "^1.4.13", "phpstan/phpstan-symfony": "^1.4.13",
"phpunit/phpunit": "^9.6.22", "phpunit/phpunit": "^9.6.22",
"rector/rector": "^1.2",
"shipmonk/composer-dependency-analyser": "^1.8.2", "shipmonk/composer-dependency-analyser": "^1.8.2",
"symfony/css-selector": "^5.4.45", "symfony/css-selector": "^5.4.45",
"symfony/debug-bundle": "^5.4.45", "symfony/debug-bundle": "^5.4.45",

61
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "df71f834528625c49553a128ca93e4aa", "content-hash": "00b8f95df6ec0572c06ad6f34847405c",
"packages": [ "packages": [
{ {
"name": "babdev/pagerfanta-bundle", "name": "babdev/pagerfanta-bundle",
@ -17856,6 +17856,65 @@
], ],
"time": "2024-06-11T12:45:25+00:00" "time": "2024-06-11T12:45:25+00:00"
}, },
{
"name": "rector/rector",
"version": "1.2.10",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "40f9cf38c05296bd32f444121336a521a293fa61"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61",
"reference": "40f9cf38c05296bd32f444121336a521a293fa61",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0",
"phpstan/phpstan": "^1.12.5"
},
"conflict": {
"rector/rector-doctrine": "*",
"rector/rector-downgrade-php": "*",
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*"
},
"suggest": {
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
},
"bin": [
"bin/rector"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
"keywords": [
"automation",
"dev",
"migration",
"refactoring"
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/1.2.10"
},
"funding": [
{
"url": "https://github.com/tomasvotruba",
"type": "github"
}
],
"time": "2024-11-08T13:59:10+00:00"
},
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
"version": "1.0.2", "version": "1.0.2",

View file

@ -8,11 +8,9 @@ use Wallabag\Entity\IgnoreOriginInstanceRule;
class IgnoreOriginInstanceRuleFixtures extends Fixture class IgnoreOriginInstanceRuleFixtures extends Fixture
{ {
private array $defaultIgnoreOriginInstanceRules; public function __construct(
private readonly array $defaultIgnoreOriginInstanceRules,
public function __construct(array $defaultIgnoreOriginInstanceRules) ) {
{
$this->defaultIgnoreOriginInstanceRules = $defaultIgnoreOriginInstanceRules;
} }
public function load(ObjectManager $manager): void public function load(ObjectManager $manager): void

View file

@ -8,11 +8,9 @@ use Wallabag\Entity\InternalSetting;
class InternalSettingFixtures extends Fixture class InternalSettingFixtures extends Fixture
{ {
private array $defaultInternalSettings; public function __construct(
private readonly array $defaultInternalSettings,
public function __construct(array $defaultInternalSettings) ) {
{
$this->defaultInternalSettings = $defaultInternalSettings;
} }
public function load(ObjectManager $manager): void public function load(ObjectManager $manager): void

View file

@ -11,11 +11,9 @@ use Wallabag\Helper\CryptoProxy;
class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface
{ {
private CryptoProxy $cryptoProxy; public function __construct(
private readonly CryptoProxy $cryptoProxy,
public function __construct(CryptoProxy $cryptoProxy) ) {
{
$this->cryptoProxy = $cryptoProxy;
} }
public function load(ObjectManager $manager): void public function load(ObjectManager $manager): void

28
rector.php Normal file
View file

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/app',
__DIR__ . '/fixtures',
__DIR__ . '/src',
__DIR__ . '/tests',
__DIR__ . '/web',
])
->withRootFiles()
->withImportNames(importShortClasses: false)
->withAttributesSets(symfony: true, doctrine: true, gedmo: true, jms: true, sensiolabs: true)
->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [
'inline_public' => true,
])
->withSkip([
ClassPropertyAssignToConstructorPromotionRector::class => [
__DIR__ . '/src/Entity/*',
],
])
->withPhpSets()
->withTypeCoverageLevel(0);

View file

@ -16,14 +16,10 @@ class CleanDownloadedImagesCommand extends Command
protected static $defaultName = 'wallabag:clean-downloaded-images'; protected static $defaultName = 'wallabag:clean-downloaded-images';
protected static $defaultDescription = 'Cleans downloaded images which are no more associated to an entry'; protected static $defaultDescription = 'Cleans downloaded images which are no more associated to an entry';
private EntryRepository $entryRepository; public function __construct(
private DownloadImages $downloadImages; private readonly EntryRepository $entryRepository,
private readonly DownloadImages $downloadImages,
public function __construct(EntryRepository $entryRepository, DownloadImages $downloadImages) ) {
{
$this->entryRepository = $entryRepository;
$this->downloadImages = $downloadImages;
parent::__construct(); parent::__construct();
} }

View file

@ -21,16 +21,12 @@ class CleanDuplicatesCommand extends Command
protected SymfonyStyle $io; protected SymfonyStyle $io;
protected int $duplicates = 0; protected int $duplicates = 0;
private EntityManagerInterface $entityManager;
private EntryRepository $entryRepository;
private UserRepository $userRepository;
public function __construct(EntityManagerInterface $entityManager, EntryRepository $entryRepository, UserRepository $userRepository)
{
$this->entityManager = $entityManager;
$this->entryRepository = $entryRepository;
$this->userRepository = $userRepository;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EntryRepository $entryRepository,
private readonly UserRepository $userRepository,
) {
parent::__construct(); parent::__construct();
} }
@ -55,7 +51,7 @@ class CleanDuplicatesCommand extends Command
try { try {
$user = $this->getUser($username); $user = $this->getUser($username);
$this->cleanDuplicates($user); $this->cleanDuplicates($user);
} catch (NoResultException $e) { } catch (NoResultException) {
$this->io->error(\sprintf('User "%s" not found.', $username)); $this->io->error(\sprintf('User "%s" not found.', $username));
return 1; return 1;
@ -104,8 +100,8 @@ class CleanDuplicatesCommand extends Command
private function similarUrl($url) private function similarUrl($url)
{ {
if (\in_array(substr($url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls if (\in_array(substr((string) $url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls
return substr($url, 0, \strlen($url)); return substr((string) $url, 0, \strlen((string) $url));
} }
return $url; return $url;

View file

@ -17,18 +17,12 @@ class ExportCommand extends Command
protected static $defaultName = 'wallabag:export'; protected static $defaultName = 'wallabag:export';
protected static $defaultDescription = 'Export all entries for an user'; protected static $defaultDescription = 'Export all entries for an user';
private EntryRepository $entryRepository; public function __construct(
private UserRepository $userRepository; private readonly EntryRepository $entryRepository,
private EntriesExport $entriesExport; private readonly UserRepository $userRepository,
private string $projectDir; private readonly EntriesExport $entriesExport,
private readonly string $projectDir,
public function __construct(EntryRepository $entryRepository, UserRepository $userRepository, EntriesExport $entriesExport, string $projectDir) ) {
{
$this->entryRepository = $entryRepository;
$this->userRepository = $userRepository;
$this->entriesExport = $entriesExport;
$this->projectDir = $projectDir;
parent::__construct(); parent::__construct();
} }

View file

@ -19,16 +19,12 @@ class GenerateUrlHashesCommand extends Command
protected static $defaultDescription = 'Generates hashed urls for each entry'; protected static $defaultDescription = 'Generates hashed urls for each entry';
protected OutputInterface $output; protected OutputInterface $output;
private EntityManagerInterface $entityManager;
private EntryRepository $entryRepository;
private UserRepository $userRepository;
public function __construct(EntityManagerInterface $entityManager, EntryRepository $entryRepository, UserRepository $userRepository)
{
$this->entityManager = $entityManager;
$this->entryRepository = $entryRepository;
$this->userRepository = $userRepository;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EntryRepository $entryRepository,
private readonly UserRepository $userRepository,
) {
parent::__construct(); parent::__construct();
} }
@ -49,7 +45,7 @@ class GenerateUrlHashesCommand extends Command
try { try {
$user = $this->getUser($username); $user = $this->getUser($username);
$this->generateHashedUrls($user); $this->generateHashedUrls($user);
} catch (NoResultException $e) { } catch (NoResultException) {
$output->writeln(\sprintf('<error>User "%s" not found.</error>', $username)); $output->writeln(\sprintf('<error>User "%s" not found.</error>', $username));
return 1; return 1;

View file

@ -33,55 +33,23 @@ class ImportCommand extends Command
protected static $defaultName = 'wallabag:import'; protected static $defaultName = 'wallabag:import';
protected static $defaultDescription = 'Import entries from a JSON export'; protected static $defaultDescription = 'Import entries from a JSON export';
private EntityManagerInterface $entityManager;
private TokenStorageInterface $tokenStorage;
private UserRepository $userRepository;
private WallabagV2Import $wallabagV2Import;
private FirefoxImport $firefoxImport;
private ChromeImport $chromeImport;
private ReadabilityImport $readabilityImport;
private InstapaperImport $instapaperImport;
private PinboardImport $pinboardImport;
private DeliciousImport $deliciousImport;
private OmnivoreImport $omnivoreImport;
private WallabagV1Import $wallabagV1Import;
private ElcuratorImport $elcuratorImport;
private ShaarliImport $shaarliImport;
private PocketHtmlImport $pocketHtmlImport;
public function __construct( public function __construct(
EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
TokenStorageInterface $tokenStorage, private readonly TokenStorageInterface $tokenStorage,
UserRepository $userRepository, private readonly UserRepository $userRepository,
WallabagV2Import $wallabagV2Import, private readonly WallabagV2Import $wallabagV2Import,
FirefoxImport $firefoxImport, private readonly FirefoxImport $firefoxImport,
ChromeImport $chromeImport, private readonly ChromeImport $chromeImport,
ReadabilityImport $readabilityImport, private readonly ReadabilityImport $readabilityImport,
InstapaperImport $instapaperImport, private readonly InstapaperImport $instapaperImport,
PinboardImport $pinboardImport, private readonly PinboardImport $pinboardImport,
DeliciousImport $deliciousImport, private readonly DeliciousImport $deliciousImport,
WallabagV1Import $wallabagV1Import, private readonly WallabagV1Import $wallabagV1Import,
ElcuratorImport $elcuratorImport, private readonly ElcuratorImport $elcuratorImport,
ShaarliImport $shaarliImport, private readonly ShaarliImport $shaarliImport,
PocketHtmlImport $pocketHtmlImport, private readonly PocketHtmlImport $pocketHtmlImport,
OmnivoreImport $omnivoreImport, private readonly OmnivoreImport $omnivoreImport,
) { ) {
$this->entityManager = $entityManager;
$this->tokenStorage = $tokenStorage;
$this->userRepository = $userRepository;
$this->wallabagV2Import = $wallabagV2Import;
$this->firefoxImport = $firefoxImport;
$this->chromeImport = $chromeImport;
$this->readabilityImport = $readabilityImport;
$this->instapaperImport = $instapaperImport;
$this->pinboardImport = $pinboardImport;
$this->deliciousImport = $deliciousImport;
$this->omnivoreImport = $omnivoreImport;
$this->wallabagV1Import = $wallabagV1Import;
$this->elcuratorImport = $elcuratorImport;
$this->shaarliImport = $shaarliImport;
$this->pocketHtmlImport = $pocketHtmlImport;
parent::__construct(); parent::__construct();
} }
@ -107,9 +75,7 @@ class ImportCommand extends Command
// Turning off doctrine default logs queries for saving memory // Turning off doctrine default logs queries for saving memory
$middlewares = $this->entityManager->getConnection()->getConfiguration()->getMiddlewares(); $middlewares = $this->entityManager->getConnection()->getConfiguration()->getMiddlewares();
$middlewaresWithoutLogging = array_filter($middlewares, function (Middleware $middleware) { $middlewaresWithoutLogging = array_filter($middlewares, fn (Middleware $middleware) => !$middleware instanceof LoggingMiddleware);
return !$middleware instanceof LoggingMiddleware;
});
$this->entityManager->getConnection()->getConfiguration()->setMiddlewares($middlewaresWithoutLogging); $this->entityManager->getConnection()->getConfiguration()->setMiddlewares($middlewaresWithoutLogging);
if ($input->getOption('useUserId')) { if ($input->getOption('useUserId')) {
@ -131,43 +97,20 @@ class ImportCommand extends Command
$this->tokenStorage->setToken($token); $this->tokenStorage->setToken($token);
$user = $this->tokenStorage->getToken()->getUser(); $user = $this->tokenStorage->getToken()->getUser();
switch ($input->getOption('importer')) { $import = match ($input->getOption('importer')) {
case 'v2': 'v2' => $this->wallabagV2Import,
$import = $this->wallabagV2Import; 'firefox' => $this->firefoxImport,
break; 'chrome' => $this->chromeImport,
case 'firefox': 'readability' => $this->readabilityImport,
$import = $this->firefoxImport; 'instapaper' => $this->instapaperImport,
break; 'pinboard' => $this->pinboardImport,
case 'chrome': 'delicious' => $this->deliciousImport,
$import = $this->chromeImport; 'elcurator' => $this->elcuratorImport,
break; 'shaarli' => $this->shaarliImport,
case 'readability': 'pocket' => $this->pocketHtmlImport,
$import = $this->readabilityImport; 'omnivore' => $this->omnivoreImport,
break; default => $this->wallabagV1Import,
case 'instapaper': };
$import = $this->instapaperImport;
break;
case 'pinboard':
$import = $this->pinboardImport;
break;
case 'delicious':
$import = $this->deliciousImport;
break;
case 'elcurator':
$import = $this->elcuratorImport;
break;
case 'shaarli':
$import = $this->shaarliImport;
break;
case 'pocket':
$import = $this->pocketHtmlImport;
break;
case 'omnivore':
$import = $this->omnivoreImport;
break;
default:
$import = $this->wallabagV1Import;
}
$import->setMarkAsRead($input->getOption('markAsRead')); $import->setMarkAsRead($input->getOption('markAsRead'));
$import->setDisableContentUpdate($input->getOption('disableContentUpdate')); $import->setDisableContentUpdate($input->getOption('disableContentUpdate'));

View file

@ -16,12 +16,9 @@ class RedisWorkerCommand extends Command
protected static $defaultName = 'wallabag:import:redis-worker'; protected static $defaultName = 'wallabag:import:redis-worker';
protected static $defaultDescription = 'Launch Redis worker'; protected static $defaultDescription = 'Launch Redis worker';
private $container; public function __construct(
private readonly ContainerInterface $container,
public function __construct(ContainerInterface $container) ) {
{
$this->container = $container;
parent::__construct(); parent::__construct();
} }

View file

@ -37,24 +37,15 @@ class InstallCommand extends Command
'curl_multi_init', 'curl_multi_init',
]; ];
private EntityManagerInterface $entityManager; public function __construct(
private EventDispatcherInterface $dispatcher; private readonly EntityManagerInterface $entityManager,
private UserManagerInterface $userManager; private readonly EventDispatcherInterface $dispatcher,
private TableMetadataStorageConfiguration $tableMetadataStorageConfiguration; private readonly UserManagerInterface $userManager,
private string $databaseDriver; private readonly TableMetadataStorageConfiguration $tableMetadataStorageConfiguration,
private array $defaultSettings; private readonly string $databaseDriver,
private array $defaultIgnoreOriginInstanceRules; private readonly array $defaultSettings,
private readonly array $defaultIgnoreOriginInstanceRules,
public function __construct(EntityManagerInterface $entityManager, EventDispatcherInterface $dispatcher, UserManagerInterface $userManager, TableMetadataStorageConfiguration $tableMetadataStorageConfiguration, string $databaseDriver, array $defaultSettings, array $defaultIgnoreOriginInstanceRules) ) {
{
$this->entityManager = $entityManager;
$this->dispatcher = $dispatcher;
$this->userManager = $userManager;
$this->tableMetadataStorageConfiguration = $tableMetadataStorageConfiguration;
$this->databaseDriver = $databaseDriver;
$this->defaultSettings = $defaultSettings;
$this->defaultIgnoreOriginInstanceRules = $defaultIgnoreOriginInstanceRules;
parent::__construct(); parent::__construct();
} }
@ -153,7 +144,7 @@ class InstallCommand extends Command
// return version should be like "PostgreSQL 9.5.4 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.38), 64-bit" // return version should be like "PostgreSQL 9.5.4 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.38), 64-bit"
$version = $conn->executeQuery('SELECT version();')->fetchOne(); $version = $conn->executeQuery('SELECT version();')->fetchOne();
preg_match('/PostgreSQL ([0-9\.]+)/i', $version, $matches); preg_match('/PostgreSQL ([0-9\.]+)/i', (string) $version, $matches);
if (isset($matches[1]) & version_compare($matches[1], '9.2.0', '<')) { if (isset($matches[1]) & version_compare($matches[1], '9.2.0', '<')) {
$fulfilled = false; $fulfilled = false;
@ -411,7 +402,7 @@ class InstallCommand extends Command
try { try {
return \in_array($databaseName, $schemaManager->listDatabases(), true); return \in_array($databaseName, $schemaManager->listDatabases(), true);
} catch (DriverException $e) { } catch (DriverException) {
// it means we weren't able to get database list, assume the database doesn't exist // it means we weren't able to get database list, assume the database doesn't exist
return false; return false;

View file

@ -15,12 +15,9 @@ class ListUserCommand extends Command
protected static $defaultName = 'wallabag:user:list'; protected static $defaultName = 'wallabag:user:list';
protected static $defaultDescription = 'List all users'; protected static $defaultDescription = 'List all users';
private UserRepository $userRepository; public function __construct(
private readonly UserRepository $userRepository,
public function __construct(UserRepository $userRepository) ) {
{
$this->userRepository = $userRepository;
parent::__construct(); parent::__construct();
} }

View file

@ -21,20 +21,13 @@ class ReloadEntryCommand extends Command
protected static $defaultName = 'wallabag:entry:reload'; protected static $defaultName = 'wallabag:entry:reload';
protected static $defaultDescription = 'Reload entries'; protected static $defaultDescription = 'Reload entries';
private EntryRepository $entryRepository; public function __construct(
private UserRepository $userRepository; private readonly EntryRepository $entryRepository,
private EntityManagerInterface $entityManager; private readonly UserRepository $userRepository,
private ContentProxy $contentProxy; private readonly EntityManagerInterface $entityManager,
private EventDispatcherInterface $dispatcher; private readonly ContentProxy $contentProxy,
private readonly EventDispatcherInterface $dispatcher,
public function __construct(EntryRepository $entryRepository, UserRepository $userRepository, EntityManagerInterface $entityManager, ContentProxy $contentProxy, EventDispatcherInterface $dispatcher) ) {
{
$this->entryRepository = $entryRepository;
$this->userRepository = $userRepository;
$this->entityManager = $entityManager;
$this->contentProxy = $contentProxy;
$this->dispatcher = $dispatcher;
parent::__construct(); parent::__construct();
} }
@ -62,7 +55,7 @@ class ReloadEntryCommand extends Command
$userId = $this->userRepository $userId = $this->userRepository
->findOneByUserName($username) ->findOneByUserName($username)
->getId(); ->getId();
} catch (NoResultException $e) { } catch (NoResultException) {
$io->error(\sprintf('User "%s" not found.', $username)); $io->error(\sprintf('User "%s" not found.', $username));
return 1; return 1;

View file

@ -17,12 +17,10 @@ class ShowUserCommand extends Command
protected static $defaultDescription = 'Show user details'; protected static $defaultDescription = 'Show user details';
protected SymfonyStyle $io; protected SymfonyStyle $io;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
public function __construct(
private readonly UserRepository $userRepository,
) {
parent::__construct(); parent::__construct();
} }
@ -46,7 +44,7 @@ class ShowUserCommand extends Command
try { try {
$user = $this->getUser($username); $user = $this->getUser($username);
$this->showUser($user); $this->showUser($user);
} catch (NoResultException $e) { } catch (NoResultException) {
$this->io->error(\sprintf('User "%s" not found.', $username)); $this->io->error(\sprintf('User "%s" not found.', $username));
return 1; return 1;

View file

@ -18,16 +18,11 @@ class TagAllCommand extends Command
protected static $defaultName = 'wallabag:tag:all'; protected static $defaultName = 'wallabag:tag:all';
protected static $defaultDescription = 'Tag all entries using the tagging rules.'; protected static $defaultDescription = 'Tag all entries using the tagging rules.';
private EntityManagerInterface $entityManager; public function __construct(
private RuleBasedTagger $ruleBasedTagger; private readonly EntityManagerInterface $entityManager,
private UserRepository $userRepository; private readonly RuleBasedTagger $ruleBasedTagger,
private readonly UserRepository $userRepository,
public function __construct(EntityManagerInterface $entityManager, RuleBasedTagger $ruleBasedTagger, UserRepository $userRepository) ) {
{
$this->entityManager = $entityManager;
$this->ruleBasedTagger = $ruleBasedTagger;
$this->userRepository = $userRepository;
parent::__construct(); parent::__construct();
} }
@ -48,7 +43,7 @@ class TagAllCommand extends Command
try { try {
$user = $this->getUser($input->getArgument('username')); $user = $this->getUser($input->getArgument('username'));
} catch (NoResultException $e) { } catch (NoResultException) {
$io->error(\sprintf('User "%s" not found.', $input->getArgument('username'))); $io->error(\sprintf('User "%s" not found.', $input->getArgument('username')));
return 1; return 1;

View file

@ -15,15 +15,11 @@ class UpdatePicturesPathCommand extends Command
protected static $defaultName = 'wallabag:update-pictures-path'; protected static $defaultName = 'wallabag:update-pictures-path';
protected static $defaultDescription = 'Update the path of the pictures for each entry when you changed your wallabag instance URL.'; protected static $defaultDescription = 'Update the path of the pictures for each entry when you changed your wallabag instance URL.';
private EntityManagerInterface $entityManager; public function __construct(
private EntryRepository $entryRepository; private readonly EntityManagerInterface $entityManager,
private string $wallabagUrl; private readonly EntryRepository $entryRepository,
private readonly string $wallabagUrl,
public function __construct(EntityManagerInterface $entityManager, EntryRepository $entryRepository, $wallabagUrl) ) {
{
$this->entityManager = $entityManager;
$this->entryRepository = $entryRepository;
$this->wallabagUrl = $wallabagUrl;
parent::__construct(); parent::__construct();
} }

View file

@ -7,25 +7,19 @@ use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Wallabag\Entity\Entry; use Wallabag\Entity\Entry;
use Wallabag\Entity\Tag;
use Wallabag\Event\EntrySavedEvent; use Wallabag\Event\EntrySavedEvent;
use Wallabag\Import\AbstractImport; use Wallabag\Import\AbstractImport;
use Wallabag\Repository\UserRepository; use Wallabag\Repository\UserRepository;
abstract class AbstractConsumer abstract class AbstractConsumer
{ {
protected $em; public function __construct(
protected $userRepository; protected EntityManagerInterface $em,
protected $import; protected UserRepository $userRepository,
protected $eventDispatcher; protected AbstractImport $import,
protected $logger; protected EventDispatcherInterface $eventDispatcher,
protected ?LoggerInterface $logger = null,
public function __construct(EntityManagerInterface $em, UserRepository $userRepository, AbstractImport $import, EventDispatcherInterface $eventDispatcher, ?LoggerInterface $logger = null) ) {
{
$this->em = $em;
$this->userRepository = $userRepository;
$this->import = $import;
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger ?: new NullLogger(); $this->logger = $logger ?: new NullLogger();
} }
@ -74,9 +68,7 @@ abstract class AbstractConsumer
// entry saved, dispatch event about it! // entry saved, dispatch event about it!
$this->eventDispatcher->dispatch(new EntrySavedEvent($entry), EntrySavedEvent::NAME); $this->eventDispatcher->dispatch(new EntrySavedEvent($entry), EntrySavedEvent::NAME);
// clear only affected entities $this->em->clear();
$this->em->clear(Entry::class);
$this->em->clear(Tag::class);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->warning('Unable to save entry', ['entry' => $storedEntry, 'exception' => $e]); $this->logger->warning('Unable to save entry', ['entry' => $storedEntry, 'exception' => $e]);

View file

@ -10,48 +10,21 @@ use OldSound\RabbitMqBundle\RabbitMq\Consumer;
*/ */
class RabbitMQConsumerTotalProxy class RabbitMQConsumerTotalProxy
{ {
private Consumer $pocketConsumer;
private Consumer $readabilityConsumer;
private Consumer $wallabagV1Consumer;
private Consumer $wallabagV2Consumer;
private Consumer $firefoxConsumer;
private Consumer $chromeConsumer;
private Consumer $instapaperConsumer;
private Consumer $pinboardConsumer;
private Consumer $deliciousConsumer;
private Consumer $elcuratorConsumer;
private Consumer $shaarliConsumer;
private Consumer $pocketHtmlConsumer;
private Consumer $omnivoreConsumer;
public function __construct( public function __construct(
Consumer $pocketConsumer, private readonly Consumer $pocketConsumer,
Consumer $readabilityConsumer, private readonly Consumer $readabilityConsumer,
Consumer $wallabagV1Consumer, private readonly Consumer $wallabagV1Consumer,
Consumer $wallabagV2Consumer, private readonly Consumer $wallabagV2Consumer,
Consumer $firefoxConsumer, private readonly Consumer $firefoxConsumer,
Consumer $chromeConsumer, private readonly Consumer $chromeConsumer,
Consumer $instapaperConsumer, private readonly Consumer $instapaperConsumer,
Consumer $pinboardConsumer, private readonly Consumer $pinboardConsumer,
Consumer $deliciousConsumer, private readonly Consumer $deliciousConsumer,
Consumer $elcuratorConsumer, private readonly Consumer $elcuratorConsumer,
Consumer $shaarliConsumer, private readonly Consumer $shaarliConsumer,
Consumer $pocketHtmlConsumer, private readonly Consumer $pocketHtmlConsumer,
Consumer $omnivoreConsumer, private readonly Consumer $omnivoreConsumer,
) { ) {
$this->pocketConsumer = $pocketConsumer;
$this->readabilityConsumer = $readabilityConsumer;
$this->wallabagV1Consumer = $wallabagV1Consumer;
$this->wallabagV2Consumer = $wallabagV2Consumer;
$this->firefoxConsumer = $firefoxConsumer;
$this->chromeConsumer = $chromeConsumer;
$this->instapaperConsumer = $instapaperConsumer;
$this->pinboardConsumer = $pinboardConsumer;
$this->deliciousConsumer = $deliciousConsumer;
$this->elcuratorConsumer = $elcuratorConsumer;
$this->shaarliConsumer = $shaarliConsumer;
$this->pocketHtmlConsumer = $pocketHtmlConsumer;
$this->omnivoreConsumer = $omnivoreConsumer;
} }
/** /**

View file

@ -20,15 +20,11 @@ use Wallabag\Repository\AnnotationRepository;
class AnnotationController extends AbstractFOSRestController class AnnotationController extends AbstractFOSRestController
{ {
protected EntityManagerInterface $entityManager; public function __construct(
protected SerializerInterface $serializer; protected EntityManagerInterface $entityManager,
protected FormFactoryInterface $formFactory; protected SerializerInterface $serializer,
protected FormFactoryInterface $formFactory,
public function __construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, FormFactoryInterface $formFactory) ) {
{
$this->entityManager = $entityManager;
$this->serializer = $serializer;
$this->formFactory = $formFactory;
} }
/** /**
@ -36,11 +32,10 @@ class AnnotationController extends AbstractFOSRestController
* *
* @see Api\WallabagRestController * @see Api\WallabagRestController
* *
* @Route("/annotations/{entry}.{_format}", name="annotations_get_annotations", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ANNOTATIONS", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/annotations/{entry}.{_format}', name: 'annotations_get_annotations', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ANNOTATIONS', subject: 'entry')]
public function getAnnotationsAction(Entry $entry, AnnotationRepository $annotationRepository) public function getAnnotationsAction(Entry $entry, AnnotationRepository $annotationRepository)
{ {
$annotationRows = $annotationRepository->findByEntryIdAndUserId($entry->getId(), $this->getUser()->getId()); $annotationRows = $annotationRepository->findByEntryIdAndUserId($entry->getId(), $this->getUser()->getId());
@ -58,11 +53,10 @@ class AnnotationController extends AbstractFOSRestController
* *
* @see Api\WallabagRestController * @see Api\WallabagRestController
* *
* @Route("/annotations/{entry}.{_format}", name="annotations_post_annotation", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_ANNOTATIONS", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/annotations/{entry}.{_format}', name: 'annotations_post_annotation', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_ANNOTATIONS', subject: 'entry')]
public function postAnnotationAction(Request $request, Entry $entry) public function postAnnotationAction(Request $request, Entry $entry)
{ {
$data = json_decode($request->getContent(), true); $data = json_decode($request->getContent(), true);
@ -93,11 +87,10 @@ class AnnotationController extends AbstractFOSRestController
* *
* @see Api\WallabagRestController * @see Api\WallabagRestController
* *
* @Route("/annotations/{annotation}.{_format}", name="annotations_put_annotation", methods={"PUT"}, defaults={"_format": "json"})
* @IsGranted("EDIT", subject="annotation")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/annotations/{annotation}.{_format}', name: 'annotations_put_annotation', methods: ['PUT'], defaults: ['_format' => 'json'])]
#[IsGranted('EDIT', subject: 'annotation')]
public function putAnnotationAction(Request $request, Annotation $annotation) public function putAnnotationAction(Request $request, Annotation $annotation)
{ {
try { try {
@ -129,11 +122,10 @@ class AnnotationController extends AbstractFOSRestController
* *
* @see Api\WallabagRestController * @see Api\WallabagRestController
* *
* @Route("/annotations/{annotation}.{_format}", name="annotations_delete_annotation", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE", subject="annotation")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/annotations/{annotation}.{_format}', name: 'annotations_delete_annotation', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE', subject: 'annotation')]
public function deleteAnnotationAction(Annotation $annotation) public function deleteAnnotationAction(Annotation $annotation)
{ {
try { try {

View file

@ -35,11 +35,10 @@ class AnnotationRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/annotations/{entry}.{_format}", name="api_get_annotations", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ANNOTATIONS", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/annotations/{entry}.{_format}', name: 'api_get_annotations', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ANNOTATIONS', subject: 'entry')]
public function getAnnotationsAction(Entry $entry) public function getAnnotationsAction(Entry $entry)
{ {
return $this->forward('Wallabag\Controller\AnnotationController::getAnnotationsAction', [ return $this->forward('Wallabag\Controller\AnnotationController::getAnnotationsAction', [
@ -100,11 +99,10 @@ class AnnotationRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/annotations/{entry}.{_format}", name="api_post_annotation", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_ANNOTATIONS", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/annotations/{entry}.{_format}', name: 'api_post_annotation', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_ANNOTATIONS', subject: 'entry')]
public function postAnnotationAction(Request $request, Entry $entry) public function postAnnotationAction(Request $request, Entry $entry)
{ {
return $this->forward('Wallabag\Controller\AnnotationController::postAnnotationAction', [ return $this->forward('Wallabag\Controller\AnnotationController::postAnnotationAction', [
@ -135,11 +133,10 @@ class AnnotationRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/annotations/{annotation}.{_format}", name="api_put_annotation", methods={"PUT"}, defaults={"_format": "json"})
* @IsGranted("EDIT", subject="annotation")
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/annotations/{annotation}.{_format}', name: 'api_put_annotation', methods: ['PUT'], defaults: ['_format' => 'json'])]
#[IsGranted('EDIT', subject: 'annotation')]
public function putAnnotationAction(Annotation $annotation, Request $request) public function putAnnotationAction(Annotation $annotation, Request $request)
{ {
return $this->forward('Wallabag\Controller\AnnotationController::putAnnotationAction', [ return $this->forward('Wallabag\Controller\AnnotationController::putAnnotationAction', [
@ -170,11 +167,10 @@ class AnnotationRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/annotations/{annotation}.{_format}", name="api_delete_annotation", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE", subject="annotation")
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/annotations/{annotation}.{_format}', name: 'api_delete_annotation', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE', subject: 'annotation')]
public function deleteAnnotationAction(Annotation $annotation) public function deleteAnnotationAction(Annotation $annotation)
{ {
return $this->forward('Wallabag\Controller\AnnotationController::deleteAnnotationAction', [ return $this->forward('Wallabag\Controller\AnnotationController::deleteAnnotationAction', [

View file

@ -23,10 +23,9 @@ class ConfigRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/config.{_format}", name="api_get_config", methods={"GET"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/config.{_format}', name: 'api_get_config', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getConfigAction(SerializerInterface $serializer) public function getConfigAction(SerializerInterface $serializer)
{ {
$this->validateAuthentication(); $this->validateAuthentication();

View file

@ -18,10 +18,9 @@ class DeveloperController extends AbstractController
/** /**
* List all clients and link to create a new one. * List all clients and link to create a new one.
* *
* @Route("/developer", name="developer", methods={"GET"})
*
* @return Response * @return Response
*/ */
#[Route(path: '/developer', name: 'developer', methods: ['GET'])]
public function indexAction(ClientRepository $repo) public function indexAction(ClientRepository $repo)
{ {
$clients = $repo->findByUser($this->getUser()->getId()); $clients = $repo->findByUser($this->getUser()->getId());
@ -34,10 +33,9 @@ class DeveloperController extends AbstractController
/** /**
* Create a client (an app). * Create a client (an app).
* *
* @Route("/developer/client/create", name="developer_create_client", methods={"GET", "POST"})
*
* @return Response * @return Response
*/ */
#[Route(path: '/developer/client/create', name: 'developer_create_client', methods: ['GET', 'POST'])]
public function createClientAction(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator) public function createClientAction(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{ {
$client = new Client($this->getUser()); $client = new Client($this->getUser());
@ -69,10 +67,9 @@ class DeveloperController extends AbstractController
/** /**
* Remove a client. * Remove a client.
* *
* @Route("/developer/client/delete/{id}", name="developer_delete_client", methods={"POST"}, requirements={"id" = "\d+"})
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/developer/client/delete/{id}', name: 'developer_delete_client', methods: ['POST'], requirements: ['id' => '\d+'])]
public function deleteClientAction(Request $request, Client $client, EntityManagerInterface $entityManager, TranslatorInterface $translator) public function deleteClientAction(Request $request, Client $client, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{ {
if (!$this->isCsrfTokenValid('delete-client', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('delete-client', $request->request->get('token'))) {
@ -97,10 +94,9 @@ class DeveloperController extends AbstractController
/** /**
* Display developer how to use an existing app. * Display developer how to use an existing app.
* *
* @Route("/developer/howto/first-app", name="developer_howto_firstapp", methods={"GET"})
*
* @return Response * @return Response
*/ */
#[Route(path: '/developer/howto/first-app', name: 'developer_howto_firstapp', methods: ['GET'])]
public function howtoFirstAppAction() public function howtoFirstAppAction()
{ {
return $this->render('Developer/howto_app.html.twig'); return $this->render('Developer/howto_app.html.twig');

View file

@ -85,11 +85,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/exists.{_format}", name="api_get_entries_exists", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ENTRIES")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/exists.{_format}', name: 'api_get_entries_exists', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ENTRIES')]
public function getEntriesExistsAction(Request $request, EntryRepository $entryRepository) public function getEntriesExistsAction(Request $request, EntryRepository $entryRepository)
{ {
$returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id'); $returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id');
@ -132,9 +131,7 @@ class EntryRestController extends WallabagRestController
} }
if (false === $returnId) { if (false === $returnId) {
$results = array_map(function ($v) { $results = array_map(fn ($v) => null !== $v, $results);
return null !== $v;
}, $results);
} }
$results = $this->replaceUrlHashes($results, $urlHashMap); $results = $this->replaceUrlHashes($results, $urlHashMap);
@ -299,11 +296,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries.{_format}", name="api_get_entries", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ENTRIES")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries.{_format}', name: 'api_get_entries', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ENTRIES')]
public function getEntriesAction(Request $request, EntryRepository $entryRepository) public function getEntriesAction(Request $request, EntryRepository $entryRepository)
{ {
$isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive'); $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
@ -390,11 +386,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}.{_format}", name="api_get_entry", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("VIEW", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}.{_format}', name: 'api_get_entry', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('VIEW', subject: 'entry')]
public function getEntryAction(Entry $entry) public function getEntryAction(Entry $entry)
{ {
return $this->sendResponse($entry); return $this->sendResponse($entry);
@ -432,11 +427,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}/export.{_format}", name="api_get_entry_export", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("VIEW", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/entries/{entry}/export.{_format}', name: 'api_get_entry_export', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('VIEW', subject: 'entry')]
public function getEntryExportAction(Entry $entry, Request $request, EntriesExport $entriesExport) public function getEntryExportAction(Entry $entry, Request $request, EntriesExport $entriesExport)
{ {
return $entriesExport return $entriesExport
@ -465,11 +459,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/list.{_format}", name="api_delete_entries_list", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE_ENTRIES")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/list.{_format}', name: 'api_delete_entries_list', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE_ENTRIES')]
public function deleteEntriesListAction(Request $request, EntryRepository $entryRepository, EventDispatcherInterface $eventDispatcher) public function deleteEntriesListAction(Request $request, EntryRepository $entryRepository, EventDispatcherInterface $eventDispatcher)
{ {
$urls = json_decode($request->query->get('urls', '[]')); $urls = json_decode($request->query->get('urls', '[]'));
@ -522,13 +515,12 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/lists.{_format}", name="api_post_entries_list", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_ENTRIES")
*
* @throws HttpException When limit is reached * @throws HttpException When limit is reached
* *
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/lists.{_format}', name: 'api_post_entries_list', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_ENTRIES')]
public function postEntriesListAction(Request $request, EntryRepository $entryRepository, EventDispatcherInterface $eventDispatcher, ContentProxy $contentProxy) public function postEntriesListAction(Request $request, EntryRepository $entryRepository, EventDispatcherInterface $eventDispatcher, ContentProxy $contentProxy)
{ {
$urls = json_decode($request->query->get('urls', '[]')); $urls = json_decode($request->query->get('urls', '[]'));
@ -706,11 +698,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries.{_format}", name="api_post_entries", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_ENTRIES")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries.{_format}', name: 'api_post_entries', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_ENTRIES')]
public function postEntriesAction( public function postEntriesAction(
Request $request, Request $request,
EntryRepository $entryRepository, EntryRepository $entryRepository,
@ -930,11 +921,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}.{_format}", name="api_patch_entries", methods={"PATCH"}, defaults={"_format": "json"})
* @IsGranted("EDIT", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}.{_format}', name: 'api_patch_entries', methods: ['PATCH'], defaults: ['_format' => 'json'])]
#[IsGranted('EDIT', subject: 'entry')]
public function patchEntriesAction(Entry $entry, Request $request, ContentProxy $contentProxy, LoggerInterface $logger, TagsAssigner $tagsAssigner, EventDispatcherInterface $eventDispatcher) public function patchEntriesAction(Entry $entry, Request $request, ContentProxy $contentProxy, LoggerInterface $logger, TagsAssigner $tagsAssigner, EventDispatcherInterface $eventDispatcher)
{ {
$data = $this->retrieveValueFromRequest($request); $data = $this->retrieveValueFromRequest($request);
@ -1045,11 +1035,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}/reload.{_format}", name="api_patch_entries_reload", methods={"PATCH"}, defaults={"_format": "json"})
* @IsGranted("RELOAD", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}/reload.{_format}', name: 'api_patch_entries_reload', methods: ['PATCH'], defaults: ['_format' => 'json'])]
#[IsGranted('RELOAD', subject: 'entry')]
public function patchEntriesReloadAction(Entry $entry, ContentProxy $contentProxy, LoggerInterface $logger, EventDispatcherInterface $eventDispatcher) public function patchEntriesReloadAction(Entry $entry, ContentProxy $contentProxy, LoggerInterface $logger, EventDispatcherInterface $eventDispatcher)
{ {
try { try {
@ -1100,11 +1089,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}.{_format}", name="api_delete_entries", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}.{_format}', name: 'api_delete_entries', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE', subject: 'entry')]
public function deleteEntriesAction(Entry $entry, Request $request, EventDispatcherInterface $eventDispatcher) public function deleteEntriesAction(Entry $entry, Request $request, EventDispatcherInterface $eventDispatcher)
{ {
$expect = $request->query->get('expect', 'entry'); $expect = $request->query->get('expect', 'entry');
@ -1152,11 +1140,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}/tags.{_format}", name="api_get_entries_tags", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_TAGS", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}/tags.{_format}', name: 'api_get_entries_tags', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_TAGS', subject: 'entry')]
public function getEntriesTagsAction(Entry $entry) public function getEntriesTagsAction(Entry $entry)
{ {
return $this->sendResponse($entry->getTags()); return $this->sendResponse($entry->getTags());
@ -1194,11 +1181,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}/tags.{_format}", name="api_post_entries_tags", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("TAG", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}/tags.{_format}', name: 'api_post_entries_tags', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('TAG', subject: 'entry')]
public function postEntriesTagsAction(Request $request, Entry $entry, TagsAssigner $tagsAssigner) public function postEntriesTagsAction(Request $request, Entry $entry, TagsAssigner $tagsAssigner)
{ {
$tags = $request->request->get('tags', ''); $tags = $request->request->get('tags', '');
@ -1244,11 +1230,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/{entry}/tags/{tag}.{_format}", name="api_delete_entries_tags", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("UNTAG", subject="entry")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/{entry}/tags/{tag}.{_format}', name: 'api_delete_entries_tags', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('UNTAG', subject: 'entry')]
public function deleteEntriesTagsAction(Entry $entry, Tag $tag) public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
{ {
$entry->removeTag($tag); $entry->removeTag($tag);
@ -1278,11 +1263,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/tags/list.{_format}", name="api_delete_entries_tags_list", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE_TAGS")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/tags/list.{_format}', name: 'api_delete_entries_tags_list', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE_TAGS')]
public function deleteEntriesTagsListAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository) public function deleteEntriesTagsListAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$list = json_decode($request->query->get('list', '[]')); $list = json_decode($request->query->get('list', '[]'));
@ -1344,11 +1328,10 @@ class EntryRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/entries/tags/lists.{_format}", name="api_post_entries_tags_list", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_TAGS")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/entries/tags/lists.{_format}', name: 'api_post_entries_tags_list', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_TAGS')]
public function postEntriesTagsListAction(Request $request, EntryRepository $entryRepository, TagsAssigner $tagsAssigner) public function postEntriesTagsListAction(Request $request, EntryRepository $entryRepository, TagsAssigner $tagsAssigner)
{ {
$list = json_decode($request->query->get('list', '[]')); $list = json_decode($request->query->get('list', '[]'));

View file

@ -55,11 +55,10 @@ class SearchRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/search.{_format}", name="api_get_search", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ENTRIES")
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/search.{_format}', name: 'api_get_search', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ENTRIES')]
public function getSearchAction(Request $request, EntryRepository $entryRepository) public function getSearchAction(Request $request, EntryRepository $entryRepository)
{ {
$term = $request->query->get('term'); $term = $request->query->get('term');

View file

@ -26,10 +26,9 @@ class TagRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/tags.{_format}", name="api_get_tags", methods={"GET"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/tags.{_format}', name: 'api_get_tags', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getTagsAction(TagRepository $tagRepository) public function getTagsAction(TagRepository $tagRepository)
{ {
$this->validateAuthentication(); $this->validateAuthentication();
@ -63,10 +62,9 @@ class TagRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/tag/label.{_format}", name="api_delete_tag_label", methods={"DELETE"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/tag/label.{_format}', name: 'api_delete_tag_label', methods: ['DELETE'], defaults: ['_format' => 'json'])]
public function deleteTagLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository) public function deleteTagLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$this->validateAuthentication(); $this->validateAuthentication();
@ -111,10 +109,9 @@ class TagRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/tags/label.{_format}", name="api_delete_tags_label", methods={"DELETE"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/tags/label.{_format}', name: 'api_delete_tags_label', methods: ['DELETE'], defaults: ['_format' => 'json'])]
public function deleteTagsLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository) public function deleteTagsLabelAction(Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$this->validateAuthentication(); $this->validateAuthentication();
@ -158,10 +155,9 @@ class TagRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/tags/{tag}.{_format}", name="api_delete_tag", methods={"DELETE"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/tags/{tag}.{_format}', name: 'api_delete_tag', methods: ['DELETE'], defaults: ['_format' => 'json'])]
public function deleteTagAction(Tag $tag, TagRepository $tagRepository, EntryRepository $entryRepository) public function deleteTagAction(Tag $tag, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$this->validateAuthentication(); $this->validateAuthentication();

View file

@ -23,10 +23,9 @@ class TaggingRuleRestController extends WallabagRestController
* ) * )
* ) * )
* *
* @Route("/api/taggingrule/export.{_format}", name="api_get_taggingrule_export", methods={"GET"}, defaults={"_format": "json"})
*
* @return Response * @return Response
*/ */
#[Route(path: '/api/taggingrule/export.{_format}', name: 'api_get_taggingrule_export', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getTaggingruleExportAction() public function getTaggingruleExportAction()
{ {
$this->validateAuthentication(); $this->validateAuthentication();

View file

@ -21,21 +21,14 @@ use Wallabag\Entity\User;
class WallabagRestController extends AbstractFOSRestController class WallabagRestController extends AbstractFOSRestController
{ {
protected EntityManagerInterface $entityManager; public function __construct(
protected SerializerInterface $serializer; protected EntityManagerInterface $entityManager,
protected AuthorizationCheckerInterface $authorizationChecker; protected SerializerInterface $serializer,
protected TokenStorageInterface $tokenStorage; protected AuthorizationCheckerInterface $authorizationChecker,
protected TranslatorInterface $translator; protected TokenStorageInterface $tokenStorage,
protected bool $registrationEnabled; protected TranslatorInterface $translator,
protected bool $registrationEnabled,
public function __construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, AuthorizationCheckerInterface $authorizationChecker, TokenStorageInterface $tokenStorage, TranslatorInterface $translator, bool $registrationEnabled) ) {
{
$this->entityManager = $entityManager;
$this->serializer = $serializer;
$this->authorizationChecker = $authorizationChecker;
$this->tokenStorage = $tokenStorage;
$this->translator = $translator;
$this->registrationEnabled = $registrationEnabled;
} }
/** /**
@ -57,10 +50,9 @@ class WallabagRestController extends AbstractFOSRestController
* *
* @deprecated Should use info endpoint instead * @deprecated Should use info endpoint instead
* *
* @Route("/api/version.{_format}", name="api_get_version", methods={"GET"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/version.{_format}', name: 'api_get_version', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getVersionAction() public function getVersionAction()
{ {
$version = $this->getParameter('wallabag.version'); $version = $this->getParameter('wallabag.version');
@ -80,10 +72,9 @@ class WallabagRestController extends AbstractFOSRestController
* ) * )
* ) * )
* *
* @Route("/api/info.{_format}", name="api_get_info", methods={"GET"}, defaults={"_format": "json"})
*
* @return JsonResponse * @return JsonResponse
*/ */
#[Route(path: '/api/info.{_format}', name: 'api_get_info', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getInfoAction(Config $craueConfig) public function getInfoAction(Config $craueConfig)
{ {
$info = new ApplicationInfo( $info = new ApplicationInfo(

View file

@ -44,39 +44,20 @@ use Wallabag\Tools\Utils;
class ConfigController extends AbstractController class ConfigController extends AbstractController
{ {
private EntityManagerInterface $entityManager;
private UserManagerInterface $userManager;
private EntryRepository $entryRepository;
private TagRepository $tagRepository;
private AnnotationRepository $annotationRepository;
private ConfigRepository $configRepository;
private EventDispatcherInterface $eventDispatcher;
private Redirect $redirectHelper;
public function __construct( public function __construct(
EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
UserManagerInterface $userManager, private readonly UserManagerInterface $userManager,
EntryRepository $entryRepository, private readonly EntryRepository $entryRepository,
TagRepository $tagRepository, private readonly TagRepository $tagRepository,
AnnotationRepository $annotationRepository, private readonly AnnotationRepository $annotationRepository,
ConfigRepository $configRepository, private readonly ConfigRepository $configRepository,
EventDispatcherInterface $eventDispatcher, private readonly EventDispatcherInterface $eventDispatcher,
Redirect $redirectHelper, private readonly Redirect $redirectHelper,
) { ) {
$this->entityManager = $entityManager;
$this->userManager = $userManager;
$this->entryRepository = $entryRepository;
$this->tagRepository = $tagRepository;
$this->annotationRepository = $annotationRepository;
$this->configRepository = $configRepository;
$this->eventDispatcher = $eventDispatcher;
$this->redirectHelper = $redirectHelper;
} }
/** #[Route(path: '/config', name: 'config', methods: ['GET', 'POST'])]
* @Route("/config", name="config", methods={"GET", "POST"}) #[IsGranted('EDIT_CONFIG')]
* @IsGranted("EDIT_CONFIG")
*/
public function indexAction(Request $request, Config $craueConfig, TaggingRuleRepository $taggingRuleRepository, IgnoreOriginUserRuleRepository $ignoreOriginUserRuleRepository, UserRepository $userRepository) public function indexAction(Request $request, Config $craueConfig, TaggingRuleRepository $taggingRuleRepository, IgnoreOriginUserRuleRepository $ignoreOriginUserRuleRepository, UserRepository $userRepository)
{ {
$config = $this->getConfig(); $config = $this->getConfig();
@ -266,10 +247,9 @@ class ConfigController extends AbstractController
/** /**
* Disable 2FA using email. * Disable 2FA using email.
*
* @Route("/config/otp/email/disable", name="disable_otp_email", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*/ */
#[Route(path: '/config/otp/email/disable', name: 'disable_otp_email', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function disableOtpEmailAction(Request $request) public function disableOtpEmailAction(Request $request)
{ {
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -292,10 +272,9 @@ class ConfigController extends AbstractController
/** /**
* Enable 2FA using email. * Enable 2FA using email.
*
* @Route("/config/otp/email", name="config_otp_email", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*/ */
#[Route(path: '/config/otp/email', name: 'config_otp_email', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function otpEmailAction(Request $request) public function otpEmailAction(Request $request)
{ {
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -321,10 +300,9 @@ class ConfigController extends AbstractController
/** /**
* Disable 2FA using OTP app. * Disable 2FA using OTP app.
*
* @Route("/config/otp/app/disable", name="disable_otp_app", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*/ */
#[Route(path: '/config/otp/app/disable', name: 'disable_otp_app', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function disableOtpAppAction(Request $request) public function disableOtpAppAction(Request $request)
{ {
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -349,10 +327,9 @@ class ConfigController extends AbstractController
/** /**
* Enable 2FA using OTP app, user will need to confirm the generated code from the app. * Enable 2FA using OTP app, user will need to confirm the generated code from the app.
*
* @Route("/config/otp/app", name="config_otp_app", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*/ */
#[Route(path: '/config/otp/app', name: 'config_otp_app', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function otpAppAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator) public function otpAppAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator)
{ {
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -367,9 +344,7 @@ class ConfigController extends AbstractController
$backupCodes = (new BackupCodes())->toArray(); $backupCodes = (new BackupCodes())->toArray();
$backupCodesHashed = array_map( $backupCodesHashed = array_map(
function ($backupCode) { fn ($backupCode) => password_hash((string) $backupCode, \PASSWORD_DEFAULT),
return password_hash($backupCode, \PASSWORD_DEFAULT);
},
$backupCodes $backupCodes
); );
@ -411,10 +386,9 @@ class ConfigController extends AbstractController
/** /**
* Validate OTP code. * Validate OTP code.
*
* @Route("/config/otp/app/check", name="config_otp_app_check", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*/ */
#[Route(path: '/config/otp/app/check', name: 'config_otp_app_check', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function otpAppCheckAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator) public function otpAppCheckAction(Request $request, GoogleAuthenticatorInterface $googleAuthenticator)
{ {
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -449,11 +423,10 @@ class ConfigController extends AbstractController
} }
/** /**
* @Route("/generate-token", name="generate_token", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return RedirectResponse|JsonResponse * @return RedirectResponse|JsonResponse
*/ */
#[Route(path: '/generate-token', name: 'generate_token', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function generateTokenAction(Request $request) public function generateTokenAction(Request $request)
{ {
$config = $this->getConfig(); $config = $this->getConfig();
@ -475,11 +448,10 @@ class ConfigController extends AbstractController
} }
/** /**
* @Route("/revoke-token", name="revoke_token", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return RedirectResponse|JsonResponse * @return RedirectResponse|JsonResponse
*/ */
#[Route(path: '/revoke-token', name: 'revoke_token', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function revokeTokenAction(Request $request) public function revokeTokenAction(Request $request)
{ {
$config = $this->getConfig(); $config = $this->getConfig();
@ -503,11 +475,10 @@ class ConfigController extends AbstractController
/** /**
* Deletes a tagging rule and redirect to the config homepage. * Deletes a tagging rule and redirect to the config homepage.
* *
* @Route("/tagging-rule/delete/{taggingRule}", name="delete_tagging_rule", methods={"GET"}, requirements={"taggingRule" = "\d+"})
* @IsGranted("DELETE", subject="taggingRule")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/tagging-rule/delete/{taggingRule}', name: 'delete_tagging_rule', methods: ['GET'], requirements: ['taggingRule' => '\d+'])]
#[IsGranted('DELETE', subject: 'taggingRule')]
public function deleteTaggingRuleAction(TaggingRule $taggingRule) public function deleteTaggingRuleAction(TaggingRule $taggingRule)
{ {
$this->entityManager->remove($taggingRule); $this->entityManager->remove($taggingRule);
@ -524,11 +495,10 @@ class ConfigController extends AbstractController
/** /**
* Edit a tagging rule. * Edit a tagging rule.
* *
* @Route("/tagging-rule/edit/{taggingRule}", name="edit_tagging_rule", methods={"GET"}, requirements={"taggingRule" = "\d+"})
* @IsGranted("EDIT", subject="taggingRule")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/tagging-rule/edit/{taggingRule}', name: 'edit_tagging_rule', methods: ['GET'], requirements: ['taggingRule' => '\d+'])]
#[IsGranted('EDIT', subject: 'taggingRule')]
public function editTaggingRuleAction(TaggingRule $taggingRule) public function editTaggingRuleAction(TaggingRule $taggingRule)
{ {
return $this->redirect($this->generateUrl('config') . '?tagging-rule=' . $taggingRule->getId() . '#set5'); return $this->redirect($this->generateUrl('config') . '?tagging-rule=' . $taggingRule->getId() . '#set5');
@ -537,11 +507,10 @@ class ConfigController extends AbstractController
/** /**
* Deletes an ignore origin rule and redirect to the config homepage. * Deletes an ignore origin rule and redirect to the config homepage.
* *
* @Route("/ignore-origin-user-rule/delete/{ignoreOriginUserRule}", name="delete_ignore_origin_rule", methods={"GET"}, requirements={"ignoreOriginUserRule" = "\d+"})
* @IsGranted("DELETE", subject="ignoreOriginUserRule")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/ignore-origin-user-rule/delete/{ignoreOriginUserRule}', name: 'delete_ignore_origin_rule', methods: ['GET'], requirements: ['ignoreOriginUserRule' => '\d+'])]
#[IsGranted('DELETE', subject: 'ignoreOriginUserRule')]
public function deleteIgnoreOriginRuleAction(IgnoreOriginUserRule $ignoreOriginUserRule) public function deleteIgnoreOriginRuleAction(IgnoreOriginUserRule $ignoreOriginUserRule)
{ {
$this->entityManager->remove($ignoreOriginUserRule); $this->entityManager->remove($ignoreOriginUserRule);
@ -558,11 +527,10 @@ class ConfigController extends AbstractController
/** /**
* Edit an ignore origin rule. * Edit an ignore origin rule.
* *
* @Route("/ignore-origin-user-rule/edit/{ignoreOriginUserRule}", name="edit_ignore_origin_rule", methods={"GET"}, requirements={"ignoreOriginUserRule" = "\d+"})
* @IsGranted("EDIT", subject="ignoreOriginUserRule")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/ignore-origin-user-rule/edit/{ignoreOriginUserRule}', name: 'edit_ignore_origin_rule', methods: ['GET'], requirements: ['ignoreOriginUserRule' => '\d+'])]
#[IsGranted('EDIT', subject: 'ignoreOriginUserRule')]
public function editIgnoreOriginRuleAction(IgnoreOriginUserRule $ignoreOriginUserRule) public function editIgnoreOriginRuleAction(IgnoreOriginUserRule $ignoreOriginUserRule)
{ {
return $this->redirect($this->generateUrl('config') . '?ignore-origin-user-rule=' . $ignoreOriginUserRule->getId() . '#set6'); return $this->redirect($this->generateUrl('config') . '?ignore-origin-user-rule=' . $ignoreOriginUserRule->getId() . '#set6');
@ -571,11 +539,10 @@ class ConfigController extends AbstractController
/** /**
* Remove all annotations OR tags OR entries for the current user. * Remove all annotations OR tags OR entries for the current user.
* *
* @Route("/reset/{type}", name="config_reset", methods={"POST"}, requirements={"id" = "annotations|tags|entries|tagging_rules"})
* @IsGranted("EDIT_CONFIG")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/reset/{type}', name: 'config_reset', methods: ['POST'], requirements: ['id' => 'annotations|tags|entries|tagging_rules'])]
#[IsGranted('EDIT_CONFIG')]
public function resetAction(Request $request, string $type, AnnotationRepository $annotationRepository, EntryRepository $entryRepository, TaggingRuleRepository $taggingRuleRepository) public function resetAction(Request $request, string $type, AnnotationRepository $annotationRepository, EntryRepository $entryRepository, TaggingRuleRepository $taggingRuleRepository)
{ {
if (!$this->isCsrfTokenValid('reset-area', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('reset-area', $request->request->get('token'))) {
@ -627,13 +594,11 @@ class ConfigController extends AbstractController
/** /**
* Delete account for current user. * Delete account for current user.
* *
* @Route("/account/delete", name="delete_account", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*
* @throws AccessDeniedHttpException * @throws AccessDeniedHttpException
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/account/delete', name: 'delete_account', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function deleteAccountAction(Request $request, UserRepository $userRepository, TokenStorageInterface $tokenStorage) public function deleteAccountAction(Request $request, UserRepository $userRepository, TokenStorageInterface $tokenStorage)
{ {
if (!$this->isCsrfTokenValid('delete-account', $request->request->get('token'))) { if (!$this->isCsrfTokenValid('delete-account', $request->request->get('token'))) {
@ -660,11 +625,10 @@ class ConfigController extends AbstractController
/** /**
* Switch view mode for current user. * Switch view mode for current user.
* *
* @Route("/config/view-mode", name="switch_view_mode", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/config/view-mode', name: 'switch_view_mode', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function changeViewModeAction(Request $request) public function changeViewModeAction(Request $request)
{ {
$user = $this->getUser(); $user = $this->getUser();
@ -683,11 +647,10 @@ class ConfigController extends AbstractController
* *
* @param string $language * @param string $language
* *
* @Route("/locale/{language}", name="changeLocale", methods={"GET"})
* @IsGranted("PUBLIC_ACCESS")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/locale/{language}', name: 'changeLocale', methods: ['GET'])]
#[IsGranted('PUBLIC_ACCESS')]
public function setLocaleAction(Request $request, ValidatorInterface $validator, $language = null) public function setLocaleAction(Request $request, ValidatorInterface $validator, $language = null)
{ {
$errors = $validator->validate($language, new LocaleConstraint(['canonicalize' => true])); $errors = $validator->validate($language, new LocaleConstraint(['canonicalize' => true]));
@ -702,11 +665,10 @@ class ConfigController extends AbstractController
/** /**
* Export tagging rules for the logged in user. * Export tagging rules for the logged in user.
* *
* @Route("/tagging-rule/export", name="export_tagging_rule", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tagging-rule/export', name: 'export_tagging_rule', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function exportTaggingRulesAction() public function exportTaggingRulesAction()
{ {
$data = SerializerBuilder::create()->build()->serialize( $data = SerializerBuilder::create()->build()->serialize(

View file

@ -33,33 +33,23 @@ use Wallabag\Repository\TagRepository;
class EntryController extends AbstractController class EntryController extends AbstractController
{ {
private EntityManagerInterface $entityManager; public function __construct(
private EventDispatcherInterface $eventDispatcher; private readonly EntityManagerInterface $entityManager,
private EntryRepository $entryRepository; private readonly EventDispatcherInterface $eventDispatcher,
private Redirect $redirectHelper; private readonly EntryRepository $entryRepository,
private PreparePagerForEntries $preparePagerForEntriesHelper; private readonly Redirect $redirectHelper,
private FilterBuilderUpdaterInterface $filterBuilderUpdater; private readonly PreparePagerForEntries $preparePagerForEntriesHelper,
private ContentProxy $contentProxy; private readonly FilterBuilderUpdaterInterface $filterBuilderUpdater,
private Security $security; private readonly ContentProxy $contentProxy,
private readonly Security $security,
public function __construct(EntityManagerInterface $entityManager, EventDispatcherInterface $eventDispatcher, EntryRepository $entryRepository, Redirect $redirectHelper, PreparePagerForEntries $preparePagerForEntriesHelper, FilterBuilderUpdaterInterface $filterBuilderUpdater, ContentProxy $contentProxy, Security $security) ) {
{
$this->entityManager = $entityManager;
$this->eventDispatcher = $eventDispatcher;
$this->entryRepository = $entryRepository;
$this->redirectHelper = $redirectHelper;
$this->preparePagerForEntriesHelper = $preparePagerForEntriesHelper;
$this->filterBuilderUpdater = $filterBuilderUpdater;
$this->contentProxy = $contentProxy;
$this->security = $security;
} }
/** /**
* @Route("/mass", name="mass_action", methods={"POST"})
* @IsGranted("EDIT_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/mass', name: 'mass_action', methods: ['POST'])]
#[IsGranted('EDIT_ENTRIES')]
public function massAction(Request $request, TagRepository $tagRepository) public function massAction(Request $request, TagRepository $tagRepository)
{ {
$values = $request->request->all(); $values = $request->request->all();
@ -76,7 +66,7 @@ class EntryController extends AbstractController
$action = 'tag'; $action = 'tag';
if (isset($values['tags'])) { if (isset($values['tags'])) {
$labels = array_filter(explode(',', $values['tags']), $labels = array_filter(explode(',', (string) $values['tags']),
function ($v) { function ($v) {
$v = trim($v); $v = trim($v);
@ -141,14 +131,12 @@ class EntryController extends AbstractController
/** /**
* @param int $page * @param int $page
* *
* @Route("/search/{page}", name="search", methods={"GET", "POST"}, defaults={"page" = 1})
* @IsGranted("LIST_ENTRIES")
*
* Default parameter for page is hardcoded (in duplication of the defaults from the Route) * Default parameter for page is hardcoded (in duplication of the defaults from the Route)
* because this controller is also called inside the layout template without any page as argument * because this controller is also called inside the layout template without any page as argument
*
* @return Response * @return Response
*/ */
#[Route(path: '/search/{page}', name: 'search', methods: ['GET', 'POST'], defaults: ['page' => 1])]
#[IsGranted('LIST_ENTRIES')]
public function searchFormAction(Request $request, $page = 1, $currentRoute = null) public function searchFormAction(Request $request, $page = 1, $currentRoute = null)
{ {
// fallback to retrieve currentRoute from query parameter instead of injected one (when using inside a template) // fallback to retrieve currentRoute from query parameter instead of injected one (when using inside a template)
@ -171,11 +159,10 @@ class EntryController extends AbstractController
} }
/** /**
* @Route("/new-entry", name="new_entry", methods={"GET", "POST"})
* @IsGranted("CREATE_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/new-entry', name: 'new_entry', methods: ['GET', 'POST'])]
#[IsGranted('CREATE_ENTRIES')]
public function addEntryFormAction(Request $request, TranslatorInterface $translator) public function addEntryFormAction(Request $request, TranslatorInterface $translator)
{ {
$entry = new Entry($this->getUser()); $entry = new Entry($this->getUser());
@ -215,11 +202,10 @@ class EntryController extends AbstractController
} }
/** /**
* @Route("/bookmarklet", name="bookmarklet", methods={"GET"})
* @IsGranted("CREATE_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/bookmarklet', name: 'bookmarklet', methods: ['GET'])]
#[IsGranted('CREATE_ENTRIES')]
public function addEntryViaBookmarkletAction(Request $request) public function addEntryViaBookmarkletAction(Request $request)
{ {
$entry = new Entry($this->getUser()); $entry = new Entry($this->getUser());
@ -239,11 +225,10 @@ class EntryController extends AbstractController
} }
/** /**
* @Route("/new", name="new", methods={"GET"})
* @IsGranted("CREATE_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/new', name: 'new', methods: ['GET'])]
#[IsGranted('CREATE_ENTRIES')]
public function addEntryAction() public function addEntryAction()
{ {
return $this->render('Entry/new.html.twig'); return $this->render('Entry/new.html.twig');
@ -252,11 +237,10 @@ class EntryController extends AbstractController
/** /**
* Edit an entry content. * Edit an entry content.
* *
* @Route("/edit/{id}", name="edit", methods={"GET", "POST"}, requirements={"id" = "\d+"})
* @IsGranted("EDIT", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/edit/{id}', name: 'edit', methods: ['GET', 'POST'], requirements: ['id' => '\d+'])]
#[IsGranted('EDIT', subject: 'entry')]
public function editEntryAction(Request $request, Entry $entry) public function editEntryAction(Request $request, Entry $entry)
{ {
$form = $this->createForm(EditEntryType::class, $entry); $form = $this->createForm(EditEntryType::class, $entry);
@ -285,11 +269,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/all/list/{page}", name="all", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/all/list/{page}', name: 'all', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showAllAction(Request $request, $page) public function showAllAction(Request $request, $page)
{ {
return $this->showEntries('all', $request, $page); return $this->showEntries('all', $request, $page);
@ -300,11 +283,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/unread/list/{page}", name="unread", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/unread/list/{page}', name: 'unread', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showUnreadAction(Request $request, $page) public function showUnreadAction(Request $request, $page)
{ {
// load the quickstart if no entry in database // load the quickstart if no entry in database
@ -320,11 +302,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/archive/list/{page}", name="archive", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/archive/list/{page}', name: 'archive', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showArchiveAction(Request $request, $page) public function showArchiveAction(Request $request, $page)
{ {
return $this->showEntries('archive', $request, $page); return $this->showEntries('archive', $request, $page);
@ -335,11 +316,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/starred/list/{page}", name="starred", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/starred/list/{page}', name: 'starred', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showStarredAction(Request $request, $page) public function showStarredAction(Request $request, $page)
{ {
return $this->showEntries('starred', $request, $page); return $this->showEntries('starred', $request, $page);
@ -350,11 +330,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/untagged/list/{page}", name="untagged", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/untagged/list/{page}', name: 'untagged', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showUntaggedEntriesAction(Request $request, $page) public function showUntaggedEntriesAction(Request $request, $page)
{ {
return $this->showEntries('untagged', $request, $page); return $this->showEntries('untagged', $request, $page);
@ -365,11 +344,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/annotated/list/{page}", name="annotated", methods={"GET"}, defaults={"page" = "1"})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/annotated/list/{page}', name: 'annotated', methods: ['GET'], defaults: ['page' => '1'])]
#[IsGranted('LIST_ENTRIES')]
public function showWithAnnotationsEntriesAction(Request $request, $page) public function showWithAnnotationsEntriesAction(Request $request, $page)
{ {
return $this->showEntries('annotated', $request, $page); return $this->showEntries('annotated', $request, $page);
@ -378,17 +356,16 @@ class EntryController extends AbstractController
/** /**
* Shows random entry depending on the given type. * Shows random entry depending on the given type.
* *
* @Route("/{type}/random", name="random_entry", methods={"GET"}, requirements={"type": "unread|starred|archive|untagged|annotated|all"})
* @IsGranted("LIST_ENTRIES")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/{type}/random', name: 'random_entry', methods: ['GET'], requirements: ['type' => 'unread|starred|archive|untagged|annotated|all'])]
#[IsGranted('LIST_ENTRIES')]
public function redirectRandomEntryAction(string $type = 'all') public function redirectRandomEntryAction(string $type = 'all')
{ {
try { try {
$entry = $this->entryRepository $entry = $this->entryRepository
->getRandomEntry($this->getUser()->getId(), $type); ->getRandomEntry($this->getUser()->getId(), $type);
} catch (NoResultException $e) { } catch (NoResultException) {
$this->addFlash('notice', 'flashes.entry.notice.no_random_entry'); $this->addFlash('notice', 'flashes.entry.notice.no_random_entry');
return $this->redirect($this->generateUrl($type)); return $this->redirect($this->generateUrl($type));
@ -400,11 +377,10 @@ class EntryController extends AbstractController
/** /**
* Shows entry content. * Shows entry content.
* *
* @Route("/view/{id}", name="view", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("VIEW", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/view/{id}', name: 'view', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('VIEW', subject: 'entry')]
public function viewAction(Entry $entry) public function viewAction(Entry $entry)
{ {
return $this->render( return $this->render(
@ -417,11 +393,10 @@ class EntryController extends AbstractController
* Reload an entry. * Reload an entry.
* Refetch content from the website and make it readable again. * Refetch content from the website and make it readable again.
* *
* @Route("/reload/{id}", name="reload_entry", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("RELOAD", subject="entry")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/reload/{id}', name: 'reload_entry', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('RELOAD', subject: 'entry')]
public function reloadAction(Entry $entry) public function reloadAction(Entry $entry)
{ {
$this->updateEntry($entry, 'entry_reloaded'); $this->updateEntry($entry, 'entry_reloaded');
@ -445,11 +420,10 @@ class EntryController extends AbstractController
/** /**
* Changes read status for an entry. * Changes read status for an entry.
* *
* @Route("/archive/{id}", name="archive_entry", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("ARCHIVE", subject="entry")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/archive/{id}', name: 'archive_entry', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('ARCHIVE', subject: 'entry')]
public function toggleArchiveAction(Request $request, Entry $entry) public function toggleArchiveAction(Request $request, Entry $entry)
{ {
$entry->toggleArchive(); $entry->toggleArchive();
@ -473,11 +447,10 @@ class EntryController extends AbstractController
/** /**
* Changes starred status for an entry. * Changes starred status for an entry.
* *
* @Route("/star/{id}", name="star_entry", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("STAR", subject="entry")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/star/{id}', name: 'star_entry', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('STAR', subject: 'entry')]
public function toggleStarAction(Request $request, Entry $entry) public function toggleStarAction(Request $request, Entry $entry)
{ {
$entry->toggleStar(); $entry->toggleStar();
@ -502,11 +475,10 @@ class EntryController extends AbstractController
/** /**
* Deletes entry and redirect to the homepage or the last viewed page. * Deletes entry and redirect to the homepage or the last viewed page.
* *
* @Route("/delete/{id}", name="delete_entry", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("DELETE", subject="entry")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/delete/{id}', name: 'delete_entry', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('DELETE', subject: 'entry')]
public function deleteEntryAction(Request $request, Entry $entry) public function deleteEntryAction(Request $request, Entry $entry)
{ {
// generates the view url for this entry to check for redirection later // generates the view url for this entry to check for redirection later
@ -539,11 +511,10 @@ class EntryController extends AbstractController
/** /**
* Get public URL for entry (and generate it if necessary). * Get public URL for entry (and generate it if necessary).
* *
* @Route("/share/{id}", name="share", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("SHARE", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/share/{id}', name: 'share', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('SHARE', subject: 'entry')]
public function shareAction(Entry $entry) public function shareAction(Entry $entry)
{ {
if (null === $entry->getUid()) { if (null === $entry->getUid()) {
@ -561,11 +532,10 @@ class EntryController extends AbstractController
/** /**
* Disable public sharing for an entry. * Disable public sharing for an entry.
* *
* @Route("/share/delete/{id}", name="delete_share", methods={"GET"}, requirements={"id" = "\d+"})
* @IsGranted("UNSHARE", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/share/delete/{id}', name: 'delete_share', methods: ['GET'], requirements: ['id' => '\d+'])]
#[IsGranted('UNSHARE', subject: 'entry')]
public function deleteShareAction(Entry $entry) public function deleteShareAction(Entry $entry)
{ {
$entry->cleanUid(); $entry->cleanUid();
@ -581,12 +551,11 @@ class EntryController extends AbstractController
/** /**
* Ability to view a content publicly. * Ability to view a content publicly.
* *
* @Route("/share/{uid}", name="share_entry", methods={"GET"}, requirements={"uid" = ".+"})
* @Cache(maxage="25200", smaxage="25200", public=true)
* @IsGranted("PUBLIC_ACCESS")
*
* @return Response * @return Response
*/ */
#[Route(path: '/share/{uid}', name: 'share_entry', methods: ['GET'], requirements: ['uid' => '.+'])]
#[Cache(maxage: 25200, smaxage: 25200, public: true)]
#[IsGranted('PUBLIC_ACCESS')]
public function shareEntryAction(Entry $entry, Config $craueConfig) public function shareEntryAction(Entry $entry, Config $craueConfig)
{ {
if (!$craueConfig->get('share_public')) { if (!$craueConfig->get('share_public')) {
@ -604,11 +573,10 @@ class EntryController extends AbstractController
* *
* @param int $page * @param int $page
* *
* @Route("/domain/{id}/{page}", name="same_domain", methods={"GET"}, requirements={"id" = "\d+"}, defaults={"page" = 1})
* @IsGranted("LIST_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/domain/{id}/{page}', name: 'same_domain', methods: ['GET'], requirements: ['id' => '\d+'], defaults: ['page' => 1])]
#[IsGranted('LIST_ENTRIES')]
public function getSameDomainEntries(Request $request, $page = 1) public function getSameDomainEntries(Request $request, $page = 1)
{ {
return $this->showEntries('same-domain', $request, $page); return $this->showEntries('same-domain', $request, $page);
@ -625,8 +593,8 @@ class EntryController extends AbstractController
*/ */
private function showEntries($type, Request $request, $page) private function showEntries($type, Request $request, $page)
{ {
$searchTerm = (isset($request->query->all('search_entry')['term']) ? trim($request->query->all('search_entry')['term']) : ''); $searchTerm = (isset($request->query->all('search_entry')['term']) ? trim((string) $request->query->all('search_entry')['term']) : '');
$currentRoute = (null !== $request->query->get('currentRoute') ? $request->query->get('currentRoute') : ''); $currentRoute = $request->query->get('currentRoute') ?? '';
$currentEntryId = $request->attributes->getInt('id'); $currentEntryId = $request->attributes->getInt('id');
$formOptions = []; $formOptions = [];
@ -679,7 +647,7 @@ class EntryController extends AbstractController
try { try {
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) { } catch (OutOfRangeCurrentPageException) {
if ($page > 1) { if ($page > 1) {
return $this->redirect($this->generateUrl($type, ['page' => $entries->getNbPages()]), 302); return $this->redirect($this->generateUrl($type, ['page' => $entries->getNbPages()]), 302);
} }
@ -708,7 +676,7 @@ class EntryController extends AbstractController
try { try {
$this->contentProxy->updateEntry($entry, $entry->getUrl()); $this->contentProxy->updateEntry($entry, $entry->getUrl());
} catch (\Exception $e) { } catch (\Exception) {
// $this->logger->error('Error while saving an entry', [ // $this->logger->error('Error while saving an entry', [
// 'exception' => $e, // 'exception' => $e,
// 'entry' => $entry, // 'entry' => $entry,

View file

@ -21,14 +21,10 @@ class ExportController extends AbstractController
/** /**
* Gets one entry content. * Gets one entry content.
* *
* @Route("/export/{entry}.{format}", name="export_entry", methods={"GET"}, requirements={
* "format": "epub|pdf|json|xml|txt|csv|md",
* "entry": "\d+"
* })
* @IsGranted("EXPORT", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/export/{entry}.{format}', name: 'export_entry', methods: ['GET'], requirements: ['format' => 'epub|pdf|json|xml|txt|csv|md', 'entry' => '\d+'])]
#[IsGranted('EXPORT', subject: 'entry')]
public function downloadEntryAction(Request $request, EntryRepository $entryRepository, EntriesExport $entriesExport, string $format, Entry $entry) public function downloadEntryAction(Request $request, EntryRepository $entryRepository, EntriesExport $entriesExport, string $format, Entry $entry)
{ {
try { try {
@ -45,14 +41,10 @@ class ExportController extends AbstractController
/** /**
* Export all entries for current user. * Export all entries for current user.
* *
* @Route("/export/{category}.{format}", name="export_entries", methods={"GET"}, requirements={
* "format": "epub|pdf|json|xml|txt|csv|md",
* "category": "all|unread|starred|archive|tag_entries|untagged|search|annotated|same_domain"
* })
* @IsGranted("EXPORT_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/export/{category}.{format}', name: 'export_entries', methods: ['GET'], requirements: ['format' => 'epub|pdf|json|xml|txt|csv|md', 'category' => 'all|unread|starred|archive|tag_entries|untagged|search|annotated|same_domain'])]
#[IsGranted('EXPORT_ENTRIES')]
public function downloadEntriesAction(Request $request, EntryRepository $entryRepository, TagRepository $tagRepository, EntriesExport $entriesExport, string $format, string $category, int $entry = 0) public function downloadEntriesAction(Request $request, EntryRepository $entryRepository, TagRepository $tagRepository, EntriesExport $entriesExport, string $format, string $category, int $entry = 0)
{ {
$method = ucfirst($category); $method = ucfirst($category);
@ -77,8 +69,8 @@ class ExportController extends AbstractController
$title = 'Tag ' . $tag->getLabel(); $title = 'Tag ' . $tag->getLabel();
} elseif ('search' === $category) { } elseif ('search' === $category) {
$searchTerm = (isset($request->query->all('search_entry')['term']) ? $request->query->all('search_entry')['term'] : ''); $searchTerm = $request->query->all('search_entry')['term'] ?? '';
$currentRoute = (null !== $request->query->get('currentRoute') ? $request->query->get('currentRoute') : ''); $currentRoute = $request->query->get('currentRoute') ?? '';
$entries = $entryRepository->getBuilderForSearchByUser( $entries = $entryRepository->getBuilderForSearchByUser(
$this->getUser()->getId(), $this->getUser()->getId(),

View file

@ -20,23 +20,19 @@ use Wallabag\Repository\EntryRepository;
class FeedController extends AbstractController class FeedController extends AbstractController
{ {
private EntryRepository $entryRepository; public function __construct(
private readonly EntryRepository $entryRepository,
public function __construct(EntryRepository $entryRepository) ) {
{
$this->entryRepository = $entryRepository;
} }
/** /**
* Shows unread entries for current user. * Shows unread entries for current user.
* *
* @Route("/feed/{username}/{token}/unread/{page}", name="unread_feed", methods={"GET"}, defaults={"page"=1, "_format"="xml"})
* @IsGranted("PUBLIC_ACCESS")
*
* @ParamConverter("user", class="Wallabag\Entity\User", converter="username_feed_token_converter")
*
* @return Response * @return Response
*/ */
#[Route(path: '/feed/{username}/{token}/unread/{page}', name: 'unread_feed', methods: ['GET'], defaults: ['page' => 1, '_format' => 'xml'])]
#[IsGranted('PUBLIC_ACCESS')]
#[ParamConverter('user', class: User::class, converter: 'username_feed_token_converter')]
public function showUnreadFeedAction(User $user, $page) public function showUnreadFeedAction(User $user, $page)
{ {
return $this->showEntries('unread', $user, $page); return $this->showEntries('unread', $user, $page);
@ -45,13 +41,11 @@ class FeedController extends AbstractController
/** /**
* Shows read entries for current user. * Shows read entries for current user.
* *
* @Route("/feed/{username}/{token}/archive/{page}", name="archive_feed", methods={"GET"}, defaults={"page"=1, "_format"="xml"})
* @IsGranted("PUBLIC_ACCESS")
*
* @ParamConverter("user", class="Wallabag\Entity\User", converter="username_feed_token_converter")
*
* @return Response * @return Response
*/ */
#[Route(path: '/feed/{username}/{token}/archive/{page}', name: 'archive_feed', methods: ['GET'], defaults: ['page' => 1, '_format' => 'xml'])]
#[IsGranted('PUBLIC_ACCESS')]
#[ParamConverter('user', class: User::class, converter: 'username_feed_token_converter')]
public function showArchiveFeedAction(User $user, $page) public function showArchiveFeedAction(User $user, $page)
{ {
return $this->showEntries('archive', $user, $page); return $this->showEntries('archive', $user, $page);
@ -60,13 +54,11 @@ class FeedController extends AbstractController
/** /**
* Shows starred entries for current user. * Shows starred entries for current user.
* *
* @Route("/feed/{username}/{token}/starred/{page}", name="starred_feed", methods={"GET"}, defaults={"page"=1, "_format"="xml"})
* @IsGranted("PUBLIC_ACCESS")
*
* @ParamConverter("user", class="Wallabag\Entity\User", converter="username_feed_token_converter")
*
* @return Response * @return Response
*/ */
#[Route(path: '/feed/{username}/{token}/starred/{page}', name: 'starred_feed', methods: ['GET'], defaults: ['page' => 1, '_format' => 'xml'])]
#[IsGranted('PUBLIC_ACCESS')]
#[ParamConverter('user', class: User::class, converter: 'username_feed_token_converter')]
public function showStarredFeedAction(User $user, $page) public function showStarredFeedAction(User $user, $page)
{ {
return $this->showEntries('starred', $user, $page); return $this->showEntries('starred', $user, $page);
@ -75,13 +67,11 @@ class FeedController extends AbstractController
/** /**
* Shows all entries for current user. * Shows all entries for current user.
* *
* @Route("/feed/{username}/{token}/all/{page}", name="all_feed", methods={"GET"}, defaults={"page"=1, "_format"="xml"})
* @IsGranted("PUBLIC_ACCESS")
*
* @ParamConverter("user", class="Wallabag\Entity\User", converter="username_feed_token_converter")
*
* @return Response * @return Response
*/ */
#[Route(path: '/feed/{username}/{token}/all/{page}', name: 'all_feed', methods: ['GET'], defaults: ['page' => 1, '_format' => 'xml'])]
#[IsGranted('PUBLIC_ACCESS')]
#[ParamConverter('user', class: User::class, converter: 'username_feed_token_converter')]
public function showAllFeedAction(User $user, $page) public function showAllFeedAction(User $user, $page)
{ {
return $this->showEntries('all', $user, $page); return $this->showEntries('all', $user, $page);
@ -90,14 +80,12 @@ class FeedController extends AbstractController
/** /**
* Shows entries associated to a tag for current user. * Shows entries associated to a tag for current user.
* *
* @Route("/feed/{username}/{token}/tags/{slug}/{page}", name="tag_feed", methods={"GET"}, defaults={"page"=1, "_format"="xml"})
* @IsGranted("PUBLIC_ACCESS")
*
* @ParamConverter("user", class="Wallabag\Entity\User", converter="username_feed_token_converter")
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
*
* @return Response * @return Response
*/ */
#[Route(path: '/feed/{username}/{token}/tags/{slug}/{page}', name: 'tag_feed', methods: ['GET'], defaults: ['page' => 1, '_format' => 'xml'])]
#[IsGranted('PUBLIC_ACCESS')]
#[ParamConverter('user', class: User::class, converter: 'username_feed_token_converter')]
#[ParamConverter('tag', options: ['mapping' => ['slug' => 'slug']])]
public function showTagsFeedAction(Request $request, User $user, Tag $tag, PreparePagerForEntries $preparePagerForEntries, $page) public function showTagsFeedAction(Request $request, User $user, Tag $tag, PreparePagerForEntries $preparePagerForEntries, $page)
{ {
$sort = $request->query->get('sort', 'created'); $sort = $request->query->get('sort', 'created');
@ -143,7 +131,7 @@ class FeedController extends AbstractController
try { try {
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) { } catch (OutOfRangeCurrentPageException) {
if ($page > 1) { if ($page > 1) {
return $this->redirect($url . '?page=' . $entries->getNbPages(), 302); return $this->redirect($url . '?page=' . $entries->getNbPages(), 302);
} }
@ -191,22 +179,13 @@ class FeedController extends AbstractController
*/ */
private function showEntries(string $type, User $user, $page = 1) private function showEntries(string $type, User $user, $page = 1)
{ {
switch ($type) { $qb = match ($type) {
case 'starred': 'starred' => $this->entryRepository->getBuilderForStarredByUser($user->getId()),
$qb = $this->entryRepository->getBuilderForStarredByUser($user->getId()); 'archive' => $this->entryRepository->getBuilderForArchiveByUser($user->getId()),
break; 'unread' => $this->entryRepository->getBuilderForUnreadByUser($user->getId()),
case 'archive': 'all' => $this->entryRepository->getBuilderForAllByUser($user->getId()),
$qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId()); default => throw new \InvalidArgumentException(\sprintf('Type "%s" is not implemented.', $type)),
break; };
case 'unread':
$qb = $this->entryRepository->getBuilderForUnreadByUser($user->getId());
break;
case 'all':
$qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
break;
default:
throw new \InvalidArgumentException(\sprintf('Type "%s" is not implemented.', $type));
}
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false); $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
$entries = new Pagerfanta($pagerAdapter); $entries = new Pagerfanta($pagerAdapter);
@ -225,7 +204,7 @@ class FeedController extends AbstractController
try { try {
$entries->setCurrentPage((int) $page); $entries->setCurrentPage((int) $page);
} catch (OutOfRangeCurrentPageException $e) { } catch (OutOfRangeCurrentPageException) {
if ($page > 1) { if ($page > 1) {
return $this->redirect($url . '/' . $entries->getNbPages()); return $this->redirect($url . '/' . $entries->getNbPages());
} }

View file

@ -20,21 +20,17 @@ use Wallabag\Repository\IgnoreOriginInstanceRuleRepository;
*/ */
class IgnoreOriginInstanceRuleController extends AbstractController class IgnoreOriginInstanceRuleController extends AbstractController
{ {
private EntityManagerInterface $entityManager; public function __construct(
private TranslatorInterface $translator; private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator) ) {
{
$this->entityManager = $entityManager;
$this->translator = $translator;
} }
/** /**
* Lists all IgnoreOriginInstanceRule entities. * Lists all IgnoreOriginInstanceRule entities.
*
* @Route("/ignore-origin-instance-rules", name="ignore_origin_instance_rules_index", methods={"GET"})
* @IsGranted("LIST_IGNORE_ORIGIN_INSTANCE_RULES")
*/ */
#[Route(path: '/ignore-origin-instance-rules', name: 'ignore_origin_instance_rules_index', methods: ['GET'])]
#[IsGranted('LIST_IGNORE_ORIGIN_INSTANCE_RULES')]
public function indexAction(IgnoreOriginInstanceRuleRepository $repository) public function indexAction(IgnoreOriginInstanceRuleRepository $repository)
{ {
$rules = $repository->findAll(); $rules = $repository->findAll();
@ -47,11 +43,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/** /**
* Creates a new ignore origin instance rule entity. * Creates a new ignore origin instance rule entity.
* *
* @Route("/ignore-origin-instance-rules/new", name="ignore_origin_instance_rules_new", methods={"GET", "POST"})
* @IsGranted("CREATE_IGNORE_ORIGIN_INSTANCE_RULES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/ignore-origin-instance-rules/new', name: 'ignore_origin_instance_rules_new', methods: ['GET', 'POST'])]
#[IsGranted('CREATE_IGNORE_ORIGIN_INSTANCE_RULES')]
public function newAction(Request $request) public function newAction(Request $request)
{ {
$ignoreOriginInstanceRule = new IgnoreOriginInstanceRule(); $ignoreOriginInstanceRule = new IgnoreOriginInstanceRule();
@ -80,11 +75,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/** /**
* Displays a form to edit an existing ignore origin instance rule entity. * Displays a form to edit an existing ignore origin instance rule entity.
* *
* @Route("/ignore-origin-instance-rules/{id}/edit", name="ignore_origin_instance_rules_edit", methods={"GET", "POST"})
* @IsGranted("EDIT", subject="ignoreOriginInstanceRule")
*
* @return Response * @return Response
*/ */
#[Route(path: '/ignore-origin-instance-rules/{id}/edit', name: 'ignore_origin_instance_rules_edit', methods: ['GET', 'POST'])]
#[IsGranted('EDIT', subject: 'ignoreOriginInstanceRule')]
public function editAction(Request $request, IgnoreOriginInstanceRule $ignoreOriginInstanceRule) public function editAction(Request $request, IgnoreOriginInstanceRule $ignoreOriginInstanceRule)
{ {
$deleteForm = $this->createDeleteForm($ignoreOriginInstanceRule); $deleteForm = $this->createDeleteForm($ignoreOriginInstanceRule);
@ -113,11 +107,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/** /**
* Deletes a site credential entity. * Deletes a site credential entity.
* *
* @Route("/ignore-origin-instance-rules/{id}", name="ignore_origin_instance_rules_delete", methods={"DELETE"})
* @IsGranted("DELETE", subject="ignoreOriginInstanceRule")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/ignore-origin-instance-rules/{id}', name: 'ignore_origin_instance_rules_delete', methods: ['DELETE'])]
#[IsGranted('DELETE', subject: 'ignoreOriginInstanceRule')]
public function deleteAction(Request $request, IgnoreOriginInstanceRule $ignoreOriginInstanceRule) public function deleteAction(Request $request, IgnoreOriginInstanceRule $ignoreOriginInstanceRule)
{ {
$form = $this->createDeleteForm($ignoreOriginInstanceRule); $form = $this->createDeleteForm($ignoreOriginInstanceRule);

View file

@ -14,11 +14,10 @@ use Wallabag\Import\ImportInterface;
abstract class BrowserController extends AbstractController abstract class BrowserController extends AbstractController
{ {
/** /**
* @Route("/import/browser", name="import_browser", methods={"GET", "POST"})
* @IsGranted("IMPORT_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/import/browser', name: 'import_browser', methods: ['GET', 'POST'])]
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class ChromeController extends BrowserController class ChromeController extends BrowserController
{ {
private ChromeImport $chromeImport; public function __construct(
private Config $craueConfig; private readonly ChromeImport $chromeImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(ChromeImport $chromeImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->chromeImport = $chromeImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/chrome', name: 'import_chrome', methods: ['GET', 'POST'])]
* @Route("/import/chrome", name="import_chrome", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -15,19 +15,14 @@ use Wallabag\Redis\Producer as RedisProducer;
class DeliciousController extends AbstractController class DeliciousController extends AbstractController
{ {
private RabbitMqProducer $rabbitMqProducer; public function __construct(
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/delicious', name: 'import_delicious', methods: ['GET', 'POST'])]
* @Route("/import/delicious", name="import_delicious", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, DeliciousImport $delicious, Config $craueConfig, TranslatorInterface $translator) public function indexAction(Request $request, DeliciousImport $delicious, Config $craueConfig, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class ElcuratorController extends WallabagController class ElcuratorController extends WallabagController
{ {
private ElcuratorImport $elcuratorImport; public function __construct(
private Config $craueConfig; private readonly ElcuratorImport $elcuratorImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(ElcuratorImport $elcuratorImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->elcuratorImport = $elcuratorImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/elcurator', name: 'import_elcurator', methods: ['GET', 'POST'])]
* @Route("/import/elcurator", name="import_elcurator", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class FirefoxController extends BrowserController class FirefoxController extends BrowserController
{ {
private FirefoxImport $firefoxImport; public function __construct(
private Config $craueConfig; private readonly FirefoxImport $firefoxImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(FirefoxImport $firefoxImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->firefoxImport = $firefoxImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/firefox', name: 'import_firefox', methods: ['GET', 'POST'])]
* @Route("/import/firefox", name="import_firefox", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -14,11 +14,10 @@ use Wallabag\Import\ImportInterface;
abstract class HtmlController extends AbstractController abstract class HtmlController extends AbstractController
{ {
/** /**
* @Route("/import/html", name="import_html", methods={"GET", "POST"})
* @IsGranted("IMPORT_ENTRIES")
*
* @return Response * @return Response
*/ */
#[Route(path: '/import/html', name: 'import_html', methods: ['GET', 'POST'])]
#[IsGranted('IMPORT_ENTRIES')]
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -13,19 +13,14 @@ use Wallabag\Import\ImportChain;
class ImportController extends AbstractController class ImportController extends AbstractController
{ {
private RabbitMQConsumerTotalProxy $rabbitMQConsumerTotalProxy; public function __construct(
private Client $redisClient; private readonly RabbitMQConsumerTotalProxy $rabbitMQConsumerTotalProxy,
private readonly Client $redisClient,
public function __construct(RabbitMQConsumerTotalProxy $rabbitMQConsumerTotalProxy, Client $redisClient) ) {
{
$this->rabbitMQConsumerTotalProxy = $rabbitMQConsumerTotalProxy;
$this->redisClient = $redisClient;
} }
/** #[Route(path: '/import/', name: 'import', methods: ['GET'])]
* @Route("/import/", name="import", methods={"GET"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function importAction(ImportChain $importChain) public function importAction(ImportChain $importChain)
{ {
return $this->render('Import/index.html.twig', [ return $this->render('Import/index.html.twig', [
@ -65,7 +60,7 @@ class ImportController extends AbstractController
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('pocket_html') + $this->rabbitMQConsumerTotalProxy->getTotalMessage('pocket_html')
+ $this->rabbitMQConsumerTotalProxy->getTotalMessage('omnivore') + $this->rabbitMQConsumerTotalProxy->getTotalMessage('omnivore')
; ;
} catch (\Exception $e) { } catch (\Exception) {
$rabbitNotInstalled = true; $rabbitNotInstalled = true;
} }
} elseif ($craueConfig->get('import_with_redis')) { } elseif ($craueConfig->get('import_with_redis')) {
@ -84,7 +79,7 @@ class ImportController extends AbstractController
+ $this->redisClient->llen('wallabag.import.pocket_html') + $this->redisClient->llen('wallabag.import.pocket_html')
+ $this->redisClient->llen('wallabag.import.omnivore') + $this->redisClient->llen('wallabag.import.omnivore')
; ;
} catch (\Exception $e) { } catch (\Exception) {
$redisNotInstalled = true; $redisNotInstalled = true;
} }
} }

View file

@ -15,19 +15,14 @@ use Wallabag\Redis\Producer as RedisProducer;
class InstapaperController extends AbstractController class InstapaperController extends AbstractController
{ {
private RabbitMqProducer $rabbitMqProducer; public function __construct(
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/instapaper', name: 'import_instapaper', methods: ['GET', 'POST'])]
* @Route("/import/instapaper", name="import_instapaper", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, InstapaperImport $instapaper, Config $craueConfig, TranslatorInterface $translator) public function indexAction(Request $request, InstapaperImport $instapaper, Config $craueConfig, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -15,19 +15,14 @@ use Wallabag\Redis\Producer as RedisProducer;
class OmnivoreController extends AbstractController class OmnivoreController extends AbstractController
{ {
private RabbitMqProducer $rabbitMqProducer; public function __construct(
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/omnivore', name: 'import_omnivore', methods: ['GET', 'POST'])]
* @Route("/import/omnivore", name="import_omnivore", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, OmnivoreImport $omnivore, Config $craueConfig, TranslatorInterface $translator) public function indexAction(Request $request, OmnivoreImport $omnivore, Config $craueConfig, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -15,19 +15,14 @@ use Wallabag\Redis\Producer as RedisProducer;
class PinboardController extends AbstractController class PinboardController extends AbstractController
{ {
private RabbitMqProducer $rabbitMqProducer; public function __construct(
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/pinboard', name: 'import_pinboard', methods: ['GET', 'POST'])]
* @Route("/import/pinboard", name="import_pinboard", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, PinboardImport $pinboard, Config $craueConfig, TranslatorInterface $translator) public function indexAction(Request $request, PinboardImport $pinboard, Config $craueConfig, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -17,23 +17,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class PocketController extends AbstractController class PocketController extends AbstractController
{ {
private Config $craueConfig; public function __construct(
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private SessionInterface $session; private readonly RedisProducer $redisProducer,
private readonly SessionInterface $session,
public function __construct(Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer, SessionInterface $session) ) {
{
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
$this->session = $session;
} }
/** #[Route(path: '/import/pocket', name: 'import_pocket', methods: ['GET'])]
* @Route("/import/pocket", name="import_pocket", methods={"GET"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(PocketImport $pocketImport) public function indexAction(PocketImport $pocketImport)
{ {
$pocket = $this->getPocketImportService($pocketImport); $pocket = $this->getPocketImportService($pocketImport);
@ -52,10 +45,8 @@ class PocketController extends AbstractController
]); ]);
} }
/** #[Route(path: '/import/pocket/auth', name: 'import_pocket_auth', methods: ['POST'])]
* @Route("/import/pocket/auth", name="import_pocket_auth", methods={"POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function authAction(Request $request, PocketImport $pocketImport) public function authAction(Request $request, PocketImport $pocketImport)
{ {
$requestToken = $this->getPocketImportService($pocketImport) $requestToken = $this->getPocketImportService($pocketImport)
@ -83,10 +74,8 @@ class PocketController extends AbstractController
); );
} }
/** #[Route(path: '/import/pocket/callback', name: 'import_pocket_callback', methods: ['GET'])]
* @Route("/import/pocket/callback", name="import_pocket_callback", methods={"GET"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function callbackAction(PocketImport $pocketImport, TranslatorInterface $translator) public function callbackAction(PocketImport $pocketImport, TranslatorInterface $translator)
{ {
$message = 'flashes.import.notice.failed'; $message = 'flashes.import.notice.failed';

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class PocketHtmlController extends HtmlController class PocketHtmlController extends HtmlController
{ {
private PocketHtmlImport $pocketHtmlImport; public function __construct(
private Config $craueConfig; private readonly PocketHtmlImport $pocketHtmlImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(PocketHtmlImport $pocketHtmlImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->pocketHtmlImport = $pocketHtmlImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/pocket_html', name: 'import_pocket_html', methods: ['GET', 'POST'])]
* @Route("/import/pocket_html", name="import_pocket_html", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -15,19 +15,14 @@ use Wallabag\Redis\Producer as RedisProducer;
class ReadabilityController extends AbstractController class ReadabilityController extends AbstractController
{ {
private RabbitMqProducer $rabbitMqProducer; public function __construct(
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/readability', name: 'import_readability', methods: ['GET', 'POST'])]
* @Route("/import/readability", name="import_readability", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, ReadabilityImport $readability, Config $craueConfig, TranslatorInterface $translator) public function indexAction(Request $request, ReadabilityImport $readability, Config $craueConfig, TranslatorInterface $translator)
{ {
$form = $this->createForm(UploadImportType::class); $form = $this->createForm(UploadImportType::class);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class ShaarliController extends HtmlController class ShaarliController extends HtmlController
{ {
private ShaarliImport $shaarliImport; public function __construct(
private Config $craueConfig; private readonly ShaarliImport $shaarliImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(ShaarliImport $shaarliImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->shaarliImport = $shaarliImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/shaarli', name: 'import_shaarli', methods: ['GET', 'POST'])]
* @Route("/import/shaarli", name="import_shaarli", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class WallabagV1Controller extends WallabagController class WallabagV1Controller extends WallabagController
{ {
private WallabagV1Import $wallabagImport; public function __construct(
private Config $craueConfig; private readonly WallabagV1Import $wallabagImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(WallabagV1Import $wallabagImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->wallabagImport = $wallabagImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/wallabag-v1', name: 'import_wallabag_v1', methods: ['GET', 'POST'])]
* @Route("/import/wallabag-v1", name="import_wallabag_v1", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -13,23 +13,16 @@ use Wallabag\Redis\Producer as RedisProducer;
class WallabagV2Controller extends WallabagController class WallabagV2Controller extends WallabagController
{ {
private WallabagV2Import $wallabagImport; public function __construct(
private Config $craueConfig; private readonly WallabagV2Import $wallabagImport,
private RabbitMqProducer $rabbitMqProducer; private readonly Config $craueConfig,
private RedisProducer $redisProducer; private readonly RabbitMqProducer $rabbitMqProducer,
private readonly RedisProducer $redisProducer,
public function __construct(WallabagV2Import $wallabagImport, Config $craueConfig, RabbitMqProducer $rabbitMqProducer, RedisProducer $redisProducer) ) {
{
$this->wallabagImport = $wallabagImport;
$this->craueConfig = $craueConfig;
$this->rabbitMqProducer = $rabbitMqProducer;
$this->redisProducer = $redisProducer;
} }
/** #[Route(path: '/import/wallabag-v2', name: 'import_wallabag_v2', methods: ['GET', 'POST'])]
* @Route("/import/wallabag-v2", name="import_wallabag_v2", methods={"GET", "POST"}) #[IsGranted('IMPORT_ENTRIES')]
* @IsGranted("IMPORT_ENTRIES")
*/
public function indexAction(Request $request, TranslatorInterface $translator) public function indexAction(Request $request, TranslatorInterface $translator)
{ {
return parent::indexAction($request, $translator); return parent::indexAction($request, $translator);

View file

@ -23,25 +23,19 @@ use Wallabag\Repository\SiteCredentialRepository;
*/ */
class SiteCredentialController extends AbstractController class SiteCredentialController extends AbstractController
{ {
private EntityManagerInterface $entityManager; public function __construct(
private TranslatorInterface $translator; private readonly EntityManagerInterface $entityManager,
private CryptoProxy $cryptoProxy; private readonly TranslatorInterface $translator,
private Config $craueConfig; private readonly CryptoProxy $cryptoProxy,
private readonly Config $craueConfig,
public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator, CryptoProxy $cryptoProxy, Config $craueConfig) ) {
{
$this->entityManager = $entityManager;
$this->translator = $translator;
$this->cryptoProxy = $cryptoProxy;
$this->craueConfig = $craueConfig;
} }
/** /**
* Lists all User entities. * Lists all User entities.
*
* @Route("/site-credentials", name="site_credentials_index", methods={"GET"})
* @IsGranted("LIST_SITE_CREDENTIALS")
*/ */
#[Route(path: '/site-credentials', name: 'site_credentials_index', methods: ['GET'])]
#[IsGranted('LIST_SITE_CREDENTIALS')]
public function indexAction(SiteCredentialRepository $repository) public function indexAction(SiteCredentialRepository $repository)
{ {
$this->isSiteCredentialsEnabled(); $this->isSiteCredentialsEnabled();
@ -56,11 +50,10 @@ class SiteCredentialController extends AbstractController
/** /**
* Creates a new site credential entity. * Creates a new site credential entity.
* *
* @Route("/site-credentials/new", name="site_credentials_new", methods={"GET", "POST"})
* @IsGranted("CREATE_SITE_CREDENTIALS")
*
* @return Response * @return Response
*/ */
#[Route(path: '/site-credentials/new', name: 'site_credentials_new', methods: ['GET', 'POST'])]
#[IsGranted('CREATE_SITE_CREDENTIALS')]
public function newAction(Request $request) public function newAction(Request $request)
{ {
$this->isSiteCredentialsEnabled(); $this->isSiteCredentialsEnabled();
@ -94,11 +87,10 @@ class SiteCredentialController extends AbstractController
/** /**
* Displays a form to edit an existing site credential entity. * Displays a form to edit an existing site credential entity.
* *
* @Route("/site-credentials/{id}/edit", name="site_credentials_edit", methods={"GET", "POST"})
* @IsGranted("EDIT", subject="siteCredential")
*
* @return Response * @return Response
*/ */
#[Route(path: '/site-credentials/{id}/edit', name: 'site_credentials_edit', methods: ['GET', 'POST'])]
#[IsGranted('EDIT', subject: 'siteCredential')]
public function editAction(Request $request, SiteCredential $siteCredential) public function editAction(Request $request, SiteCredential $siteCredential)
{ {
$this->isSiteCredentialsEnabled(); $this->isSiteCredentialsEnabled();
@ -132,11 +124,10 @@ class SiteCredentialController extends AbstractController
/** /**
* Deletes a site credential entity. * Deletes a site credential entity.
* *
* @Route("/site-credentials/{id}", name="site_credentials_delete", methods={"DELETE"})
* @IsGranted("DELETE", subject="siteCredential")
*
* @return RedirectResponse * @return RedirectResponse
*/ */
#[Route(path: '/site-credentials/{id}', name: 'site_credentials_delete', methods: ['DELETE'])]
#[IsGranted('DELETE', subject: 'siteCredential')]
public function deleteAction(Request $request, SiteCredential $siteCredential) public function deleteAction(Request $request, SiteCredential $siteCredential)
{ {
$this->isSiteCredentialsEnabled(); $this->isSiteCredentialsEnabled();

View file

@ -7,10 +7,8 @@ use Symfony\Component\Routing\Annotation\Route;
class StaticController extends AbstractController class StaticController extends AbstractController
{ {
/** #[Route(path: '/howto', name: 'howto', methods: ['GET'])]
* @Route("/howto", name="howto", methods={"GET"}) #[IsGranted('IS_AUTHENTICATED_FULLY')]
* @IsGranted("IS_AUTHENTICATED_FULLY")
*/
public function howtoAction() public function howtoAction()
{ {
$addonsUrl = $this->getParameter('addons_url'); $addonsUrl = $this->getParameter('addons_url');
@ -23,10 +21,8 @@ class StaticController extends AbstractController
); );
} }
/** #[Route(path: '/about', name: 'about', methods: ['GET'])]
* @Route("/about", name="about", methods={"GET"}) #[IsGranted('IS_AUTHENTICATED_FULLY')]
* @IsGranted("IS_AUTHENTICATED_FULLY")
*/
public function aboutAction() public function aboutAction()
{ {
return $this->render( return $this->render(
@ -38,10 +34,8 @@ class StaticController extends AbstractController
); );
} }
/** #[Route(path: '/quickstart', name: 'quickstart', methods: ['GET'])]
* @Route("/quickstart", name="quickstart", methods={"GET"}) #[IsGranted('IS_AUTHENTICATED_FULLY')]
* @IsGranted("IS_AUTHENTICATED_FULLY")
*/
public function quickstartAction() public function quickstartAction()
{ {
return $this->render( return $this->render(

View file

@ -25,35 +25,29 @@ use Wallabag\Repository\TagRepository;
class TagController extends AbstractController class TagController extends AbstractController
{ {
private EntityManagerInterface $entityManager; public function __construct(
private TagsAssigner $tagsAssigner; private readonly EntityManagerInterface $entityManager,
private Redirect $redirectHelper; private readonly TagsAssigner $tagsAssigner,
private Security $security; private readonly Redirect $redirectHelper,
private readonly Security $security,
public function __construct(EntityManagerInterface $entityManager, TagsAssigner $tagsAssigner, Redirect $redirectHelper, Security $security) ) {
{
$this->entityManager = $entityManager;
$this->tagsAssigner = $tagsAssigner;
$this->redirectHelper = $redirectHelper;
$this->security = $security;
} }
/** /**
* @Route("/new-tag/{entry}", name="new_tag", methods={"POST"}, requirements={"entry" = "\d+"})
* @IsGranted("TAG", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/new-tag/{entry}', name: 'new_tag', methods: ['POST'], requirements: ['entry' => '\d+'])]
#[IsGranted('TAG', subject: 'entry')]
public function addTagFormAction(Request $request, Entry $entry, TranslatorInterface $translator) public function addTagFormAction(Request $request, Entry $entry, TranslatorInterface $translator)
{ {
$form = $this->createForm(NewTagType::class, new Tag()); $form = $this->createForm(NewTagType::class, new Tag());
$form->handleRequest($request); $form->handleRequest($request);
$tags = $form->get('label')->getData() ?? ''; $tags = $form->get('label')->getData() ?? '';
$tagsExploded = explode(',', $tags); $tagsExploded = explode(',', (string) $tags);
// avoid too much tag to be added // avoid too much tag to be added
if (\count($tagsExploded) >= NewTagType::MAX_TAGS || \strlen($tags) >= NewTagType::MAX_LENGTH) { if (\count($tagsExploded) >= NewTagType::MAX_TAGS || \strlen((string) $tags) >= NewTagType::MAX_LENGTH) {
$message = $translator->trans('flashes.tag.notice.too_much_tags', [ $message = $translator->trans('flashes.tag.notice.too_much_tags', [
'%tags%' => NewTagType::MAX_TAGS, '%tags%' => NewTagType::MAX_TAGS,
'%characters%' => NewTagType::MAX_LENGTH, '%characters%' => NewTagType::MAX_LENGTH,
@ -89,11 +83,10 @@ class TagController extends AbstractController
/** /**
* Removes tag from entry. * Removes tag from entry.
* *
* @Route("/remove-tag/{entry}/{tag}", name="remove_tag", methods={"GET"}, requirements={"entry" = "\d+", "tag" = "\d+"})
* @IsGranted("UNTAG", subject="entry")
*
* @return Response * @return Response
*/ */
#[Route(path: '/remove-tag/{entry}/{tag}', name: 'remove_tag', methods: ['GET'], requirements: ['entry' => '\d+', 'tag' => '\d+'])]
#[IsGranted('UNTAG', subject: 'entry')]
public function removeTagFromEntry(Request $request, Entry $entry, Tag $tag) public function removeTagFromEntry(Request $request, Entry $entry, Tag $tag)
{ {
$entry->removeTag($tag); $entry->removeTag($tag);
@ -113,11 +106,10 @@ class TagController extends AbstractController
/** /**
* Shows tags for current user. * Shows tags for current user.
* *
* @Route("/tag/list", name="tag", methods={"GET"})
* @IsGranted("LIST_TAGS")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tag/list', name: 'tag', methods: ['GET'])]
#[IsGranted('LIST_TAGS')]
public function showTagAction(TagRepository $tagRepository, EntryRepository $entryRepository) public function showTagAction(TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$allTagsWithNbEntries = $tagRepository->findAllTagsWithNbEntries($this->getUser()->getId()); $allTagsWithNbEntries = $tagRepository->findAllTagsWithNbEntries($this->getUser()->getId());
@ -138,13 +130,12 @@ class TagController extends AbstractController
/** /**
* @param int $page * @param int $page
* *
* @Route("/tag/list/{slug}/{page}", name="tag_entries", methods={"GET"}, defaults={"page" = "1"})
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
* @IsGranted("LIST_ENTRIES")
* @IsGranted("VIEW", subject="tag")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tag/list/{slug}/{page}', name: 'tag_entries', methods: ['GET'], defaults: ['page' => '1'])]
#[ParamConverter('tag', options: ['mapping' => ['slug' => 'slug']])]
#[IsGranted('LIST_ENTRIES')]
#[IsGranted('VIEW', subject: 'tag')]
public function showEntriesForTagAction(Tag $tag, EntryRepository $entryRepository, PreparePagerForEntries $preparePagerForEntries, $page, Request $request) public function showEntriesForTagAction(Tag $tag, EntryRepository $entryRepository, PreparePagerForEntries $preparePagerForEntries, $page, Request $request)
{ {
$entriesByTag = $entryRepository->findAllByTagId( $entriesByTag = $entryRepository->findAllByTagId(
@ -158,7 +149,7 @@ class TagController extends AbstractController
try { try {
$entries->setCurrentPage($page); $entries->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) { } catch (OutOfRangeCurrentPageException) {
if ($page > 1) { if ($page > 1) {
return $this->redirect($this->generateUrl($request->attributes->get('_route'), [ return $this->redirect($this->generateUrl($request->attributes->get('_route'), [
'slug' => $tag->getSlug(), 'slug' => $tag->getSlug(),
@ -179,12 +170,11 @@ class TagController extends AbstractController
* Rename a given tag with a new label * Rename a given tag with a new label
* Create a new tag with the new name and drop the old one. * Create a new tag with the new name and drop the old one.
* *
* @Route("/tag/rename/{slug}", name="tag_rename", methods={"POST"})
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
* @IsGranted("EDIT", subject="tag")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tag/rename/{slug}', name: 'tag_rename', methods: ['POST'])]
#[ParamConverter('tag', options: ['mapping' => ['slug' => 'slug']])]
#[IsGranted('EDIT', subject: 'tag')]
public function renameTagAction(Tag $tag, Request $request, TagRepository $tagRepository, EntryRepository $entryRepository) public function renameTagAction(Tag $tag, Request $request, TagRepository $tagRepository, EntryRepository $entryRepository)
{ {
$form = $this->createForm(RenameTagType::class, new Tag()); $form = $this->createForm(RenameTagType::class, new Tag());
@ -233,11 +223,10 @@ class TagController extends AbstractController
/** /**
* Tag search results with the current search term. * Tag search results with the current search term.
* *
* @Route("/tag/search/{filter}", name="tag_this_search", methods={"GET"})
* @IsGranted("CREATE_TAGS")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tag/search/{filter}', name: 'tag_this_search', methods: ['GET'])]
#[IsGranted('CREATE_TAGS')]
public function tagThisSearchAction($filter, Request $request, EntryRepository $entryRepository) public function tagThisSearchAction($filter, Request $request, EntryRepository $entryRepository)
{ {
$currentRoute = $request->query->has('currentRoute') ? $request->query->get('currentRoute') : ''; $currentRoute = $request->query->has('currentRoute') ? $request->query->get('currentRoute') : '';
@ -255,7 +244,7 @@ class TagController extends AbstractController
// check to avoid duplicate tags creation // check to avoid duplicate tags creation
foreach ($this->entityManager->getUnitOfWork()->getScheduledEntityInsertions() as $entity) { foreach ($this->entityManager->getUnitOfWork()->getScheduledEntityInsertions() as $entity) {
if ($entity instanceof Tag && strtolower($entity->getLabel()) === strtolower($filter)) { if ($entity instanceof Tag && strtolower($entity->getLabel()) === strtolower((string) $filter)) {
continue 2; continue 2;
} }
$this->entityManager->persist($entry); $this->entityManager->persist($entry);
@ -269,12 +258,11 @@ class TagController extends AbstractController
/** /**
* Delete a given tag for the current user. * Delete a given tag for the current user.
* *
* @Route("/tag/delete/{slug}", name="tag_delete", methods={"GET"})
* @ParamConverter("tag", options={"mapping": {"slug": "slug"}})
* @IsGranted("DELETE", subject="tag")
*
* @return Response * @return Response
*/ */
#[Route(path: '/tag/delete/{slug}', name: 'tag_delete', methods: ['GET'])]
#[ParamConverter('tag', options: ['mapping' => ['slug' => 'slug']])]
#[IsGranted('DELETE', subject: 'tag')]
public function removeTagAction(Tag $tag, Request $request, EntryRepository $entryRepository) public function removeTagAction(Tag $tag, Request $request, EntryRepository $entryRepository)
{ {
foreach ($tag->getEntriesByUserId($this->getUser()->getId()) as $entry) { foreach ($tag->getEntriesByUserId($this->getUser()->getId()) as $entry) {

View file

@ -29,21 +29,17 @@ use Wallabag\Repository\UserRepository;
*/ */
class UserController extends AbstractController class UserController extends AbstractController
{ {
private EntityManagerInterface $entityManager; public function __construct(
private TranslatorInterface $translator; private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator) ) {
{
$this->entityManager = $entityManager;
$this->translator = $translator;
} }
/** /**
* Creates a new User entity. * Creates a new User entity.
*
* @Route("/users/new", name="user_new", methods={"GET", "POST"})
* @IsGranted("CREATE_USERS")
*/ */
#[Route(path: '/users/new', name: 'user_new', methods: ['GET', 'POST'])]
#[IsGranted('CREATE_USERS')]
public function newAction(Request $request, UserManagerInterface $userManager, EventDispatcherInterface $eventDispatcher) public function newAction(Request $request, UserManagerInterface $userManager, EventDispatcherInterface $eventDispatcher)
{ {
$user = $userManager->createUser(); $user = $userManager->createUser();
@ -77,10 +73,9 @@ class UserController extends AbstractController
/** /**
* Displays a form to edit an existing User entity. * Displays a form to edit an existing User entity.
*
* @Route("/users/{id}/edit", name="user_edit", methods={"GET", "POST"})
* @IsGranted("EDIT", subject="user")
*/ */
#[Route(path: '/users/{id}/edit', name: 'user_edit', methods: ['GET', 'POST'])]
#[IsGranted('EDIT', subject: 'user')]
public function editAction(Request $request, User $user, UserManagerInterface $userManager, GoogleAuthenticatorInterface $googleAuthenticator) public function editAction(Request $request, User $user, UserManagerInterface $userManager, GoogleAuthenticatorInterface $googleAuthenticator)
{ {
$deleteForm = $this->createDeleteForm($user); $deleteForm = $this->createDeleteForm($user);
@ -120,10 +115,9 @@ class UserController extends AbstractController
/** /**
* Deletes a User entity. * Deletes a User entity.
*
* @Route("/users/{id}", name="user_delete", methods={"DELETE"})
* @IsGranted("DELETE", subject="user")
*/ */
#[Route(path: '/users/{id}', name: 'user_delete', methods: ['DELETE'])]
#[IsGranted('DELETE', subject: 'user')]
public function deleteAction(Request $request, User $user) public function deleteAction(Request $request, User $user)
{ {
$form = $this->createDeleteForm($user); $form = $this->createDeleteForm($user);
@ -145,14 +139,10 @@ class UserController extends AbstractController
/** /**
* @param int $page * @param int $page
* *
* @Route("/users/list/{page}", name="user_index", methods={"GET"}, defaults={"page" = 1})
* @IsGranted("LIST_USERS")
*
* Default parameter for page is hardcoded (in duplication of the defaults from the Route)
* because this controller is also called inside the layout template without any page as argument
*
* @return Response * @return Response
*/ */
#[Route(path: '/users/list/{page}', name: 'user_index', methods: ['GET'], defaults: ['page' => 1])]
#[IsGranted('LIST_USERS')] // Default parameter for page is hardcoded (in duplication of the defaults from the Route)
public function searchFormAction(Request $request, UserRepository $userRepository, $page = 1) public function searchFormAction(Request $request, UserRepository $userRepository, $page = 1)
{ {
$qb = $userRepository->createQueryBuilder('u'); $qb = $userRepository->createQueryBuilder('u');
@ -161,7 +151,7 @@ class UserController extends AbstractController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$searchTerm = (isset($request->query->all('search_user')['term']) ? $request->query->all('search_user')['term'] : ''); $searchTerm = $request->query->all('search_user')['term'] ?? '';
$qb = $userRepository->getQueryBuilderForSearch($searchTerm); $qb = $userRepository->getQueryBuilderForSearch($searchTerm);
} }
@ -172,7 +162,7 @@ class UserController extends AbstractController
try { try {
$pagerFanta->setCurrentPage($page); $pagerFanta->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) { } catch (OutOfRangeCurrentPageException) {
if ($page > 1) { if ($page > 1) {
return $this->redirect($this->generateUrl('user_index', ['page' => $pagerFanta->getNbPages()]), 302); return $this->redirect($this->generateUrl('user_index', ['page' => $pagerFanta->getNbPages()]), 302);
} }

View file

@ -22,7 +22,7 @@ class JsonArrayType extends JsonType
$value = \is_resource($value) ? stream_get_contents($value) : $value; $value = \is_resource($value) ? stream_get_contents($value) : $value;
return json_decode($value, true); return json_decode((string) $value, true);
} }
public function getName(): string public function getName(): string

View file

@ -10,17 +10,12 @@ use Doctrine\Migrations\Version\MigrationFactory;
*/ */
class MigrationFactoryDecorator implements MigrationFactory class MigrationFactoryDecorator implements MigrationFactory
{ {
private MigrationFactory $migrationFactory; public function __construct(
private string $tablePrefix; private readonly MigrationFactory $migrationFactory,
private array $defaultIgnoreOriginInstanceRules; private readonly string $tablePrefix,
private string $fetchingErrorMessage; private readonly array $defaultIgnoreOriginInstanceRules,
private readonly string $fetchingErrorMessage,
public function __construct(MigrationFactory $migrationFactory, string $tablePrefix, array $defaultIgnoreOriginInstanceRules, string $fetchingErrorMessage) ) {
{
$this->migrationFactory = $migrationFactory;
$this->tablePrefix = $tablePrefix;
$this->defaultIgnoreOriginInstanceRules = $defaultIgnoreOriginInstanceRules;
$this->fetchingErrorMessage = $fetchingErrorMessage;
} }
public function createVersion(string $migrationClassName): AbstractMigration public function createVersion(string $migrationClassName): AbstractMigration

View file

@ -89,9 +89,7 @@ abstract class WallabagMigration extends AbstractMigration
*/ */
protected function generateIdentifierName(array $columnNames, string $prefix = ''): string protected function generateIdentifierName(array $columnNames, string $prefix = ''): string
{ {
$hash = implode('', array_map(static function ($column): string { $hash = implode('', array_map(static fn ($column): string => dechex(crc32($column)), $columnNames));
return dechex(crc32($column));
}, $columnNames));
return strtoupper(substr($prefix . '_' . $hash, 0, $this->platform->getMaxIdentifierLength())); return strtoupper(substr($prefix . '_' . $hash, 0, $this->platform->getMaxIdentifierLength()));
} }

View file

@ -14,12 +14,11 @@ use Wallabag\Repository\AnnotationRepository;
/** /**
* Annotation. * Annotation.
*
* @ExclusionPolicy("none")
*/ */
#[ORM\Table(name: 'annotation')] #[ORM\Table(name: 'annotation')]
#[ORM\Entity(repositoryClass: AnnotationRepository::class)] #[ORM\Entity(repositoryClass: AnnotationRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]
#[ExclusionPolicy('none')]
class Annotation class Annotation
{ {
use EntityTimestampsTrait; use EntityTimestampsTrait;
@ -34,10 +33,9 @@ class Annotation
/** /**
* @var string * @var string
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'text', type: 'text')] #[ORM\Column(name: 'text', type: 'text')]
#[Groups(['entries_for_user', 'export_all'])]
private $text; private $text;
/** /**
@ -54,36 +52,26 @@ class Annotation
/** /**
* @var string * @var string
*
* @Assert\Length(
* max = 10000,
* maxMessage = "validator.quote_length_too_high"
* )
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'quote', type: 'text')] #[ORM\Column(name: 'quote', type: 'text')]
#[Assert\Length(max: 10000, maxMessage: 'validator.quote_length_too_high')]
#[Groups(['entries_for_user', 'export_all'])]
private $quote; private $quote;
/** /**
* @var array * @var array
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'ranges', type: 'array')] #[ORM\Column(name: 'ranges', type: 'array')]
#[Groups(['entries_for_user', 'export_all'])]
private $ranges; private $ranges;
/**
* @Exclude
*/
#[ORM\ManyToOne(targetEntity: User::class)] #[ORM\ManyToOne(targetEntity: User::class)]
#[Exclude]
private $user; private $user;
/**
* @Exclude
*/
#[ORM\JoinColumn(name: 'entry_id', referencedColumnName: 'id', onDelete: 'cascade')] #[ORM\JoinColumn(name: 'entry_id', referencedColumnName: 'id', onDelete: 'cascade')]
#[ORM\ManyToOne(targetEntity: Entry::class, inversedBy: 'annotations')] #[ORM\ManyToOne(targetEntity: Entry::class, inversedBy: 'annotations')]
#[Exclude]
private $entry; private $entry;
/* /*
@ -220,10 +208,8 @@ class Annotation
return $this->user; return $this->user;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('user')]
* @SerializedName("user")
*/
public function getUserName() public function getUserName()
{ {
return $this->user->getName(); return $this->user->getName();
@ -254,10 +240,8 @@ class Annotation
return $this->entry; return $this->entry;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('annotator_schema_version')]
* @SerializedName("annotator_schema_version")
*/
public function getVersion() public function getVersion()
{ {
return 'v1.0'; return 'v1.0';

View file

@ -28,9 +28,9 @@ class Client extends BaseClient
* type="string", * type="string",
* example="Default Client", * example="Default Client",
* ) * )
* @Groups({"user_api_with_client"})
*/ */
#[ORM\Column(name: 'name', type: 'text', nullable: false)] #[ORM\Column(name: 'name', type: 'text', nullable: false)]
#[Groups(['user_api_with_client'])]
protected $name; protected $name;
#[ORM\OneToMany(targetEntity: RefreshToken::class, mappedBy: 'client', cascade: ['remove'])] #[ORM\OneToMany(targetEntity: RefreshToken::class, mappedBy: 'client', cascade: ['remove'])]
@ -47,10 +47,9 @@ class Client extends BaseClient
* type="string", * type="string",
* example="2lmubx2m9vy80ss8c4wwcsg8ok44s88ocwcc8wo0w884oc8440", * example="2lmubx2m9vy80ss8c4wwcsg8ok44s88ocwcc8wo0w884oc8440",
* ) * )
*
* @SerializedName("client_secret")
* @Groups({"user_api_with_client"})
*/ */
#[SerializedName('client_secret')]
#[Groups(['user_api_with_client'])]
protected $secret; protected $secret;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'clients')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'clients')]
@ -95,17 +94,15 @@ class Client extends BaseClient
} }
/** /**
* @VirtualProperty
*
* @OA\Property( * @OA\Property(
* description="Client secret used for authorization", * description="Client secret used for authorization",
* type="string", * type="string",
* example="3_1lpybsn0od40css4w4ko8gsc8cwwskggs8kgg448ko0owo4c84", * example="3_1lpybsn0od40css4w4ko8gsc8cwwskggs8kgg448ko0owo4c84",
* ) * )
*
* @SerializedName("client_id")
* @Groups({"user_api_with_client"})
*/ */
#[VirtualProperty]
#[SerializedName('client_id')]
#[Groups(['user_api_with_client'])]
public function getClientId() public function getClientId()
{ {
return $this->getId() . '_' . $this->getRandomId(); return $this->getId() . '_' . $this->getRandomId();

View file

@ -21,66 +21,50 @@ class Config
/** /**
* @var int * @var int
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'id', type: 'integer')] #[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\GeneratedValue(strategy: 'AUTO')]
#[Groups(['config_api'])]
private $id; private $id;
/** /**
* @var int * @var int
*
* @Assert\NotBlank()
* @Assert\Range(
* min = 1,
* max = 100000,
* maxMessage = "validator.item_per_page_too_high"
* )
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'items_per_page', type: 'integer', nullable: false)] #[ORM\Column(name: 'items_per_page', type: 'integer', nullable: false)]
#[Assert\NotBlank]
#[Assert\Range(min: 1, max: 100000, maxMessage: 'validator.item_per_page_too_high')]
#[Groups(['config_api'])]
private $itemsPerPage; private $itemsPerPage;
/** /**
* @var string * @var string
*
* @Assert\NotBlank()
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'language', type: 'string', nullable: false)] #[ORM\Column(name: 'language', type: 'string', nullable: false)]
#[Assert\NotBlank]
#[Groups(['config_api'])]
private $language; private $language;
/** /**
* @var string|null * @var string|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'feed_token', type: 'string', nullable: true)] #[ORM\Column(name: 'feed_token', type: 'string', nullable: true)]
#[Groups(['config_api'])]
private $feedToken; private $feedToken;
/** /**
* @var int|null * @var int|null
*
* @Assert\Range(
* min = 1,
* max = 100000,
* maxMessage = "validator.feed_limit_too_high"
* )
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'feed_limit', type: 'integer', nullable: true)] #[ORM\Column(name: 'feed_limit', type: 'integer', nullable: true)]
#[Assert\Range(min: 1, max: 100000, maxMessage: 'validator.feed_limit_too_high')]
#[Groups(['config_api'])]
private $feedLimit; private $feedLimit;
/** /**
* @var float|null * @var float|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'reading_speed', type: 'float', nullable: true)] #[ORM\Column(name: 'reading_speed', type: 'float', nullable: true)]
#[Groups(['config_api'])]
private $readingSpeed; private $readingSpeed;
/** /**
@ -91,58 +75,51 @@ class Config
/** /**
* @var int|null * @var int|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'action_mark_as_read', type: 'integer', nullable: true, options: ['default' => 0])] #[ORM\Column(name: 'action_mark_as_read', type: 'integer', nullable: true, options: ['default' => 0])]
#[Groups(['config_api'])]
private $actionMarkAsRead; private $actionMarkAsRead;
/** /**
* @var int|null * @var int|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'list_mode', type: 'integer', nullable: true)] #[ORM\Column(name: 'list_mode', type: 'integer', nullable: true)]
#[Groups(['config_api'])]
private $listMode; private $listMode;
/** /**
* @var int|null * @var int|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'display_thumbnails', type: 'integer', nullable: true, options: ['default' => 1])] #[ORM\Column(name: 'display_thumbnails', type: 'integer', nullable: true, options: ['default' => 1])]
#[Groups(['config_api'])]
private $displayThumbnails; private $displayThumbnails;
/** /**
* @var string|null * @var string|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'font', type: 'text', nullable: true)] #[ORM\Column(name: 'font', type: 'text', nullable: true)]
#[Groups(['config_api'])]
private $font; private $font;
/** /**
* @var float|null * @var float|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'fontsize', type: 'float', nullable: true)] #[ORM\Column(name: 'fontsize', type: 'float', nullable: true)]
#[Groups(['config_api'])]
private $fontsize; private $fontsize;
/** /**
* @var float|null * @var float|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'line_height', type: 'float', nullable: true)] #[ORM\Column(name: 'line_height', type: 'float', nullable: true)]
#[Groups(['config_api'])]
private $lineHeight; private $lineHeight;
/** /**
* @var float|null * @var float|null
*
* @Groups({"config_api"})
*/ */
#[ORM\Column(name: 'max_width', type: 'float', nullable: true)] #[ORM\Column(name: 'max_width', type: 'float', nullable: true)]
#[Groups(['config_api'])]
private $maxWidth; private $maxWidth;
/** /**

View file

@ -18,7 +18,6 @@ use Wallabag\Repository\EntryRepository;
/** /**
* Entry. * Entry.
* *
* @XmlRoot("entry")
* @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())") * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
*/ */
#[ORM\Table(name: '`entry`')] #[ORM\Table(name: '`entry`')]
@ -32,6 +31,7 @@ use Wallabag\Repository\EntryRepository;
#[ORM\Index(columns: ['user_id', 'is_starred', 'starred_at'])] #[ORM\Index(columns: ['user_id', 'is_starred', 'starred_at'])]
#[ORM\Entity(repositoryClass: EntryRepository::class)] #[ORM\Entity(repositoryClass: EntryRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]
#[XmlRoot('entry')]
class Entry class Entry
{ {
use EntityTimestampsTrait; use EntityTimestampsTrait;
@ -39,43 +39,36 @@ class Entry
/** @Serializer\XmlAttribute */ /** @Serializer\XmlAttribute */
/** /**
* @var int * @var int
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'id', type: 'integer')] #[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\GeneratedValue(strategy: 'AUTO')]
#[Groups(['entries_for_user', 'export_all'])]
private $id; private $id;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'uid', type: 'string', length: 23, nullable: true)] #[ORM\Column(name: 'uid', type: 'string', length: 23, nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $uid; private $uid;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'title', type: 'text', nullable: true)] #[ORM\Column(name: 'title', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $title; private $title;
/** /**
* Define the url fetched by wallabag (the final url after potential redirections). * Define the url fetched by wallabag (the final url after potential redirections).
* *
* @var string|null * @var string|null
*
* @Assert\NotBlank()
* @Assert\Url(
* message = "The url '{{ value }}' is not a valid url",
* )
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'url', type: 'text', nullable: true)] #[ORM\Column(name: 'url', type: 'text', nullable: true)]
#[Assert\NotBlank]
#[Assert\Url(message: "The url '{{ value }}' is not a valid url")]
#[Groups(['entries_for_user', 'export_all'])]
private $url; private $url;
/** /**
@ -88,20 +81,18 @@ class Entry
* From where user retrieved/found the url (an other article, a twitter, or the given_url if non are provided). * From where user retrieved/found the url (an other article, a twitter, or the given_url if non are provided).
* *
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'origin_url', type: 'text', nullable: true)] #[ORM\Column(name: 'origin_url', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $originUrl; private $originUrl;
/** /**
* Define the url entered by the user (without redirections). * Define the url entered by the user (without redirections).
* *
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'given_url', type: 'text', nullable: true)] #[ORM\Column(name: 'given_url', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $givenUrl; private $givenUrl;
/** /**
@ -112,159 +103,134 @@ class Entry
/** /**
* @var bool * @var bool
*
* @Exclude
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'is_archived', type: 'boolean')] #[ORM\Column(name: 'is_archived', type: 'boolean')]
#[Exclude]
#[Groups(['entries_for_user', 'export_all'])]
private $isArchived = false; private $isArchived = false;
/** /**
* @var \DateTimeInterface|null * @var \DateTimeInterface|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'archived_at', type: 'datetime', nullable: true)] #[ORM\Column(name: 'archived_at', type: 'datetime', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $archivedAt; private $archivedAt;
/** /**
* @var bool * @var bool
*
* @Exclude
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'is_starred', type: 'boolean')] #[ORM\Column(name: 'is_starred', type: 'boolean')]
#[Exclude]
#[Groups(['entries_for_user', 'export_all'])]
private $isStarred = false; private $isStarred = false;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'content', type: 'text', nullable: true)] #[ORM\Column(name: 'content', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $content; private $content;
/** /**
* @var \DateTimeInterface * @var \DateTimeInterface
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'created_at', type: 'datetime')] #[ORM\Column(name: 'created_at', type: 'datetime')]
#[Groups(['entries_for_user', 'export_all'])]
private $createdAt; private $createdAt;
/** /**
* @var \DateTimeInterface * @var \DateTimeInterface
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'updated_at', type: 'datetime')] #[ORM\Column(name: 'updated_at', type: 'datetime')]
#[Groups(['entries_for_user', 'export_all'])]
private $updatedAt; private $updatedAt;
/** /**
* @var \DateTimeInterface|null * @var \DateTimeInterface|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'published_at', type: 'datetime', nullable: true)] #[ORM\Column(name: 'published_at', type: 'datetime', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $publishedAt; private $publishedAt;
/** /**
* @var array|null * @var array|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'published_by', type: 'array', nullable: true)] #[ORM\Column(name: 'published_by', type: 'array', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $publishedBy; private $publishedBy;
/** /**
* @var \DateTimeInterface|null * @var \DateTimeInterface|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'starred_at', type: 'datetime', nullable: true)] #[ORM\Column(name: 'starred_at', type: 'datetime', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $starredAt; private $starredAt;
/**
* @Groups({"entries_for_user", "export_all"})
*/
#[ORM\JoinTable] #[ORM\JoinTable]
#[ORM\OneToMany(targetEntity: Annotation::class, mappedBy: 'entry', cascade: ['persist', 'remove'])] #[ORM\OneToMany(targetEntity: Annotation::class, mappedBy: 'entry', cascade: ['persist', 'remove'])]
#[Groups(['entries_for_user', 'export_all'])]
private $annotations; private $annotations;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'mimetype', type: 'text', nullable: true)] #[ORM\Column(name: 'mimetype', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $mimetype; private $mimetype;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'language', type: 'string', length: 20, nullable: true)] #[ORM\Column(name: 'language', type: 'string', length: 20, nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $language; private $language;
/** /**
* @var int * @var int
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'reading_time', type: 'integer', nullable: false)] #[ORM\Column(name: 'reading_time', type: 'integer', nullable: false)]
#[Groups(['entries_for_user', 'export_all'])]
private $readingTime = 0; private $readingTime = 0;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'domain_name', type: 'text', nullable: true)] #[ORM\Column(name: 'domain_name', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $domainName; private $domainName;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'preview_picture', type: 'text', nullable: true)] #[ORM\Column(name: 'preview_picture', type: 'text', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $previewPicture; private $previewPicture;
/** /**
* @var string|null * @var string|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'http_status', type: 'string', length: 3, nullable: true)] #[ORM\Column(name: 'http_status', type: 'string', length: 3, nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $httpStatus; private $httpStatus;
/** /**
* @var array|null * @var array|null
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'headers', type: 'array', nullable: true)] #[ORM\Column(name: 'headers', type: 'array', nullable: true)]
#[Groups(['entries_for_user', 'export_all'])]
private $headers; private $headers;
/** /**
* @var bool * @var bool
*
* @Exclude
*
* @Groups({"entries_for_user", "export_all"})
*/ */
#[ORM\Column(name: 'is_not_parsed', type: 'boolean', options: ['default' => false])] #[ORM\Column(name: 'is_not_parsed', type: 'boolean', options: ['default' => false])]
#[Exclude]
#[Groups(['entries_for_user', 'export_all'])]
private $isNotParsed = false; private $isNotParsed = false;
/**
* @Exclude
*
* @Groups({"export_all"})
*/
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'entries')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'entries')]
#[Exclude]
#[Groups(['export_all'])]
private $user; private $user;
#[ORM\JoinTable(name: 'entry_tag')] #[ORM\JoinTable(name: 'entry_tag')]
@ -403,11 +369,9 @@ class Entry
return $this->isArchived; return $this->isArchived;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('is_archived')]
* @SerializedName("is_archived") #[Groups(['entries_for_user', 'export_all'])]
* @Groups({"entries_for_user", "export_all"})
*/
public function is_Archived() public function is_Archived()
{ {
return (int) $this->isArchived(); return (int) $this->isArchived();
@ -444,11 +408,9 @@ class Entry
return $this->isStarred; return $this->isStarred;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('is_starred')]
* @SerializedName("is_starred") #[Groups(['entries_for_user', 'export_all'])]
* @Groups({"entries_for_user", "export_all"})
*/
public function is_Starred() public function is_Starred()
{ {
return (int) $this->isStarred(); return (int) $this->isStarred();
@ -493,28 +455,22 @@ class Entry
return $this->user; return $this->user;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('user_name')]
* @SerializedName("user_name")
*/
public function getUserName() public function getUserName()
{ {
return $this->user->getUserName(); return $this->user->getUserName();
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('user_email')]
* @SerializedName("user_email")
*/
public function getUserEmail() public function getUserEmail()
{ {
return $this->user->getEmail(); return $this->user->getEmail();
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('user_id')]
* @SerializedName("user_id")
*/
public function getUserId() public function getUserId()
{ {
return $this->user->getId(); return $this->user->getId();
@ -669,11 +625,9 @@ class Entry
return $tags; return $tags;
} }
/** #[VirtualProperty]
* @VirtualProperty #[SerializedName('tags')]
* @SerializedName("tags") #[Groups(['entries_for_user', 'export_all'])]
* @Groups({"entries_for_user", "export_all"})
*/
public function getSerializedTags() public function getSerializedTags()
{ {
$data = []; $data = [];
@ -823,12 +777,11 @@ class Entry
* Used in the entries filter so it's more explicit for the end user than the uid. * Used in the entries filter so it's more explicit for the end user than the uid.
* Also used in the API. * Also used in the API.
* *
* @VirtualProperty
* @SerializedName("is_public")
* @Groups({"entries_for_user"})
*
* @return bool * @return bool
*/ */
#[VirtualProperty]
#[SerializedName('is_public')]
#[Groups(['entries_for_user'])]
public function isPublic() public function isPublic()
{ {
return null !== $this->uid; return null !== $this->uid;

View file

@ -25,14 +25,14 @@ class IgnoreOriginInstanceRule implements IgnoreOriginRuleInterface, RuleInterfa
/** /**
* @var string * @var string
* *
* @Assert\NotBlank()
* @Assert\Length(max=255)
* @RulerZAssert\ValidRule( * @RulerZAssert\ValidRule(
* allowed_variables={"host","_all"}, * allowed_variables={"host","_all"},
* allowed_operators={"=","~"} * allowed_operators={"=","~"}
* ) * )
*/ */
#[ORM\Column(name: 'rule', type: 'string', nullable: false)] #[ORM\Column(name: 'rule', type: 'string', nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
private $rule; private $rule;
/** /**

View file

@ -25,14 +25,14 @@ class IgnoreOriginUserRule implements IgnoreOriginRuleInterface, RuleInterface
/** /**
* @var string * @var string
* *
* @Assert\NotBlank()
* @Assert\Length(max=255)
* @RulerZAssert\ValidRule( * @RulerZAssert\ValidRule(
* allowed_variables={"host","_all"}, * allowed_variables={"host","_all"},
* allowed_operators={"=","~"} * allowed_operators={"=","~"}
* ) * )
*/ */
#[ORM\Column(name: 'rule', type: 'string', nullable: false)] #[ORM\Column(name: 'rule', type: 'string', nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
private $rule; private $rule;
#[ORM\JoinColumn(nullable: false)] #[ORM\JoinColumn(nullable: false)]

View file

@ -27,27 +27,24 @@ class SiteCredential
/** /**
* @var string * @var string
*
* @Assert\NotBlank()
* @Assert\Length(max=255)
*/ */
#[ORM\Column(name: 'host', type: 'string', length: 255)] #[ORM\Column(name: 'host', type: 'string', length: 255)]
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
private $host; private $host;
/** /**
* @var string * @var string
*
* @Assert\NotBlank()
*/ */
#[ORM\Column(name: 'username', type: 'text')] #[ORM\Column(name: 'username', type: 'text')]
#[Assert\NotBlank]
private $username; private $username;
/** /**
* @var string * @var string
*
* @Assert\NotBlank()
*/ */
#[ORM\Column(name: 'password', type: 'text')] #[ORM\Column(name: 'password', type: 'text')]
#[Assert\NotBlank]
private $password; private $password;
/** /**

View file

@ -12,38 +12,33 @@ use Wallabag\Repository\TagRepository;
/** /**
* Tag. * Tag.
*
* @XmlRoot("tag")
* @ExclusionPolicy("all")
*/ */
#[ORM\Table(name: '`tag`')] #[ORM\Table(name: '`tag`')]
#[ORM\Index(columns: ['label'])] #[ORM\Index(columns: ['label'])]
#[ORM\Entity(repositoryClass: TagRepository::class)] #[ORM\Entity(repositoryClass: TagRepository::class)]
class Tag #[XmlRoot('tag')]
#[ExclusionPolicy('all')]
class Tag implements \Stringable
{ {
/** /**
* @var int * @var int
*
* @Expose
*/ */
#[ORM\Column(name: 'id', type: 'integer')] #[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\GeneratedValue(strategy: 'AUTO')]
#[Expose]
private $id; private $id;
/** /**
* @var string * @var string
*
* @Expose
*/ */
#[ORM\Column(name: 'label', type: 'text')] #[ORM\Column(name: 'label', type: 'text')]
#[Expose]
private $label; private $label;
/**
* @Expose
* @Gedmo\Slug(fields={"label"}, prefix="t:")
*/
#[ORM\Column(length: 128, unique: true)] #[ORM\Column(length: 128, unique: true)]
#[Gedmo\Slug(fields: ['label'], prefix: 't:')]
#[Expose]
private $slug; private $slug;
#[ORM\ManyToMany(targetEntity: Entry::class, mappedBy: 'tags', cascade: ['persist'])] #[ORM\ManyToMany(targetEntity: Entry::class, mappedBy: 'tags', cascade: ['persist'])]
@ -54,7 +49,7 @@ class Tag
$this->entries = new ArrayCollection(); $this->entries = new ArrayCollection();
} }
public function __toString() public function __toString(): string
{ {
return $this->label; return $this->label;
} }

View file

@ -12,11 +12,10 @@ use Wallabag\Repository\TaggingRuleRepository;
/** /**
* Tagging rule. * Tagging rule.
*
* @XmlRoot("tagging_rule")
*/ */
#[ORM\Table(name: '`tagging_rule`')] #[ORM\Table(name: '`tagging_rule`')]
#[ORM\Entity(repositoryClass: TaggingRuleRepository::class)] #[ORM\Entity(repositoryClass: TaggingRuleRepository::class)]
#[XmlRoot('tagging_rule')]
class TaggingRule implements RuleInterface class TaggingRule implements RuleInterface
{ {
/** /**
@ -30,32 +29,27 @@ class TaggingRule implements RuleInterface
/** /**
* @var string * @var string
* *
* @Assert\NotBlank()
* @Assert\Length(max=255)
* @RulerZAssert\ValidRule( * @RulerZAssert\ValidRule(
* allowed_variables={"title", "url", "isArchived", "isStarred", "content", "language", "mimetype", "readingTime", "domainName"}, * allowed_variables={"title", "url", "isArchived", "isStarred", "content", "language", "mimetype", "readingTime", "domainName"},
* allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches", "notmatches"} * allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches", "notmatches"}
* ) * )
*
* @Groups({"export_tagging_rule"})
*/ */
#[ORM\Column(name: 'rule', type: 'string', nullable: false)] #[ORM\Column(name: 'rule', type: 'string', nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
#[Groups(['export_tagging_rule'])]
private $rule; private $rule;
/** /**
* @var array<string> * @var array<string>
*
* @Assert\NotBlank()
*
* @Groups({"export_tagging_rule"})
*/ */
#[ORM\Column(name: 'tags', type: 'simple_array', nullable: false)] #[ORM\Column(name: 'tags', type: 'simple_array', nullable: false)]
#[Assert\NotBlank]
#[Groups(['export_tagging_rule'])]
private $tags = []; private $tags = [];
/**
* @Exclude
*/
#[ORM\ManyToOne(targetEntity: Config::class, inversedBy: 'taggingRules')] #[ORM\ManyToOne(targetEntity: Config::class, inversedBy: 'taggingRules')]
#[Exclude]
private $config; private $config;
/** /**

View file

@ -20,15 +20,13 @@ use Wallabag\Repository\UserRepository;
/** /**
* User. * User.
*
* @XmlRoot("user")
*
* @UniqueEntity("email")
* @UniqueEntity("username")
*/ */
#[ORM\Table(name: '`user`')] #[ORM\Table(name: '`user`')]
#[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\HasLifecycleCallbacks] #[ORM\HasLifecycleCallbacks]
#[UniqueEntity('email')]
#[UniqueEntity('username')]
#[XmlRoot('user')]
class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface
{ {
use EntityTimestampsTrait; use EntityTimestampsTrait;
@ -42,12 +40,11 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="int", * type="int",
* example=12, * example=12,
* ) * )
*
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[ORM\Column(name: 'id', type: 'integer')] #[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')] #[ORM\GeneratedValue(strategy: 'AUTO')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $id; protected $id;
/** /**
@ -58,9 +55,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string", * type="string",
* example="Walla Baggger", * example="Walla Baggger",
* ) * )
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[ORM\Column(name: 'name', type: 'text', nullable: true)] #[ORM\Column(name: 'name', type: 'text', nullable: true)]
#[Groups(['user_api', 'user_api_with_client'])]
protected $name; protected $name;
/** /**
@ -71,9 +68,8 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string", * type="string",
* example="wallabag", * example="wallabag",
* ) * )
*
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[Groups(['user_api', 'user_api_with_client'])]
protected $username; protected $username;
/** /**
@ -84,9 +80,8 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string", * type="string",
* example="wallabag@wallabag.io", * example="wallabag@wallabag.io",
* ) * )
*
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[Groups(['user_api', 'user_api_with_client'])]
protected $email; protected $email;
/** /**
@ -97,9 +92,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string", * type="string",
* example="2023-06-27T19:25:44+0000", * example="2023-06-27T19:25:44+0000",
* ) * )
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[ORM\Column(name: 'created_at', type: 'datetime')] #[ORM\Column(name: 'created_at', type: 'datetime')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $createdAt; protected $createdAt;
/** /**
@ -110,9 +105,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string", * type="string",
* example="2023-06-27T19:37:30+0000", * example="2023-06-27T19:37:30+0000",
* ) * )
* @Groups({"user_api", "user_api_with_client"})
*/ */
#[ORM\Column(name: 'updated_at', type: 'datetime')] #[ORM\Column(name: 'updated_at', type: 'datetime')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $updatedAt; protected $updatedAt;
#[ORM\OneToMany(targetEntity: Entry::class, mappedBy: 'user', cascade: ['remove'])] #[ORM\OneToMany(targetEntity: Entry::class, mappedBy: 'user', cascade: ['remove'])]
@ -140,10 +135,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* description="Default client created during user registration. Used for further authorization", * description="Default client created during user registration. Used for further authorization",
* ref=@Model(type=Client::class, groups={"user_api_with_client"}) * ref=@Model(type=Client::class, groups={"user_api_with_client"})
* ) * )
*
* @Groups({"user_api_with_client"})
* @Accessor(getter="getFirstClient")
*/ */
#[Groups(['user_api_with_client'])]
#[Accessor(getter: 'getFirstClient')]
protected $default_client; protected $default_client;
#[ORM\Column(type: 'integer', nullable: true)] #[ORM\Column(type: 'integer', nullable: true)]
@ -383,7 +377,7 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
foreach ($this->backupCodes as $key => $backupCode) { foreach ($this->backupCodes as $key => $backupCode) {
// backup code are hashed using `password_hash` // backup code are hashed using `password_hash`
// see ConfigController->otpAppAction // see ConfigController->otpAppAction
if (password_verify($code, $backupCode)) { if (password_verify($code, (string) $backupCode)) {
return $key; return $key;
} }
} }

View file

@ -12,11 +12,9 @@ class ConfigUpdatedEvent extends Event
{ {
public const NAME = 'config.updated'; public const NAME = 'config.updated';
protected $config; public function __construct(
protected Config $config,
public function __construct(Config $entry) ) {
{
$this->config = $entry;
} }
public function getConfig(): Config public function getConfig(): Config

View file

@ -12,11 +12,9 @@ class EntryDeletedEvent extends Event
{ {
public const NAME = 'entry.deleted'; public const NAME = 'entry.deleted';
protected $entry; public function __construct(
protected Entry $entry,
public function __construct(Entry $entry) ) {
{
$this->entry = $entry;
} }
public function getEntry(): Entry public function getEntry(): Entry

View file

@ -12,11 +12,9 @@ class EntrySavedEvent extends Event
{ {
public const NAME = 'entry.saved'; public const NAME = 'entry.saved';
protected $entry; public function __construct(
protected Entry $entry,
public function __construct(Entry $entry) ) {
{
$this->entry = $entry;
} }
public function getEntry(): Entry public function getEntry(): Entry

View file

@ -9,13 +9,10 @@ use Symfony\Component\Security\Http\Event\LoginFailureEvent;
class AuthenticationFailureListener implements EventSubscriberInterface class AuthenticationFailureListener implements EventSubscriberInterface
{ {
private $requestStack; public function __construct(
private $logger; private readonly RequestStack $requestStack,
private readonly LoggerInterface $logger,
public function __construct(RequestStack $requestStack, LoggerInterface $logger) ) {
{
$this->requestStack = $requestStack;
$this->logger = $logger;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -15,27 +15,17 @@ use Wallabag\Entity\Config;
*/ */
class CreateConfigListener implements EventSubscriberInterface class CreateConfigListener implements EventSubscriberInterface
{ {
private $em; public function __construct(
private $itemsOnPage; private readonly EntityManagerInterface $em,
private $feedLimit; private $itemsOnPage,
private $language; private $feedLimit,
private $readingSpeed; private $language,
private $actionMarkAsRead; private $readingSpeed,
private $listMode; private $actionMarkAsRead,
private $requestStack; private $listMode,
private $displayThumbnails; private $displayThumbnails,
private readonly RequestStack $requestStack,
public function __construct(EntityManagerInterface $em, $itemsOnPage, $feedLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode, $displayThumbnails, RequestStack $requestStack) ) {
{
$this->em = $em;
$this->itemsOnPage = $itemsOnPage;
$this->feedLimit = $feedLimit;
$this->language = $language;
$this->readingSpeed = $readingSpeed;
$this->actionMarkAsRead = $actionMarkAsRead;
$this->listMode = $listMode;
$this->requestStack = $requestStack;
$this->displayThumbnails = $displayThumbnails;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -11,11 +11,9 @@ use Symfony\Component\HttpKernel\KernelEvents;
*/ */
class LocaleListener implements EventSubscriberInterface class LocaleListener implements EventSubscriberInterface
{ {
private $defaultLocale; public function __construct(
private $defaultLocale = 'en',
public function __construct($defaultLocale = 'en') ) {
{
$this->defaultLocale = $defaultLocale;
} }
public function onKernelRequest(RequestEvent $event) public function onKernelRequest(RequestEvent $event)

View file

@ -15,11 +15,9 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
*/ */
class PasswordResettingListener implements EventSubscriberInterface class PasswordResettingListener implements EventSubscriberInterface
{ {
private $router; public function __construct(
private readonly UrlGeneratorInterface $router,
public function __construct(UrlGeneratorInterface $router) ) {
{
$this->router = $router;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -11,19 +11,12 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class RegistrationListener implements EventSubscriberInterface class RegistrationListener implements EventSubscriberInterface
{ {
/** /**
* @var bool * @param bool $registrationEnabled
*/ */
private $registrationEnabled; public function __construct(
private $registrationEnabled,
/** private readonly UrlGeneratorInterface $urlGenerator,
* @var UrlGeneratorInterface ) {
*/
private $urlGenerator;
public function __construct($registrationEnabled, UrlGeneratorInterface $urlGenerator)
{
$this->registrationEnabled = $registrationEnabled;
$this->urlGenerator = $urlGenerator;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -16,11 +16,9 @@ use Wallabag\Entity\User;
*/ */
class UserLocaleListener class UserLocaleListener
{ {
private SessionInterface $session; public function __construct(
private readonly SessionInterface $session,
public function __construct(SessionInterface $session) ) {
{
$this->session = $session;
} }
public function onInteractiveLogin(InteractiveLoginEvent $event) public function onInteractiveLogin(InteractiveLoginEvent $event)

View file

@ -12,17 +12,12 @@ use Wallabag\Helper\DownloadImages;
class DownloadImagesSubscriber implements EventSubscriberInterface class DownloadImagesSubscriber implements EventSubscriberInterface
{ {
private $em; public function __construct(
private $downloadImages; private readonly EntityManagerInterface $em,
private $enabled; private readonly DownloadImages $downloadImages,
private $logger; private $enabled,
private readonly LoggerInterface $logger,
public function __construct(EntityManagerInterface $em, DownloadImages $downloadImages, $enabled, LoggerInterface $logger) ) {
{
$this->em = $em;
$this->downloadImages = $downloadImages;
$this->enabled = $enabled;
$this->logger = $logger;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -9,13 +9,10 @@ use Wallabag\Event\ConfigUpdatedEvent;
class GenerateCustomCSSSubscriber implements EventSubscriberInterface class GenerateCustomCSSSubscriber implements EventSubscriberInterface
{ {
private $em; public function __construct(
private $compiler; private readonly EntityManagerInterface $em,
private readonly Compiler $compiler,
public function __construct(EntityManagerInterface $em, Compiler $compiler) ) {
{
$this->em = $em;
$this->compiler = $compiler;
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array

View file

@ -17,11 +17,9 @@ use Wallabag\Entity\Entry;
*/ */
class SQLiteCascadeDeleteSubscriber implements EventSubscriber class SQLiteCascadeDeleteSubscriber implements EventSubscriber
{ {
private $doctrine; public function __construct(
private readonly ManagerRegistry $doctrine,
public function __construct(ManagerRegistry $doctrine) ) {
{
$this->doctrine = $doctrine;
} }
/** /**

View file

@ -8,11 +8,9 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
class SchemaAdapterSubscriber implements EventSubscriber class SchemaAdapterSubscriber implements EventSubscriber
{ {
private string $databaseTablePrefix; public function __construct(
private readonly string $databaseTablePrefix,
public function __construct(string $databaseTablePrefix) ) {
{
$this->databaseTablePrefix = $databaseTablePrefix;
} }
public function getSubscribedEvents(): array public function getSubscribedEvents(): array

View file

@ -9,11 +9,9 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
class AuthenticatorProvider implements ExpressionFunctionProviderInterface class AuthenticatorProvider implements ExpressionFunctionProviderInterface
{ {
private HttpClientInterface $requestHtmlFunctionClient; public function __construct(
private readonly HttpClientInterface $requestHtmlFunctionClient,
public function __construct(HttpClientInterface $requestHtmlFunctionClient) ) {
{
$this->requestHtmlFunctionClient = $requestHtmlFunctionClient;
} }
public function getFunctions(): array public function getFunctions(): array
@ -31,12 +29,10 @@ class AuthenticatorProvider implements ExpressionFunctionProviderInterface
{ {
return new ExpressionFunction( return new ExpressionFunction(
'request_html', 'request_html',
function () { function (): void {
throw new \Exception('Not supported'); throw new \Exception('Not supported');
}, },
function (array $arguments, $uri) { fn (array $arguments, $uri) => $this->requestHtmlFunctionClient->request('GET', $uri)->getContent()
return $this->requestHtmlFunctionClient->request('GET', $uri)->getContent();
}
); );
} }
@ -44,7 +40,7 @@ class AuthenticatorProvider implements ExpressionFunctionProviderInterface
{ {
return new ExpressionFunction( return new ExpressionFunction(
'preg_match', 'preg_match',
function () { function (): void {
throw new \Exception('Not supported'); throw new \Exception('Not supported');
}, },
function (array $arguments, $pattern, $html) { function (array $arguments, $pattern, $html) {
@ -63,7 +59,7 @@ class AuthenticatorProvider implements ExpressionFunctionProviderInterface
{ {
return new ExpressionFunction( return new ExpressionFunction(
'xpath', 'xpath',
function () { function (): void {
throw new \Exception('Not supported'); throw new \Exception('Not supported');
}, },
function (array $arguments, $xpathQuery, $html) { function (array $arguments, $xpathQuery, $html) {
@ -71,7 +67,7 @@ class AuthenticatorProvider implements ExpressionFunctionProviderInterface
$crawler = new Crawler((string) $html); $crawler = new Crawler((string) $html);
$crawler = $crawler->filterXPath($xpathQuery); $crawler = $crawler->filterXPath($xpathQuery);
} catch (\Throwable $e) { } catch (\Throwable) {
return ''; return '';
} }

View file

@ -10,17 +10,12 @@ use Symfony\Component\Form\DataTransformerInterface;
*/ */
class StringToListTransformer implements DataTransformerInterface class StringToListTransformer implements DataTransformerInterface
{ {
/**
* @var string
*/
private $separator;
/** /**
* @param string $separator The separator used in the list * @param string $separator The separator used in the list
*/ */
public function __construct($separator = ',') public function __construct(
{ private $separator = ',',
$this->separator = $separator; ) {
} }
/** /**

View file

@ -28,12 +28,8 @@ class ClientType extends AbstractType
$builder->get('redirect_uris') $builder->get('redirect_uris')
->addModelTransformer(new CallbackTransformer( ->addModelTransformer(new CallbackTransformer(
function ($originalUri) { fn ($originalUri) => $originalUri,
return $originalUri; fn ($submittedUri) => [$submittedUri]
},
function ($submittedUri) {
return [$submittedUri];
}
)) ))
; ;
} }

View file

@ -14,17 +14,14 @@ use Wallabag\Entity\Config;
class ConfigType extends AbstractType class ConfigType extends AbstractType
{ {
private $languages = [];
private $fonts = [];
/** /**
* @param array $languages Languages come from configuration, array just code language as key and label as value * @param array $languages Languages come from configuration, array just code language as key and label as value
* @param array $fonts Fonts come from configuration, array just font name as key / value * @param array $fonts Fonts come from configuration, array just font name as key / value
*/ */
public function __construct($languages, $fonts) public function __construct(
{ private $languages,
$this->languages = $languages; private $fonts,
$this->fonts = $fonts; ) {
} }
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)

View file

@ -21,16 +21,13 @@ use Wallabag\Repository\EntryRepository;
class EntryFilterType extends AbstractType class EntryFilterType extends AbstractType
{ {
private $repository;
private $tokenStorage;
/** /**
* Repository & user are used to get a list of language entries for this user. * Repository & user are used to get a list of language entries for this user.
*/ */
public function __construct(EntryRepository $entryRepository, TokenStorageInterface $tokenStorage) public function __construct(
{ private readonly EntryRepository $repository,
$this->repository = $entryRepository; private readonly TokenStorageInterface $tokenStorage,
$this->tokenStorage = $tokenStorage; ) {
} }
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)

View file

@ -17,26 +17,19 @@ use Wallabag\Tools\Utils;
*/ */
class ContentProxy class ContentProxy
{ {
protected $graby;
protected $tagger;
protected $ignoreOriginProcessor;
protected $validator;
protected $logger;
protected $mimeTypes; protected $mimeTypes;
protected $fetchingErrorMessage;
protected $eventDispatcher; protected $eventDispatcher;
protected $storeArticleHeaders;
public function __construct(Graby $graby, RuleBasedTagger $tagger, RuleBasedIgnoreOriginProcessor $ignoreOriginProcessor, ValidatorInterface $validator, LoggerInterface $logger, $fetchingErrorMessage, $storeArticleHeaders = false) public function __construct(
{ protected Graby $graby,
$this->graby = $graby; protected RuleBasedTagger $tagger,
$this->tagger = $tagger; protected RuleBasedIgnoreOriginProcessor $ignoreOriginProcessor,
$this->ignoreOriginProcessor = $ignoreOriginProcessor; protected ValidatorInterface $validator,
$this->validator = $validator; protected LoggerInterface $logger,
$this->logger = $logger; protected $fetchingErrorMessage,
protected $storeArticleHeaders = false,
) {
$this->mimeTypes = new MimeTypes(); $this->mimeTypes = new MimeTypes();
$this->fetchingErrorMessage = $fetchingErrorMessage;
$this->storeArticleHeaders = $storeArticleHeaders;
} }
/** /**
@ -59,7 +52,7 @@ class ContentProxy
$fetchedContent['title'] = $this->sanitizeContentTitle( $fetchedContent['title'] = $this->sanitizeContentTitle(
$fetchedContent['title'], $fetchedContent['title'],
isset($fetchedContent['headers']['content-type']) ? $fetchedContent['headers']['content-type'] : '' $fetchedContent['headers']['content-type'] ?? ''
); );
// when content is imported, we have information in $content // when content is imported, we have information in $content
@ -107,7 +100,9 @@ class ContentProxy
return; return;
} }
$this->logger->warning('Language validation failed. ' . (string) $errors); foreach ($errors as $error) {
$this->logger->warning('Language validation failed. ' . $error->getMessage());
}
} }
/** /**
@ -128,7 +123,9 @@ class ContentProxy
return; return;
} }
$this->logger->warning('PreviewPicture validation failed. ' . (string) $errors); foreach ($errors as $error) {
$this->logger->warning('PreviewPicture validation failed. ' . $error->getMessage());
}
} }
/** /**

View file

@ -13,13 +13,12 @@ use Psr\Log\LoggerInterface;
*/ */
class CryptoProxy class CryptoProxy
{ {
private $logger;
private $encryptionKey; private $encryptionKey;
public function __construct($encryptionKeyPath, LoggerInterface $logger) public function __construct(
{ $encryptionKeyPath,
$this->logger = $logger; private readonly LoggerInterface $logger,
) {
if (!file_exists($encryptionKeyPath)) { if (!file_exists($encryptionKeyPath)) {
$key = Key::createNewRandomKey(); $key = Key::createNewRandomKey();

View file

@ -16,19 +16,16 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
class DownloadImages class DownloadImages
{ {
public const REGENERATE_PICTURES_QUALITY = 80; public const REGENERATE_PICTURES_QUALITY = 80;
private $client;
private $baseFolder;
private $logger;
private $mimeTypes; private $mimeTypes;
private $wallabagUrl; private $wallabagUrl;
public function __construct(HttpClientInterface $downloadImagesClient, $baseFolder, $wallabagUrl, LoggerInterface $logger) public function __construct(
{ private readonly HttpClientInterface $client,
$this->client = $downloadImagesClient; private $baseFolder,
$this->baseFolder = $baseFolder; $wallabagUrl,
$this->wallabagUrl = rtrim($wallabagUrl, '/'); private readonly LoggerInterface $logger,
$this->logger = $logger; ) {
$this->wallabagUrl = rtrim((string) $wallabagUrl, '/');
$this->mimeTypes = new MimeTypes(); $this->mimeTypes = new MimeTypes();
$this->setFolder(); $this->setFolder();
@ -174,7 +171,7 @@ class DownloadImages
try { try {
$im = imagecreatefromstring($res->getContent()); $im = imagecreatefromstring($res->getContent());
} catch (\Exception $e) { } catch (\Exception) {
$im = false; $im = false;
} }
@ -193,7 +190,7 @@ class DownloadImages
$imagick->readImageBlob($res->getContent()); $imagick->readImageBlob($res->getContent());
$imagick->setImageFormat('gif'); $imagick->setImageFormat('gif');
$imagick->writeImages($localPath, true); $imagick->writeImages($localPath, true);
} catch (\Exception $e) { } catch (\Exception) {
// if Imagick fail, fallback to the default solution // if Imagick fail, fallback to the default solution
imagegif($im, $localPath); imagegif($im, $localPath);
} }
@ -294,9 +291,7 @@ class DownloadImages
preg_match_all($pattern, $srcsetAttribute, $matches); preg_match_all($pattern, $srcsetAttribute, $matches);
$srcset = \call_user_func_array('array_merge', $matches); $srcset = \call_user_func_array('array_merge', $matches);
$srcsetUrls = array_map(function ($src) { $srcsetUrls = array_map(fn ($src) => trim(explode(' ', (string) $src, 2)[0]), $srcset);
return trim(explode(' ', $src, 2)[0]);
}, $srcset);
$urls = array_merge($srcsetUrls, $urls); $urls = array_merge($srcsetUrls, $urls);
} }

View file

@ -19,10 +19,6 @@ use Wallabag\Entity\User;
*/ */
class EntriesExport class EntriesExport
{ {
private $wallabagUrl;
private $logoPath;
private $translator;
private $tokenStorage;
private $title = ''; private $title = '';
private $entries = []; private $entries = [];
private $author = 'wallabag'; private $author = 'wallabag';
@ -34,12 +30,12 @@ class EntriesExport
* @param string $logoPath Path to the logo FROM THE BUNDLE SCOPE * @param string $logoPath Path to the logo FROM THE BUNDLE SCOPE
* @param TokenStorageInterface $tokenStorage Needed to retrieve the current user * @param TokenStorageInterface $tokenStorage Needed to retrieve the current user
*/ */
public function __construct(TranslatorInterface $translator, $wallabagUrl, $logoPath, TokenStorageInterface $tokenStorage) public function __construct(
{ private readonly TranslatorInterface $translator,
$this->translator = $translator; private $wallabagUrl,
$this->wallabagUrl = $wallabagUrl; private $logoPath,
$this->logoPath = $logoPath; private readonly TokenStorageInterface $tokenStorage,
$this->tokenStorage = $tokenStorage; ) {
} }
/** /**

View file

@ -10,11 +10,9 @@ use Wallabag\Entity\User;
class PreparePagerForEntries class PreparePagerForEntries
{ {
private $tokenStorage; public function __construct(
private readonly TokenStorageInterface $tokenStorage,
public function __construct(TokenStorageInterface $tokenStorage) ) {
{
$this->tokenStorage = $tokenStorage;
} }
/** /**

View file

@ -13,13 +13,10 @@ use Wallabag\Entity\User;
*/ */
class Redirect class Redirect
{ {
private $router; public function __construct(
private $tokenStorage; private readonly UrlGeneratorInterface $router,
private readonly TokenStorageInterface $tokenStorage,
public function __construct(UrlGeneratorInterface $router, TokenStorageInterface $tokenStorage) ) {
{
$this->router = $router;
$this->tokenStorage = $tokenStorage;
} }
/** /**

View file

@ -9,15 +9,11 @@ use Wallabag\Repository\IgnoreOriginInstanceRuleRepository;
class RuleBasedIgnoreOriginProcessor class RuleBasedIgnoreOriginProcessor
{ {
protected $rulerz; public function __construct(
protected $logger; protected RulerZ $rulerz,
protected $ignoreOriginInstanceRuleRepository; protected LoggerInterface $logger,
protected IgnoreOriginInstanceRuleRepository $ignoreOriginInstanceRuleRepository,
public function __construct(RulerZ $rulerz, LoggerInterface $logger, IgnoreOriginInstanceRuleRepository $ignoreOriginInstanceRuleRepository) ) {
{
$this->rulerz = $rulerz;
$this->logger = $logger;
$this->ignoreOriginInstanceRuleRepository = $ignoreOriginInstanceRuleRepository;
} }
/** /**

View file

@ -14,17 +14,12 @@ use Wallabag\Repository\TagRepository;
class RuleBasedTagger class RuleBasedTagger
{ {
private $rulerz; public function __construct(
private $tagRepository; private readonly RulerZ $rulerz,
private $entryRepository; private readonly TagRepository $tagRepository,
private $logger; private readonly EntryRepository $entryRepository,
private readonly LoggerInterface $logger,
public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository, LoggerInterface $logger) ) {
{
$this->rulerz = $rulerz;
$this->tagRepository = $tagRepository;
$this->entryRepository = $entryRepository;
$this->logger = $logger;
} }
/** /**

View file

@ -8,14 +8,9 @@ use Wallabag\Repository\TagRepository;
class TagsAssigner class TagsAssigner
{ {
/** public function __construct(
* @var TagRepository protected TagRepository $tagRepository,
*/ ) {
protected $tagRepository;
public function __construct(TagRepository $tagRepository)
{
$this->tagRepository = $tagRepository;
} }
/** /**
@ -44,7 +39,7 @@ class TagsAssigner
} }
foreach ($tags as $label) { foreach ($tags as $label) {
$label = trim(mb_convert_case($label, \MB_CASE_LOWER)); $label = trim(mb_convert_case((string) $label, \MB_CASE_LOWER));
// avoid empty tag // avoid empty tag
if ('' === $label) { if ('' === $label) {

View file

@ -14,19 +14,13 @@ use Wallabag\SiteConfig\SiteConfigBuilder;
class Authenticator implements LoggerAwareInterface class Authenticator implements LoggerAwareInterface
{ {
/** @var SiteConfigBuilder */
private $configBuilder;
/** @var LoginFormAuthenticator */
private $authenticator;
/** @var LoggerInterface */ /** @var LoggerInterface */
private $logger; private $logger;
public function __construct(SiteConfigBuilder $configBuilder, LoginFormAuthenticator $authenticator) public function __construct(
{ private readonly SiteConfigBuilder $configBuilder,
$this->configBuilder = $configBuilder; private readonly LoginFormAuthenticator $authenticator,
$this->authenticator = $authenticator; ) {
$this->logger = new NullLogger(); $this->logger = new NullLogger();
} }

View file

@ -11,19 +11,14 @@ use Symfony\Contracts\HttpClient\ResponseStreamInterface;
class WallabagClient implements HttpClientInterface class WallabagClient implements HttpClientInterface
{ {
private $restrictedAccess; private readonly HttpClientInterface $httpClient;
private HttpClientInterface $httpClient;
private HttpBrowser $browser;
private Authenticator $authenticator;
private LoggerInterface $logger;
public function __construct($restrictedAccess, HttpBrowser $browser, Authenticator $authenticator, LoggerInterface $logger)
{
$this->restrictedAccess = $restrictedAccess;
$this->browser = $browser;
$this->authenticator = $authenticator;
$this->logger = $logger;
public function __construct(
private $restrictedAccess,
private readonly HttpBrowser $browser,
private readonly Authenticator $authenticator,
private readonly LoggerInterface $logger,
) {
$this->httpClient = HttpClient::create([ $this->httpClient = HttpClient::create([
'timeout' => 10, 'timeout' => 10,
]); ]);

View file

@ -7,7 +7,6 @@ use OldSound\RabbitMqBundle\RabbitMq\ProducerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Wallabag\Entity\Entry; use Wallabag\Entity\Entry;
use Wallabag\Entity\Tag;
use Wallabag\Entity\User; use Wallabag\Entity\User;
use Wallabag\Event\EntrySavedEvent; use Wallabag\Event\EntrySavedEvent;
use Wallabag\Helper\ContentProxy; use Wallabag\Helper\ContentProxy;
@ -15,11 +14,6 @@ use Wallabag\Helper\TagsAssigner;
abstract class AbstractImport implements ImportInterface abstract class AbstractImport implements ImportInterface
{ {
protected $em;
protected $logger;
protected $contentProxy;
protected $tagsAssigner;
protected $eventDispatcher;
protected $producer; protected $producer;
protected $user; protected $user;
protected $markAsRead; protected $markAsRead;
@ -28,13 +22,13 @@ abstract class AbstractImport implements ImportInterface
protected $importedEntries = 0; protected $importedEntries = 0;
protected $queuedEntries = 0; protected $queuedEntries = 0;
public function __construct(EntityManagerInterface $em, ContentProxy $contentProxy, TagsAssigner $tagsAssigner, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger) public function __construct(
{ protected EntityManagerInterface $em,
$this->em = $em; protected ContentProxy $contentProxy,
$this->logger = $logger; protected TagsAssigner $tagsAssigner,
$this->contentProxy = $contentProxy; protected EventDispatcherInterface $eventDispatcher,
$this->tagsAssigner = $tagsAssigner; protected LoggerInterface $logger,
$this->eventDispatcher = $eventDispatcher; ) {
} }
public function setLogger(LoggerInterface $logger): void public function setLogger(LoggerInterface $logger): void
@ -178,9 +172,7 @@ abstract class AbstractImport implements ImportInterface
$entryToBeFlushed = []; $entryToBeFlushed = [];
// clear only affected entities $this->em->clear();
$this->em->clear(Entry::class);
$this->em->clear(Tag::class);
} }
++$i; ++$i;
} }

View file

@ -39,7 +39,7 @@ class ChromeImport extends BrowserImport
'is_archived' => (int) $this->markAsRead, 'is_archived' => (int) $this->markAsRead,
'is_starred' => false, 'is_starred' => false,
'tags' => '', 'tags' => '',
'created_at' => substr($entry['date_added'], 0, 10), 'created_at' => substr((string) $entry['date_added'], 0, 10),
]; ];
if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) { if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) {

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