Skip to content

Commit

Permalink
fix: Fixed Loggable behaviour, removed relationship between UserLogEn…
Browse files Browse the repository at this point in the history
…try and User for future entity-manager separation.

Add missing Doctrine mapping:

```
    gedmo_loggable:
        type: attribute
        prefix: Gedmo\Loggable\Entity\MappedSuperclass
        dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity/MappedSuperclass"
        alias: GedmoLoggableMappedSuperclass
        is_bundle: false
```
  • Loading branch information
ambroisemaupate committed Jul 12, 2023
1 parent 0f29cc7 commit 96d180b
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 204 deletions.
6 changes: 6 additions & 0 deletions config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ doctrine:
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
gedmo_loggable:
type: attribute
prefix: Gedmo\Loggable\Entity\MappedSuperclass
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity/MappedSuperclass"
alias: GedmoLoggableMappedSuperclass
is_bundle: false

resolve_target_entities:
Symfony\Component\Security\Core\User\UserInterface: RZ\Roadiz\CoreBundle\Entity\User
Expand Down
12 changes: 9 additions & 3 deletions lib/RoadizCoreBundle/config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ doctrine:
mappings:
App:
is_bundle: false
type: annotation
type: attribute
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
RoadizCoreBundle:
is_bundle: true
type: annotation
type: attribute
dir: 'src/Entity'
prefix: 'RZ\Roadiz\CoreBundle\Entity'
alias: RoadizCoreBundle
Expand All @@ -32,10 +32,16 @@ doctrine:
alias: AbstractEntities
App\GeneratedEntity:
is_bundle: false
type: annotation
type: attribute
dir: '%kernel.project_dir%/src/GeneratedEntity'
prefix: 'App\GeneratedEntity'
alias: App\GeneratedEntity
gedmo_loggable:
type: attribute
prefix: Gedmo\Loggable\Entity\MappedSuperclass
dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Loggable/Entity/MappedSuperclass"
alias: GedmoLoggableMappedSuperclass
is_bundle: false

resolve_target_entities:
Symfony\Component\Security\Core\User\UserInterface: RZ\Roadiz\CoreBundle\Entity\User
Expand Down
3 changes: 0 additions & 3 deletions lib/RoadizCoreBundle/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,6 @@ services:
- '%roadiz_core.entity_generator_factory.options%'

Gedmo\Loggable\LoggableListener:
alias: RZ\Roadiz\CoreBundle\Doctrine\Loggable\UserLoggableListener

RZ\Roadiz\CoreBundle\Doctrine\Loggable\UserLoggableListener:
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
Expand Down
35 changes: 35 additions & 0 deletions lib/RoadizCoreBundle/migrations/Version20230712163432.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20230712163432 extends AbstractMigration
{
public function getDescription(): string
{
return 'Remove relation between UserLogEntry and User (to separate entity managers)';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE user_log_entries DROP FOREIGN KEY FK_BC2E42C7A76ED395');
$this->addSql('DROP INDEX IDX_BC2E42C7A76ED395 ON user_log_entries');
$this->addSql('ALTER TABLE user_log_entries DROP user_id');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE user_log_entries ADD user_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE user_log_entries ADD CONSTRAINT FK_BC2E42C7A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON UPDATE NO ACTION ON DELETE SET NULL');
$this->addSql('CREATE INDEX IDX_BC2E42C7A76ED395 ON user_log_entries (user_id)');
}
}
54 changes: 15 additions & 39 deletions lib/RoadizCoreBundle/src/Console/VersionsPurgeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

namespace RZ\Roadiz\CoreBundle\Console;

use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\Persistence\ManagerRegistry;
use RZ\Roadiz\CoreBundle\Entity\UserLogEntry;
use RZ\Roadiz\CoreBundle\Repository\UserLogEntryRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -68,6 +71,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 0;
}

private function getRepository(): UserLogEntryRepository
{
return $this->managerRegistry->getRepository(UserLogEntry::class);
}

/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
private function purgeByDate(InputInterface $input, OutputInterface $output): void
{
$io = new SymfonyStyle($input, $output);
Expand All @@ -77,13 +89,7 @@ private function purgeByDate(InputInterface $input, OutputInterface $output): vo
if ($dateTime >= new \DateTime()) {
throw new \InvalidArgumentException('Before date must be in the past.');
}
$qb = $em->getRepository(UserLogEntry::class)->createQueryBuilder('l');
$count = $qb->select($qb->expr()->countDistinct('l'))
->where($qb->expr()->lt('l.loggedAt', ':loggedAt'))
->setParameter('loggedAt', $dateTime)
->getQuery()
->getSingleScalarResult()
;
$count = $this->getRepository()->countAllBeforeLoggedIn($dateTime);
$question = new ConfirmationQuestion(sprintf(
'Do you want to purge <info>%s</info> version(s) before <info>%s</info>?',
$count,
Expand All @@ -94,20 +100,13 @@ private function purgeByDate(InputInterface $input, OutputInterface $output): vo
$question
)
) {
$qb = $em->getRepository(UserLogEntry::class)->createQueryBuilder('l');
$result = $qb->delete(UserLogEntry::class, 'l')
->where($qb->expr()->lt('l.loggedAt', ':loggedAt'))
->setParameter('loggedAt', $dateTime)
->getQuery()
->execute()
;
$result = $this->getRepository()->deleteAllBeforeLoggedIn($dateTime);
$io->success(sprintf('%s version(s) were deleted.', $result));
}
}

