Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/code_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v1
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: 8.0
extensions: pdo_sqlite, pdo_mysql, pdo_pgsql
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: shivammathur/setup-php@v1
- uses: shivammathur/setup-php@v2
with:
php-version: 8.0
extensions: pdo_sqlite, pdo_mysql, pdo_pgsql
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: shivammathur/setup-php@v1
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pdo_sqlite, pdo_mysql, pdo_pgsql
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"doctrine/persistence": "^2.5|^3.0",
"doctrine/dbal": "^3.3",
"doctrine/orm": "^2.12",
"doctrine/doctrine-bundle": "^2.6",
"doctrine/doctrine-bundle": "^2.7.2",
"symfony/cache": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/http-kernel": "^5.4|^6.0",
Expand All @@ -36,7 +36,7 @@
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpstan/phpstan": "^1.7.10",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.13.4",
"rector/rector": "^0.18.5",
"symplify/easy-coding-standard": "^10.2.9",
"symplify/phpstan-extensions": "^10.2.9",
"phpstan/phpstan-doctrine": "^1.3",
Expand Down
11 changes: 2 additions & 9 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;
use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector;
use Rector\Nette\Set\NetteSetList;
use Rector\Php80\Rector\FunctionLike\UnionTypesRector;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([__DIR__ . '/src', __DIR__ . '/tests', __DIR__ . '/utils']);
Expand All @@ -17,12 +16,7 @@

$rectorConfig->skip([
RenamePropertyToMatchTypeRector::class => [__DIR__ . '/tests/ORM/'],

UnionTypesRector::class => [
// to keep BC return types
__DIR__ . '/src/Contract/Entity',
'src/Model/*/*Trait.php',
],
TypedPropertyFromAssignsRector::class => [__DIR__ . '/tests/Repository/'],
]);

