Skip to content

Commit 4de41de

Browse files
phansysfranmomu
authored andcommitted
[Loggable] Add LogEntryInterface
1 parent 42072bd commit 4de41de

File tree

16 files changed

+188
-44
lines changed

16 files changed

+188
-44
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ a release.
2323
- Tree: Add `Nested::ALLOWED_NODE_POSITIONS` constant in order to expose the available node positions
2424
- Support for `doctrine/collections` 2.0
2525
- Support for `doctrine/event-manager` 2.0
26+
- Loggable: Add `LogEntryInterface` interface in order to be implemented by log entry models
2627

2728
### Fixed
2829
- Sortable: Fix return value check of Comparable interface (#2541)
@@ -35,6 +36,9 @@ a release.
3536
- Deprecate the annotation reader being allowed to be any object.
3637
In 4.0, a `Doctrine\Common\Annotations\Reader` or `Gedmo\Mapping\Driver\AttributeReader` instance will be required.
3738
- `Gedmo\DoctrineExtensions::registerAnnotations()` is deprecated and will be removed in 4.0, the method has been no-op'd as all supported `doctrine/annotations` versions support autoloading
39+
- Loggable: Constants `LoggableListener::ACTION_CREATE`, `LoggableListener::ACTION_UPDATE` and `LoggableListener::ACTION_REMOVE`
40+
are deprecated. Use `LogEntryInterface::ACTION_CREATE`, `LogEntryInterface::ACTION_UPDATE` and `LogEntryInterface::ACTION_REMOVE`
41+
instead.
3842

3943
## [3.10.0] - 2022-11-14
4044
### Changed

doc/loggable.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ on how to setup and use the extensions in most optimized way.
3232

3333
### Loggable annotations:
3434

35-
- **@Gedmo\Mapping\Annotation\Loggable(logEntryClass="my\class")** this class annotation
36-
will store logs to optionally specified **logEntryClass**. You will still need to specify versioned fields with the following annotation.
35+
- **@Gedmo\Mapping\Annotation\Loggable(logEntryClass="My\LoggableModel")** this class annotation will store logs to optionally
36+
specified **logEntryClass**. The class provided in this annotation MUST implement ``Gedmo\Loggable\LogEntryInterface``. You will
37+
still need to specify versioned fields with the following annotation.
3738
- **@Gedmo\Mapping\Annotation\Versioned** tracks annotated property for changes
3839

39-
**Note:** If you need to use a different class, it must extend ``Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry``.
40-
4140
### Loggable attributes:
4241

43-
- **\#[Gedmo\Mapping\Annotation\Loggable(logEntryClass: MyClass::class]** this class attribute
44-
will store logs to optionally specified **logEntryClass**. You will still need to specify versioned fields with the following attribute.
42+
- **\#[Gedmo\Mapping\Annotation\Loggable(logEntryClass: My\LoggableModel::class]** this class attribute will store logs to optionally
43+
specified **logEntryClass**. The class provided in this attribute MUST implement ``Gedmo\Loggable\LogEntryInterface``. You will
44+
still need to specify versioned fields with the following attribute.
4545
- **\#[Gedmo\Mapping\Annotation\Versioned]** tracks attributed property for changes
4646

4747
### Loggable username:

phpstan-baseline.neon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ parameters:
7676
path: src/Loggable/Document/Repository/LogEntryRepository.php
7777

7878
-
79-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<object\\>\\:\\:getReflectionProperty\\(\\)\\.$#"
79+
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<Gedmo\\\\Loggable\\\\LogEntryInterface\\>\\:\\:getReflectionProperty\\(\\)\\.$#"
8080
count: 1
8181
path: src/Loggable/LoggableListener.php
8282

8383
-
84-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<object\\>\\:\\:newInstance\\(\\)\\.$#"
84+
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<Gedmo\\\\Loggable\\\\LogEntryInterface\\>\\:\\:newInstance\\(\\)\\.$#"
8585
count: 1
8686
path: src/Loggable/LoggableListener.php
8787

src/Loggable/Document/MappedSuperclass/AbstractLogEntry.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111

1212
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoODM;
1313
use Doctrine\ODM\MongoDB\Types\Type;
14+
use Gedmo\Loggable\LogEntryInterface;
1415

1516
/**
17+
* @phpstan-template T of object
18+
*
19+
* @phpstan-implements LogEntryInterface<T>
20+
*
1621
* @MongoODM\MappedSuperclass
1722
*/
1823
#[MongoODM\MappedSuperclass]
19-
abstract class AbstractLogEntry
24+
abstract class AbstractLogEntry implements LogEntryInterface
2025
{
2126
/**
2227
* @var string|null
@@ -29,6 +34,8 @@ abstract class AbstractLogEntry
2934
/**
3035
* @var string|null
3136
*
37+
* @phpstan-var self::ACTION_CREATE|self::ACTION_UPDATE|self::ACTION_REMOVE|null
38+
*
3239
* @MongoODM\Field(type="string")
3340
*/
3441
#[MongoODM\Field(type: Type::STRING)]
@@ -53,6 +60,8 @@ abstract class AbstractLogEntry
5360
/**
5461
* @var string|null
5562
*
63+
* @phpstan-var class-string<T>|null
64+
*
5665
* @MongoODM\Field(type="string")
5766
*/
5867
#[MongoODM\Field(type: Type::STRING)]

src/Loggable/Entity/MappedSuperclass/AbstractLogEntry.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111

1212
use Doctrine\DBAL\Types\Types;
1313
use Doctrine\ORM\Mapping as ORM;
14+
use Gedmo\Loggable\LogEntryInterface;
1415

1516
/**
17+
* @phpstan-template T of object
18+
*
19+
* @phpstan-implements LogEntryInterface<T>
20+
*
1621
* @ORM\MappedSuperclass
1722
*/
1823
#[ORM\MappedSuperclass]
19-
abstract class AbstractLogEntry
24+
abstract class AbstractLogEntry implements LogEntryInterface
2025
{
2126
/**
2227
* @var int|null
@@ -33,6 +38,8 @@ abstract class AbstractLogEntry
3338
/**
3439
* @var string|null
3540
*
41+
* @phpstan-var self::ACTION_CREATE|self::ACTION_UPDATE|self::ACTION_REMOVE|null
42+
*
3643
* @ORM\Column(type="string", length=8)
3744
*/
3845
#[ORM\Column(type: Types::STRING, length: 8)]
@@ -57,6 +64,8 @@ abstract class AbstractLogEntry
5764
/**
5865
* @var string|null
5966
*
67+
* @phpstan-var class-string<T>|null
68+
*
6069
* @ORM\Column(name="object_class", type="string", length=191)
6170
*/
6271
#[ORM\Column(name: 'object_class', type: Types::STRING, length: 191)]

src/Loggable/LogEntryInterface.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Doctrine Behavioral Extensions package.
5+
* (c) Gediminas Morkevicius <[email protected]> http://www.gediminasm.org
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace Gedmo\Loggable;
11+
12+
/**
13+
* Interface to be implemented by log entry models.
14+
*
15+
* @phpstan-template T of object
16+
*
17+
* @author Javier Spagnoletti <[email protected]>
18+
*/
19+
interface LogEntryInterface
20+
{
21+
public const ACTION_CREATE = 'create';
22+
23+
public const ACTION_UPDATE = 'update';
24+
25+
public const ACTION_REMOVE = 'remove';
26+
27+
/**
28+
* @phpstan-param self::ACTION_CREATE|self::ACTION_UPDATE|self::ACTION_REMOVE $action
29+
*
30+
* @return void
31+
*/
32+
public function setAction(string $action);
33+
34+
/**
35+
* @return string|null
36+
*
37+
* @phpstan-return self::ACTION_CREATE|self::ACTION_UPDATE|self::ACTION_REMOVE|null
38+
*/
39+
public function getAction();
40+
41+
/**
42+
* @return void
43+
*/
44+
public function setUsername(string $username);
45+
46+
/**
47+
* @return string|null
48+
*/
49+
public function getUsername();
50+
51+
/**
52+
* @phpstan-param class-string<T> $objectClass
53+
*
54+
* @return void
55+
*/
56+
public function setObjectClass(string $objectClass);
57+
58+
/**
59+
* @return string|null
60+
*
61+
* @phpstan-return class-string<T>
62+
*/
63+
public function getObjectClass();
64+
65+
/**
66+
* @return void
67+
*/
68+
public function setLoggedAt();
69+
70+
/**
71+
* @return \DateTimeInterface|null
72+
*/
73+
public function getLoggedAt();
74+
75+
/**
76+
* @return void
77+
*/
78+
public function setObjectId(string $objectId);
79+
80+
/**
81+
* @return string|null
82+
*/
83+
public function getObjectId();
84+
85+
/**
86+
* @param array<string, mixed> $data
87+
*
88+
* @return void
89+
*/
90+
public function setData(array $data);
91+
92+
/**
93+
* @return array<string, mixed>|null
94+
*/
95+
public function getData();
96+
97+
/**
98+
* @return void
99+
*/
100+
public function setVersion(int $version);
101+
102+
/**
103+
* @return int|null
104+
*/
105+
public function getVersion();
106+
}

src/Loggable/LoggableListener.php

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
* @phpstan-type LoggableConfiguration = array{
2626
* loggable?: bool,
27-
* logEntryClass?: class-string,
27+
* logEntryClass?: class-string<LogEntryInterface>,
2828
* useObjectClass?: class-string,
2929
* versioned?: string[],
3030
* }
@@ -38,19 +38,19 @@
3838
class LoggableListener extends MappedEventSubscriber
3939
{
4040
/**
41-
* Create action
41+
* @deprecated use `LogEntryInterface::ACTION_CREATE` instead
4242
*/
43-
public const ACTION_CREATE = 'create';
43+
public const ACTION_CREATE = LogEntryInterface::ACTION_CREATE;
4444

4545
/**
46-
* Update action
46+
* @deprecated use `LogEntryInterface::ACTION_UPDATE` instead
4747
*/
48-
public const ACTION_UPDATE = 'update';
48+
public const ACTION_UPDATE = LogEntryInterface::ACTION_UPDATE;
4949

5050
/**
51-
* Remove action
51+
* @deprecated use `LogEntryInterface::ACTION_REMOVE` instead
5252
*/
53-
public const ACTION_REMOVE = 'remove';
53+
public const ACTION_REMOVE = LogEntryInterface::ACTION_REMOVE;
5454

5555
/**
5656
* Username for identification
@@ -64,7 +64,7 @@ class LoggableListener extends MappedEventSubscriber
6464
* key generated yet - MySQL case. These entries
6565
* will be updated with new keys on postPersist event
6666
*
67-
* @var array
67+
* @var array<int, LogEntryInterface>
6868
*/
6969
protected $pendingLogEntryInserts = [];
7070

@@ -74,7 +74,9 @@ class LoggableListener extends MappedEventSubscriber
7474
* These are pending relations in case it does not
7575
* have an identifier yet
7676
*
77-
* @var array
77+
* @var array<int, array<int, array<string, LogEntryInterface|string>>>
78+
*
79+
* @phpstan-var array<int, array<int, array{log: LogEntryInterface, field: string}>>
7880
*/
7981
protected $pendingRelatedObjects = [];
8082

@@ -186,13 +188,13 @@ public function onFlush(EventArgs $eventArgs)
186188
$uow = $om->getUnitOfWork();
187189

188190
foreach ($ea->getScheduledObjectInsertions($uow) as $object) {
189-
$this->createLogEntry(self::ACTION_CREATE, $object, $ea);
191+
$this->createLogEntry(LogEntryInterface::ACTION_CREATE, $object, $ea);
190192
}
191193
foreach ($ea->getScheduledObjectUpdates($uow) as $object) {
192-
$this->createLogEntry(self::ACTION_UPDATE, $object, $ea);
194+
$this->createLogEntry(LogEntryInterface::ACTION_UPDATE, $object, $ea);
193195
}
194196
foreach ($ea->getScheduledObjectDeletions($uow) as $object) {
195-
$this->createLogEntry(self::ACTION_REMOVE, $object, $ea);
197+
$this->createLogEntry(LogEntryInterface::ACTION_REMOVE, $object, $ea);
196198
}
197199
}
198200

@@ -203,7 +205,7 @@ public function onFlush(EventArgs $eventArgs)
203205
* @phpstan-param class-string $class
204206
*
205207
* @return string
206-
* @phpstan-return class-string
208+
* @phpstan-return class-string<LogEntryInterface>
207209
*/
208210
protected function getLogEntryClass(LoggableAdapter $ea, $class)
209211
{
@@ -214,8 +216,8 @@ protected function getLogEntryClass(LoggableAdapter $ea, $class)
214216
* Handle any custom LogEntry functionality that needs to be performed
215217
* before persisting it
216218
*
217-
* @param object $logEntry The LogEntry being persisted
218-
* @param object $object The object being Logged
219+
* @param LogEntryInterface $logEntry The LogEntry being persisted
220+
* @param object $object The object being Logged
219221
*
220222
* @return void
221223
*/
@@ -231,9 +233,9 @@ protected function getNamespace()
231233
/**
232234
* Returns an objects changeset data
233235
*
234-
* @param LoggableAdapter $ea
235-
* @param object $object
236-
* @param object $logEntry
236+
* @param LoggableAdapter $ea
237+
* @param object $object
238+
* @param LogEntryInterface $logEntry
237239
*
238240
* @return array
239241
*/
@@ -278,7 +280,9 @@ protected function getObjectChangeSetData($ea, $object, $logEntry)
278280
* @param string $action
279281
* @param object $object
280282
*
281-
* @return \Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry|null
283+
* @phpstan-param LogEntryInterface::ACTION_CREATE|LogEntryInterface::ACTION_UPDATE|LogEntryInterface::ACTION_REMOVE $action
284+
*
285+
* @return LogEntryInterface|null
282286
*/
283287
protected function createLogEntry($action, $object, LoggableAdapter $ea)
284288
{
@@ -294,7 +298,7 @@ protected function createLogEntry($action, $object, LoggableAdapter $ea)
294298
if ($config = $this->getConfiguration($om, $meta->getName())) {
295299
$logEntryClass = $this->getLogEntryClass($ea, $meta->getName());
296300
$logEntryMeta = $om->getClassMetadata($logEntryClass);
297-
/** @var \Gedmo\Loggable\Entity\LogEntry $logEntry */
301+
/** @var LogEntryInterface $logEntry */
298302
$logEntry = $logEntryMeta->newInstance();
299303

300304
$logEntry->setAction($action);
@@ -304,23 +308,23 @@ protected function createLogEntry($action, $object, LoggableAdapter $ea)
304308

305309
// check for the availability of the primary key
306310
$uow = $om->getUnitOfWork();
307-
if (self::ACTION_CREATE === $action && $ea->isPostInsertGenerator($meta)) {
311+
if (LogEntryInterface::ACTION_CREATE === $action && $ea->isPostInsertGenerator($meta)) {
308312
$this->pendingLogEntryInserts[spl_object_id($object)] = $logEntry;
309313
} else {
310314
$logEntry->setObjectId($wrapped->getIdentifier());
311315
}
312316
$newValues = [];
313-
if (self::ACTION_REMOVE !== $action && isset($config['versioned'])) {
317+
if (LogEntryInterface::ACTION_REMOVE !== $action && isset($config['versioned'])) {
314318
$newValues = $this->getObjectChangeSetData($ea, $object, $logEntry);
315319
$logEntry->setData($newValues);
316320
}
317321

318-
if (self::ACTION_UPDATE === $action && 0 === count($newValues)) {
322+
if (LogEntryInterface::ACTION_UPDATE === $action && 0 === count($newValues)) {
319323
return null;
320324
}
321325

322326
$version = 1;
323-
if (self::ACTION_CREATE !== $action) {
327+
if (LogEntryInterface::ACTION_CREATE !== $action) {
324328
$version = $ea->getNewVersion($logEntryMeta, $object);
325329
if (empty($version)) {
326330
// was versioned later

0 commit comments

Comments
 (0)