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

View file

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

View file

@ -173,6 +173,7 @@
"phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-symfony": "^1.4.13",
"phpunit/phpunit": "^9.6.22",
"rector/rector": "^1.2",
"shipmonk/composer-dependency-analyser": "^1.8.2",
"symfony/css-selector": "^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",
"This file is @generated automatically"
],
"content-hash": "df71f834528625c49553a128ca93e4aa",
"content-hash": "00b8f95df6ec0572c06ad6f34847405c",
"packages": [
{
"name": "babdev/pagerfanta-bundle",
@ -17856,6 +17856,65 @@
],
"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",
"version": "1.0.2",

View file

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

View file

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

View file

@ -11,11 +11,9 @@ use Wallabag\Helper\CryptoProxy;
class SiteCredentialFixtures extends Fixture implements DependentFixtureInterface
{
private CryptoProxy $cryptoProxy;
public function __construct(CryptoProxy $cryptoProxy)
{
$this->cryptoProxy = $cryptoProxy;
public function __construct(
private readonly CryptoProxy $cryptoProxy,
) {
}
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 $defaultDescription = 'Cleans downloaded images which are no more associated to an entry';
private EntryRepository $entryRepository;
private DownloadImages $downloadImages;
public function __construct(EntryRepository $entryRepository, DownloadImages $downloadImages)
{
$this->entryRepository = $entryRepository;
$this->downloadImages = $downloadImages;
public function __construct(
private readonly EntryRepository $entryRepository,
private readonly DownloadImages $downloadImages,
) {
parent::__construct();
}

View file

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

View file

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

View file

@ -19,16 +19,12 @@ class GenerateUrlHashesCommand extends Command
protected static $defaultDescription = 'Generates hashed urls for each entry';
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();
}
@ -49,7 +45,7 @@ class GenerateUrlHashesCommand extends Command
try {
$user = $this->getUser($username);
$this->generateHashedUrls($user);
} catch (NoResultException $e) {
} catch (NoResultException) {
$output->writeln(\sprintf('<error>User "%s" not found.</error>', $username));
return 1;

View file

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

View file

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

View file

@ -37,24 +37,15 @@ class InstallCommand extends Command
'curl_multi_init',
];
private EntityManagerInterface $entityManager;
private EventDispatcherInterface $dispatcher;
private UserManagerInterface $userManager;
private TableMetadataStorageConfiguration $tableMetadataStorageConfiguration;
private string $databaseDriver;
private array $defaultSettings;
private 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;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EventDispatcherInterface $dispatcher,
private readonly UserManagerInterface $userManager,
private readonly TableMetadataStorageConfiguration $tableMetadataStorageConfiguration,
private readonly string $databaseDriver,
private readonly array $defaultSettings,
private readonly array $defaultIgnoreOriginInstanceRules,
) {
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"
$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', '<')) {
$fulfilled = false;
@ -411,7 +402,7 @@ class InstallCommand extends Command
try {
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
return false;

View file

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

View file

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

View file

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

View file

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

View file

@ -15,15 +15,11 @@ class UpdatePicturesPathCommand extends Command
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.';
private EntityManagerInterface $entityManager;
private EntryRepository $entryRepository;
private string $wallabagUrl;
public function __construct(EntityManagerInterface $entityManager, EntryRepository $entryRepository, $wallabagUrl)
{
$this->entityManager = $entityManager;
$this->entryRepository = $entryRepository;
$this->wallabagUrl = $wallabagUrl;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly EntryRepository $entryRepository,
private readonly string $wallabagUrl,
) {
parent::__construct();
}

View file

@ -7,25 +7,19 @@ use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Wallabag\Entity\Entry;
use Wallabag\Entity\Tag;
use Wallabag\Event\EntrySavedEvent;
use Wallabag\Import\AbstractImport;
use Wallabag\Repository\UserRepository;
abstract class AbstractConsumer
{
protected $em;
protected $userRepository;
protected $import;
protected $eventDispatcher;
protected $logger;
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;
public function __construct(
protected EntityManagerInterface $em,
protected UserRepository $userRepository,
protected AbstractImport $import,
protected EventDispatcherInterface $eventDispatcher,
protected ?LoggerInterface $logger = null,
) {
$this->logger = $logger ?: new NullLogger();
}
@ -74,9 +68,7 @@ abstract class AbstractConsumer
// entry saved, dispatch event about it!
$this->eventDispatcher->dispatch(new EntrySavedEvent($entry), EntrySavedEvent::NAME);
// clear only affected entities
$this->em->clear(Entry::class);
$this->em->clear(Tag::class);
$this->em->clear();
} catch (\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
{
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(
Consumer $pocketConsumer,
Consumer $readabilityConsumer,
Consumer $wallabagV1Consumer,
Consumer $wallabagV2Consumer,
Consumer $firefoxConsumer,
Consumer $chromeConsumer,
Consumer $instapaperConsumer,
Consumer $pinboardConsumer,
Consumer $deliciousConsumer,
Consumer $elcuratorConsumer,
Consumer $shaarliConsumer,
Consumer $pocketHtmlConsumer,
Consumer $omnivoreConsumer,
private readonly Consumer $pocketConsumer,
private readonly Consumer $readabilityConsumer,
private readonly Consumer $wallabagV1Consumer,
private readonly Consumer $wallabagV2Consumer,
private readonly Consumer $firefoxConsumer,
private readonly Consumer $chromeConsumer,
private readonly Consumer $instapaperConsumer,
private readonly Consumer $pinboardConsumer,
private readonly Consumer $deliciousConsumer,
private readonly Consumer $elcuratorConsumer,
private readonly Consumer $shaarliConsumer,
private readonly Consumer $pocketHtmlConsumer,
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
{
protected EntityManagerInterface $entityManager;
protected SerializerInterface $serializer;
protected FormFactoryInterface $formFactory;
public function __construct(EntityManagerInterface $entityManager, SerializerInterface $serializer, FormFactoryInterface $formFactory)
{
$this->entityManager = $entityManager;
$this->serializer = $serializer;
$this->formFactory = $formFactory;
public function __construct(
protected EntityManagerInterface $entityManager,
protected SerializerInterface $serializer,
protected FormFactoryInterface $formFactory,
) {
}
/**
@ -36,11 +32,10 @@ class AnnotationController extends AbstractFOSRestController
*
* @see Api\WallabagRestController
*
* @Route("/annotations/{entry}.{_format}", name="annotations_get_annotations", methods={"GET"}, defaults={"_format": "json"})
* @IsGranted("LIST_ANNOTATIONS", subject="entry")
*
* @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)
{
$annotationRows = $annotationRepository->findByEntryIdAndUserId($entry->getId(), $this->getUser()->getId());
@ -58,11 +53,10 @@ class AnnotationController extends AbstractFOSRestController
*
* @see Api\WallabagRestController
*
* @Route("/annotations/{entry}.{_format}", name="annotations_post_annotation", methods={"POST"}, defaults={"_format": "json"})
* @IsGranted("CREATE_ANNOTATIONS", subject="entry")
*
* @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)
{
$data = json_decode($request->getContent(), true);
@ -93,11 +87,10 @@ class AnnotationController extends AbstractFOSRestController
*
* @see Api\WallabagRestController
*
* @Route("/annotations/{annotation}.{_format}", name="annotations_put_annotation", methods={"PUT"}, defaults={"_format": "json"})
* @IsGranted("EDIT", subject="annotation")
*
* @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)
{
try {
@ -129,11 +122,10 @@ class AnnotationController extends AbstractFOSRestController
*
* @see Api\WallabagRestController
*
* @Route("/annotations/{annotation}.{_format}", name="annotations_delete_annotation", methods={"DELETE"}, defaults={"_format": "json"})
* @IsGranted("DELETE", subject="annotation")
*
* @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)
{
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
*/
#[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)
{
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
*/
#[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)
{
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
*/
#[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)
{
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
*/
#[Route(path: '/api/annotations/{annotation}.{_format}', name: 'api_delete_annotation', methods: ['DELETE'], defaults: ['_format' => 'json'])]
#[IsGranted('DELETE', subject: 'annotation')]
public function deleteAnnotationAction(Annotation $annotation)
{
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
*/
#[Route(path: '/api/config.{_format}', name: 'api_get_config', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getConfigAction(SerializerInterface $serializer)
{
$this->validateAuthentication();

View file

@ -18,10 +18,9 @@ class DeveloperController extends AbstractController
/**
* List all clients and link to create a new one.
*
* @Route("/developer", name="developer", methods={"GET"})
*
* @return Response
*/
#[Route(path: '/developer', name: 'developer', methods: ['GET'])]
public function indexAction(ClientRepository $repo)
{
$clients = $repo->findByUser($this->getUser()->getId());
@ -34,10 +33,9 @@ class DeveloperController extends AbstractController
/**
* Create a client (an app).
*
* @Route("/developer/client/create", name="developer_create_client", methods={"GET", "POST"})
*
* @return Response
*/
#[Route(path: '/developer/client/create', name: 'developer_create_client', methods: ['GET', 'POST'])]
public function createClientAction(Request $request, EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
$client = new Client($this->getUser());
@ -69,10 +67,9 @@ class DeveloperController extends AbstractController
/**
* Remove a client.
*
* @Route("/developer/client/delete/{id}", name="developer_delete_client", methods={"POST"}, requirements={"id" = "\d+"})
*
* @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)
{
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.
*
* @Route("/developer/howto/first-app", name="developer_howto_firstapp", methods={"GET"})
*
* @return Response
*/
#[Route(path: '/developer/howto/first-app', name: 'developer_howto_firstapp', methods: ['GET'])]
public function howtoFirstAppAction()
{
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
*/
#[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)
{
$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) {
$results = array_map(function ($v) {
return null !== $v;
}, $results);
$results = array_map(fn ($v) => null !== $v, $results);
}
$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
*/
#[Route(path: '/api/entries.{_format}', name: 'api_get_entries', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ENTRIES')]
public function getEntriesAction(Request $request, EntryRepository $entryRepository)
{
$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
*/
#[Route(path: '/api/entries/{entry}.{_format}', name: 'api_get_entry', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('VIEW', subject: 'entry')]
public function getEntryAction(Entry $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
*/
#[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)
{
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
*/
#[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)
{
$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
*
* @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)
{
$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
*/
#[Route(path: '/api/entries.{_format}', name: 'api_post_entries', methods: ['POST'], defaults: ['_format' => 'json'])]
#[IsGranted('CREATE_ENTRIES')]
public function postEntriesAction(
Request $request,
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
*/
#[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)
{
$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
*/
#[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)
{
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
*/
#[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)
{
$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
*/
#[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)
{
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
*/
#[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)
{
$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
*/
#[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)
{
$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
*/
#[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)
{
$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
*/
#[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)
{
$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
*/
#[Route(path: '/api/search.{_format}', name: 'api_get_search', methods: ['GET'], defaults: ['_format' => 'json'])]
#[IsGranted('LIST_ENTRIES')]
public function getSearchAction(Request $request, EntryRepository $entryRepository)
{
$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
*/
#[Route(path: '/api/tags.{_format}', name: 'api_get_tags', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getTagsAction(TagRepository $tagRepository)
{
$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
*/
#[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)
{
$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
*/
#[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)
{
$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
*/
#[Route(path: '/api/tags/{tag}.{_format}', name: 'api_delete_tag', methods: ['DELETE'], defaults: ['_format' => 'json'])]
public function deleteTagAction(Tag $tag, TagRepository $tagRepository, EntryRepository $entryRepository)
{
$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
*/
#[Route(path: '/api/taggingrule/export.{_format}', name: 'api_get_taggingrule_export', methods: ['GET'], defaults: ['_format' => 'json'])]
public function getTaggingruleExportAction()
{
$this->validateAuthentication();

View file

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

View file

@ -44,39 +44,20 @@ use Wallabag\Tools\Utils;
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(
EntityManagerInterface $entityManager,
UserManagerInterface $userManager,
EntryRepository $entryRepository,
TagRepository $tagRepository,
AnnotationRepository $annotationRepository,
ConfigRepository $configRepository,
EventDispatcherInterface $eventDispatcher,
Redirect $redirectHelper,
private readonly EntityManagerInterface $entityManager,
private readonly UserManagerInterface $userManager,
private readonly EntryRepository $entryRepository,
private readonly TagRepository $tagRepository,
private readonly AnnotationRepository $annotationRepository,
private readonly ConfigRepository $configRepository,
private readonly EventDispatcherInterface $eventDispatcher,
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("/config", name="config", methods={"GET", "POST"})
* @IsGranted("EDIT_CONFIG")
*/
#[Route(path: '/config', name: 'config', methods: ['GET', 'POST'])]
#[IsGranted('EDIT_CONFIG')]
public function indexAction(Request $request, Config $craueConfig, TaggingRuleRepository $taggingRuleRepository, IgnoreOriginUserRuleRepository $ignoreOriginUserRuleRepository, UserRepository $userRepository)
{
$config = $this->getConfig();
@ -266,10 +247,9 @@ class ConfigController extends AbstractController
/**
* 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)
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -292,10 +272,9 @@ class ConfigController extends AbstractController
/**
* 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)
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -321,10 +300,9 @@ class ConfigController extends AbstractController
/**
* 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)
{
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.
*
* @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)
{
if (!$this->isCsrfTokenValid('otp', $request->request->get('token'))) {
@ -367,9 +344,7 @@ class ConfigController extends AbstractController
$backupCodes = (new BackupCodes())->toArray();
$backupCodesHashed = array_map(
function ($backupCode) {
return password_hash($backupCode, \PASSWORD_DEFAULT);
},
fn ($backupCode) => password_hash((string) $backupCode, \PASSWORD_DEFAULT),
$backupCodes
);
@ -411,10 +386,9 @@ class ConfigController extends AbstractController
/**
* 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)
{
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
*/
#[Route(path: '/generate-token', name: 'generate_token', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function generateTokenAction(Request $request)
{
$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
*/
#[Route(path: '/revoke-token', name: 'revoke_token', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function revokeTokenAction(Request $request)
{
$config = $this->getConfig();
@ -503,11 +475,10 @@ class ConfigController extends AbstractController
/**
* 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
*/
#[Route(path: '/tagging-rule/delete/{taggingRule}', name: 'delete_tagging_rule', methods: ['GET'], requirements: ['taggingRule' => '\d+'])]
#[IsGranted('DELETE', subject: 'taggingRule')]
public function deleteTaggingRuleAction(TaggingRule $taggingRule)
{
$this->entityManager->remove($taggingRule);
@ -524,11 +495,10 @@ class ConfigController extends AbstractController
/**
* Edit a tagging rule.
*
* @Route("/tagging-rule/edit/{taggingRule}", name="edit_tagging_rule", methods={"GET"}, requirements={"taggingRule" = "\d+"})
* @IsGranted("EDIT", subject="taggingRule")
*
* @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)
{
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.
*
* @Route("/ignore-origin-user-rule/delete/{ignoreOriginUserRule}", name="delete_ignore_origin_rule", methods={"GET"}, requirements={"ignoreOriginUserRule" = "\d+"})
* @IsGranted("DELETE", subject="ignoreOriginUserRule")
*
* @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)
{
$this->entityManager->remove($ignoreOriginUserRule);
@ -558,11 +527,10 @@ class ConfigController extends AbstractController
/**
* 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
*/
#[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)
{
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.
*
* @Route("/reset/{type}", name="config_reset", methods={"POST"}, requirements={"id" = "annotations|tags|entries|tagging_rules"})
* @IsGranted("EDIT_CONFIG")
*
* @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)
{
if (!$this->isCsrfTokenValid('reset-area', $request->request->get('token'))) {
@ -627,13 +594,11 @@ class ConfigController extends AbstractController
/**
* Delete account for current user.
*
* @Route("/account/delete", name="delete_account", methods={"POST"})
* @IsGranted("EDIT_CONFIG")
*
* @throws AccessDeniedHttpException
*
* @return RedirectResponse
*/
#[Route(path: '/account/delete', name: 'delete_account', methods: ['POST'])]
#[IsGranted('EDIT_CONFIG')]
public function deleteAccountAction(Request $request, UserRepository $userRepository, TokenStorageInterface $tokenStorage)
{
if (!$this->isCsrfTokenValid('delete-account', $request->request->get('token'))) {
@ -660,11 +625,10 @@ class ConfigController extends AbstractController
/**
* Switch view mode for current user.
*
* @Route("/config/view-mode", name="switch_view_mode", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return RedirectResponse
*/
#[Route(path: '/config/view-mode', name: 'switch_view_mode', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function changeViewModeAction(Request $request)
{
$user = $this->getUser();
@ -683,11 +647,10 @@ class ConfigController extends AbstractController
*
* @param string $language
*
* @Route("/locale/{language}", name="changeLocale", methods={"GET"})
* @IsGranted("PUBLIC_ACCESS")
*
* @return RedirectResponse
*/
#[Route(path: '/locale/{language}', name: 'changeLocale', methods: ['GET'])]
#[IsGranted('PUBLIC_ACCESS')]
public function setLocaleAction(Request $request, ValidatorInterface $validator, $language = null)
{
$errors = $validator->validate($language, new LocaleConstraint(['canonicalize' => true]));
@ -702,11 +665,10 @@ class ConfigController extends AbstractController
/**
* Export tagging rules for the logged in user.
*
* @Route("/tagging-rule/export", name="export_tagging_rule", methods={"GET"})
* @IsGranted("EDIT_CONFIG")
*
* @return Response
*/
#[Route(path: '/tagging-rule/export', name: 'export_tagging_rule', methods: ['GET'])]
#[IsGranted('EDIT_CONFIG')]
public function exportTaggingRulesAction()
{
$data = SerializerBuilder::create()->build()->serialize(

View file

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

View file

@ -21,14 +21,10 @@ class ExportController extends AbstractController
/**
* 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
*/
#[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)
{
try {
@ -45,14 +41,10 @@ class ExportController extends AbstractController
/**
* 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
*/
#[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)
{
$method = ucfirst($category);
@ -77,8 +69,8 @@ class ExportController extends AbstractController
$title = 'Tag ' . $tag->getLabel();
} elseif ('search' === $category) {
$searchTerm = (isset($request->query->all('search_entry')['term']) ? $request->query->all('search_entry')['term'] : '');
$currentRoute = (null !== $request->query->get('currentRoute') ? $request->query->get('currentRoute') : '');
$searchTerm = $request->query->all('search_entry')['term'] ?? '';
$currentRoute = $request->query->get('currentRoute') ?? '';
$entries = $entryRepository->getBuilderForSearchByUser(
$this->getUser()->getId(),

View file

@ -20,23 +20,19 @@ use Wallabag\Repository\EntryRepository;
class FeedController extends AbstractController
{
private EntryRepository $entryRepository;
public function __construct(EntryRepository $entryRepository)
{
$this->entryRepository = $entryRepository;
public function __construct(
private readonly EntryRepository $entryRepository,
) {
}
/**
* 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
*/
#[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)
{
return $this->showEntries('unread', $user, $page);
@ -45,13 +41,11 @@ class FeedController extends AbstractController
/**
* 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
*/
#[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)
{
return $this->showEntries('archive', $user, $page);
@ -60,13 +54,11 @@ class FeedController extends AbstractController
/**
* 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
*/
#[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)
{
return $this->showEntries('starred', $user, $page);
@ -75,13 +67,11 @@ class FeedController extends AbstractController
/**
* 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
*/
#[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)
{
return $this->showEntries('all', $user, $page);
@ -90,14 +80,12 @@ class FeedController extends AbstractController
/**
* 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
*/
#[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)
{
$sort = $request->query->get('sort', 'created');
@ -143,7 +131,7 @@ class FeedController extends AbstractController
try {
$entries->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) {
} catch (OutOfRangeCurrentPageException) {
if ($page > 1) {
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)
{
switch ($type) {
case 'starred':
$qb = $this->entryRepository->getBuilderForStarredByUser($user->getId());
break;
case 'archive':
$qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId());
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));
}
$qb = match ($type) {
'starred' => $this->entryRepository->getBuilderForStarredByUser($user->getId()),
'archive' => $this->entryRepository->getBuilderForArchiveByUser($user->getId()),
'unread' => $this->entryRepository->getBuilderForUnreadByUser($user->getId()),
'all' => $this->entryRepository->getBuilderForAllByUser($user->getId()),
default => throw new \InvalidArgumentException(\sprintf('Type "%s" is not implemented.', $type)),
};
$pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
$entries = new Pagerfanta($pagerAdapter);
@ -225,7 +204,7 @@ class FeedController extends AbstractController
try {
$entries->setCurrentPage((int) $page);
} catch (OutOfRangeCurrentPageException $e) {
} catch (OutOfRangeCurrentPageException) {
if ($page > 1) {
return $this->redirect($url . '/' . $entries->getNbPages());
}

View file

@ -20,21 +20,17 @@ use Wallabag\Repository\IgnoreOriginInstanceRuleRepository;
*/
class IgnoreOriginInstanceRuleController extends AbstractController
{
private EntityManagerInterface $entityManager;
private TranslatorInterface $translator;
public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
) {
}
/**
* 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)
{
$rules = $repository->findAll();
@ -47,11 +43,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/**
* 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
*/
#[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)
{
$ignoreOriginInstanceRule = new IgnoreOriginInstanceRule();
@ -80,11 +75,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/**
* 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
*/
#[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)
{
$deleteForm = $this->createDeleteForm($ignoreOriginInstanceRule);
@ -113,11 +107,10 @@ class IgnoreOriginInstanceRuleController extends AbstractController
/**
* 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
*/
#[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)
{
$form = $this->createDeleteForm($ignoreOriginInstanceRule);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,35 +25,29 @@ use Wallabag\Repository\TagRepository;
class TagController extends AbstractController
{
private EntityManagerInterface $entityManager;
private TagsAssigner $tagsAssigner;
private Redirect $redirectHelper;
private 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;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly TagsAssigner $tagsAssigner,
private readonly Redirect $redirectHelper,
private readonly Security $security,
) {
}
/**
* @Route("/new-tag/{entry}", name="new_tag", methods={"POST"}, requirements={"entry" = "\d+"})
* @IsGranted("TAG", subject="entry")
*
* @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)
{
$form = $this->createForm(NewTagType::class, new Tag());
$form->handleRequest($request);
$tags = $form->get('label')->getData() ?? '';
$tagsExploded = explode(',', $tags);
$tagsExploded = explode(',', (string) $tags);
// 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', [
'%tags%' => NewTagType::MAX_TAGS,
'%characters%' => NewTagType::MAX_LENGTH,
@ -89,11 +83,10 @@ class TagController extends AbstractController
/**
* 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
*/
#[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)
{
$entry->removeTag($tag);
@ -113,11 +106,10 @@ class TagController extends AbstractController
/**
* Shows tags for current user.
*
* @Route("/tag/list", name="tag", methods={"GET"})
* @IsGranted("LIST_TAGS")
*
* @return Response
*/
#[Route(path: '/tag/list', name: 'tag', methods: ['GET'])]
#[IsGranted('LIST_TAGS')]
public function showTagAction(TagRepository $tagRepository, EntryRepository $entryRepository)
{
$allTagsWithNbEntries = $tagRepository->findAllTagsWithNbEntries($this->getUser()->getId());
@ -138,13 +130,12 @@ class TagController extends AbstractController
/**
* @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
*/
#[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)
{
$entriesByTag = $entryRepository->findAllByTagId(
@ -158,7 +149,7 @@ class TagController extends AbstractController
try {
$entries->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) {
} catch (OutOfRangeCurrentPageException) {
if ($page > 1) {
return $this->redirect($this->generateUrl($request->attributes->get('_route'), [
'slug' => $tag->getSlug(),
@ -179,12 +170,11 @@ class TagController extends AbstractController
* Rename a given tag with a new label
* 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
*/
#[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)
{
$form = $this->createForm(RenameTagType::class, new Tag());
@ -233,11 +223,10 @@ class TagController extends AbstractController
/**
* Tag search results with the current search term.
*
* @Route("/tag/search/{filter}", name="tag_this_search", methods={"GET"})
* @IsGranted("CREATE_TAGS")
*
* @return Response
*/
#[Route(path: '/tag/search/{filter}', name: 'tag_this_search', methods: ['GET'])]
#[IsGranted('CREATE_TAGS')]
public function tagThisSearchAction($filter, Request $request, EntryRepository $entryRepository)
{
$currentRoute = $request->query->has('currentRoute') ? $request->query->get('currentRoute') : '';
@ -255,7 +244,7 @@ class TagController extends AbstractController
// check to avoid duplicate tags creation
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;
}
$this->entityManager->persist($entry);
@ -269,12 +258,11 @@ class TagController extends AbstractController
/**
* 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
*/
#[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)
{
foreach ($tag->getEntriesByUserId($this->getUser()->getId()) as $entry) {

View file

@ -29,21 +29,17 @@ use Wallabag\Repository\UserRepository;
*/
class UserController extends AbstractController
{
private EntityManagerInterface $entityManager;
private TranslatorInterface $translator;
public function __construct(EntityManagerInterface $entityManager, TranslatorInterface $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
) {
}
/**
* 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)
{
$user = $userManager->createUser();
@ -77,10 +73,9 @@ class UserController extends AbstractController
/**
* 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)
{
$deleteForm = $this->createDeleteForm($user);
@ -120,10 +115,9 @@ class UserController extends AbstractController
/**
* 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)
{
$form = $this->createDeleteForm($user);
@ -145,14 +139,10 @@ class UserController extends AbstractController
/**
* @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
*/
#[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)
{
$qb = $userRepository->createQueryBuilder('u');
@ -161,7 +151,7 @@ class UserController extends AbstractController
$form->handleRequest($request);
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);
}
@ -172,7 +162,7 @@ class UserController extends AbstractController
try {
$pagerFanta->setCurrentPage($page);
} catch (OutOfRangeCurrentPageException $e) {
} catch (OutOfRangeCurrentPageException) {
if ($page > 1) {
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;
return json_decode($value, true);
return json_decode((string) $value, true);
}
public function getName(): string

View file

@ -10,17 +10,12 @@ use Doctrine\Migrations\Version\MigrationFactory;
*/
class MigrationFactoryDecorator implements MigrationFactory
{
private MigrationFactory $migrationFactory;
private string $tablePrefix;
private array $defaultIgnoreOriginInstanceRules;
private 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 __construct(
private readonly MigrationFactory $migrationFactory,
private readonly string $tablePrefix,
private readonly array $defaultIgnoreOriginInstanceRules,
private readonly string $fetchingErrorMessage,
) {
}
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
{
$hash = implode('', array_map(static function ($column): string {
return dechex(crc32($column));
}, $columnNames));
$hash = implode('', array_map(static fn ($column): string => dechex(crc32($column)), $columnNames));
return strtoupper(substr($prefix . '_' . $hash, 0, $this->platform->getMaxIdentifierLength()));
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,15 +20,13 @@ use Wallabag\Repository\UserRepository;
/**
* User.
*
* @XmlRoot("user")
*
* @UniqueEntity("email")
* @UniqueEntity("username")
*/
#[ORM\Table(name: '`user`')]
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\HasLifecycleCallbacks]
#[UniqueEntity('email')]
#[UniqueEntity('username')]
#[XmlRoot('user')]
class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface
{
use EntityTimestampsTrait;
@ -42,12 +40,11 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="int",
* example=12,
* )
*
* @Groups({"user_api", "user_api_with_client"})
*/
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $id;
/**
@ -58,9 +55,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string",
* example="Walla Baggger",
* )
* @Groups({"user_api", "user_api_with_client"})
*/
#[ORM\Column(name: 'name', type: 'text', nullable: true)]
#[Groups(['user_api', 'user_api_with_client'])]
protected $name;
/**
@ -71,9 +68,8 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string",
* example="wallabag",
* )
*
* @Groups({"user_api", "user_api_with_client"})
*/
#[Groups(['user_api', 'user_api_with_client'])]
protected $username;
/**
@ -84,9 +80,8 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string",
* example="wallabag@wallabag.io",
* )
*
* @Groups({"user_api", "user_api_with_client"})
*/
#[Groups(['user_api', 'user_api_with_client'])]
protected $email;
/**
@ -97,9 +92,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string",
* example="2023-06-27T19:25:44+0000",
* )
* @Groups({"user_api", "user_api_with_client"})
*/
#[ORM\Column(name: 'created_at', type: 'datetime')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $createdAt;
/**
@ -110,9 +105,9 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
* type="string",
* example="2023-06-27T19:37:30+0000",
* )
* @Groups({"user_api", "user_api_with_client"})
*/
#[ORM\Column(name: 'updated_at', type: 'datetime')]
#[Groups(['user_api', 'user_api_with_client'])]
protected $updatedAt;
#[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",
* 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;
#[ORM\Column(type: 'integer', nullable: true)]
@ -383,7 +377,7 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI
foreach ($this->backupCodes as $key => $backupCode) {
// backup code are hashed using `password_hash`
// see ConfigController->otpAppAction
if (password_verify($code, $backupCode)) {
if (password_verify($code, (string) $backupCode)) {
return $key;
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,17 +14,14 @@ use Wallabag\Entity\Config;
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 $fonts Fonts come from configuration, array just font name as key / value
*/
public function __construct($languages, $fonts)
{
$this->languages = $languages;
$this->fonts = $fonts;
public function __construct(
private $languages,
private $fonts,
) {
}
public function buildForm(FormBuilderInterface $builder, array $options)

View file

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

View file

@ -17,26 +17,19 @@ use Wallabag\Tools\Utils;
*/
class ContentProxy
{
protected $graby;
protected $tagger;
protected $ignoreOriginProcessor;
protected $validator;
protected $logger;
protected $mimeTypes;
protected $fetchingErrorMessage;
protected $eventDispatcher;
protected $storeArticleHeaders;
public function __construct(Graby $graby, RuleBasedTagger $tagger, RuleBasedIgnoreOriginProcessor $ignoreOriginProcessor, ValidatorInterface $validator, LoggerInterface $logger, $fetchingErrorMessage, $storeArticleHeaders = false)
{
$this->graby = $graby;
$this->tagger = $tagger;
$this->ignoreOriginProcessor = $ignoreOriginProcessor;
$this->validator = $validator;
$this->logger = $logger;
public function __construct(
protected Graby $graby,
protected RuleBasedTagger $tagger,
protected RuleBasedIgnoreOriginProcessor $ignoreOriginProcessor,
protected ValidatorInterface $validator,
protected LoggerInterface $logger,
protected $fetchingErrorMessage,
protected $storeArticleHeaders = false,
) {
$this->mimeTypes = new MimeTypes();
$this->fetchingErrorMessage = $fetchingErrorMessage;
$this->storeArticleHeaders = $storeArticleHeaders;
}
/**
@ -59,7 +52,7 @@ class ContentProxy
$fetchedContent['title'] = $this->sanitizeContentTitle(
$fetchedContent['title'],
isset($fetchedContent['headers']['content-type']) ? $fetchedContent['headers']['content-type'] : ''
$fetchedContent['headers']['content-type'] ?? ''
);
// when content is imported, we have information in $content
@ -107,7 +100,9 @@ class ContentProxy
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;
}
$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
{
private $logger;
private $encryptionKey;
public function __construct($encryptionKeyPath, LoggerInterface $logger)
{
$this->logger = $logger;
public function __construct(
$encryptionKeyPath,
private readonly LoggerInterface $logger,
) {
if (!file_exists($encryptionKeyPath)) {
$key = Key::createNewRandomKey();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -8,14 +8,9 @@ use Wallabag\Repository\TagRepository;
class TagsAssigner
{
/**
* @var TagRepository
*/
protected $tagRepository;
public function __construct(TagRepository $tagRepository)
{
$this->tagRepository = $tagRepository;
public function __construct(
protected TagRepository $tagRepository,
) {
}
/**
@ -44,7 +39,7 @@ class TagsAssigner
}
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
if ('' === $label) {

View file

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

View file

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

View file

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

View file

@ -39,7 +39,7 @@ class ChromeImport extends BrowserImport
'is_archived' => (int) $this->markAsRead,
'is_starred' => false,
'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']) {

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