// doctrine annotations to attributes
Expand All @@ -31,7 +25,6 @@
SetList::DEAD_CODE,
SetList::CODE_QUALITY,
SetList::CODING_STYLE,
NetteSetList::NETTE_CODE_QUALITY,
SetList::NAMING,
LevelSetList::UP_TO_PHP_80,
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
final class DoctrineBehaviorsExtension extends Extension
{
/**
* @param string[] $configs
* @param array<array<mixed>> $configs
*/
public function load(array $configs, ContainerBuilder $containerBuilder): void
{
Expand Down
62 changes: 30 additions & 32 deletions src/EventSubscriber/BlameableEventSubscriber.php
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep $entity instead of changing it to $object as it's more specific to this case.

Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@

namespace Knp\DoctrineBehaviors\EventSubscriber;

use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreRemoveEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\UnitOfWork;
use Knp\DoctrineBehaviors\Contract\Entity\BlameableInterface;
use Knp\DoctrineBehaviors\Contract\Provider\UserProviderInterface;

final class BlameableEventSubscriber implements EventSubscriberInterface
#[AsDoctrineListener(event: Events::loadClassMetadata)]
#[AsDoctrineListener(event: Events::prePersist)]
#[AsDoctrineListener(event: Events::preUpdate)]
#[AsDoctrineListener(event: Events::preRemove)]
final class BlameableEventSubscriber
{
/**
* @var string
Expand Down Expand Up @@ -59,10 +65,10 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $loadClassMetadataE
/**
* Stores the current user into createdBy and updatedBy properties
*/
public function prePersist(LifecycleEventArgs $lifecycleEventArgs): void
public function prePersist(PrePersistEventArgs $prePersistEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof BlameableInterface) {
$object = $prePersistEventArgs->getObject();
if (! $object instanceof BlameableInterface) {
return;
}

Expand All @@ -72,28 +78,28 @@ public function prePersist(LifecycleEventArgs $lifecycleEventArgs): void
return;
}

if (! $entity->getCreatedBy()) {
$entity->setCreatedBy($user);
if (! $object->getCreatedBy()) {
$object->setCreatedBy($user);

$this->getUnitOfWork()
->propertyChanged($entity, self::CREATED_BY, null, $user);
->propertyChanged($object, self::CREATED_BY, null, $user);
}

if (! $entity->getUpdatedBy()) {
$entity->setUpdatedBy($user);
if (! $object->getUpdatedBy()) {
$object->setUpdatedBy($user);

$this->getUnitOfWork()
->propertyChanged($entity, self::UPDATED_BY, null, $user);
->propertyChanged($object, self::UPDATED_BY, null, $user);
}
}

/**
* Stores the current user into updatedBy property
*/
public function preUpdate(LifecycleEventArgs $lifecycleEventArgs): void
public function preUpdate(PreUpdateEventArgs $preUpdateEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof BlameableInterface) {
$object = $preUpdateEventArgs->getObject();
if (! $object instanceof BlameableInterface) {
return;
}

Expand All @@ -102,20 +108,20 @@ public function preUpdate(LifecycleEventArgs $lifecycleEventArgs): void
return;
}

$oldValue = $entity->getUpdatedBy();
$entity->setUpdatedBy($user);
$updatedBy = $object->getUpdatedBy();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$updatedBy = $object->getUpdatedBy();
$oldUpdatedBy = $object->getUpdatedBy();

$object->setUpdatedBy($user);

$this->getUnitOfWork()
->propertyChanged($entity, self::UPDATED_BY, $oldValue, $user);
->propertyChanged($object, self::UPDATED_BY, $updatedBy, $user);
}

/**
* Stores the current user into deletedBy property
*/
public function preRemove(LifecycleEventArgs $lifecycleEventArgs): void
public function preRemove(PreRemoveEventArgs $preRemoveEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof BlameableInterface) {
$object = $preRemoveEventArgs->getObject();
if (! $object instanceof BlameableInterface) {
return;
}

Expand All @@ -124,19 +130,11 @@ public function preRemove(LifecycleEventArgs $lifecycleEventArgs): void
return;
}

$oldDeletedBy = $entity->getDeletedBy();
$entity->setDeletedBy($user);
$oldDeletedBy = $object->getDeletedBy();
$object->setDeletedBy($user);

$this->getUnitOfWork()
->propertyChanged($entity, self::DELETED_BY, $oldDeletedBy, $user);
}

/**
* @return string[]
*/
public function getSubscribedEvents(): array
{
return [Events::prePersist, Events::preUpdate, Events::preRemove, Events::loadClassMetadata];
->propertyChanged($object, self::DELETED_BY, $oldDeletedBy, $user);
}

private function mapEntity(ClassMetadataInfo $classMetadataInfo): void
Expand Down
61 changes: 29 additions & 32 deletions src/EventSubscriber/LoggableEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,77 +4,74 @@

namespace Knp\DoctrineBehaviors\EventSubscriber;

use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Doctrine\ORM\Event\PostUpdateEventArgs;
use Doctrine\ORM\Event\PreRemoveEventArgs;
use Doctrine\ORM\Events;
use Knp\DoctrineBehaviors\Contract\Entity\LoggableInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;

final class LoggableEventSubscriber implements EventSubscriberInterface
#[AsDoctrineListener(event: Events::postPersist)]
#[AsDoctrineListener(event: Events::postUpdate)]
#[AsDoctrineListener(event: Events::preRemove)]
final class LoggableEventSubscriber
{
public function __construct(
private LoggerInterface $logger
) {
}

public function postPersist(LifecycleEventArgs $lifecycleEventArgs): void
public function postPersist(PostPersistEventArgs $postPersistEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof LoggableInterface) {
$object = $postPersistEventArgs->getObject();
if (! $object instanceof LoggableInterface) {
return;
}

$createLogMessage = $entity->getCreateLogMessage();
$createLogMessage = $object->getCreateLogMessage();
$this->logger->log(LogLevel::INFO, $createLogMessage);

$this->logChangeSet($lifecycleEventArgs);
$this->logChangeSet($postPersistEventArgs);
}

public function postUpdate(LifecycleEventArgs $lifecycleEventArgs): void
public function postUpdate(PostUpdateEventArgs $postUpdateEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof LoggableInterface) {
$object = $postUpdateEventArgs->getObject();
if (! $object instanceof LoggableInterface) {
return;
}

$this->logChangeSet($lifecycleEventArgs);
$this->logChangeSet($postUpdateEventArgs);
}

public function preRemove(LifecycleEventArgs $lifecycleEventArgs): void
public function preRemove(PreRemoveEventArgs $preRemoveEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
$object = $preRemoveEventArgs->getObject();

if ($entity instanceof LoggableInterface) {
$this->logger->log(LogLevel::INFO, $entity->getRemoveLogMessage());
if ($object instanceof LoggableInterface) {
$this->logger->log(LogLevel::INFO, $object->getRemoveLogMessage());
}
}

/**
* @return string[]
*/
public function getSubscribedEvents(): array
{
return [Events::postPersist, Events::postUpdate, Events::preRemove];
}

/**
* Logs entity changeset
*/
private function logChangeSet(LifecycleEventArgs $lifecycleEventArgs): void
private function logChangeSet(PostPersistEventArgs|PostUpdateEventArgs $lifecycleEventArgs): void
{
$entityManager = $lifecycleEventArgs->getEntityManager();
$entityManager = $lifecycleEventArgs->getObjectManager();
$unitOfWork = $entityManager->getUnitOfWork();
$entity = $lifecycleEventArgs->getEntity();
$object = $lifecycleEventArgs->getObject();

$entityClass = $entity::class;
$entityClass = $object::class;
$classMetadata = $entityManager->getClassMetadata($entityClass);

/** @var LoggableInterface $entity */
$unitOfWork->computeChangeSet($classMetadata, $entity);
$changeSet = $unitOfWork->getEntityChangeSet($entity);
/** @var LoggableInterface $object */
$unitOfWork->computeChangeSet($classMetadata, $object);
$changeSet = $unitOfWork->getEntityChangeSet($object);

$message = $entity->getUpdateLogMessage($changeSet);
$message = $object->getUpdateLogMessage($changeSet);

if ($message === '') {
return;
Expand Down
28 changes: 12 additions & 16 deletions src/EventSubscriber/SluggableEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@

namespace Knp\DoctrineBehaviors\EventSubscriber;

use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Knp\DoctrineBehaviors\Contract\Entity\SluggableInterface;
use Knp\DoctrineBehaviors\Repository\DefaultSluggableRepository;

final class SluggableEventSubscriber implements EventSubscriberInterface
#[AsDoctrineListener(event: Events::loadClassMetadata)]
#[AsDoctrineListener(event: Events::prePersist)]
#[AsDoctrineListener(event: Events::preUpdate)]
final class SluggableEventSubscriber
{
/**
* @var string
Expand All @@ -40,22 +44,14 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $loadClassMetadataE
]);
}

public function prePersist(LifecycleEventArgs $lifecycleEventArgs): void
public function prePersist(PrePersistEventArgs $prePersistEventArgs): void
{
$this->processLifecycleEventArgs($lifecycleEventArgs);
$this->processLifecycleEventArgs($prePersistEventArgs);
}

public function preUpdate(LifecycleEventArgs $lifecycleEventArgs): void
public function preUpdate(PreUpdateEventArgs $preUpdateEventArgs): void
{
$this->processLifecycleEventArgs($lifecycleEventArgs);
}

/**
* @return string[]
*/
public function getSubscribedEvents(): array
{
return [Events::loadClassMetadata, Events::prePersist, Events::preUpdate];
$this->processLifecycleEventArgs($preUpdateEventArgs);
}

private function shouldSkip(ClassMetadataInfo $classMetadataInfo): bool
Expand All @@ -67,7 +63,7 @@ private function shouldSkip(ClassMetadataInfo $classMetadataInfo): bool
return $classMetadataInfo->hasField(self::SLUG);
}

private function processLifecycleEventArgs(LifecycleEventArgs $lifecycleEventArgs): void
private function processLifecycleEventArgs(PrePersistEventArgs|PreUpdateEventArgs $lifecycleEventArgs): void
{
$entity = $lifecycleEventArgs->getEntity();
if (! $entity instanceof SluggableInterface) {
Expand Down
Loading