Refactor subject conversion handling and enhance audit logging

- Replaced `Subject|array` return types with `SubjectBag` in `SubjectConverterInterface` for more robust handling.
- Updated `getSubjectsForEntity` to include an optional `$includeAssociated` parameter for finer control over associated subject resolution.
- Refactored `AuditEvent` to differentiate `mainSubject` from associated subjects, improving clarity in audit logging.
- Introduced database schema changes to add `main_subject` and `subjects` columns in the `chill_main_audit_trail` table.
- Added `SubjectBag` class for grouped subject management and implemented deduplication logic.
- Updated all converters and test cases to use the new `SubjectBag` approach, ensuring compatibility.
- Improved event dispatching in controllers to utilize the updated `AuditEvent` structure and refined metadata handling.
This commit is contained in:
2026-02-13 16:56:04 +01:00
parent 443ee4cb1a
commit 32c5f21438
20 changed files with 332 additions and 84 deletions

View File

@@ -17,6 +17,7 @@ readonly class AuditEvent
{
public function __construct(
public string $action,
public object $mainSubject,
/**
* @var list<object>
*/

View File

@@ -34,13 +34,10 @@ final readonly class AuditEvent2Trail implements AuditEvent2TrailInterface
$event->description->trans($this->translator)
: $event->description;
$subjects = array_reduce(
$event->subjects,
function (array $carry, mixed $item): array {
return array_merge($carry, $this->subjectConverterManager->getSubjectsForEntity($item));
},
[]
);
$subjectBag = $this->subjectConverterManager->getSubjectsForEntity($event->mainSubject, true);
foreach ($event->subjects as $target) {
$subjectBag->append($this->subjectConverterManager->getSubjectsForEntity($target, false));
}
$user = $this->security->getUser();
@@ -50,7 +47,8 @@ final readonly class AuditEvent2Trail implements AuditEvent2TrailInterface
$this->clock->now(),
$user instanceof User ? $user : null,
$description,
array_map(fn (Subject $subject) => $subject->asArray(), $subjects),
$subjectBag->subject->asArray(),
array_map(fn (Subject $subject) => $subject->asArray(), $subjectBag->associatedSubjects),
$event->metadata,
);
}

View File

