Problem/Motivation
Currently process steps are hard coded on to ContentProcess. This makes a number of things complicated.
1) Any new processes have to be added directly to the ContentProcess class making it very complicated for extended process logic.
2) All dependencies of a step much be a dependency of ContentProcess. This complicated injection.
3) Testing is nearly impossible
1) related to #2, all ContentProcess dependencies are dependencies of each process step making a big complicated process.
2) methods are protected meaning testing must be indirect.
4) All changes much be made directly to the class meaning the only option for new processes is to modify ContentProcess or replace the service making extension _very_ complicated and error prone.
Proposed resolution
Core provides a solution that basically solves all of these problems, Plugins! So we can pretty painlessly convert these methods to plugins.
User interface changes
n/a.
API changes
New plugin API. Fully backwards compatible with existing yaml_content definitions..
Data model changes
n/a
| Comment | File | Size | Author |
|---|---|---|---|
| split-processing-into-plugins.patch | 36.86 KB | neclimdul | |
| #16 | 2995174-16--processing-plugins.patch | 36.89 KB | slucero |
Comments
Comment #2
neclimdulreviewable
Comment #4
sluceroThank you for identifying this and putting the work in to get the fix moving! It's been a pain point for a while I've wanted to address, and there's actually some work refactoring the whole module to be more plugin-based in the
8.x-2.xbranch, but that's stagnated for a while now.I look forward to digging into this and getting you some feedback on it.
Comment #5
neclimdultestbot... bah. just adds the @group annotations to the new tests.
Comment #6
neclimdulExcited to hear if this works. I saw the 2.x branch but the patches I've been posting where for a project and was working this towards a menu process step that itself would allow menu links to specify a parent. Bonus and kinda the purpose of using a plugin instead of a new method, the even listener in #2879468: Nodes Cannot Create Menu Links Automatically could just pull in the plugin manager as a service and use that plugin's logic for the heavy lifting.
Comment #7
sluceroThis work looks great! The last patch from #5 appears to be empty, but reviewing the work from the initial patch looks great!
Just reading through the patch I'm noting things as I find them:
The docblock for this needs to be updated to reflect the correct return value.
This processing context is something we've been needing for a while and can definitely help with some problems in the event dispatching as well.
This should likely be made abstract so it can implement the YamlContentProcessInterface as well.
This docblock needs to be generalized to be accurate here.
Docblock needs updating.
This whole docblock needs to be updated at some point to reflect the current or new structure.
For clarity we'll probably want to rename this key, but we'll need to support it for backward compatibility as well. Maybe check for either "plugin" or "callback"?
We should probably customize this to make it easier to handle the exceptions.
I like this solution for how you've passed in the configuration from the content data as actual plugin configuration.
Nice work on this! Aside from some of the revisions I've noted above, I want to test this against some existing codebases and working content files to make sure we're not introducing any regressions. From there we'll want to create some documentation for how to create these plugins as well, but that won't need to hold up getting this merged in.
Thanks for all the hard work!
Comment #8
sluceroComment #9
neclimdul1. done
2. Oh, we are so on the same page. That makes me very happy. I actually was playing with using it in events and it was great but it was getting really invasive and breaking BC so I set it aside but would love to see how it works out.
3 & 4. copy paste fails... fixed
6 & 7. So I'd kept all this as is so all the docs both docblock and handbook, didn't have to be touched. Plugins are more about supporting code rather then defining things like the structure of your YAML, etc so that's technically fine as it is. If you want I'll happily change the code though if you want.
8. Yeah, that's copy/pasted from the old implementation trying to limit how much I disturbed things. You are right that isn't the best exception though. If we just call createInstance() without checking its going to throw PluginNotFoundException which may be good enough for our needs. We could also override the createInstance method and have it throw a specific yaml content exception as well.
9. Again thanks! I initially tried to squash it into the process method arguments but it was awkward. When I realized args are plugin specific and exactly like configuration things got a lot simpler. :)
Looking forward to seeing how your testing goes! I created those testing issues largely to test this and its working for my use case but both of those are still admittedly limited.
Comment #11
sluceroThanks for the quick turnaround on the feedback and revisions!
I'll loop back and address the other comments, but tonight I ran through and applied the coding style updates from code sniffer.
Comment #12
neclimdulThanks! Good changes.
Comment #13
sluceroThe backward compatibility concern is something I've still got to face in refactoring the events, but I think this could help a great deal with some of the issues I've faced in #2949902: Consolidate Event Dispatching Into Consistent Pattern.
Ya, sorry the docblock note was more of an observation as I read through the code again and saw that the notes there had become outdated again. I think before making this change it would be valuable to go ahead and refresh that to reflect the current status of it since we're touching that code again. In that same vein I think introducing a more intuitive keyword to replace "callback" would be a good step forward, and we can deprecate support for "callback" to remove it in the mythical 1.0 release.
Regarding the goal of plugins to add supporting code I think that's fair and we can define the generic structure for using these plugins in the plugin manager while just documenting specific arguments that might be expected in the separate plugin doc blocks.
Since that's leftover from the current implementation let's go ahead and leave it for now. Soon I'd like to tackle exception handling more directly overall to provide some more helpful tools for writing and debugging the content import files anyway, and determining the best solution for this would be better addressed in that context.
Comment #15
michelleThe patch in #11 works really well. I did have a bit of confusion with the return value from the plugin, though. It's supposed to be an entity ID but doesn't look like it's actually used for anything. In my case, I didn't have an entity and just returned a string for the menu link UUID and that worked fine. I don't think it really needs to return anything at all except the docblock was expecting it. Maybe look at just getting rid of that if it's not being used?
Comment #16
sluceroI've pulled in the latest updates in the 8.x-1.x branch and rerolled the patch. The change is pretty minimal and unrelated to this issue.
Comment #17
slucero@Michelle I don't think it's currently being used for anything, but some of the added reporting to better track individual entities being created will leverage it, so I'd like to keep it in there.
I'm marking this issue for inclusion in the alpha5 release (#2983642: Release Plan: 8.x-1.x-alpha5). It's been in use for a few months on one of my projects without any issue, and before merging it in I'll be testing builds with it on a couple of other projects I have access to.
Comment #19
sluceroI've confirmed this build successfully and as expected using 2 separate projects with complex data being imported. I've merged it into the dev branch for inclusion in the alpha5 release under #2983642: Release Plan: 8.x-1.x-alpha5.