Problem/Motivation
While working on #2560795: Source plugins have a hidden dependency on migrate_drupal, I discovered (with help from @chx and @tim.plunkett) that it's impossible (at least without doing a bunch of black magic) for an annotation class to extend another annotation class if they reside in different namespaces. This is a major gotcha for anyone who wants to define a new annotation by extending an existing one.
Proposed Resolution
AnnotatedClassDiscovery should accept an array of additional namespaces in which to search for annotation classes.
Remaining Tasks
^^ Write that, in patch form. Commit heartily, then sit back and have a drink.
API Changes
Additional argument to AnnotatedClassDiscovery::__construct() and greater flexibility in defining annotations.
Comment | File | Size | Author |
---|---|---|---|
#48 | interdiff-annotations.txt | 1.13 KB | mikeryan |
#48 | 2600926-48.patch | 10.27 KB | mikeryan |
#44 | 2600926-44.patch | 11.22 KB | hussainweb |
#44 | interdiff-42-44.txt | 2.03 KB | hussainweb |
#42 | 2600926-42.patch | 10.94 KB | mikeryan |
Comments
Comment #2
phenaproximaComment #3
chx CreditAttribution: chx commentedAnd there should be a parameter in services.yml,
timplunkett suggested a service id instead of 'some\annotation\class' but I do not think that's a good idea -- the acting plugin manager knows the annotation class but not its own service id (or it shouldn't ).
Comment #4
tim.plunkettDepends on if the plugin manager looks for this data, or if it's passed to the manager. In the former case, a classname makes more sense. In the latter, a service ID would be better.
Doesn't matter to me!
Comment #5
chx CreditAttribution: chx commentedErm nope, we agreed on 1) adding a method call to the default plugin manager class to gather namespaces b) a
MigrateDrupalServiceProvider implements ServiceModifierInterface
which will do a nice$container->getDefinition('plugin.manager.migrate.source')->addMethodCalls('addAnnotationNamespace', 'Drupal\migrate_drupal\whatever')
.Comment #6
phenaproximaHere's an initial, test-less patch. For dissection and discussion.
Comment #7
chx CreditAttribution: chx commentedYes, that's how I imagined it, exactly!!
Comment #8
dawehnerI'm curious whether it could be enough to explicitly list additional annotation classes, not namespaces ...
Comment #9
chx CreditAttribution: chx commentedThe annotation reader takes namespaces...?
Comment #10
dawehnerAdding a related issue: #2557433: Add internal, event, and property to the list of ignored annotations in the plugin annotation system
Comment #11
alexpottTo have committers consider it for inclusion in RC, we should add a statement to the issue summary of why we need to make this change during RC, including what happens if we do not make the change and what any disruptions from it are. We can add a section
<h3>Why this should be an RC target</h3>
to the summary.Comment #12
phenaproximaRe-upping the patch just so testbot will take a crack at it.
Comment #14
phenaproximaComment #15
phenaproximaThis blocks #2560795: Source plugins have a hidden dependency on migrate_drupal. Therefore, it is a blocker. Ain't logic fun?
Comment #16
alvar0hurtad0I'm working on it
Comment #17
alvar0hurtad0Here's the reroll
Comment #18
XanoThis is useful! Thanks a lot for creating this :)
Use the short array syntax:
[]
.I suggest using a loop and calling
::addNamespace
using executable code. It improves static analysis of the code.Use the short array syntax:
[]
.Use the short array syntax:
[]
.This was accidentally added in the last re-roll and must be removed.
Use the short array syntax:
[]
.Comment #19
benjy CreditAttribution: benjy at PreviousNext commentedCan this still go into 8.0.x or does it need to be 8.1? It currently blocks #2560795: Source plugins have a hidden dependency on migrate_drupal
Comment #20
phenaproximaTechnically it's an API addition, so it'll probably be in 8.1 (depending on the strictness of the committer). Tagging appropriately.
Comment #21
benjy CreditAttribution: benjy at PreviousNext commentedJust a straight re-roll with the feedback from #18.
Comment #22
alexpottIt would be nice to see some test coverage just so I can confirm you are trying to solve what I think you are. If it is this seems a useful API addition.
Comment #23
benjy CreditAttribution: benjy at PreviousNext commentedHere we go. I might rename a couple of things in the test like PluginExampleExtended to PluginExtended and plugin_test_extra to plugin_test_extended but you get the idea.
Comment #24
benjy CreditAttribution: benjy at PreviousNext commentedOK, done the renames, this is ready for a final review. Removing the framework manager tag as I think #22 counts as that.
Comment #25
jibranSeems ready to me. Just need a change notice.
Comment #27
benjy CreditAttribution: benjy at PreviousNext commentedChange record created, just needs publishing. https://www.drupal.org/node/2686097
Comment #28
dawehnerI really like the feature itself. Nice! ON the other hand I wonder whether it really makes sense to add this additional parameter instead of leveraging the existing
$plugin_namespace
and allow to pass in either a string or an array of values. IN the future this could then be even replaced by variable function arguments.Comment #29
catch#28 looks like a CNR.
Comment #30
benjy CreditAttribution: benjy at PreviousNext commented@dawehner, are you referring to the DefaultPluginManager or the AnnotatedClassDiscovery or both? I'm not sure how we'd reuse $plugin_namespace, surely that can be different to the annotation namespaces?
Comment #31
dawehner@benjy
You are absolutely right, I mixed up stuff.
Comment #32
xjmComment #33
alexpottI think we need to document how a module would be expected to provide these additional annotation namespaces. It's not immediately obvious. I think the answer is to use service decoration to replace the existing plugin manager and add the addition annotation namespaces... but how will this work for multiple decorations - ie where two different modules are adding adding annotation namespaces?
Comment #34
mikeryanBlocks major issue #2560795: Source plugins have a hidden dependency on migrate_drupal.
Comment #35
mikeryan@alexpott: Here's how #2560795: Source plugins have a hidden dependency on migrate_drupal is using it:
Then migration plugins doing Drupal-to-Drupal migration simply reference MigrateDrupalSource rather than MigrateSource.
Comment #36
benjy CreditAttribution: benjy at PreviousNext commentedCan't we do this in a follow-up? We already have a test which clearly shows how its used and a change record. The additional docs of how a module hooks into the right place to do such a task would be nice but not a blocker?
Comment #37
benjy CreditAttribution: benjy at PreviousNext commentedcross posted with @mikeryan, what @alexpott is asking for is an example that shows how you'd decorate an existing plugin manager to add your additional annotation class to the discovery.
Comment #38
mikeryanAh yes, realized that context once I looked closely at the patch itself...
Comment #39
jibran+1 for #36.
Comment #40
alexpottI think the parameter should be
$additional_annotation_namespaces
since in the test actually there is no requirement to add'Drupal\plugin_test\Plugin\Annotation'
to the array.Comment #41
alexpottLet's return $this for fluency. And it seems strange that this is not going on an interface anywhere...
Comment #42
mikeryanRenaming and fluencizing...
Doesn't look like there's an appropriate interface out there, what would be a good name for a new one? PluginAnnotationNamespaceInterface?
Comment #43
dawehnerWe should either document that this should be called before using anything like
createInstance()/getDefinitions()
OR we should invalidate the discovery automatically.Comment #44
hussainwebFixing for #43. I did both for a good measure. Just documenting that seemed like not a very great idea, but I am not sure if I caught all the properties that need to be reset.
Speaking of which, I am not sure if the method
addAnnotationNamespace
is even useful to this issue. I don't think this is tested either.Comment #45
dawehnerThis does a
$this->cacheSet()
call, so do we really want to do that?Comment #46
hussainweb@dawehner: I think we have to. If we don't and instead just set
$this->definitions
toNULL
, a call togetDefinitions()
will callgetCachedDefinitions()
which will load the definitions from cache (using$this->cacheGet()
).Comment #47
alexpottImo as this is not used in this issue it should be removed. If this is what we plan to use in the migrate issue then it should be tested here.
Comment #48
mikeryanHere it is without the unused method - I've verified this works with the latest (about-to-be-uploaded) patch on #2560795: Source plugins have a hidden dependency on migrate_drupal, and with the migrate_plus/migrate_tools modules.
Comment #49
willwh CreditAttribution: willwh at Drupalize.Me commentedI've tested this patch, thanks mike! This applies against current 8.1.x. I've tested this with the patch from#2560795.
Comment #50
mikeryan@alexpott: Anything further we can do to get this (and its companion #2560795: Source plugins have a hidden dependency on migrate_drupal) in for 8.1?
Thanks.
Comment #51
alexpottSorry @mikeryan this had fallen off my radar - it looks great!
Committed ff85e2e and pushed to 8.1.x and 8.2.x. Thanks!
Comment #53
mikeryanThanks @alexpott!
Comment #54
lhridley CreditAttribution: lhridley commentedpatch 2600926-48.patch no longer applies against 8.1-RC1. Is it no longer needed, or does it need to be re-rolled?
Nevermind, I see that it's in there (my bad).
Comment #56
quietone CreditAttribution: quietone as a volunteer commentedPublished change recor.d