Updated: Comment #N
Problem/Motivation
DiscoveryInterface::getDefinition() returns NULL when a plugin ID cannot be found.
#2168333: Ensure custom EntityType controllers can be provided by modules adds an optional parameter, defaulting to FALSE, that when TRUE throws an exception instead of returning NULL
Proposed resolution
Move this optional parameter to the interface and all subclasses.
Remaining tasks
- (done, made default true) Consider making it default to TRUE, or just making that the actual expected behavior, and never return NULL
- (done) review | Contributor task documentation for reviewing patch
User interface changes
N/A
API changes
None yet.
| Comment | File | Size | Author |
|---|---|---|---|
| #84 | plugin-2178795-84.patch | 737 bytes | tim.plunkett |
| #80 | interdiff-2178795-77-80.txt | 398 bytes | yesct |
| #80 | drupal_2178795_80.patch | 48.91 KB | yesct |
| #77 | interdiff.txt | 945 bytes | jlbellido |
| #77 | drupal_2178795_77.patch | 48.91 KB | jlbellido |
Comments
Comment #1
yched commentedMeaning we'd need a hasDefinition() method for simple existence checks ?
Comment #2
berdirNot having an argument at all would require that method. But having that method might be a good idea anyway, as if ($manager->hasDefininition()) makes more sense than getDefinition().
I'd vote for having the argument and default to TRUE (throwing exception). That's the same behavior as $container->get().
Comment #3
dawehnerA non existing plugin is certainly not the code path you expect to have, so an exception is a good tool here.
Comment #4
tim.plunkettHere's two patches, one keeping the default as FALSE, the other as TRUE. Depending on how many failures we have for TRUE, we can decide what to do.
Also, the abstract base classes for the exception throwing should just be a trait, but we still can't do that yet.
Comment #8
tim.plunkettHm, not too bad. I'll be looking into this tonight.
Comment #9
tim.plunkettGoing to double down on defaulting to TRUE, it's much better for DX and seems to be the expectation.
#2143057: DefaultPluginManager::getDefinition() violates interface has the fix for DateTimeItemTest, but this issue also encompasses that fix, so I'm going to mark it as a dupe.
Many of the other fails were because field_test uses the 'entity_test' entity type, but doesn't always enable entity_test.module. How that works is beyond me.
Finally, #1875992: Add EntityFormDisplay objects for entity forms moved a bunch of code around, and turned 'text_textfield' into 'text_text', which somehow didn't break until now...
There might have been other fails, but that text_text one was a LOT of the time, so just sending this to the bot.
Comment #11
tim.plunkettI think the InstallUninstallTest failures are actually #2155635: Allow plugin managers to opt in to cache clear during module install, which sucks.
This should fix the rest.
Comment #13
tim.plunkettOh, or maybe it was just FieldTypePluginManager
Comment #15
tim.plunkettUgh. Because they are exceptions, it interrupts the rest of the test. So we can only find one at a time...
Adding to all places that wrap getDefinition() in an if(), they definitely want NULL instead.
Comment #16
tim.plunkettRerolled for #2184951: Allow plugins to declare themselves a derivative and #2110501: ControllerBase should implement ContainerInjectionInterface like FormBase
Comment #19
tim.plunkettAh, in #2184951: Allow plugins to declare themselves a derivative there is a first check to getDefinition on the full $plugin_id, and not just on the $base_plugin_id. That one will usually fail, and is only used for overrides. The second call on the $base_plugin_id will always happen, and is the correct place to (possibly) throw an exception.
Added a comment to that effect.
Comment #20
yched commentedStill +1 on a hasDefinition($plugin_id) ?
Comment #21
tim.plunkettFine by me.
Comment #24
tim.plunkettI had a condition backwards, but also found a nice place to encapsulate a field exception.
Comment #25
tim.plunkettEh, let's not copy all of that boilerplate.
Comment #26
yched commentedHm - not sure why we'd want to do that ?
Plus, there might be places that call FieldTypePM::getDefinition($unknow_plugin_id) but are not "attempting to create a field" ?
I'd tend to leave FieldTypePM::getDefinition() untouched / non-overriden, and have Field::preSaveNew() catch the generic plugin exception and throw its more specific one ?
Comment #27
tim.plunkettHrmmmmmmm fair enough, since the exception message is a bit overspecific.
I'll just pass FALSE and avoid the overhead of catching the exception.
Comment #28
neclimdulSeems like I've seen this code before. I was leaning toward just making this the default functionality but that would be bad for derivatives.
So, seems like this is a useful addition. +1
Comment #29
tim.plunkettAfter further discussion with @neclimdul and @msonnabaum, I tried out patches where it always threw an exception, and another where we used a constant instead of TRUE/FALSE. Both of those were way more unwieldy than this, and with no real gain. So, sticking with this.
It needed a reroll after #2185831: Split up ParamConverterManager and stop throwing NotFoundHttpException for the edit access checks, no changes.
Comment #30
tim.plunkettGit context conflict with #2175415: Add FieldTypePluginManagerInterface, no changes.
Comment #32
tim.plunkettConflicted with #2189985: Rename UnknownPluginException to PluginNotFoundException
Comment #36
tim.plunkettComment #38
tim.plunkettI don't know how to use returnValueMap with a parameter that might be TRUE or FALSE. $this->isType('bool') doesn't work there. Switching to returnCallback.
Comment #39
tim.plunkettRerolled around #2170415: Plugin definitions are documented as arrays, but they don't have to be
Comment #40
tim.plunkettWow, I didn't know #2095303: Rename 'field_entity' to 'field_config' and 'field_instance' to 'field_instance_config' was happening. Rerolled.
Comment #41
eclipsegc commentedI will call out some things I don't like here, namely the addition of yet more base class things to inherit from. Traits would really clean this up, and while I know we all know that, I'm going to call it out so that we have yet another place where traits could make things less WTF. That being said the basic functionality here is very sensible to me.
A few nitpicks, otherwise I'm generally ++ to this.
Why'd this change?
What about this patch caused new dependencies to be needed for this test?
Why'd this change?
Not going to change the status cause these could be completely justified. Please just gimme a couple explanations here and I'd be happy to rtbc this.
Eclipse
Comment #42
tim.plunkettFor #41.1 and 41.3, see #2143057: DefaultPluginManager::getDefinition() violates interface. They're just wrong, and it silently fails in HEAD. Throwing an exception reveals the bug.
Same thing actually for #41.2, many many many tests that only enable field_test use the test entity types in entity_test, and it just silently returns NULL.
Comment #43
eclipsegc commentedThat is perfectly sensible.
Eclipse
Comment #44
neclimdul+1 to RTBC
Still have the thoughts/concerns from #29 but as Tim said they make things worse right now so this is the correct approach.
Comment #45
alexpottdiscovery-2178795-40.patch no longer applies.
Comment #46
xanoRe-roll, and I made the following minor change while re-rolling this particular line:
From:
to:
Comment #47
neclimdulAgreed, that is appropriate. The docs only document the true case and null is falsy but this is more correct for returning a bool.
Comment #48
alexpottdrupal_2178795_46.patch no longer applies.
Comment #49
berdirRe-roll, conflicted in DateTimeItem.
Comment #50
yesct commentedapplies fine.
defaults to true. Also we dont have to give the defaults anymore (we used to, but dont now) according to 1354. https://drupal.org/node/1354#param
if an exception is thrown, then uh... it wont be able to return, right? so I'm thinking this is NULL if it's invalid and exception_on_invalid is FALSE.
why are these leaving the @return? should just be fine with {@inheritdoc}, right?
Comment #51
yesct commentedhere is a patch that just takes out that (incorrect) defaults to, and fixes the return details.
Comment #53
tim.plunkettOh I forgot about this!
Comment #54
tim.plunkettOkay, let's see how this goes.
Comment #56
eclipsegc commentedProbably need to declare and abstract getDefinitions() method on the DiscoveryTrait.
Eclipse
Comment #57
tim.plunkettGood point!
Fixed the tests as well.
Comment #58
tim.plunkettI was really surprised today when I realized this hadn't gone in yet.
This was RTBC before, and is a big win IMO.
Comment #59
tim.plunkettThe patch is smaller because hunks like these were committed in other issues.
Comment #61
berdirPretty sure that this is dead code now with the standardized plugin cache clearer...
Comment #62
xanoI removed the optional exceptions like we did back in #1846070: Improve exception messages when plugins cannot be found, because if you don't want an exception, you should have used hasDefinition() first. This way we also don't have to change the interface, and we keep our API simple and consistent.
Comment #64
sun+1, most sane and most sensible approach.
Comment #65
tim.plunkettThat was the direction of the OP. See #1 and #2.
Also, your patch makes zero changes to the actual calling code, if you want to hijack an issue at least make the necessary changes correctly.
Comment #66
xanoNot everybody agrees on that approach, so I wanted to propose an alternative.
I didn't want to spend time on something that did not seem important for demonstrating my proposal. If the approach I suggested will be accepted, then I will gladly finish the conversion. Please be careful when you tell people they hijacked issues. It's not motivating.
Comment #67
tim.plunkettI meant, your most recent patch matches the OP. And we have since diverged from that approach...
Comment #68
xanoI'll work on an improved version of #58.
Comment #69
xanoThis patch follows #58.
Comment #70
yesct commentedAh, ok, so #62 was not pursued and back to getting #58 to pass. ok.
why? what is result[2] now?
why is *this* issue revealing that we need to declare that migrate and display tests need to enable field, filter and block?
field kinda makes sense, but filter and block? because they provide fields....? that were expected? but when they were not there, null was returned before and now we are throwing exception? so we had tests that were not really testing what we thought they were?
Comment #71
xanoBecause entity_test.module is enabled now, it adds an additional entity operation between the other ones. I'm not sure the test should test for the order of operations. Should we just assert whether the correct URL exists on the page instead, or is order really important here?
-@tim.plunkett in #9.
This may be related. I found out the test needed Text's field, and as Text depends on Field and Filter, and Simpletest does not enable dependencies automatically, I had to add all of them here.
Comment #72
yesct commentedoops I this should not have been included.
-----
Novice task to make a new patch to take out that file. (the issue is not novice but making a new patch with just the needed files is)
https://drupal.org/contributor-tasks/create-patch
Comment #73
yesct commentedComment #74
yesct commentedComment #75
jlbellidoI'll do #72
Comment #76
jlbellidoComment #77
jlbellidoJust Re-rolled #69 and deleted the .htaccess file from core/modules/simpletest/files/ in #69 as @YesCT said in #72
Thanks!
Comment #78
yesct commentedremoving novice tag since that one novice task was done. thanks @jlbellido
Seems like the remaining task here is a review.
Comment #79
tim.plunkettI would RTBC this myself if it weren't predominately my patch. Thanks @jlbellido!
Comment #80
yesct commentedlooked at the diff of the last couple patches and it seems @jlbellido added a blank line accidentally. removing that.
looked at this whole thing again, rtbc from me.
Comment #81
cordoval commentedjust some comments as i read through, if bad ones please disregard
why the () around $entity_type = .. ? i don't think you need them?
you changed the false to true here, is that fine?
Comment #83
webchickI had a pretty hilarious exchange in IRC with timplunkett while reading this patch where I basically repeated everything I said about not liking the optional parameter in #2168333-54: Ensure custom EntityType controllers can be provided by modules. Oh, well, at least I'm consistent, even if I have the memory of a goldfish. :P~
It doesn't really make sense though to have one type of plugin use this method of error trapping and the rest not, given this has buy-in from all of the plugin subsystem maintainers from what I can see. The DIscoveryTrait is nice. I also like the fact that it defaults to TRUE (meaning, show the exception), which IMO is what you'd expect. I'm still a bit worried about what this will do to existing contrib modules out there though, since that FALSE parameter had to be stuck in some pretty innocuous places in the patch.
Nevertheless, I think this is good to go in, since it makes an existing situation in HEAD a tad bit nicer/more consistent.
Committed and pushed to 8.x. Thanks!
Comment #84
tim.plunkettThis was retested today... But somehow still conflicted with #2039435: Convert EntityManager to extend DefaultPluginManager in a phpunit test.
This doesn't need to wait for a bot run, its a PHPUnit test:
$ vendor/bin/phpunit ./tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.phpI also ran all phpunit tests locally.
Comment #85
webchickThanks!
Committed and pushed hotfix to 8.x.
Comment #87
tim.plunkettThanks for the quick turnaround.
Comment #89
berdirAlready committed.