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.
The aggregator fetcher looks ridiculously simple to convert, there's only one of them in core, and it would be minimal code/architectural changes in order to demo plugins.
Looks like we need to:
- Make the info hook sane and able to support multiple fetchers.
- Move the existing aggregator_aggregator_fetch to be a method on a class.
- Add that class to the info hook information
- Update the $success = module_invoke($fetcher, 'aggregator_fetch', $feed); to be plugins code.
That should be the extent of what's necessary here.
Comment | File | Size | Author |
---|---|---|---|
#2 | plugins-aggregator.patch | 13.01 KB | effulgentsia |
Comments
Comment #1
effulgentsia CreditAttribution: effulgentsia commentedOn it.
Comment #2
effulgentsia CreditAttribution: effulgentsia commentedComment #3
neclimdulJust did a skim but it looks awesome. Very straight forward. Thanks!
Comment #4
neclimdulIt seems like this should probably be wrapped in a try/catch
Comment #5
neclimdulCompletely unrelated because I see they're copy and paste but so I remember to follow up, these seem like minor bugs:
This should be by reference even if it is an object.
um... why? This should just be:
return !($feed->source_string === FALSE); ?>
Comment #6
neclimdulWent ahead and made the changes along with the "kitten" because they don't really change anything.
Comment #7
sunThe additional "Type" component in the namespace looks superfluous to me.
Do we want to update _aggregator_get_variables() to no longer return $fetcher?
I thought we'd get rid of info hooks...?
Everything after the first sentence belongs into some high-level architectural module/group documentation (in code), which we probably need to (re-)design/standardize for the new plugin system first.
Totally a separate issue, just mentioning.
This seems to be a Configurable Thingie™. I can't wait to convert that. ;) (@see #1668820: Concept, base class, and interface for Configurables (e.g., node types, image styles, vocabularies, views, etc))
The second "aggregator" is definitely wrong in this namespace.
Comment #8
EclipseGc CreditAttribution: EclipseGc commentedI'm happy to address the non-implementation questions here.
It most certainly is, but we sort of standardized on that internally so that all plugin types a give module might support would be in one common directory and labeled as such. This is yet another directory, which is starting to be sort of annoying, but it's also self documenting "here are all the plugin types" sort of behavior, which we in the ctools world really appreciate and try to take with us whenever possible. If you really don't like the directory, I'm sure its presence is debatable but this is the reasoning.
Ultimately yes, but the annotation discovery is in a separate branch, and we wanted to delay it for a separate patch because there will likely be issues around translating the annotations for the UI, and that could be one heck of an issue in and of itself. As such the decision was made to not even attempt to put that into the initial plugins patch so that we could push it on through. That leaves us with our best source of discoverability still being hooks. This is trivial to change at a later date. (Consists of writing appropriate annotations for every plugin class and changing the discovery in the plugin type class. VERY straight forward.) More on this in another of your comments.
Actually it's not. This is part of the prep for eventually moving to annotations. This says:
namespace: Drupal\aggregator
The class will be a plugin
defined by the aggregator module
the plugin type is fetcher
This logic allows the annotation discovery to find all plugins that a particular module defined a type for. So if aggregator were up to being usable outside of core, Feeds module could provide it's own fetchers for it, and those plugins would be found in:
Drupal\feeds\Plugin\aggregator\fetcher
So the second "aggregator" only looks weird for the implementing module. For any other module it explicitly informs anyone who looks at it, which module defined this plugin type (which is really handy). It also gives the eventual annotation discovery class a unique directory naming convention for finding plugins of a particular type.
Hopefully this clarifies a few things, the rest is aggregator specific implementation, so I'll let neclimdul or effulgentsia answer.
Eclipse
Comment #9
sunThat makes sense, thanks :)
1) I'm confident the identical questions will come up in the main issue, so "be warned" ;) -- perhaps there's a way to address that upfront; e.g., via (temporary or not) in-code docs.
2) Still not sure about the extra "Type" part in the namespace. I wasn't thinking about the extra directory, only about the duplication of Type within the class name. In order to produce a potential name clash, something Type-alike would have to be located within the parent \Plugin space. I can't think of anything, do you?
Comment #10
EclipseGc CreditAttribution: EclipseGc commentedThere would literally have to be a "type" module for that to happen, and then we'd have to be using an additional level of directories under the type dir before it would happen, and even then, I think only windows could have that problem. I'd call it pretty edge-case-y and rather unlikely. It would also only potentially affect annotation discovery, so yeah I'd call this a pretty remote possibility, but I think your warning is well taken here. I'm not sure what we can do beyond just trying to set a "good example" and then follow it ourselves. Some best practices may be due for my d.o docs with an eye towards this problem though, so thanks for that. I'll see if I can do anything to preemptively fix this.
Eclipse
Comment #11
Dries CreditAttribution: Dries commentedI actually think it is good clean-up.
However, there are a couple of unexpected things for me:
It is a bit odd that an instance of a 'FetcherType' returns an object that returns a list. I wonder if 'FetcherType' is best renamed to 'FetcherFactory' or something?
It would be nice if we could get rid of the 'aggregator' in the middle of the path. Not sure that makes sense though.
I expected the title and the description to be provided by DefaultFetcher() through two getters; getTitle() and getDescription().
Again, I find it weird that FetcherType creates a factory. Better to rename FetcherType to FetcherFactory.
This duplication would be avoided if we had getTitle() and getDescription() as part of DefaultFetcher.
Comment #12
EclipseGc CreditAttribution: EclipseGc commentedYeah, I actually went into a bit of detail on this in my response to sun. The aggregator in the middle is in anticipation of getting annotations committed, and is actually very useful outside of the defining module because it tells us what module defined the plugin type that handles plugins in this directory. But ultimately, that directory is a supporting directory for the annotation based plugins as we move that direction.
This would require us to either make these static methods on the classes, or to instantiate the class in order to get the data. This is actually one of the fundamental points of plugins in general, we're getting all the "definitions" to support the user interface. Instantiating the classes associated with those instances just to get the various meta-data/definitions we need is likely to be problematic, which is why we separate this information from the class.
Eclipse
Comment #13
merlinofchaos CreditAttribution: merlinofchaos commentedI echo Eclipse: It's *very* important that title and description and any other properties needed for "generate a list of these" do not require instantiating the class; when you have potentially hundreds of plugins, that's a lot of memory we don't want to use just to generate a list of titles and descriptions of all of them.
Also, what duplication are you talking about? The duplication you see is from a documentation function? Perhaps the documentation hook should document 'Example fetcher' instead of 'Default fetcher'?
While I do have issues with 'PluginType' as a name, it's more than just a Factory because more complicated plugin systems will do more than just getDefinition and Instance off of it. I posited Controller but it was pointed out to me that it's not an MVC Controller so that name might not be suitable. Not sure what that leaves us. I'd go with Overlord but I don't think anybody but me would laugh.
Comment #14
EclipseGc CreditAttribution: EclipseGc commented$factory_overlord = new FetcherType();
FTW!!!
Comment #15
merlinofchaos CreditAttribution: merlinofchaos commentedPossible words that I can think of off the top of my head: Manager, Handler, Arbiter.
Manager isn't too bad. Handler would make me sad because Views has a bunch of handlers but we're already going to have a bit of a terminology problem here anyway.
Comment #16
neclimdulIt'd probably make more sense if the Plugin namespace are CamelCased
Plugins\Aggregator\Fetcher
Right that could maybe be handled that way but there's a logic to the way we handle metadata like this. I'll take a bit different approach to explaining it. Plugins generally revolve around this metadata because that's the metadata we use to build UI's and sometimes functionality. For example, a common plugin type EclipseGC will be making is a layout and the plugin would look something like this:
twocol.yaml
In this example you'll notice there's no class to pass around or pull metadata off of. There will be a default class that all plugins use that gets passed this metadata and interacts with the layout rendering code. And when the UI is running only the metadata is of any concern to us.
So what's to take from this is the need for the DiscoveryInterface to separate the implementation/storage of the metadata from the code requesting it. So then we have options for implementations like the yaml file I made, an info hook, the really cool annotation reader chx wrote that doesn't load code into memory, a static or set of static methods on the plugin... really the sky's the limit but for the common case I'm going to be suggesting chx's annotation reader we're working on getting ready as a follow up.
Hope that clarifies the info hook.
Comment #17
neclimdulAs far as the type discussion goes, this is the first time its really come up. It has seemed to be pretty clear since its holding the logic for the type. I think this is something we can discuss better in the reviews eclipse is working on setting up though.
Comment #18
effulgentsia CreditAttribution: effulgentsia commentedYep, this keeps on surfacing as something Dries and others find unintuitive. As I said in #1497366-150: Introduce Plugin System to Core:
Even for simple types, a plugin type is more than just a factory, because getDefinitions() is not a common feature of factories, at least as I understand what factories typically are in other systems. And as merlinofchaos points out, some plugin types will contain additional functionality appropriate to the particular features of that system. The approach I took in #2 was to name the class
FetcherType
(since it's neither just a lister, nor just a factory, and "Type" is the only word we've come up with so far to capture the combination of things this class does), but to assign the object to the local variables$fetcher_lister
and$fetcher_factory
, since in those local contexts, the FetcherType object was only being used for the more limited aspect reflected in those local variable names. But it doesn't look like this successfully resolved the confusion around this.I think it would be good to come up with a convention for how to organize 3 kinds of things that modules may want to implement related to plugins:
- plugins
- plugin types
- plugin system components (e.g., alternate factories, alternate discovery methodologies)
What #2 did was:
- put plugins in
Drupal\[module implementing the plugin]\Plugin\[module implementing the plugin type this plugin is for]\[name of the plugin type this plugin is for]\[name of the plugin]
- put plugin types in
Drupal\[module implementing the plugin type]\Plugin\Type\[name of the plugin type]
- no plugin system components needed for aggregator, but if it were, I would have put it into
Drupal\[module implementing the plugin system component]\Plugin\[Discovery|Factory|etc.]\[some descriptive class name]
Perhaps a better convention would be 3 top-level (within Drupal\$module) namespaces: Plugin, PluginType, PluginComponent? For example:
- Drupal\aggregator\PluginType\FetcherType
- Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher
- If there were a component: Drupal\aggregator\PluginComponent\Discovery\SomeCustomDiscovery
Any other ideas?
Not sure if this was intentional, but the above suggestion uses Plugins (plural) whereas I stuck with singular, because with the exception of "Tests", we have so far stuck with singular namespace names. I'm open to plural if someone wants to make a compelling case for it. I don't think "because there's often more than one" is a compelling enough case, because many of our namespaces contain more than one class of a similar kind but the namespace is still singular (e.g., Drupal\Core\EventSubscriber).
As far as capitalizing Aggregator, I disagree, because what this part of the namespace refers to is the module "aggregator", and elsewhere, we've agreed to retain lowercase when referring literally to the module name.
As far as capitalizing Fetcher, this is an interesting question, because currently the only string identifier of the "fetcher plugin type" is the class name FetcherType, so this alone would support capitalization. However, CTools has a concept of lowercase identifiers for plugin types, and while that concept doesn't exist yet in the plugins-next branch, it has re-emerged in the plugins-annotations branch, because AnnotatedClassDiscovery needs to be given a module and type, and currently both are lowercase by convention. We can change that, but I think keeping it lowercase would be more consistent if we ever want to use plugin type identifiers as part of a machine name.
Comment #19
neclimdulI think with the exception of sun's comments that where lost a while back I think this is mostly terminology discussions. I don't want to loose the feedback here but maybe this should have its own issue?
Comment #20
sunMy major concerns have been addressed by clarifications actually.
The remaining concerns are on:
- namespace names (e.g., /Plugin/Type/FetcherType vs. /Plugin/FetcherType)
- *Type plugin classes being both the type definition, definitions/variant/derivative lister, and factory.
Frankly, I believe that both of them will be much more easy to resolve, once we've converted some more stuff throughout core, see it live, and see the big picture. There's nothing easier than to move/rename files ;)
Comment #21
effulgentsia CreditAttribution: effulgentsia commentedPer #15 and discussion with Dries, neclimdul, and EclipseGc, we renamed Type to Manager within class names. I also removed the Type subnamespace from the aggregator use case and tests.
http://drupalcode.org/sandbox/eclipsegc/1441840.git/commitdiff/dde4875
Comment #22
neclimdulSuns concerns are addressed and Dries concerns I think are addressed. Seems like we need a follow up core issue tagged revisit before release on the namespace issue and I think we can move this back to fixed.
Thanks for cleaning up the names effulgentsia.
Comment #23
effulgentsia CreditAttribution: effulgentsia commentedI don't think we even need this quite yet. Once an initial patch lands and people start converting systems over, the namespace structure topic will naturally come up, be discussed, and if necessary, a dedicated issue for it will get made.
Comment #25
ParisLiakos CreditAttribution: ParisLiakos commentedjust opened: #1930274: Convert aggregator processors and parsers to plugins