Problem/Motivation
All implementations of TempStore provide a getMetadata()
method which returns either NULL or a \stdClass with two properties: owner
and updated
.
It is tricky for consumers of this API to know what the properties are and what they represent.
Most commonly, the owner value is used to load a user and the updated property is used to format a date representing the time that has elapsed.
Proposed resolution
Provide a dedicated class to represent this information, with two helper methods that encompass the most common use cases.
Remaining tasks
User interface changes
N/A
API changes
BC layer provided. Deprecation errors will fire for code accessing the properties.
Data model changes
N/A
Release notes snippet
N/A
Comment | File | Size | Author |
---|---|---|---|
#24 | 3025867-lock-24-interdiff.txt | 2.38 KB | tim.plunkett |
#24 | 3025867-lock-24.patch | 27.32 KB | tim.plunkett |
Comments
Comment #2
tim.plunkettCR added: https://www.drupal.org/node/3025869
Comment #3
xjmCan it still return NULL?
Comment #4
tim.plunkettIt sure can
Comment #7
tim.plunkettHmmm, need to fix a deprecation in Views as well.
Comment #9
tim.plunkettComment #10
Kristen PolOk, I made a pass through this but need to look again with fresh eyes (hopefully tomorrow). For testing, just test locking for views, yes?
Since there is getOwnerId and getOwner, seems like this variable (and elsewhere) should change to ownerId.
Unclear why this is called $editingLock.
Ah, it's to not conflict with old $lock? And owner (instead of ownerId) is to keep consistent with old naming.
Comment #11
tim.plunkett10.3 exactly. Not sure how best to document that
It feels bad to purposefully choose subpar names, but the good ones are taken and need BC
Comment #12
tim.plunkettActually, with a bit more BC layer we can safely use the ideal names after all!
Comment #13
Berdir#1748022: Make cache()->get() return a classed CacheItem object is very similar and has a ton of discussion around BC, might be interesting.
Comment #14
Kristen PolThanks for the changes in #12! Much better. :) Does anything need to be done for @Berdir's comment?
Comment #15
BerdirOne thing that the other issue did was to extend from \stdClass to pass explicit checks against that. But no idea how to do that in a BC way, e.g. detect checks against that, and if that's in any way necessary here.
Cache items are probably used 50x (random guess) more often than this thing, so it's far less likely that something breaks due to that. I think for cache items we at least had explicit test coverage for that.
Comment #16
tim.plunkettThis should not be necessary. It was either an object or it was NULL, there was never any reason to care beyond that.
Comment #17
Kristen PolI tested the patch from #12 by:
1) Created a view
2) Created view as user 1 and saved
3) Edited the view as user 2 and didn't save
4) Loaded the view as user 1 and it showed it was locked
5) Broke the lock and changes were gone
6) Repeated the above to get the lock as user 2 and broke the lock
Appears to be working as expected.
Comment #18
Kristen PolThe code looks ok, the view locking passes manual testing, and tests are passing. Marking this RTBC.
Comment #19
alexpott+1 to the idea of making a Lock value object.
It feels odd to move from service injection to service location. Are we sure we want to do this?
Comment #20
tim.plunkettAfter discussing #19 with @alexpott, I realized that we're coupling the presentation to the value object (via the date formatter).
But the "break lock" link is a pattern in core thanks to the Views UI and will be reused in Layout Builder. Let's establish that with a RenderElement.
Comment #22
tim.plunkettBleh.
Citing
\Drupal\Core\Session\AccountProxy::loadUserEntity()
as precedent for using user.module code in Drupal\Core code...Comment #23
phenaproximaThis usage example is not accurate; #type should be break_lock_link.
Why did this change? Seems like it could also assert that there is an ownerId attribute, in addition to updated.
This seems like a good place to call $this->getLock(). Generally I see no reason for objects not to use their own APIs.
This stuff seems like it should be in a trait.
Nit: Maybe removeLock() or clearLock() would be a clearer name for this method?
Seeing as how the 'owner' and 'updated' properties have BC, is there any reason not to simply return $lock from this?
Comment #24
tim.plunkett#23
1) Well spotted
2) Added in ownerId, but it's still a change as we updated the property name. Actually getting the old
owner
has BC, but not the way the internals of assertObjectHasAttribute3) Sure
4) I disagree; there's only one usage of it and the only reason the lock is stored here is because of legacy Views UI code. I don't think it makes sense to store the lock as a stateful property
5) Discussed and I think it's fine as-is. Once again, only within Views UI
6) Nice, this should work now (the BC layers evolved over time)
Comment #25
phenaproximaWell, that's all I got, folks. Looks legit and nice to me.
Comment #26
andypostCR should mention about new render element, it is useful for contrib/custom code
Comment #27
tim.plunkettDone
Comment #29
xjmNice addition; this makes it much cleaner
It makes sense for these to be
final
andprivate
under current policy since this is just a value object that will be constructed inline, and therefore inherently not swappable.+1 for adding this BC layer. @tim.plunkett and I discussed this in Slack awhile back but I forgot to document on the issue.
The reason this part of the BC layer is only provided on the Views UI form is that setting it isn't that useful generically; we just have to let Views access it still because everything is public there. (The two properties in the getter BC layer are the actual values in the value object.)
I was a bit alarmed on the hardcoded UIDs of
2
and1
here -- seems brittle and hardcoding serial IDs in a test runner has caused us criticals before -- but the test already has:(etc.)
So we don't need to fix that here.
False value is
FALSE
!All this looks good to me now. Committed and pushed to 8.7.x and published the CR. Thanks!