@@ -25,4 +25,26 @@ class Subject
{
return [...$this->identifiers, 't' => $this->type];
}
public function isEqual(Subject $subject): bool
{
if ($subject->type !== $this->type) {
return false;
}
foreach ($this->identifiers as $k => $identifierValue) {
if (!array_key_exists($k, $subject->identifiers)) {
return false;
}
if ($subject->identifiers[$k] !== $identifierValue) {
return false;
}
}
if (count($this->identifiers) !== count($subject->identifiers)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Audit;
final class SubjectBag
{
public function __construct(
public Subject $subject,
/**
* @var list<Subject>
*/
public array $associatedSubjects = [],
) {}
public function append(SubjectBag $subjectBag): void
{
$toAppend = [$subjectBag->subject, ...$subjectBag->associatedSubjects];
foreach ($toAppend as $subject) {
if ($subject->isEqual($this->subject)) {
continue;
}
foreach ($this->associatedSubjects as $associatedSubject) {
if ($subject->isEqual($associatedSubject)) {
continue 2;
}
}
$this->associatedSubjects[] = $subject;
}
}
}

View File

@@ -18,10 +18,8 @@ interface SubjectConverterInterface
{
/**
* @param T $subject
*
* @return Subject|list<Subject>
*/
public function convert(mixed $subject): Subject|array;
public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag;
/**
* Determines whether the given subject is supported for conversion.

View File

@@ -22,7 +22,7 @@ final readonly class SubjectConverterManager implements SubjectConverterManagerI
private iterable $converters,
) {}
public function getSubjectsForEntity(mixed $subject): array
public function getSubjectsForEntity(mixed $subject, bool $includeAssociated = false): SubjectBag
{
foreach ($this->converters as $converter) {
if ($converter instanceof SubjectConverterManagerAwareInterface) {
@@ -30,9 +30,7 @@ final readonly class SubjectConverterManager implements SubjectConverterManagerI
}
if ($converter->supportsConvert($subject)) {
$subjects = $converter->convert($subject);
return $subjects instanceof Subject ? [$subjects] : $subjects;
return $converter->convert($subject);
}
}

View File

@@ -13,8 +13,5 @@ namespace Chill\MainBundle\Audit;
interface SubjectConverterManagerInterface
{
/**
* @return list<Subject>
*/
public function getSubjectsForEntity(mixed $subject): array;
public function getSubjectsForEntity(object $subject, bool $includeAssociated = false): SubjectBag;
}

View File

@@ -26,26 +26,28 @@ class AuditTrail
public function __construct(
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true, name: 'id')]
#[ORM\Column(name: 'id', type: 'uuid', unique: true)]
private UuidInterface $id,
#[ORM\Column(type: Types::STRING, length: 255, name: 'action')]
#[ORM\Column(name: 'action', type: Types::STRING, length: 255)]
private string $action,
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, name: 'occurredat')]
#[ORM\Column(name: 'occurredat', type: Types::DATETIMETZ_IMMUTABLE)]
private \DateTimeImmutable $occurredAt,
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(nullable: true, name: 'user_id', referencedColumnName: 'id')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true)]
private ?User $user = null,
#[ORM\Column(type: Types::STRING, length: 255, nullable: false, options: ['default' => ''], name: 'description')]
#[ORM\Column(name: 'description', type: Types::STRING, nullable: false, options: ['default' => ''])]
private string $description = '',
#[ORM\Column(name: 'main_subject', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $mainSubject = [],
/**
* @var list<array<string, mixed>>
*/
#[ORM\Column(type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"], name: 'targets')]
private array $targets = [],
#[ORM\Column(name: 'subjects', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $subjects = [],
/**
* @var array<array-key, mixed>
*/
#[ORM\Column(type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"], name: 'metadata')]
#[ORM\Column(name: 'metadata', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $metadata = [],
) {}
@@ -77,9 +79,17 @@ class AuditTrail
/**
* @return list<array<string, mixed>>
*/
public function getTargets(): array
public function getSubjects(): array
{
return $this->targets;
return $this->subjects;
}
/**
* @return array<string, mixed>
*/
public function getMainSubject(): array
{
return $this->mainSubject;
}
/**

View File

@@ -42,7 +42,8 @@ class AuditTrailRepository extends ServiceEntityRepository
'occurredat' => ':occured_at',
'user_id' => ':user_id',
'description' => ':description',
'targets' => ':targets',
'main_subject' => ':main_subject',
'subjects' => ':subjects',
'metadata' => ':metadata',
])
->setParameter('id', $auditTrail->getId())
@@ -50,9 +51,24 @@ class AuditTrailRepository extends ServiceEntityRepository
->setParameter('occured_at', $auditTrail->getOccurredAt(), Types::DATETIMETZ_IMMUTABLE)
->setParameter('user_id', $auditTrail->getUser()?->getId(), Types::INTEGER)
->setParameter('description', $auditTrail->getDescription())
->setParameter('targets', $auditTrail->getTargets(), Types::JSON)
->setParameter('main_subject', $auditTrail->getMainSubject(), Types::JSON)
->setParameter('subjects', $auditTrail->getSubjects(), Types::JSON)
->setParameter('metadata', $auditTrail->getMetadata(), Types::JSON);
$sql->executeQuery();
}
/**
* @param array{} $criteria
*
* @return array<AuditTrail>
*/
public function findByCriteria(array $criteria, int $offset = 0, int $limit = 100): array
{
return $this->createQueryBuilder('audit')
->orderBy('audit.occurredAt', 'DESC')
->setMaxResults($limit)
->setFirstResult($offset)
->getQuery()->getResult();
}
}

View File

