Move source files directly under src/ directory

This commit is contained in:
Yassine Guedidi
2024-02-19 00:39:48 +01:00
parent 804261bc26
commit a37b385c23
190 changed files with 19 additions and 21 deletions

View File

@ -0,0 +1,26 @@
<?php
namespace Wallabag\CoreBundle\Event;
use Symfony\Contracts\EventDispatcher\Event;
use Wallabag\CoreBundle\Entity\Config;
/**
* This event is fired as soon as user configuration is updated.
*/
class ConfigUpdatedEvent extends Event
{
public const NAME = 'config.updated';
protected $config;
public function __construct(Config $entry)
{
$this->config = $entry;
}
public function getConfig(): Config
{
return $this->config;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace Wallabag\CoreBundle\Event;
use Symfony\Contracts\EventDispatcher\Event;
use Wallabag\CoreBundle\Entity\Entry;
/**
* This event is fired as soon as an entry is deleted.
*/
class EntryDeletedEvent extends Event
{
public const NAME = 'entry.deleted';
protected $entry;
public function __construct(Entry $entry)
{
$this->entry = $entry;
}
public function getEntry(): Entry
{
return $this->entry;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace Wallabag\CoreBundle\Event;
use Symfony\Contracts\EventDispatcher\Event;
use Wallabag\CoreBundle\Entity\Entry;
/**
* This event is fired as soon as an entry was saved.
*/
class EntrySavedEvent extends Event
{
public const NAME = 'entry.saved';
protected $entry;
public function __construct(Entry $entry)
{
$this->entry = $entry;
}
public function getEntry(): Entry
{
return $this->entry;
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\AuthenticationEvents;
class AuthenticationFailureListener implements EventSubscriberInterface
{
private $requestStack;
private $logger;
public function __construct(RequestStack $requestStack, LoggerInterface $logger)
{
$this->requestStack = $requestStack;
$this->logger = $logger;
}
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => 'onAuthenticationFailure',
];
}
/**
* On failure, add a custom error in log so server admin can configure fail2ban to block IP from people who try to login too much.
*/
public function onAuthenticationFailure()
{
$request = $this->requestStack->getMasterRequest();
$this->logger->error('Authentication failure for user "' . $request->request->get('_username') . '", from IP "' . $request->getClientIp() . '", with UA: "' . $request->server->get('HTTP_USER_AGENT') . '".');
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use Doctrine\ORM\EntityManagerInterface;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Wallabag\CoreBundle\Entity\Config;
/**
* This listener will create the associated configuration when a user register.
* This configuration will be created right after the registration (no matter if it needs an email validation).
*/
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 static function getSubscribedEvents()
{
return [
// when a user register using the normal form
FOSUserEvents::REGISTRATION_COMPLETED => 'createConfig',
// when we manually create a user using the command line
// OR when we create it from the config UI
FOSUserEvents::USER_CREATED => 'createConfig',
];
}
public function createConfig(UserEvent $event)
{
$language = $this->language;
if ($this->requestStack->getMasterRequest()) {
$session = $this->requestStack->getMasterRequest()->getSession();
$language = $session->get('_locale', $this->language);
}
$config = new Config($event->getUser());
$config->setItemsPerPage($this->itemsOnPage);
$config->setFeedLimit($this->feedLimit);
$config->setLanguage($language);
$config->setReadingSpeed($this->readingSpeed);
$config->setActionMarkAsRead($this->actionMarkAsRead);
$config->setListMode($this->listMode);
$config->setDisplayThumbnails($this->displayThumbnails);
$this->em->persist($config);
$this->em->flush();
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* @see http://symfony.com/doc/current/cookbook/session/locale_sticky_session.html
*/
class LocaleListener implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
// try to see if the locale has been set as a _locale routing parameter
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
// if no explicit locale has been set on this request, use one from the session
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
public static function getSubscribedEvents()
{
return [
// must be registered before the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 17]],
];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Listener responsible to change the redirection at the end of the password resetting.
*
* @see http://symfony.com/doc/current/bundles/FOSUserBundle/controller_events.html
*/
class PasswordResettingListener implements EventSubscriberInterface
{
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
public static function getSubscribedEvents()
{
return [
FOSUserEvents::RESETTING_RESET_SUCCESS => 'onPasswordResettingSuccess',
];
}
public function onPasswordResettingSuccess(FormEvent $event)
{
$url = $this->router->generate('homepage');
$event->setResponse(new RedirectResponse($url));
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class RegistrationListener implements EventSubscriberInterface
{
/**
* @var bool
*/
private $registrationEnabled;
/**
* @var UrlGeneratorInterface
*/
private $urlGenerator;
public function __construct($registrationEnabled, UrlGeneratorInterface $urlGenerator)
{
$this->registrationEnabled = $registrationEnabled;
$this->urlGenerator = $urlGenerator;
}
public static function getSubscribedEvents()
{
return [
FOSUserEvents::REGISTRATION_INITIALIZE => 'onRegistrationInitialize',
];
}
public function onRegistrationInitialize(GetResponseUserEvent $event)
{
if ($this->registrationEnabled) {
return;
}
$event->setResponse(new RedirectResponse($this->urlGenerator->generate('fos_user_security_login'), 301));
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Wallabag\CoreBundle\Event\Listener;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Wallabag\CoreBundle\Entity\User;
/**
* Stores the locale of the user in the session after the login.
* If no locale are defined (if user doesn't change it from the login screen), override it with the user's config one.
*
* This can be used by the LocaleListener afterwards.
*
* @see http://symfony.com/doc/master/cookbook/session/locale_sticky_session.html
*/
class UserLocaleListener
{
private SessionInterface $session;
public function __construct(SessionInterface $session)
{
$this->session = $session;
}
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
\assert($user instanceof User);
if (null !== $user->getConfig()->getLanguage() && null === $this->session->get('_locale')) {
$this->session->set('_locale', $user->getConfig()->getLanguage());
}
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Wallabag\CoreBundle\Event\Subscriber;
use Spiriit\Bundle\FormFilterBundle\Event\GetFilterConditionEvent;
use Spiriit\Bundle\FormFilterBundle\Event\Subscriber\DoctrineORMSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* This custom class override the default behavior of SpiriitFormFilterBundle on `filter_date_range`
* It converts a date_range to date_time_range to add hour to be able to grab a whole day (from 00:00:00 to 23:59:59).
*/
class CustomDoctrineORMSubscriber extends DoctrineORMSubscriber implements EventSubscriberInterface
{
public function filterDateRange(GetFilterConditionEvent $event)
{
$expr = $event->getFilterQuery()->getExpressionBuilder();
$values = $event->getValues();
$value = $values['value'];
// left date should start at midnight
if (isset($value['left_date'][0]) && $value['left_date'][0] instanceof \DateTime) {
$value['left_date'][0]->setTime(0, 0, 0);
}
// right adte should end one second before midnight
if (isset($value['right_date'][0]) && $value['right_date'][0] instanceof \DateTime) {
$value['right_date'][0]->setTime(23, 59, 59);
}
if (isset($value['left_date'][0]) || isset($value['right_date'][0])) {
$event->setCondition($expr->dateTimeInRange($event->getField(), $value['left_date'][0], $value['right_date'][0]));
}
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace Wallabag\CoreBundle\Event\Subscriber;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Wallabag\CoreBundle\Entity\Entry;
use Wallabag\CoreBundle\Event\EntryDeletedEvent;
use Wallabag\CoreBundle\Event\EntrySavedEvent;
use Wallabag\CoreBundle\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 static function getSubscribedEvents()
{
return [
EntrySavedEvent::NAME => 'onEntrySaved',
EntryDeletedEvent::NAME => 'onEntryDeleted',
];
}
/**
* Download images and updated the data into the entry.
*/
public function onEntrySaved(EntrySavedEvent $event)
{
if (!$this->enabled) {
$this->logger->debug('DownloadImagesSubscriber: disabled.');
return;
}
$entry = $event->getEntry();
$html = $this->downloadImages($entry);
if (false !== $html) {
$this->logger->debug('DownloadImagesSubscriber: updated html.');
$entry->setContent($html);
}
// update preview picture
$previewPicture = $this->downloadPreviewImage($entry);
if (false !== $previewPicture) {
$this->logger->debug('DownloadImagesSubscriber: update preview picture.');
$entry->setPreviewPicture($previewPicture);
}
$this->em->persist($entry);
$this->em->flush();
}
/**
* Remove images related to the entry.
*/
public function onEntryDeleted(EntryDeletedEvent $event)
{
if (!$this->enabled) {
$this->logger->debug('DownloadImagesSubscriber: disabled.');
return;
}
$this->downloadImages->removeImages($event->getEntry()->getId());
}
/**
* Download all images from the html.
*
* @todo If we want to add async download, it should be done in that method
*
* @return string|false False in case of async
*/
private function downloadImages(Entry $entry)
{
return $this->downloadImages->processHtml(
$entry->getId(),
$entry->getContent(),
$entry->getUrl()
);
}
/**
* Download the preview picture.
*
* @todo If we want to add async download, it should be done in that method
*
* @return string|false False in case of async
*/
private function downloadPreviewImage(Entry $entry)
{
return $this->downloadImages->processSingleImage(
$entry->getId(),
$entry->getPreviewPicture(),
$entry->getUrl()
);
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace Wallabag\CoreBundle\Event\Subscriber;
use Doctrine\ORM\EntityManagerInterface;
use ScssPhp\ScssPhp\Compiler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Wallabag\CoreBundle\Event\ConfigUpdatedEvent;
class GenerateCustomCSSSubscriber implements EventSubscriberInterface
{
private $em;
private $compiler;
public function __construct(EntityManagerInterface $em, Compiler $compiler)
{
$this->em = $em;
$this->compiler = $compiler;
}
public static function getSubscribedEvents()
{
return [
ConfigUpdatedEvent::NAME => 'onConfigUpdated',
];
}
/**
* Generate custom CSS.
*/
public function onConfigUpdated(ConfigUpdatedEvent $event)
{
$config = $event->getConfig();
$css = $this->compiler->compileString(
'h1 { font-family: "' . $config->getFont() . '";}
#article {
max-width: ' . $config->getMaxWidth() . 'em;
font-family: "' . $config->getFont() . '";
}
#article article {
font-size: ' . $config->getFontsize() . 'em;
line-height: ' . $config->getLineHeight() . 'em;
}
;
')->getCss();
$config->setCustomCSS($css);
$this->em->persist($config);
$this->em->flush();
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Wallabag\CoreBundle\Event\Subscriber;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\Persistence\ManagerRegistry;
use Wallabag\CoreBundle\Entity\Entry;
/**
* SQLite doesn't care about cascading remove, so we need to manually remove associated stuf for an Entry.
* Foreign Key Support can be enabled by running `PRAGMA foreign_keys = ON;` at runtime (AT RUNTIME !).
* But it needs a compilation flag that not all SQLite instance has ...
*
* @see https://www.sqlite.org/foreignkeys.html#fk_enable
*/
class SQLiteCascadeDeleteSubscriber implements EventSubscriber
{
private $doctrine;
public function __construct(ManagerRegistry $doctrine)
{
$this->doctrine = $doctrine;
}
/**
* @return array
*/
public function getSubscribedEvents()
{
return [
'preRemove',
];
}
/**
* We removed everything related to the upcoming removed entry because SQLite can't handle it on it own.
* We do it in the preRemove, because we can't retrieve tags in the postRemove (because the entry id is gone).
*/
public function preRemove(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if (!$this->doctrine->getConnection()->getDatabasePlatform() instanceof SqlitePlatform
|| !$entity instanceof Entry) {
return;
}
$em = $this->doctrine->getManager();
if (null !== $entity->getTags()) {
foreach ($entity->getTags() as $tag) {
$entity->removeTag($tag);
}
}
if (null !== $entity->getAnnotations()) {
foreach ($entity->getAnnotations() as $annotation) {
$em->remove($annotation);
}
}
$em->flush();
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Wallabag\CoreBundle\Event\Subscriber;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Puts a prefix to each table.
* This way were used instead of using the built-in strategy from Doctrine, using `naming_strategy`
* Because it conflicts with the DefaultQuoteStrategy (that escape table name, like user for Postgres)
* see #1498 for more detail.
*
* Solution from :
* - http://stackoverflow.com/a/23860613/569101
* - http://doctrine-orm.readthedocs.org/en/latest/reference/namingstrategy.html
*/
class TablePrefixSubscriber implements EventSubscriber
{
protected $tablePrefix = '';
public function __construct($tablePrefix)
{
$this->tablePrefix = (string) $tablePrefix;
}
public function getSubscribedEvents()
{
return ['loadClassMetadata'];
}
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
{
$classMetadata = $args->getClassMetadata();
// if we are in an inheritance hierarchy, only apply this once
if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
return;
}
$classMetadata->setPrimaryTable(['name' => $this->tablePrefix . $classMetadata->getTableName()]);
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if (ClassMetadataInfo::MANY_TO_MANY === $mapping['type'] && isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])) {
$mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->tablePrefix . $mappedTableName;
}
}
}
}