Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
We moved all the source plugins into their relevant modules within core but now they all have a hidden dependency on migrate_drupal because the source classes extend DrupalSqlBase. This is exposed when you use the migrate source plugin manager to discover the plugins but then get a fatal error when instantiating a plugin because of the missing DrupalSqlBase class.
Proposed resolution
- Add an annotated class discovery variant which automatically discovers provider dependencies based on namespace (of its class and every class it extends). Which is different from core that just looks at the namespace of the class and not its parents.
- Use this in the new MigrationSourcePluginManager.
- Move the provider filter logic from findDefinitions into a decorator and while at it, expand it into multiple provider support.
- Add a migrate specific decorator which removes plugins which try to use non-existing source plugins. Since we automatically discover the migrate_drupal provider dependency of the source plugins as they extend the DrupalSqlBase class this fixes the original issue.. almost.
- Add the provider list to the few migrations which are not automatically covered because they use a source from migrate: empty and embedded_data. Currently, there are only three, all three using embedded_data. Now we are really done with the original issue.
- While it could be called a different issue, we are also fixing when a non-migrate_drupal source uses a migrate_drupal deriver by using the new ProviderFilterDecorator -- in fact, this is the reason it exists: DerivativeDiscoveryDecorator::getDeriverClass() will get cranky and throw an exception if you try to call a nonexisting deriver. Could be a follow up but since it's already done, why not. Process plugins are definitely a followup because they need the definition normalizer to happen on discovery instead of runtime. Destination plugins could be here but they are an easy followup as they are rarely a problem.
Remaining tasks
Add tests, doxygen.
Followup: #2786355: Move multiple provider plugin work from migrate into core's plugin system
User interface changes
n/a
API changes
n/a
Data model changes
n/a
Comment | File | Size | Author |
---|---|---|---|
#224 | 2560795-3-224.patch | 30.78 KB | alexpott |
#224 | 220-224-interdiff.txt | 1.22 KB | alexpott |
#220 | 2560795-3-220.patch | 29.56 KB | alexpott |
#220 | 219-220-interdiff.txt | 1.3 KB | alexpott |
#219 | 2560795-3-219.patch | 29.56 KB | alexpott |
Comments
Comment #2
benjy CreditAttribution: benjy at PreviousNext commentedFor purist sakes, we could argue to keep it in migrate_drupal but it’s not a very big class and it’s much simpler to move the class to migrate, I'm +1 for option 1 at this stage.
Comment #3
phenaproximaI'm preferential, overall, to option #3, which is to introduce a new annotation type, provided by Migrate Drupal, used specifically for Drupal sources. It could be called MigrateDrupalSource, and it would provide the added benefit of giving us an official place to document hidden-but-crucial annotation properties like source_provider and minimum_schema_version, which is already its own issue: #2559345: Document source_provider and minimum_schema_version annotation properties
But if that doesn't pan out, I'm also OK with option #1.
Comment #4
webchickThis sounds like something we need to figure out in order to declare the API complete. Marking as Migrate critical.
Comment #5
mikeryanI prefer option #3. Moving DrupalSqlBase to migrate means that you won't get actual errors in discovery of source plugins, but you will be discovering source plugins that don't actually make sense without migrate_drupal enabled.
Comment #6
phenaproximaDiscussed on IRC with @benjy, and we devised what seems to both of us like a reasonable solution: standardize the source_provider annotation property and use it to filter out plugins which cannot be instantiated for dependency reasons.
Example: consider the d6_user source plugin. With this proposed solution, its annotation would look like this:
With this kind of tagging, the plugin manager can know ahead of time that the plugin is built on top of Migrate Drupal (the
drupal
part of the source_provider value), that it's relevant to Drupal 6, and that it's part of the User module's migration path. The hierarchy helps with grouping plugins (i.e., in the Views-like UI that @benjy's working on), to any level of specificity.We could apply this same logic to non-Drupal sources:
There are a lot more details to be fleshed out here, but so far this strikes me as workable. Thoughts?
Comment #7
benjy CreditAttribution: benjy at PreviousNext commentedI think we should roll a path with something like #6.
Comment #8
mikeryanIf we move forward with #6, does that subsume #2559345: Document source_provider and minimum_schema_version annotation properties?
Also note #2569805: For Drupal migration, identify the source module - for the UI we want to be able to identify the source module for all Drupal migrations, including variables, and the source_provider annotation by itself doesn't get us there, can we work a solution for that in here? E.g., allow the source provider to be overridden in the configuration:
and have a getProvider() API?
Comment #9
phenaproxima@benjy and I talked more about this on IRC. We still think this is workable, but the main issue is how to make the system aware that a source_provider value like
drupal.6.node
ordrupal.7.aggregator
is a dependency on the Migrate Drupal module.My thought is we could add something like this to Migrate Drupal:
This would explicitly mark the plugin.manager.migrate.source service as being responsible for plugins whose source_provider annotation matches the drupal.* pattern. By comparing source_provider annotations to service tags, @benjy's UI would easily be able to tell which plugins can be instantiated.
Comment #10
phenaproximaTook a first pass at this:
drupal.MODULE.SCHEMA_EXPRESSION
. MODULE is obviously the name of the module, and SCHEMA_EXPRESSION is an optional regular expression which the installed schema version must match.Comment #13
phenaproximaI done screwed up. Maybe this will be better...
Comment #17
phenaproximaWanna play again?
Comment #24
quietone CreditAttribution: quietone commentedHow will the user know which module has an incompatible schema version?
Comment #26
phenaproximaOK, screw it. PIFR is randomly failing the patch, repeatedly, for no very good or obvious reason. DrupalCI, thy results are canonical.
Comment #29
phenaproximaEurgh!!! I give up.
Comment #30
benjy CreditAttribution: benjy at PreviousNext commentedOnly did a super quick review, couple of notes below. I'm still in favour of the major.minor.patch format for the source provider but i'm unsure about altering the service tags for source modules that want to specific a new pattern. Let me think on it some more.
I'm not sure about the regex, do we really need that? Maybe we could just specify a minimum?
I think the thing is, the plugin manager is already responsible for those plugins, that's exactly the problem we have now. Is there a part to this patch missing that would have filtered out plugins that didn't match a registered pattern in the plugin manager?
Comment #31
chx CreditAttribution: chx commentedLast I heard, annotation properties were not in short supply. You do not even need to define them on the annotation class if you do not want. So: if you want to depend on a module, say so! If you want a version regex, say so! Magic strings mixing these into one mess of a property: nope.
Comment #32
chx CreditAttribution: chx commentedOf course the best would be to roll the migration templates back into migrate_drupal and also to only use templates when necessary and stick with config entities when not but I guess those ships have sailed. (These are the two why I try not to participate much.)
Comment #33
chx CreditAttribution: chx commentedI filed an issue for putting them where they belong because it is impossible to find migrations these days. #2589805: Add documentation on how to find the menu migrations
Comment #34
phenaproximaI spoke with @EclipseGc and @jhodgdon about this at BADCamp and I believe I've found a much more elegant solution.
We can define an entirely new annotation type -- MigrateDrupalSource -- which extends MigrateSource and lives in Migrate Drupal. We can then apply that annotation to all plugins which depend on DrupalSqlBase. This will have the effect that, if Migrate Drupal is disabled, any MigrateDrupalSource-annotated plugins will be completely invisible to the plugin system. Boo-yah!
Not only does this solve our dependency issue, it's also easy to implement and it gives us the flexibility to add Migrate Drupal-specific annotation properties that are documented in a single, sensible place.
I will try to create the patch for this ASAP. It's such a beautiful solution that I could almost weep.
Comment #35
phenaproximaRejoice!
Comment #36
chx CreditAttribution: chx commentedGreat solution! More comments on the new annotation to explain why it's necessary would be welcome though.
Comment #38
phenaproximaThis will not work until #2600926: Allow annotations to inherit across namespaces is in core. Postponing.
Also removing the Migrate Critical tag since this is only revealed by @benjy's migration UI, which is not open to the public yet :) Under 98% of circumstances, users will not run into this problem.
Comment #39
benjy CreditAttribution: benjy at PreviousNext commentedComment #40
mikeryanAre we still using the "Migrate critical" tag? At any rate, with the plugin patch in, it is also revealed by migrate_tools, and will affect anything trying to do straight-forward discovery on migration plugins. Under 98% of non-Drupal migration circumstances, users *will* run into this problem.
Without migrate_drupal enabled:
With migrate_drupal enabled, but no "migrate" connection to a Drupal database configured:
Comment #41
mikeryanApplied both patches (with a trivial reroll of this one, not finding the d7_field_instance place to patch). I still get the attempt at the missing cckfield service. I believe the node deriver is triggering that, continuing to dig...
Comment #42
mikeryanCapturing where I am with this, quitting for the night:
Comment #43
mikeryanOK, here's a version of the patch that I've got working with migrate_tools (don't exactly know what's up with actions in the interdiff...). Basically, just having the node derivers sanity check the cckfield service let's me get to the point where the tools can handle the rest.
Comment #44
willwh CreditAttribution: willwh at Drupalize.Me commentedI've rerolled this patch, because it's no longer applying against the current 8.1.x-dev branch. I've never made an interdiff before, so this was fun :)
Comment #45
mikeryanThe last patch dropped the MigrateDrupalSource annotation, which is kinda important. Restoring here - this (along with the annotations patch) works with migrate_plus/migrate_tools in contrib.
Comment #46
agoradesign CreditAttribution: agoradesign commentedHi Mike,
it seems that your patch is not complete (anymore?). I've setup a site with the current dev of core 8.1.x, migrate_tools 8.2.x and migrate_plus 8.2.x, and applied this and other patch, that is also needed for migrate_tools to work. But when I run
drush migrate-status
, I get this error:-> this class still has the "MigrateSource" annotation, changing it to "MigrateDrupalSource" helps.
Comment #47
mikeryan@agoradesign: Thanks for picking that up, I've added it in.
Comment #48
mikeryanComment #49
mikeryan#2600926: Allow annotations to inherit across namespaces has been committed, this is now unblocked - let's give the bots a shot at it...
Comment #54
heddnLet's see what happens when we use 8.2.x? I'm not expecting much better luck.
Comment #56
mikeryanThe testbot is not reporting anything useful, but locally running the action tests:
Note that it's the D7 MigrateActionsTest causing D6NodeDeriver to be invoked (and ultimately try to use d6_field_instance). I have no idea what's changed in the current patch that would cause this.
Once upon a time, on a former MacBook, I had figured out how to get PhpUnit tests to stop at breakpoints in PhpStorm, having trouble now (I've got a debug configuration that will run the tests within PhpStorm, but my breakpoints are ignored)...
Comment #57
mikeryanWait, WTF, the action tests actually pass in PhpStorm but not at the command line...
Comment #58
mikeryanOK, debugging in migrate_tools:
There's not much we can do about it from migrate_tools - the exception entirely aborts getDefinitions() so we get no migration plugins to work with, not even the ones that would work if we could only discover them...
Perhaps the derivers can catch PluginNotFoundException on the getSourcePlugin() calls, but it feels like the problem is deeper than that. I may throw that into the patch though just to see if it makes the testbot any happier.
Comment #59
agoradesign CreditAttribution: agoradesign commentedThe same error happened to me on my 8.1.x test install last weekend, as soon as I enabled migrate_drupal. Without migrate_drupal, I had no problems
Comment #60
mikeryanIn IRC, @dawehner was asking why we didn't take the approach of adding migrate_drupal as a module dependency to the migration .yml files - didn't have an answer off the top of my head.
As for the failure of this annotation-based patch to work, looking at the tests for #2600926: Allow annotations to inherit across namespaces I realize that somewhere we need to inject that additional namespace for MigrateDrupalSource to be picked up. Looking at that now...
Comment #61
mikeryanOK, got the additional annotation namespace in (also fixed up one more source plugin which wasn't using MigrateDrupalSource). In the migrate_tools context we're now getting ConnectionNotDefinedException, but let's see how the testbot does with this.
Comment #63
mikeryanThat's better - now just MigrationTest is failing, with "The "d6_field" plugin does not exist.". It's actually bogosity in the test, which is using a Drupal source plugin without enabling migrate_drupal. It got away with this before - all it's doing is getting the source plugin and fetching its ID, so the lack of migrate_drupal or any source connection didn't bit it - but now that the source plugin uses the MigrateDrupalSource annotation, the hidden dependency of the d6_field plugin on migrate_drupal is revealed. Let's see if we can find a source plugin not dependent on migrate_drupal...
Comment #64
mikeryanOK, I expect this one to pass.
Comment #66
mikeryanIn the meantime - this patch is necessary but not sufficient for the tool use case (in general, being able to do getDefinitions() on the migration plugin manager without crashing and burning). It addresses the case where migrate_drupal is not enabled yet source plugins implicitly dependent on it exist in enabled modules. We've still got the problem of having migrate_drupal enabled and trying to get all plugins, where exceptions will go flying - either because there's no Drupal source database connection configured, or there is one configured, but plugins targeting a Drupal version other than the one that database contains will be... confused. I'll open a separate issue for that.
Comment #67
mikeryanFollowing up in #2700693: [meta] Make MigratePluginManager::getDefinitions() work cleanly with migrate_drupal enabled
Comment #68
mikeryanOK, both branches have passed - ready for manual review.
Comment #69
willwh CreditAttribution: willwh at Drupalize.Me commentedSo the secret sauce here was Annotations on the Source Plugin Manager. This is working for me :)
Comment #70
agoradesign CreditAttribution: agoradesign commentedIs there a chance to get this in for today's 8.1-rc1???
Comment #71
agoradesign CreditAttribution: agoradesign commentedChanging this back to version 8.1.x, as it was changed to 8.2.x in comment #54 only for the test bot
Comment #72
benjy CreditAttribution: benjy at PreviousNext commentedFunny, we'd have gotten this for free with config entities, however its actually a pretty good idea and solves the try/catch in the static constructors mentioned below.
I don't think we want to replace the existing service manager, we should just decorate it. See https://www.previousnext.com.au/blog/decorated-services-drupal-8
A try/catch in the static constructor doesn't feel right, i've said before a temporary fix would be to move this to migrate_drupal. But as dawehner mentioned above, adding a module dependency to the plugin definition and filtering these out in the plugin manager would solve this.
Comment #73
J.R. CreditAttribution: J.R. as a volunteer commented(Edit):
PS: Info for changes for 8.1.0
http://mikeryan.name/blog/mikeryan/migration-update-for-drupal-8-1
Comment #74
mikeryanComment #75
mikeryanComment #76
ayalon CreditAttribution: ayalon at Liip commentedI'm using this patch for a while now with the version 2.x-dev source plugins and migrate tools. Should be part of the next Drupal minor.
Comment #77
catch#72 still needs addressing.
Comment #78
mikeryan@ayalon: The tools no longer require this fix (nevertheless, it still should be fixed).
Comment #79
dsnopekI've been trying to use 'migrate' to import the demo data in Panopoly (we did this in D7 too) per #2732417: Port Panopoly Demo to Drupal 8!, and without this patch, I need to enable 'drupal_migrate' even though we're importing data using the 'embedded_data' source plugin and not importing anything from an older Drupal version. The error I get without the patch is:
Comment #80
mikeryanRestoring the "Migrate critical" tag, it's really a big problem for any migration scenario outside of the core upgrade (e.g., working on the D8 version of wordpress_migrate, it has to include a logically-unnecessary dependency on migrate_drupal for plugin discovery to work).
Comment #81
ckaotikI'm using the patch from #64, but still cannot get migrate_tools'
drush ms
working without enabling migrate_drupal.They use the
\Drupal::service('plugin.manager.config_entity_migration')->createInstances([])
to fetch a list of migrations and die ond6_field_formatter_settings
(core/modules/field/migration_templates/d6_field_formatter_settings.yml), because it explicitly declares the use ofclass: Drupal\migrate_drupal\Plugin\migrate\CckMigration
. Seems we missed this one.I just wish we had a way to overwrite/decide ourselves which migrations we want to use, instead of just always loading anything we can find... But that's another issue for another day ;)
Comment #82
mikeryanPlugins do have a means of filtering on a module dependency - the provider key. So, I added "provider: migrate_drupal" to all the Drupal migrations. That's not quite enough, though, because derivers are invoked before the provider is checked. So, I extended ContainerDerivativeDiscoveryDecorator to pre-check the provider.
I borrowed the base (migrate_drupal not installed) test from #2700693: [meta] Make MigratePluginManager::getDefinitions() work cleanly with migrate_drupal enabled - this still leaves the other angle (migrate_drupal is installed but no database is configured) broken, but we can pick up on that one in the other issue.
Comment #83
benjy CreditAttribution: benjy at PreviousNext commentedThis seems like a pretty good solution to me. +1
Comment #84
benjy CreditAttribution: benjy at PreviousNext commentedchx suggested that we could also fix this in core? We could test this patch against the test in #82.
Comment #85
mikeryan@benjy: It's not clear to me what that patch changes in behavior? The provider check is still too late to prevent us from invoking an invalid deriver.
If we do want to make this a broader fix, we could simply put the provider check in ContainerDerivativeDiscoveryDecorator... like so.
Comment #86
mikeryanOh, duh, that's going to break, because anything else using ContainerDerivativeDiscoveryDecorator would need to pass in a module handler...
Comment #88
benjy CreditAttribution: benjy at PreviousNext commentedLooking at the code now, you're right. I'm happy with the solution in #82 but would be good to get a review from alexpott.
Comment #89
mikeryanOK - patch in #82 needs review, we'll pretend #85 didn't happen...
Comment #90
mikeryanDraft change record added.
Comment #91
penyaskitoIsn't there any way of getting this list from Drupal core? I'm guessing we will forget to edit this test if new migrations are added to modules that don't have any already.
Comment #92
vasi CreditAttribution: vasi at Evolving Web commentedI'm not sure if I like overriding 'provider' this way. By default the 'provider' of each plugin is the module that defines it. Presumably Drupal uses this information in some way? Are there any other situations where provider is overridden? Any documentation of what this means, semantically?
Also, we already have a 'Drupal 6' or 'Drupal 7' tag that indicates that migrations are for migrate_drupal. I don't like having to say this same thing in two places, it provides one more way for people to mess up.
Comment #93
mikeryanWe could use the MigrationPluginManager... Oops;)! Kind of a chicken-and-egg problem there... I suppose we *could* use YamlDiscovery to dynamically set $modules, but I'm not sure that's worth it - we would have to do that in the constructor, wouldn't we? Or could it be done in setUp()?
Core does explicitly support providing a provider in configuration (it checks for a configured provider before setting the provider to the current module), although I can't find any example of it being used in core outside of tests. I think it does make sense, in that our precise problem here is that migrate_drupal is logically a provider of these migrations, but we've chosen to have them live in their relevant modules (for reasons detailed in #2533886: [meta] Move module-specific migration support into the particular modules supported).
As near as I can tell, the meaning of "provider" is not documented, but the one thing it is used for is to exclude plugins whose provider is not enabled (exactly what we need).
The behavior we're looking for is that no Drupal migration plugin should be instantiated by the plugin manager unless both the module it contains and migrate_drupal are enabled. The Yaml discovery ensures the former, and making migrate_drupal a provider ensures the latter. I don't see a cleaner way to handle this.
Comment #94
penyaskitoRerolled #82 after #2691659: d7 filter weights not migrating to d8 landed. Two phpcs raised issues fixed, see interdiff.
Comment #95
penyaskitoComment #96
animaci CreditAttribution: animaci commentedWhen I use this patch I get error message: Migration migration_name does not exist.
Do you have maybe any idea? Thanks!
Comment #97
mikeryan@animaci: That's not much to go on. Exactly what context do you see that message? What operation are you performing?
Comment #98
mikeryanThis situation continues to be a major PITA for non-upgrade migration scenarios, and blocks cleaner contrib integration: #2752335: Properly integrate configuration-entity-based migrations with the core plugin manager.
Comment #99
animaci CreditAttribution: animaci commented@mikeryan: Thanks, I think it was my fault, it was not caused by the patch. Sorry for confusion. Just forget my comment :) Thanks!
Comment #100
phenaproximaLooks pretty decent to me. I have a few minor issues, but overall this seems like a good, clean solution.
Now THAT is a class name :) It's a mouthful but it doesn't really explain what this class does. Can a doc comment be added for that?
Should be "Constructs a new MigrateContainerDerivativeDiscoveryDecator."
It's pretty obvious from the parameter type that it's implementing DiscoveryInterface ;-)
$base_definition should be type hinted if possible.
providerExists() is just a call to the module handler, so do we really need it in its own method?
We need a comment here explaining the nature of this test. What would happen if the test broke? Also...for correctness' sake, kernel tests should use $this->container->get(), not \Drupal::service().
Comment #101
mikeryanAddressed all the comments above, except
This function signature matches the parent.
Comment #102
mikeryanAnyone out there willing to review the latest patch and either give it an RTBC or identify any other changes needed?
Comment #103
benjy CreditAttribution: benjy at PreviousNext commentedI think the patch is good, I did mention in #88 that a review from alexpott would be good. Maybe a RTBC is the best way to get that :)
Comment #104
mikeryanThe current approach is not a BC breaker.
Comment #105
alexpottI think the approach is valid but I do share some of the concerns of @vasi in #92. However if migrate_drupal is installed then existing contrib and custom plugins that depend on it will continue to work - so this is not a migrate BC break per se. And therefore I agreed with @mikeryan that we should commit this to 8.1.x as well.
I discussed how to inform developers that they need to add the provider key for migrate plugins that depend on migrate_drupal - we considered triggering a user recoverable error but that doesn't really buy us anything because it valid for a migration plugin to not have a provider.
Given that this patch achieves what we want it to and we can continue to evaluate it as solution once committed I'm happy to see this go in.
Committed and pushed 89815ba33923ecd0018b62afb393d05d987a40fa to 8.2.x and e98b14a to 8.1.x. Thanks!
Comment #107
chx CreditAttribution: chx commentedWhat on earth have happened. This needs to be rolled back and properly fixed! Any solution that involves editing every migration is a hack. Not for the first time we are hacking migrate to fix a core bug. :(
A) roll back, that's why I set it to RTBC
B) I will post a patch that fixes this in the plugin subsystem and then the source plugins. The real problem is that the source plugins have a dependency on more than one provider. Currently the plugin system uses one provider which is the module its namespace is in but it's entirely possible as the issue shows that a plugin depends on more than one provider and so the plugin needs to be able to have a list of providers it depends on. That's a plugin system limitation I thought I have made this clear but since I really badly don't want to post any non migrate patches I didn't but apparently I need to. Also, all the decorator needs to do is inherit the provider part of the definition and then DefaultPluginManager::findDefinitions() will throw the definition out if the providers are not there. Already explicit provider definitions are honored (see AnnotatedClassDiscovery::prepareAnnotationDefinition) so the plugin system just needs to allow for an array as I mentioned previously and that's all.
Comment #108
chx CreditAttribution: chx at Migrate Rocks commentedActually, AFAIK DerivativeDiscoveryDecorator::mergeDerivativeDefinition already inherits everything including providers. Here's a tentative patch with one plugin edited for demo, non-testing because it first needs a rollback. I need to rename ProviderDiscovery to ProviderDecorate and perhaps add a wrapper method for the service call but it shows the way.
Comment #109
mikeryanA couple of points:
Comment #110
chx CreditAttribution: chx at Migrate Rocks commentedEdit: deleted.
Comment #111
chx CreditAttribution: chx at Migrate Rocks commentedI can't let this go and just edit a comment in a fixed issue. Let me reiterate:
The fundamental flaw of this issue is people hacking migrate when the shortcoming is in core. This is not the first time this happens. Can we stop doing this?
It is entirely possible to come up with a plan that covers almost all of the migration to find their dependencies automatically and only require the source or migration plugins to use an explicit provider when the automated process is inadequate. Mike points out the three migrations using the embedded_data source need to do this. That's fine. That's three.
What core misses here
End. Note that most of this is already coded either above or in https://www.drupal.org/node/2488258#comment-11402375 -- that patch persists use statements but processing them instead is better.
Once this is done, we will need to use the code above to copy source plugin providers into the Migration plugin providers. And then just opt in MigrateSource into this new mechanism and mostly be done:
so this plugin depends on node, migrate and migrate_drupal. Yes, a few plugins will need explicit provider lists (VocabularyPerType , NodeRevision twice, CommentVariablePerCommentType, TermNodeRevision, ViewMode , FieldInstancePerViewMode, UrlAlias twice) but most of them won't. And most definitely you won't need to edit every migration.
Comment #113
alexpottOkay discussed with @mikeryan in IRC - we agreed to revert and go for a fix that does not require updates to migrations whilst also being simple.
Comment #114
alexpottSo here's an approach built on @vasi's suggestion of re-using tags. It decorates discovery to remove any definitions with missing definitions. I think this is better than the previous approach because no migrations have to change and it affects all definitions not just derivatives. Improved the test as well. I think it would be great to a test module with a migration that does not depend on Drupal.
No interdiff because new approach.
Comment #115
alexpottWe have such migrations already in a test module...
Comment #116
benjy CreditAttribution: benjy at PreviousNext commentedTags for me have always been optional, basically just a feature for the UI and if you don't provide them then no problem, your migrations still work. Now they have functional meaning which can lead to fatal errors. I think using the provider key still makes more sense as that is a defined value, not just free text like tags.
Just because core doesn't have to update its migrations here, everyone else is still going to have to update their custom migrations unless of course they copied from core and have the tags already, which could be the case.
Comment #117
chx CreditAttribution: chx at Migrate Rocks commentedI am coding as fast as I can. Wait an hour or two, I am almost done. Teaser trailer:
Comment #118
chx CreditAttribution: chx at Migrate Rocks commentedProgress report.
Comment #120
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedTry #2. So this patch
Comment #122
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedEh.
Comment #123
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedIt's a bit annoying I can't delete comments and at the same time I'd like to show where I am. It's minimal fixes :/
Comment #126
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedInterdiff is against #120 just to show how inconsequential the change is: the problem was passing in the module list instead of the module handler. This is what I get for trying to simplify the code from findDefinitions.
Comment #128
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedWIN! MigrationTest tries to use d6_field source plugin but the patch removes that because migrate_drupal is not enabled. That's fun.
The rest seems to be fixed by not even passing in the module handler but the providerExists method itself.
Comment #129
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedComment #130
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedAfter talking to alexpott the inherit decorator is not needed because the source plugin will be gone already so what's needed instead is a plugin which filters out migrations if their source plugin is missing.
AnnotatedClassDiscoveryAutomatedProviders now always merges.
Also, the ProviderFilterDecorator is only for a very rare case: where the migration explicitly specifies providers and uses a deriver. No such thing currently.
Added all the necessary provider notations to sources (9) and migrations (3) which makes the test written by alexpott pass. Still much, much better than changing 147 migration YAMLs (plus all the custom ones using core sources).
Comment #131
alexpottSo the problem we have is
class UrlAlias extends UrlAliasBase {
- where the use on migrate_drupal is inUrlAliasBase
and not UrlAlias. I think this is unexpected. I guess the question is how tricky / expensive is it to determine the full class chain and it's use statements.Comment #132
alexpottAnd this is where doctrine's limited static reflection is not going to help :(
Comment #133
alexpottI don't think this code is necessary.
Comment #134
alexpottThe patch in #130 is changing this... (core/lib/Drupal/Component/Annotation/AnnotationInterface.php)
Comment #136
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commented> So the problem we have is class UrlAlias extends UrlAliasBase { - where the use on migrate_drupal is in UrlAliasBase and not UrlAlias. I think this is unexpected. I guess the question is how tricky / expensive is it to determine the full class chain and it's use statements.
I would love to leave that to a followup. It's not exactly tricky, the scaffolding is in place: currently we use the MockFileFinder but Psr0FindFile exists and StaticReflectionParser::parse has code for finding the parent already, the optimization would need to be changed to include any extends or simply we would need to switch off the optimization. But I can do it in this issue if necessary.
> I don't think this code is necessary.
Please open an issue to remove it from InfoHookDecorator and from here. I copy-pasted. This I do not know. Edit: based on our discussion, the decorated object might implement additional interfaces and then the decorator shouldn't remove that functionality. Nevermind the decorated object will fail any type hints at least the method calls work...
I will amend the doxygen tomorrow to reflect it can be a string or an array.
Comment #137
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedHere we go. interdiff is only the relevant parts, I didn't interdiff reverting every source plugin. Doxygen later.
Edit: base on discussions with alexpott the next version will do away with reflection and use a class rather. I will post when I have written doxygen.
Comment #139
jibranI think title and the component of this issue should be changed now after the new direction.
Comment #140
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commented@jibran, how's the new title?
Patch removes some cruft from #137 and tightens AnnotatedClassDiscoveryAutomatedProviders , adds doxygen where it was missing.
Comment #141
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedComment #142
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedReverted providerExists for even better BC. Interdiff against #137. This is beginning to look like done, there's very little change in existing classes outside of migrate and a few new classes. BC is now complete. The next step will be #2767483: Refactor the process definition normalizer into a decorator so process plugins are in a uniform format while discovering and then another followup which uses this fact to change NoSourcePluginDecorator into NoPluginDecorator .
Comment #143
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedWhile #142 is ready, this version reads slightly better in my opinion. And it's a bit shorter, too.
Comment #145
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedOne semicolon. No change.
Comment #146
jibranSome minor review points. Totally loving the new title.
Can we add a desc why it can be string and array as well?
Can we make it SCREAMING_SNAKE_CASE?
Is there a reason for using array_flip first then array_keys?
Now I know who has been adding do while to the core :P. I personally don't like it as coder but meh!
Desc missing.
Removes.
A lot of magic and I love it.
Desc block missing.
Comment #147
benjy CreditAttribution: benjy at PreviousNext commentedIs this still needed?
Comment #148
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commented> A lot of magic and I love it.
Where?? I have contemplated quite a few versions and this seemed like the most readable.
I removed the array_keys / array_flip trickery. Let's not get tricky.
Edit: crossposted with benjy's review but yes the MigrateSourcePluginManager uses the new discovery so it's totally necessary, yes.
Edit2: jibran and benjy both confirmed the closures seemed like a bit magic but they are OK just need to get used to it. Good I haven't used the double array_filter I was planning...
Comment #150
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedRandom bot failure.
Comment #152
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedgit.drupal.org failed while the bot was checking out...
Comment #154
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commented#2767723: Git server outage and reduced availability
Comment #157
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedFinally!
Comment #158
neclimdulWith my submission for the most superficial review of 2016:
s/str4ing/string/
Comment #159
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedComment #162
mikeryanI see that this is committed to 8.3.x - what about 8.2.x (at least)?
Comment #163
alexpott@mikeryan those status messages are an unfortunate consequence of creating the new 8.3.x branch - nothing (other than that has occurred) it has both the original commit and then revert. So it's still not committed anywhere.
Comment #164
dawehnerThis sounds like a BC break for me. As a caller you can no longer be sure what you can, and there could be code breaking it. Can we do something about it?
Is this actual english?
Nitpick: Afaik we don't do this inline
Why can't we inject the class loader here?
Can we document why we need this casting to array here? This is probably because plugin definitions can be arrays as well
IMHO using
array_diff
would be more semantic here. An alternative could be to provide a $provider_not_exists and check whether the result is not empty.This could be moved to the plugin component, couldn't it?
Comment #165
mikeryans/disocovery/discovery/
Let's also test with migrate_drupal enabled and no database connection (yet) configured.
Comment #166
alexpottI agree with @dawehner wrt to #164.1. Imo we should add new methods on a new interface something like getProviders() and setProviders(). It should be documented that getProvider() returns the "main" provider. Main is something that a plugin manager with allows plugins to have multiple providers can decide.
Comment #167
generalredneckThis is a reroll against 8.1.x-dev as some updates made the patch quit applying over there as of 8.1.8.
Oh and corrected that fat fingered 4.
Please continue about your business in getting this in for 8.2... just need it for 8.1 at the moment. :)
Comment #168
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedI am not a good judge of what needs to be done and what not. I have been long wary of handling this issue because the penultimate destination is adding a provider and a providers key to the definition and I so badly don't want that. So I would rather do nothing. I changed getProvider to forcibly return a single provider always and marked setProvider it accepts array or string. It doesn't matter much anyways because the plugin subsystem classes work on the definition directly anyways which nothing else should do anyways so while there is a minimal amount of BC break here it's in an internal array structure for which an API getter exists and that doesn't change. Let it just be.
> Let's also test with migrate_drupal enabled and no database connection (yet) configured.
That's a different issue.
> An alternative could be to provide a $provider_not_exists and check whether the result is not empty.
I had that in previous patches. It's unreadable. This is the most readable.
Comment #170
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedDisregard. I tried to typehint the classloader. LOL.
Comment #171
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedWith less typos causing fatals.
Comment #174
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedOne more type hint. I only removed it from the class doxygen and forgot the code itself. Another good reason why I hate, hate, hate to write doxygen like this
That's just a burden.
Hope it's now all done. And now the issue is cluttered even more and noone will find my writeup above. Excellent. Love pointless doxygen.
Comment #176
phenaproximais_array(isset())?! isset() returns boolean, so this will always evaluate to FALSE. Unless I'm missing something?
Also, this should return FALSE if $this->definition['provider'] is not set, to maintain BC.
Missing @param documentation for $finder.
Nitpick, but if this is a class loader, can it be called $classLoader instead of the more ambiguous $finder?
$annotation_namespaces and $class_loader should be type hinted.
If this is required to have a findFile() method, can we add a method_exists() sanity check here (and throw LogicException if the class loader doesn't implement findFile()) to prevent bugs from originating further up the call chain?
This strikes me as a bit magical, can there be a comment explaining the while() condition at least?
Missing description.
Nitpick, but I think $args should be type hinted for clarity's sake.
Please change array() syntax to [] for consistency in the same file.
This should have a type hint, and so should the parameter.
Should be migrations, plural.
migrate_drupal *does* exist in core, so let's change the wording here; maybe something like "in case a plugin specifies a non-existent provider."
Wrong class name.
Why can't this be injected?
$args should be type hinted.
Er...how about "Tests the default Migrate plugin manager"?
Effectively repeats the @covers annotation, so might as well remove this line.
Should say "do not depend". Also, how about adding an assertCount()?
Discocovery? :)
Comment #177
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedUnfollowed.
Comment #178
phenaproximaFixed most of my nitpicks.
Comment #180
phenaproximaHopefully this will fix the failures. It turns out you shouldn't type hint a class loader, because there are many different class loaders that could be used (and none of them implement a single interface). For the record, my foot tastes great.
Comment #182
phenaproximaNo it didn't. We just got whacked by inexplicable CI errors.
Comment #183
dpalmer CreditAttribution: dpalmer commentedSubscribed
Comment #184
alexpottHere are we creating a doctrine class or a core class... because now there's a class with this name in this namespace. This has cause us issues in the plugin system in the past.
This is an API change. Component classes exist to be extended. Whilst it is neat to re-use all this code perhaps we should not. Of course not re-using the code introduces risks too.
Weird indentation.
It's weird we have access to classAnnotationOptimize here - i guess that is because we're in a sub class... still odd.
Comment #185
phenaproximaComment #186
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedHey, look a ClassFinderInterface! I didn't know that existed... oh.
> Would it be preferable to make $parser optional, then create it in the method if it's not passed?
You can make it optional but you can't recreate it in the method as you do not have the data necessary as far as I am aware. So if you make it optional, you need to throw http://php.net/manual/en/class.invalidargumentexception.php
> so the code is taking advantage of a PHP quirk.
http://www.phpwtf.org/php-protected-and-assault I am not even sure this is PHP specific.
> Personally I'm OK with that, but I suppose it could be potentially dangerous in weird edge cases. Is it worth addressing now?
Nope. This whole shebang should be addressed upstream and that's not "now".
> For the record, my foot tastes great.
It took me four tries to fix the same so you are much ahead and meanwhile I realized why they don't implement interfaces: what would load the interface that the class loader implements? :)
Comment #187
dawehnerHow do even people develop code without proving along the way that things is working. I guess some people just use testing as an afterthought.
This issue is marked against 8.3.x, so I don't see why getting this patch is as soon as possible, is a requirement or so.
Comment #188
phenaproximaTouché. It'd probably need to be an interface built into PHP's core, based on a PSR standard. IMHO PHP should have such an interface, and while I'm dreaming I'd like a pet dragon.
Comment #189
mikeryanIt was automatically bumped to 8.3.x, but we really want to get this fixed in 8.2.x and not wait yet another 6 months.
Comment #190
alexpottRe #184.1 What I'm saying is that we should alias Doctrine's StaticReflectionParser in core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php because AnnotatedClassDiscovery is in Drupal\Component\Plugin\Discovery and we're adding Drupal\Component\Plugin\Discovery\StaticReflectionParser.
Re #184.3 I meant the rest of the comment.
I think if we want to get this in 8.2.x we need to make the changes to core's plugin system as minimal as possible. The changes to core/lib/Drupal/Component/Annotation/Plugin.php and core/lib/Drupal/Component/Annotation/AnnotationInterface.php are fine and easy to see there's no impact (still need a CR though). Whereas the other changes are tricker. I'd be in favour of trying to do this in migrate and then having a issue to move the functionality into core's plugin system for a minor (or major release).
Comment #191
alexpottThe patch attached just moves the customisation to the plugin system into the experimental migrate module and marks them internal because even if migrate gets to beta we might remove in 8.3.0 if we get around to #2786355: Move multiple provider plugin work from migrate into core's plugin system.
It'd be nice to add explicit unit tests of:
Since atm they only have implicit coverage.
No interdiff because it would be bigger then the patch - much of the code has be moved around.
Comment #192
alexpottComment #193
mikeryanI think it should be made clear that when there are multiple providers, this returns the first one.
Could we incorporate the class loader class name here?
Doesn't getProvider() only return the first provider? We need a getProviders(), don't we?
Comment #194
alexpottAddressing #193
Comment #195
phenaproximaThis can all be replaced with
return (array) $this->definition['provider']
.If the key is not set, it will cast to an empty array. If it's a string, it will be cast to [$provider].
The
return $provider
bit essentially acts just like array_filter(). Let's either remove the call to array_filter() (my preference) or change this toreturn $provider !== 'component'
.Comment #196
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commented> If the key is not set, it will cast to an empty array.
and emit a warning.
return is_array($this->definition['provider']) ? $this->definition['provider'] : [$this->definition['provider']];
this, however, can indeed be replaced.Comment #197
alexpottAddressing #195.1
I don;t get #195.2 that's a anonymous function being passed to array filter. array_filter() was originally added because that method called getProvider which returned FALSE if there was no provider yet - it does not anymore. But I left the truthiness check in because (a) there is utterly no harm and (b) I don't trust parsing code with regular expressions to never return an empty string... which is what StaticReflection parser does. Ah!!! @phenaproxima nice spot what we have here is unnecessary calls to array_unique and array_filter.
Comment #198
phenaproximaThis is great stuff, in my opinion. I would RTBC it if I could.
Comment #199
mikeryanYep, let's do this.
Comment #200
catchThis is going to need a couple of read throughs.
I found some nits on the first read through. I found myself wondering whether we really need to go to all this trouble, but the issue summary explains the problem well enough. It would be nice if the issue title explained the problem.
Names of the providers?
knows
#2023325: Add interface for classloader so it can be cleanly swapped + adapters would be useful here, but not a blocker.
Comment #201
alexpottJust addressing #200
Comment #203
phenaproximaNot so much...random CI failure.
Comment #204
catchWhile the use statement parsing is clever, I don't like it very much. i.e. I wonder even with contrib whether the three lines of YAML it saves per plugin would add up to the amount of code added to support not doing that (which includes a double-nested foreach).
In irc alexpott mentioned it means contrib plugins don't need to be updated once the patch is in, so as a bc layer (kinda) that's nice, but it still doesn't sit right with me.
At a minimum the issue summary could use some more justification for this.
Comment #205
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedI don't think the amount of code is large -- it's a lot of copy-paste ATM -- but in all honesty: whatever. This is my idea, take it or leave it. We can go on with manual it has been coded above. Whatever.
Comment #206
mikeryanThe originally committed patch at #101 passes tests for 8.1.x/8.2.x/8.3.x.
Comment #207
phenaproximaFor whatever my opinion is worth, I prefer @chx's solution.
@mikeryan's patch in #101 is the most expedient solution -- it is simple, it is small, it keeps the solution confined to Migrate, and it was already good enough to be committed once.
The reason I support @chx's way is because it is better long-term DX. If people have to declare a specific provider in their plugin definitions in order to get around cross-provider dependencies, and they forget to do it (or do it incorrectly), they are liable to encounter all manner of crazy-making, hard-to-debug devilry. @chx's patch utterly prevents that and makes plugin discovery smarter in general. Although it adds a substantial amount of extra code, in my opinion it is an overall win for the plugin system.
I would also like to see the words "sparkly unicorn" in core, so there's that.
Comment #208
mikeryanJust for the record, I don't really care at this point which of the two patches goes in - I just care that one of them gets in soon (in time for 8.2.0-rc).
Comment #209
catchTo elaborate on #204. It seems possible that someone defines their classes using FQCN instead of use statements - that's against coding standards, but it's not illegal. If they do that, their code will not work. The only way to find out why would be to fix the code style (at which point it magically works), or somehow track it down to this code.
I realise that forgetting to add the YAML values is more likely, but at least then your actual code is wrong/incomplete vs. it not working just because it's a bit messy.
Comment #210
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedDo note
+ $providers = $annotation->getProviders();
please. If you choose to list your providers manually, be my guest. That's still an open avenue and an easy out if things broke.Comment #211
phenaproximaI agree with @catch that handling FQCNs is important. However, I think that most Drupal programmers are going to be using
use
statements most of the time, so I think we should handle FQCNs in a follow-up issue filed against the plugin system.Comment #212
mikeryanUsing FQCN is pretty edge-casey, and actually their code (in and of itself) will work, it's just that the provider would not be automatically recognized (so, no worse than forgetting an explicit provider if we took the approach of the first patch).
Comment #214
alexpottAnother thing in favour of the latest solution is if plugin A that is being extended by plugin B and plugin A is changed to have additional dependencies in the future then Plugin B will not have to be changed to include the additional (or changed) dependencies.
Comment #215
xjmSo @alexpott explained this issue to me at length. I think both HEAD and the handbook are missing a bit of documentation about how
namespace
anduse
statements are currently leveraged for discovering plugin dependencies, and I think this patch is also missing the documentation for how to use this more complete API relying onnamespace
anduse
statements within the Migrate system (both in the Migrate handbook and in the API docs).Since Migrate is experimental this issue is not subject to the documentation gates; however, this documentation would be a required part of making Migrate stable so it's definitely in our interest to add it soon.
With this as the proposed resolution for the plugin discovery problem, how and where exactly developers place their
use
andnamespace
declarations becomes very important and impacts functional code within the plugin system.Comment #216
xjmAlso it would be really great to give this issue a title that explains the issue.
Comment #217
xjmComment #218
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedComment #219
alexpottLooking at the patch and core's AnnotatedClassDiscovery I think we shouldn't use use statements. Core's AnnotatedClassDiscovery uses the namespace of the plugin class to determine the provider. What we should do here is use the namespaces of the parent classes and not look at the use statements. This will be way less prone to surprise than parsing use statements.
So this patch changes this:
to:
Comment #220
alexpottFixing some commentary.
Comment #221
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedIn your wisdom we are humbled. That is an amazing, sturdy idea.
Comment #222
xjmI am much more comfortable with that solution! It seems robust and will cover the fundamental problem.
I think we do still need some small bit of documentation here, at least in the Migrate topic docs (somewhere) and probably in the handbook. Also, we want a followup for adding this to core for 8.3.x, right?
NR for docs.
Comment #223
xjm@alexpott pointed out #2786355: Move multiple provider plugin work from migrate into core's plugin system -- adding it to the summary.
Comment #224
alexpottHere's some docs.
Comment #225
phenaproximaI also really like the idea of dealing with the parent class rather than all the use statements, but let us not forget to handle the interfaces implemented by the plugin class...not sure how StaticReflectionParser handles those, but they will also need to be part of the discovered providers.
Comment #226
alexpott@phenaproxima core's AnnotatedClassDiscovery does not look at interfaces. If we need to do this then for me this is a separate issue. We don't need to do that to fix the problem here. And if the problem was widespread I think we'd be seeing issues around this for core's AnnotatedClassDiscovery provider determination.
Comment #227
phenaproxima@alexpott: As we discussed on IRC, I am inclined to agree. In Migrate's case, interface handling is an edge case and we don't need to deal with it now. When this functionality moves into the general plugin system, I think we'll need to give it more thought, because I think pulling parent classes and interfaces from different providers is much less of a zany edge case in the wild. That said, I think you're right that we would be seeing complaints about it if it were a widespread problem...but what can I say? I believe in programming defensively, and knowing that there is this invisible line in the sand makes me nervous because we know that if two things exist, someone will eventually find a need to use them together. And when they do, it will break.
Having said my piece, I think we can proceed with what we've got. It's still a great solution to the immediate problem.
Comment #228
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedDocs have been written.
Comment #230
catchCommitted/pushed to 8.3.x and cherry-picked to 8.2.x. Thanks!
Comment #231
xjmComment #232
hass CreditAttribution: hass commentedCan someone write a understandable change record with examples, please? I do not understand when I need to set this in the migration, why I need to set it. A before / after example would also be helpful to understand it.
Comment #233
xjmA change record is a good idea. While he point of this issue is actually that the developer shouldn't need to do anything in most cases (because plugins should always be dependent on the namespace that provides the parent), I didn't entirely get it until someone explained it to me (twice). So it can be a simple CR explaining that Migrate source plugins now automatically depend on the providers for their parents' namespaces.
I can't think of a scenario where a source plugin would need to manually implement the API, but if there is one, we could include an example of that as well.
Thanks @hass!
Comment #234
mikeryanPending an updated change record, I'd just like to point out to address @hass's concern - the existing draft change record was associated with a previous version of the patch, not the final solution (which automated provider detection for cases where the lack of provider would cause errors). You don't need to change anything in your migrations to prevent these plugin errors - it'd be nice to add an explicit provider if you have a Drupal migration which does not depend on migrate_drupal's DrupalSqlBase plugin (like, for example, block_content_body_field), but this patch will not break any existing migrations.
Comment #235
mikeryanI've updated the draft change record.
Comment #236
mikeryanSo... Unfortunately, I reviewed the source code only, and did not test it in its actual context until tackling #2752335: Properly integrate configuration-entity-based migrations with the core plugin manager. This does not actually work in real life, although somehow the test does.
Test:
Reality:
We find the problem in DefaultPluginManager::processDefinition():
We are looking here at the Action source plugin - $definition['class'] is 'Drupal\action\Plugin\migrate\source\Action', which of course inherits from DrupalSqlBase, which (without migrate_drupal installed) fails to autoload in the call to is_subclass_of().
So, is there an answer to this that can be a quickfix, rather than revert and try again (the existing patch doesn't seem to do any active harm)? Like, override processDefinition() to omit the offending form business? Well, probably not that, but open to suggestions...
Comment #237
mikeryanJust a quick side note - the test only tests getDefinitions(), not createInstances(). I ran into this using createInstances() and spent a while trying to figure out why that would break when getDefinitions() doesn't, until discovering getDefinitions() is broken... Probably the fix will fix both, but it would be good to test both just to be safe.
Probably the first thing to do is figure out how the test passes, and "fix" it to fail...
Comment #238
phenaproximaLet me begin by saying that this is not by any means a long-term solution. That said, here's what I propose as a quick fix.
DefaultPluginManager does this:
if (!isset($definition['forms']['configure']) && isset($definition['class']) && is_subclass_of($definition['class'], PluginFormInterface::class)) {
Let's take advantage of that first isset() to dodge the call to is_subclass_of(). We can have MigratePluginManager override processDefinition(), then in our overridden version, we can set $definition['forms']['configure'] to FALSE before calling the parent method.
I also suggest we open a follow-up issue for this. I think this issue has dragged on long enough and risks becoming a zombie.
Comment #239
chx CreditAttribution: chx at Smartsheet, Migrate Rocks commentedThe trivial fix is to fix this "upstream" by adding a class_exists. If it doesn't exist then it can't be a subclass of so no BC break.
Comment #240
Berdirclass exists of what? the problem is that the parent class of something doesn't exist, we don't even know what that is before we load it.
This is also not really a problem of this issue, contrib has had troubles with that check since that was committed (pretty new in 8.2), see https://www.drupal.org/node/2796827, search_api had to create a new submodule and so on.
Comment #241
phenaproxima@Berdir is correct -- it seems this is affecting more than just us. The main effort to fix it is going on in #2796953: [regression] Plugins extending from classes of uninstalled modules lead to fatal error during discovery. If we want to quick-fix this, well...I don't see any short-term problem with the approach in #238, since no Migrate plugin is user-configurable as yet.
Comment #242
mikeryanCore issue is #2796953: [regression] Plugins extending from classes of uninstalled modules lead to fatal error during discovery, it's critical so hopefully should get quick action, it probably doesn't make sense to pursue a quickfix here. However, we should figure out why the tests fail to fail, I'll open a followup...
Comment #243
mikeryan#2797269: Improve MigrationPluginListTest opened.
Comment #244
mikeryanAnother followup: #2797421: Sourceless migration plugins are broken
Comment #245
mpp CreditAttribution: mpp at AmeXio commentedThe patch no longer applies:
I'll add migrate_drupal as a dependency until this issue is resolved.
Comment #246
mikeryanThe patch has been committed to core (see #229 above), thus won't apply. It's still open for review of the change record.
Comment #247
xjmI published the CR after a quick skim. Does this need to be reverted for comments #236 on? If not, let's continue to discuss in followups. Thanks!
Comment #248
mikeryanNo need to revert - the actual bug (#2796953: [regression] Plugins extending from classes of uninstalled modules lead to fatal error during discovery) in the way of this working fully as expected is elsewhere, and it's still no worse than it was before.