@@ -14,6 +14,7 @@ namespace Chill\MainBundle\Tests\Audit;
use Chill\MainBundle\Audit\AuditEvent;
use Chill\MainBundle\Audit\AuditEvent2Trail;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use Chill\MainBundle\Audit\SubjectConverterManagerInterface;
use Chill\MainBundle\Entity\AuditTrail;
use PHPUnit\Framework\TestCase;
@@ -44,15 +45,22 @@ class AuditEvent2TrailTest extends TestCase
$event = new AuditEvent(
action: 'test_action',
subjects: [$subject = new \stdClass()],
mainSubject: $subject = new \stdClass(),
description: $description->reveal(),
metadata: ['foo' => 'bar']
);
$security->getUser()->willReturn(null);
$subjectConverterManager->getSubjectsForEntity($subject)
->willReturn([new Subject('stdClass', ['id' => '1'])]);
$subjectConverterManager->getSubjectsForEntity($subject, true)
->willReturn(
new SubjectBag(
new Subject('stdClass', ['id' => '1']),
[
new Subject('stdClass2', ['id' => '2']),
]
)
);
$service = new AuditEvent2Trail(
$translator->reveal(),
@@ -66,7 +74,8 @@ class AuditEvent2TrailTest extends TestCase
$this->assertInstanceOf(AuditTrail::class, $trail);
$this->assertSame('test_action', $trail->getAction());
$this->assertSame('translated description', $trail->getDescription());
$this->assertSame([['id' => '1', 't' => 'stdClass']], $trail->getTargets());
$this->assertSame(['id' => '1', 't' => 'stdClass'], $trail->getMainSubject());
$this->assertSame([['id' => '2', 't' => 'stdClass2']], $trail->getSubjects());
$this->assertSame(['foo' => 'bar'], $trail->getMetadata());
$this->assertEquals($clock->now(), $trail->getOccurredAt());
}
@@ -80,11 +89,22 @@ class AuditEvent2TrailTest extends TestCase
$event = new AuditEvent(
action: 'test_action',
mainSubject: $subject = new \stdClass(),
subjects: [],
description: 'string description',
metadata: []
);
$subjectConverterManager->getSubjectsForEntity($subject, true)
->willReturn(
new SubjectBag(
new Subject('stdClass', ['id' => '1']),
[
new Subject('stdClass2', ['id' => 2]),
]
)
);
$security->getUser()->willReturn(null);
$service = new AuditEvent2Trail(

View File

@@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Tests\Audit;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use PHPUnit\Framework\TestCase;
/**
* @internal
*
* @coversNothing
*/
class SubjectBagTest extends TestCase
{
public function testAppend(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$bag = new SubjectBag($subject1);
$subject2 = new Subject('type2', ['id' => '2']);
$associated1 = new Subject('type3', ['id' => '3']);
$bag2 = new SubjectBag($subject2, [$associated1]);
$bag->append($bag2);
$this->assertCount(2, $bag->associatedSubjects);
$this->assertSame($subject2, $bag->associatedSubjects[0]);
$this->assertSame($associated1, $bag->associatedSubjects[1]);
}
public function testAppendAvoidDuplicates(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$associated1 = new Subject('type2', ['id' => '2']);
$bag = new SubjectBag($subject1, [$associated1]);
// Duplicate of associated1
$subject2 = new Subject('type2', ['id' => '2']);
$bag2 = new SubjectBag($subject2);
$bag->append($bag2);
$this->assertCount(1, $bag->associatedSubjects, 'Should not add duplicate of already present associated subject');
// Add another one
$subject3 = new Subject('type3', ['id' => '3']);
$bag3 = new SubjectBag($subject3, [$subject2]); // subject2 is duplicate of associated1
$bag->append($bag3);
$this->assertCount(2, $bag->associatedSubjects);
$this->assertSame($subject3, $bag->associatedSubjects[1]);
}
public function testAppendAvoidDuplicateWithMainSubject(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$associated1 = new Subject('type2', ['id' => '2']);
$bag = new SubjectBag($subject1, [$associated1]);
// Duplicate of associated1
$subject2 = new Subject('type1', ['id' => '1']);
$bag2 = new SubjectBag($subject2);
$bag->append($bag2);
$this->assertCount(1, $bag->associatedSubjects, 'Should not add duplicate of already present associated subject');
}
}

View File

@@ -13,6 +13,7 @@ namespace Chill\MainBundle\Tests\Audit;
use Chill\MainBundle\Audit\Exception\ConvertSubjectException;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use Chill\MainBundle\Audit\SubjectConverterInterface;
use Chill\MainBundle\Audit\SubjectConverterManager;
use PHPUnit\Framework\TestCase;
@@ -38,7 +39,7 @@ class SubjectConverterManagerTest extends TestCase
public function testReturnsSingleSubjectWhenConverterReturnsSubject(): void
{
$subject = new \stdClass();
$auditSubject = new Subject('type', ['id' => '123']);
$auditSubject = new SubjectBag(new Subject('type', ['id' => '123']));
$converter = $this->prophesize(SubjectConverterInterface::class);
$converter->supportsConvert($subject)->willReturn(true);
@@ -48,33 +49,13 @@ class SubjectConverterManagerTest extends TestCase
$result = $manager->getSubjectsForEntity($subject);
$this->assertCount(1, $result);
$this->assertSame(['id' => '123', 't' => 'type'], $result[0]->asArray());
}
public function testReturnsListOfSubjectsWhenConverterReturnsArray(): void
{
$subject = new \stdClass();
$auditSubject1 = new Subject('type1', ['id' => '123']);
$auditSubject2 = new Subject('type2', ['id' => '456']);
$converter = $this->prophesize(SubjectConverterInterface::class);
$converter->supportsConvert($subject)->willReturn(true);
$converter->convert($subject)->willReturn([$auditSubject1, $auditSubject2]);
$manager = new SubjectConverterManager([$converter->reveal()]);
$result = $manager->getSubjectsForEntity($subject);
$this->assertCount(2, $result);
$this->assertSame(['id' => '123', 't' => 'type1'], $result[0]->asArray());
$this->assertSame(['id' => '456', 't' => 'type2'], $result[1]->asArray());
$this->assertSame($auditSubject, $result);
}
public function testSkipsConverterThatDoesNotSupportSubject(): void
{
$subject = new \stdClass();
$auditSubject = new Subject('type', ['id' => '123']);
$auditSubject = new SubjectBag(new Subject('type', ['id' => '123']));
$converter1 = $this->prophesize(SubjectConverterInterface::class);
$converter1->supportsConvert($subject)->willReturn(false);
@@ -88,7 +69,6 @@ class SubjectConverterManagerTest extends TestCase
$result = $manager->getSubjectsForEntity($subject);
$this->assertCount(1, $result);
$this->assertSame(['id' => '123', 't' => 'type'], $result[0]->asArray());
$this->assertSame($auditSubject, $result);
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Tests\Audit;
use Chill\MainBundle\Audit\Subject;
use PHPUnit\Framework\TestCase;
/**
* @internal
*
* @covers \Chill\MainBundle\Audit\Subject
*/
class SubjectTest extends TestCase
{
public function testIsEqual(): void
{
$subject1 = new Subject('type1', ['id' => '1', 'name' => 'test']);
$subject2 = new Subject('type1', ['id' => '1', 'name' => 'test']);
$this->assertTrue($subject1->isEqual($subject2));
}
public function testIsEqualDifferentType(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$subject2 = new Subject('type2', ['id' => '1']);
$this->assertFalse($subject1->isEqual($subject2));
}
public function testIsEqualDifferentIdentifierValue(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$subject2 = new Subject('type1', ['id' => '2']);
$this->assertFalse($subject1->isEqual($subject2));
}
public function testIsEqualDifferentIdentifierKey(): void
{
$subject1 = new Subject('type1', ['id' => '1']);
$subject2 = new Subject('type1', ['other' => '1']);
$this->assertFalse($subject1->isEqual($subject2));
}
public function testIsEqualDifferentIdentifierCount(): void
{
$subject1 = new Subject('type1', ['id' => '1', 'name' => 'test']);
$subject2 = new Subject('type1', ['id' => '1']);
$this->assertFalse($subject1->isEqual($subject2));
$subject3 = new Subject('type1', ['id' => '1']);
$subject4 = new Subject('type1', ['id' => '1', 'name' => 'test']);
$this->assertFalse($subject3->isEqual($subject4));
}
public function testAsArray(): void
{
$subject = new Subject('type1', ['id' => '1', 'name' => 'test']);
$this->assertSame(['id' => '1', 'name' => 'test', 't' => 'type1'], $subject->asArray());
}
}

View File

@@ -23,7 +23,20 @@ final class Version20260123162433 extends AbstractMigration
public function up(Schema $schema): void
{
$this->addSql("CREATE TABLE chill_main_audit_trail (id UUID NOT NULL, user_id INT DEFAULT NULL, action VARCHAR(255) NOT NULL, occurredAt TIMESTAMP(0) WITH TIME ZONE NOT NULL, description VARCHAR(255) DEFAULT '' NOT NULL, targets JSONB DEFAULT '[]'::jsonb NOT NULL, metadata JSONB DEFAULT '[]'::jsonb NOT NULL, PRIMARY KEY(id))");
$this->addSql(
<<<'SQL'
CREATE TABLE chill_main_audit_trail (
id UUID NOT NULL,
user_id INT DEFAULT NULL,
action VARCHAR(255) NOT NULL,
occurredAt TIMESTAMP(0) WITH TIME ZONE NOT NULL,
description TEXT DEFAULT '' NOT NULL,
main_subject JSONB DEFAULT '[]'::jsonb NOT NULL,
subjects JSONB DEFAULT '[]'::jsonb NOT NULL,
metadata JSONB DEFAULT '[]'::jsonb NOT NULL,
PRIMARY KEY(id))
SQL
);
$this->addSql('CREATE INDEX IDX_331A47F4A76ED395 ON chill_main_audit_trail (user_id)');
$this->addSql('COMMENT ON COLUMN chill_main_audit_trail.id IS \'(DC2Type:uuid)\'');
$this->addSql('COMMENT ON COLUMN chill_main_audit_trail.occurredAt IS \'(DC2Type:datetimetz_immutable)\'');

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Audit\SubjectConverter;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use Chill\MainBundle\Audit\SubjectConverterInterface;
use Chill\MainBundle\Audit\SubjectConverterManagerAwareInterface;
use Chill\MainBundle\Audit\SubjectConverterManagerAwareTrait;
@@ -24,15 +25,15 @@ class AccompanyingPeriodSubjectConverter implements SubjectConverterInterface, S
{
use SubjectConverterManagerAwareTrait;
public function convert(mixed $subject): Subject|array
public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag
{
$data = [new Subject('accompanying_period', ['id' => $subject->getId()])];
$main = new SubjectBag(new Subject('accompanying_period', ['id' => $subject->getId()]));
foreach ($subject->getCurrentParticipations() as $participation) {
array_push($data, ...$this->subjectConverterManager->getSubjectsForEntity($participation->getPerson()));
$main->append($this->subjectConverterManager->getSubjectsForEntity($participation->getPerson(), false));
}
return $data;
return $main;
}
public function supportsConvert(mixed $subject): bool

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Audit\SubjectConverter;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use Chill\MainBundle\Audit\SubjectConverterInterface;
use Chill\MainBundle\Audit\SubjectConverterManagerAwareInterface;
use Chill\MainBundle\Audit\SubjectConverterManagerAwareTrait;
@@ -24,12 +25,12 @@ class AccompanyingPeriodWorkSubjectConverter implements SubjectConverterInterfac
{
use SubjectConverterManagerAwareTrait;
public function convert(mixed $subject): Subject|array
public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag
{
$data = [new Subject('accompanying_period_work', ['id' => $subject->getId()])];
$data = new SubjectBag(new Subject('accompanying_period_work', ['id' => $subject->getId()]));
foreach ($subject->getPersons() as $person) {
array_push($data, ...$this->subjectConverterManager->getSubjectsForEntity($person));
$data->append($this->subjectConverterManager->getSubjectsForEntity($person));
}
return $data;

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Audit\SubjectConverter;
use Chill\MainBundle\Audit\Subject;
use Chill\MainBundle\Audit\SubjectBag;
use Chill\MainBundle\Audit\SubjectConverterInterface;
use Chill\PersonBundle\Entity\Person;
@@ -20,9 +21,9 @@ use Chill\PersonBundle\Entity\Person;
*/
class PersonSubjectConverter implements SubjectConverterInterface
{
public function convert(mixed $subject): Subject|array
public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag
{
return new Subject('person', ['id' => $subject->getId()]);
return new SubjectBag(new Subject('person', ['id' => $subject->getId()]));
}
public function supportsConvert(mixed $subject): bool

View File

@@ -80,7 +80,8 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$this->eventDispatcher->dispatch(
new AuditEvent(
AuditTrail::AUDIT_UPDATE,
[$accompanyingCourse],
$accompanyingCourse,
[],
new TranslatableMessage('accompanying_period.audit.close'),
['action' => 'close']
)
@@ -133,7 +134,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$em->remove($accompanyingCourse);
$em->flush();
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_DELETE, [$accompanyingCourse]));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_DELETE, $accompanyingCourse));
$this->addFlash('success', $this->translator
->trans('The accompanying course has been successfully removed.'));
@@ -175,9 +176,9 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$this->eventDispatcher->dispatch(new AuditEvent(
AuditTrail::AUDIT_VIEW,
[$accompanyingCourse],
new TranslatableMessage('accompanying_period.audit.show_edit_page'),
['action' => 'show_edit_page']
$accompanyingCourse,
description: new TranslatableMessage('accompanying_period.audit.show_edit_page'),
metadata: ['action' => 'show_edit_page']
));
return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [
@@ -212,7 +213,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
{
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_VIEW, [$accompanyingCourse]));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_VIEW, $accompanyingCourse));
// compute some warnings
// get persons without household
@@ -283,7 +284,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$em->persist($period);
$em->flush();
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, [$period]));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, $period));
return $this->redirectToRoute('chill_person_accompanying_course_edit', [
'accompanying_period_id' => $period->getId(),
@@ -322,7 +323,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$em->persist($period);
$em->flush();
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, [$period]));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_CREATE, $period));
return $this->redirectToRoute('chill_person_accompanying_course_edit', [
'accompanying_period_id' => $period->getId(),
@@ -348,7 +349,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$accompanyingCourse->reOpen();
$this->managerRegistry->getManager()->flush();
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_UPDATE, [$accompanyingCourse], new TranslatableMessage('accompanying_period.audit.reopen'), ['action' => 'reopen']));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_UPDATE, $accompanyingCourse, description: new TranslatableMessage('accompanying_period.audit.reopen'), metadata: ['action' => 'reopen']));
return $this->redirectToRoute('chill_person_accompanying_course_index', [
'accompanying_period_id' => $accompanyingCourse->getId(),

View File

@@ -162,9 +162,9 @@ final class AccompanyingCourseWorkController extends AbstractController
$this->eventDispatcher->dispatch(
new AuditEvent(
AuditTrail::AUDIT_VIEW,
[$period],
new TranslatableMessage('accompanying_period.audit.show_list_work'),
['action' => 'show_list_work']
$period,
description: new TranslatableMessage('accompanying_period.audit.show_list_work'),
metadata: ['action' => 'show_list_work']
)
);
@@ -188,7 +188,7 @@ final class AccompanyingCourseWorkController extends AbstractController
$this->eventDispatcher->dispatch(
new AuditEvent(
AuditTrail::AUDIT_VIEW,
[$work],
$work,
)
);

View File

@@ -206,7 +206,7 @@ final class PersonController extends AbstractController
'You are not allowed to see this person.'
);
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_VIEW, [$person]));
$this->eventDispatcher->dispatch(new AuditEvent(AuditTrail::AUDIT_VIEW, $person));
return $this->render(
'@ChillPerson/Person/view.html.twig',