-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce the Revisionable extension #2825
base: main
Are you sure you want to change the base?
Conversation
758fae8
to
9428ca6
Compare
Having no username set in the |
Thanks, I've updated everything to account for that. |
25c3e45
to
6f21faf
Compare
b143ad5
to
f4bc83a
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2825 +/- ##
==========================================
+ Coverage 78.53% 78.92% +0.39%
==========================================
Files 168 181 +13
Lines 8790 9353 +563
==========================================
+ Hits 6903 7382 +479
- Misses 1887 1971 +84 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
761f013
to
8af0d92
Compare
What's the status of this PR? Anything I can do to help/test? Would like to see it merged soon! |
I don't think I have anything big to add to this PR at this point. It really just needs testing and making sure the idea is solid (especially as part of the rationale for a new extension versus trying to make a version of loggable that is DBAL 4 friendly is allowing both the old and new data to live side-by-side so an app can either keep that old data by either polyfilling the deprecated DBAL array type or migrating it into the new extension). |
99c5d53
to
5b3b1cb
Compare
I started trying to test/use this in an ODM configuration. Notables so far:
So at the moment I've not been able to create/trigger any revisions, I guess there is a way to enable this without EDIT: Yes, the
|
The loggable listener has to be open because of its Maybe it's too soon to go with a hard final listener, but I'm not going to take the "no I'm not going to open it up for inheritance" standpoint if there's a legitimate use case that a hard final blocks. Maybe somewhere down the road, something can be figured out for how interfaces can be built for the listeners (as right now the hook points into Doctrine are all Doctrine event listeners, so the interface is more so specifying the required events to subscribe to and less what a public-ish API looks like).
The new extension is more strictly typed given it's being written as new code with the PHP 7.4 minimum in mind, compared to all of the other extensions which were written in PHP 5 times;
I wanted to make the revision model a little more strict in terms of having valid state, hence the introduction of the static
That'd have to be done after this PR landed. Trying to shoot a PR off over there would just result in a PR with constantly failing builds, it's easier to handle that update after this change lands. For manual config in a Symfony app, you can take the loggable listener service in https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/frameworks/symfony.md#extensions-compatible-with-all-managers and change that to the revisionable listener (it'll hook into the same events so it's just changing the service ID and class name)
It'll get done before this merges. I did call out the needed mapping changes in the PR description, but the gist of it is you switch |
If action is no longer nullable does it make sense set a default then, to avoid e.g.
(or whatever, if the syntax is slightly off) |
0572145
to
a4e4d90
Compare
} elseif ($documentMeta->isSingleValuedAssociation($field)) { | ||
assert(class_exists($mapping['targetDocument'])); | ||
|
||
$value = $value ? $this->getDocumentManager()->getReference($mapping['targetDocument'], $value) : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a stricter condition around $value
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a !== null
would work in this branch? It'd be another one of those "we gotta test it thoroughly" things, and TBH there's only a very basic "does it work without erroring" smoke test for the revert()
capabilities so we'd need to build out some good test fixtures here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where me not knowing the MongoDB ODM well doesn't help any.
1 "isSingleValuedAssociation"
2 "67ce41458a6433683e0c45e6"
This is the only time the branch gets reached in the RevisionableDocumentTest
. Looking at the comment fixture, it looks like this is going to be the ReferenceOne
relation to the article, so I guess $value
in this case is the document identifier? If that's the case then this could most likely work as a !== null
check, assuming that it goes from a non-null to a null value when a non-required reference is removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Friendly ping @franmomu 🙏
Based on your experience, maybe you have a chance to help with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a keyword for this new extension at composer.json
.
Co-authored-by: Javier Spagnoletti <[email protected]>
Co-authored-by: Javier Spagnoletti <[email protected]>
…ode for similar in loggable
Ref: #2502
As the issue notes, the loggable extension is incompatible with ORM 4.x due to the removal of the array field type. The issue also has a patch for migrating to JSON, but because of the need for a data migration, it's not a patch that can be easily dropped in. Enter the new revisionable extension.
Mostly the same thing as the loggable extension, except for changing the way the data is collected for the history object's data field. For the ORM, the data was stored as a serialized PHP array, which while it works, is less than optimal:
The new extension uses the mapping layers of the ORM and ODM to store the data in its database representation, and for the ORM, as a native JSON field:
Another benefit to introducing a new extension is that the old and new versions can live side-by-side and allows for a data migration so long as your log entry data can be unserialized back into PHP and its info mapped to a database value (https://gist.github.com/mbabker/1879a3e55feac953e23cb2f025654052 was something I quickly hacked into the example app code as a proof of concept, a full-on tool could be built out using the logic here).
There are some other extras baked into this branch which generally help improve things too, including:
WrapperInterface
implementations (and@method
annotated on the interface itself to add to 4.0) to handle mapping values to PHP and database formats for each managerDifferences between the two extensions include:
prePersistLogEntry()
hook that existed in the loggable listener, the Doctrine event manager can be used here without needing to have an open classRevisionable
attribute instead ofLoggable
, and reuses the existingVersioned
attribute; for migrating, you're basically looking at a handful of lines changed no matter the mapping (changing a class import and annotation/attribute when using that mapping, XML goes from<gedmo:loggable/>
to<gedmo:revisionable/>