private function purgeByCount(InputInterface $input, OutputInterface $output): void
{
$deleteCount = 0;
$io = new SymfonyStyle($input, $output);
$count = (int) $input->getOption('count');
$em = $this->managerRegistry->getManagerForClass(UserLogEntry::class);
Expand All @@ -121,30 +120,7 @@ private function purgeByCount(InputInterface $input, OutputInterface $output): v
$question
)
) {
$qb = $em->getRepository(UserLogEntry::class)->createQueryBuilder('l');
$objects = $qb->select('MAX(l.version) as maxVersion', 'l.objectId', 'l.objectClass')
->groupBy('l.objectId', 'l.objectClass')
->getQuery()
->getArrayResult()
;
$deleteQuery = $qb->delete(UserLogEntry::class, 'l')
->andWhere($qb->expr()->eq('l.objectId', ':objectId'))
->andWhere($qb->expr()->eq('l.objectClass', ':objectClass'))
->andWhere($qb->expr()->lt('l.version', ':lowestVersion'))
->getQuery()
;

foreach ($objects as $object) {
$lowestVersion = (int) $object['maxVersion'] - $count;
if ($lowestVersion > 1) {
$deleteCount += $deleteQuery->execute([
'objectId' => $object['objectId'],
'objectClass' => $object['objectClass'],
'lowestVersion' => $lowestVersion
]);
}
}

$deleteCount = $this->getRepository()->deleteAllExceptCount($count);
$io->success(sprintf('%s version(s) were deleted.', $deleteCount));
}
}
Expand Down

This file was deleted.

30 changes: 2 additions & 28 deletions lib/RoadizCoreBundle/src/Entity/UserLogEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry;
use Gedmo\Loggable\Entity\Repository\LogEntryRepository;
use RZ\Roadiz\CoreBundle\Repository\UserLogEntryRepository;

/**
* Add User to Gedmo\Loggable\Entity\LogEntry
*/
#[
ORM\Entity(repositoryClass: LogEntryRepository::class),
ORM\Entity(repositoryClass: UserLogEntryRepository::class),
ORM\Table(name: "user_log_entries", options: ["row_format" => "DYNAMIC"]),
ORM\Index(columns: ["object_class"], name: "log_class_lookup_idx"),
ORM\Index(columns: ["logged_at"], name: "log_date_lookup_idx"),
Expand All @@ -21,30 +21,4 @@
]
class UserLogEntry extends AbstractLogEntry
{
/**
* @var User|null
*/
#[ORM\ManyToOne(targetEntity: 'RZ\Roadiz\CoreBundle\Entity\User')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', unique: false, onDelete: 'SET NULL')]
protected ?User $user = null;

/**
* @return User|null
*/
public function getUser(): ?User
{
return $this->user;
}

/**
* @param User|null $user
*
* @return UserLogEntry
*/
public function setUser(?User $user): UserLogEntry
{
$this->user = $user;

return $this;
}
}
54 changes: 54 additions & 0 deletions lib/RoadizCoreBundle/src/EventSubscriber/LoggableSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\EventSubscriber;

use Gedmo\Loggable\LoggableListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;

final class LoggableSubscriber implements EventSubscriberInterface
{
private LoggableListener $loggableListener;
private ?TokenStorageInterface $tokenStorage;
private ?AuthorizationCheckerInterface $authorizationChecker;

public function __construct(
LoggableListener $loggableListener,
TokenStorageInterface $tokenStorage = null,
AuthorizationCheckerInterface $authorizationChecker = null
) {
$this->loggableListener = $loggableListener;
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $authorizationChecker;
}

public function onKernelRequest(RequestEvent $event): void
{
if (HttpKernelInterface::MAIN_REQUEST !== $event->getRequestType()) {
return;
}

if (null === $this->tokenStorage || null === $this->authorizationChecker) {
return;
}

$token = $this->tokenStorage->getToken();

if (null !== $token && $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$this->loggableListener->setUsername($token);
}
}

public static function getSubscribedEvents(): array
{
return array(
KernelEvents::REQUEST => 'onKernelRequest',
);
}
}
Loading

0 comments on commit 96d180b

Please sign in to comment.