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
hook_filter_info() is a hook for defining a set of callbacks that effectively map to a single object
Proposed resolution
That's almost the definition of what our plugins are. Let's convert it!
Remaining tasks
None now that #1779026: Convert Text Formats to Configuration System is in
User interface changes
N/A
API changes
Replaced with \Drupal\filter\Plugin\filter\filter\FilterInterface:
- hook_filter_info()
- hook_filter_FILTER_settings()
- hook_filter_FILTER_prepare()
- hook_filter_FILTER_process()
- hook_filter_FILTER_tips()
Removed:
filter_get_filters() (Previously used in conjunction with a format's filter, now the information is stored directly on the filter)
Comment | File | Size | Author |
---|---|---|---|
#102 | filter-1868772-102.patch | 134.01 KB | tim.plunkett |
#102 | interdiff.txt | 4.26 KB | tim.plunkett |
#100 | filter-1868772-100.patch | 133.69 KB | tim.plunkett |
#100 | interdiff.txt | 1.32 KB | tim.plunkett |
#98 | filter-1868772-98.patch | 134.95 KB | tim.plunkett |
Comments
Comment #1
tim.plunkettThis is a work-in-progress, and includes the text format conversion patch, which isn't currently passing tests.
I'll post a sandbox of this later.
Comment #2
tim.plunkettOkay, this is with the callbacks converted.
Some unit tests will fail, because they call private _filter_*() functions directly that are moved.
Also, filters are passed around as stdClass in a lot of places
Comment #4
tim.plunkettMore fixes, cleaner patch.
Comment #6
tim.plunkettFixed those three failures, the fourth was random.
Comment #8
tim.plunkettOkay, trying out loading the plugins.
Comment #10
tim.plunkettThis also now includes #1869566: Allow any collection of plugins to be lazily instantiated
Comment #12
tim.plunkettOkay, this should be working now.
Also attaching the patch without the other two issues.
Comment #14
tim.plunkettOkay, after this I think I'm happy. Just some @todo's to fill in now.
Comment #16
tim.plunkettWhoops. A little overzealous.
Comment #17
yched CreditAttribution: yched commentedYay, thanks for attacking this !
[edit: numbered my items]
1.
This is a typical case where having #1764380: Merge PluginSettingsInterface into ConfigurableInterface would help consistency across core subsystems.
Not a blocker, obviously - just saying :-)
2.
Not good in FilterManager :-)
3.
Nitpicky, but I'm really not fond of FooManager instead of FooPluginManager (I know that's what Entity does, I dislike it there as well :-). According to the coding standards in http://drupal.org/node/608152 :
"Classes and interfaces should have names that stand alone to tell what they do without having to refer to the namespace, read well, and are as short as possible without losing functionality information or leading to ambiguity"
What this is is a "plugin manager", not a "manager" (which, in itself doesn't mean anything - "manager" is a very versatile word, and it would be a shame to see confiscated by the Plugin API, we could have many other sorts of managers).
The interface & base class are PluginManagerInterface & PluginManagerBase - thus the specialized instances are SomethingPluginManager.
4.
I wonder if we really have use cases for this. Weights being mostly arbitrary, I'm not sure how a default weight of 1 or 10 can make any general sense. Probably outside the scope of this "direct convertion to plugin API" patch, but that might be a good opportunity to get rid of a strange feature ?
5.
Process after alter ? ;-)
6.
In similar cases for other plugin types, it has been considered that a list of plugin definitions has no "natural" order that would make sense over another one, and that ordering should be done in the UI code that needs to present a list of plugins.
7.
No biggie, but I'm wondering if we shouldn't be adding that once and for all in PluginManagerBase::processDefinition() instead (and remove it once and for all when the bug is fixed).
8.
Doesn't this duplicate the check in FilterManager::processDefinition() ?
9.
settingsForm() rather than settings() ?
10.
All methods in FilterInterface receive a FilterFormat $format. Yet, a FilterPlugin is the instantiation of a specific filter_plugin id with some specific settings - meaning, a different format using the same filter with different (or the same...) settings will not reuse the same plugin instance, right ?
Therefore, given that a given filter object will not be reused across different formats, wouldn't it make more sense for the $format to be injected in the filters constructor rather than in each method separately ?
Actually, unless really needed, it would be a best if FilterPlugin objects stayed agnostic about what the're being used in, and didn't hardcode anything about "I know I'm being used in a filter format". Just like image effects plugins do not need to know anything about a the notion of "image styles" to do their work, and could potentially be used in other contexts.
Container knows its containees, but not the opposite (and containees might be contained in different kinds of stuff)
I might be wrong, but aside from FilterTestReplace (a test filter), I don't see $format being actually used in any of the actual plugin class methods, and I'm not sure why it should ?
Comment #18
tim.plunkett3) I started with that and just thought it looked silly. All Filters are plugins, but we don't need to remind people of that. It is the manager of the filters. And yes, you can tell it's my opinion, because I wrote EntityManager too :)
4) Filters are unique in that they DO have a weight. "
Limit allowed HTML tags
" should generally come first, since it might restrict BR/P tags, but "Convert line breaks into HTML (i.e. <br> and <p>)
" will add them back. It's an important part of the architecture.5) D'OH!
6) Unlike the other order, this one is stupid. Agreed on removing.
7) Out of scope, but I might go ahead an open a separate issue.
8) Yep, I copied most of that and it's mostly a duplicate. I had forgotten that 7) WASN'T done upstream
9) Sure, I think that is clearer and matches other places
10) That was a 1:1 conversion from the hooks to the methods, and I didn't want to needlessly break contrib by removing something. But I also agree that you shouldn't need that
Comment #19
yched CreditAttribution: yched commented3)
FilterManager still violates the code standards though :-)
It's not about reminding people that all filters are plugins, I'm not arguing for HTMLFilterPlugin instead of HTMLFilter.
It's about stating that the plugin manager is a Plugin manager.
10)
Yeah, removing the knowledge about $formats within $filters altogether would need some double-checking with @sun, and could happen in a followup.
But having the $format as a property of the Filter, injected at construct time, is a natural consequence of the migration to an OO API, and doesn't break anything. The previous magic-callback-based API, where a filter was just a collection of functions, had no other way than passing the $format in each function, but that constraint doesn't hold anymore when filters are object. And in the current design of the patch, a $filter is de facto created to be used in a single given format, so passing the format again in each method is just misleading IMO.
Comment #20
tim.plunkettMeant to do this earlier.
Comment #21
tim.plunkett#1779026: Convert Text Formats to Configuration System is still changing slightly, but is very very close, so I'm going to temporarily postpone this so I don't have to keep working on a moving target. I'll be back soon.
Comment #22
tim.plunkettRerolled to keep up with HEAD. Still need to respond to #19.
Comment #23
gddThe hook_MODULE_config_CRUD() calls will have to go as well. Just a heads up.
Comment #24
gddHere, have a free reroll to HEAD
Comment #25
yched CreditAttribution: yched commentedAs an additional argument for FilterPluginManager rather than FilterManager:
just realized we have an AliasManager right now, and that #1331486: Move module_invoke_*() and friends to an Extensions class is about to add a ModuleManager. Both of them are completely non plugin-related, of course.
The common pattern is to name FooThing the classes that implement ThingInterface. Can we standardize on calling FooPluginManager the classes that implement PluginManagerInterface ? When you are a PluginManager, "Plugin" is the important word, not "Manager", coz there are lots of managers :-).
Comment #26
tim.plunkettThat last reroll had some parts missing. And the formats patch changed a good deal since I worked on this, so I have some catching up to do. Just posting a sloppy reroll for now.
And yes @yched, I'll switch the naming around... :)
This has a lot of cobwebs, no reviews yet please :)
Comment #28
tim.plunkettComment #30
tim.plunkettI think this will be green, but there's still some needless changes made by this patch that I'd like to clean up.
Comment #31
tim.plunkettBecause of #1779026-176: Convert Text Formats to Configuration System, and various other possible contrib usecases, I'm not going to remove the format being passed to filter methods.
I'd switch to injecting the format into the filter constructor like I did in the block issue, but #1890534: It's confusing that "Block/$block" sometimes refers to the entity and sometimes to the plugin happened, so who knows :)
If this fails then I'll clean it up, I removed a couple things I hope we don't need :)
Comment #32
yched CreditAttribution: yched commentedIMO #1890534: It's confusing that "Block/$block" sometimes refers to the entity and sometimes to the plugin means
"ideally filters should not need to know $format", not
"if they *do* need $format, it should be injected in each method separately rather than in the constructor"
Comment #33
tim.plunkettFair point :)
Here's that taken care of.
Comment #35
sunThanks for working on this! :)
Filters definitely are a perfect fit for plugins. This is definitely a step in the right direction.
With this baseline, there might still be hope to get some more fundamental filter system changes into D8, which are being summarized in #1828224: Split filter process into text processing and filtering. Of course, that would require us to move on rather quickly here. So let's try :)
Initial review + early feedback on the current patch:
This static should be obsolete, I think. Definitions should be "property-cached" on the manager already.
1) Passing $filter to
Filter::process()
seems unnecessary?2) I'm not fond of removing $format from the arguments. AFAIK, there are advanced filters out there that dynamically adjust themselves depending on the existence/configuration of other filters in a format.
That's a unique use-case for filters. I can perfectly understand the "plugin purists" perspective you guys discussed earlier in here, but that doesn't really apply to the Filter API.
I think having access to the $format is pretty essential for filters.
I'd actually like to see more "smart/intelligent" filters, which adjust themselves (in safe ways), in case another filter is active, and the combination of the two wouldn't lead to results that anyone would intend to have.
If you don't want to pass $format, then what I actually care for is, I think, passing the FilterBag of all configured filters in the set (i.e., $format->filters ?) to each filter. The format itself isn't necessary. Only the other filters are. (including their weight and settings)
We should totally split the long summary from the short summary into two separate methods.
The long tips (being output on the /filter/tips page) should actually return a render array and thus be named
buildUsage()
.The short tips are supposed to return either a single string, or a render array that is suitable for #type 'item_list'; thus,
getSummaryItem()
.Hm. Can we clarify the code comment to explain why this is needed?
I think we should actually replace this with a NestedArray::merge() now, since filter plugins should be able to use nested array keys for their settings.
Hrm. I really dislike classes in \Plugin, but ok...
1) Since we know that this won't be empty, we can safely use
array_combine()
directly here.2) That said, can't we simply assign the result of
getDefinitions()
to $this->instanceIDs?and
<p>
)"),+ * type = FILTER_TYPE_MARKUP_LANGUAGE
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/filter/filter/FilterHtml.php
+ * title = @Translation("Limit allowed HTML tags"),
+ * type = FILTER_TYPE_HTML_RESTRICTOR,
+ * default_settings = {
+ * "allowed_html" = "
Comment #36
tim.plunkettThanks for the review! Working through this now.
Comment #37
yched CreditAttribution: yched commentedWe really need to bring #1764380: Merge PluginSettingsInterface into ConfigurableInterface to a system-wide agreement about this. Having all plugin types handle their settings in their own separate way is a heartbreak.
My current position, quoted from over there :
" I'd question whether we really expect "several chunks of metadata, each collected separately with separate alter step and static + persistent caches that we need to figure out when to clean" will be more performant and manageable than "one single, all-inclusive list of metadata". Doesn't seem obvious to me, and at least is clearly more painful code wise."
Comment #38
tim.plunkettPushed up filter-plugins-1868772-tim. Don't mind the messy history, my commit messages were not written with the plan to push this publicly :)
Removed drupal_static
I've removed passing the filter to itself :)
I stopped passing the format to each method, because it's passed to the constructor and stored as $this->format. If we want to pass the other filters instead, that's a good follow-up.
I'm just swapping the "tips callback" out for a tips() method, it's not really in-scope for a conversion to start making changes like that.
Changed the comment.
I switched to NestedArray, and in general cleaned up how the defaults are provided.
While just working with this now, having FilterBag in \Plugin threw me off, so I moved it :)
Good call, we don't need any of that drupal_map_assoc() call.
I'm punting on breaking up the annotation, so that it stays alterable. See @yched's comment.
I hadn't meant for them to be temporary, but we should decide if we want to leave it, and if not, how to replace it (true get()/set() calls? direct access of configuration?)
The cache bit it in the annotation now. Same problem as above.
---
Leaving assigned in case I have any stupid errors or test fails to fix up.
Comment #40
tim.plunkettArgh, I always get the order of NestedArray::mergeDeep() wrong.
Also, now that we don't have the drupal_static in filter_get_filters(), there is a bunch to be cleaned up.
ec8543b Fix order of NestedArray::mergeDeep().
f2363b7 Remove sortFilters().
fc3e34a Revert unnecessary changes to filter_get_filter_types_by_format().
c465514 Kill filter_get_filters() once and for all.
Comment #42
tim.plunkettc7fa141 Pass the correct parameters to filter methods.
d5b9d0b Restore functionality removed by last patch.
Okay sun, it's all yours. Don't change *too* much please :)
Comment #43
tim.plunkettRebased the branch against 8.x
Comment #45
tim.plunkettTestbot fluke. Sun, you implied you had more feedback to give, or are we done?
Comment #45.0
tim.plunkettfollowing issue summaries
Comment #46
tim.plunkettUpdated the issue summary.
Comment #47
sunStarted to review the patch and the branch last night. Working on this.
Upfront, I've to say that it took me and still takes me hours to decipher the class hierarchies, code paths, and called code. Plugin managers on their own are way too abstracted already, the additional layer of FilterBag exceeds the sanity threshold.
Also, the responsibilities between FilterBag vs. FilterPluginManager are very fuzzy and do not seem to be cleanly separated. That's primarily caused by
FilterBag::initializePlugin()
, since that contains instantiation logic that simply doesn't belong in there, but exclusively into the plugin manager instead.The more I study this, the more it appears to me that the concept of FilterBag shouldn't exist in the first place, and instead, we simply need PluginManagers that are smart by design.
As I'll also note below, this patch currently causes the text format creation form to take 2 seconds to load on my machine. Which is caused by this call trace:
FilterFormat::__construct()
-> new FilterBag(FilterFormat, FilterPluginManager)
FilterBag::__construct()
-> FilterPluginManager->get[ALL]Definitions()
-> Discovery::getDefinitions()
So, alas, a complete file system scan and annotation parsing flow on every instantiation of a text format.
Lastly, the current code introduces not one, not two, but three different variables/properties for the settings of a filter plugin instance:
default_settings
settings
configuration
I'm still in the process of figuring out from where each one of those comes from, and what exactly it contains at which point in time, and ultimately, what the actual resulting set of settings for a particular filter is. What's already clear is that the three data variables are needlessly merged into each other a dozen of times during the plugin instantiation process. It looks like origin, availability, intention, and purpose of each one of them wasn't clear, so the current code simply performs some "safety merges" in various spots.
We'll have to figure these points out, but I'm sure we'll get there. :)
I've changed a couple of issues in my local branch already, will push as soon as I figured out some more details.
Should be ::$label, especially since this is not a user-defined "title".
Hm.
It looks like we handled this case gracefully previously.
That was most probably wrong. At the same time, this means a significant API change.
We've lost the order/sorting here?
Looking some more through the code, sorting filter instances should be responsibility of FilterBag; i.e., whenever you add a filter to the bag, their processing order must be guaranteed.
Still ::tips().
.
The more I look into this, the more I believe that FilterBag needs to be lazy-instantiated - either through a dedicated
getFilters()
method, or through a magic __get() method.But. Further investigation shows that FilterBag is already designed for lazy-loading!
But: The call to
FilterPluginManager::getDefinitions()
in FilterBag's constructor completely destroys that, as it triggers a complete discovery of all filter plugins in the system on every instantiation of FilterBag (which is supposed to lazy-load exactly that)."view", "displays"
Should be filter.plugin_manager
We want to retain this @todo.
Instead of inlining it, I think we want to move the sort callback onto the FilterBag. We could as well leave it on FilterFormat though.
Apparently, you moved it to FilterBase, but don't use it anywhere.
That said, unless we always work off filter plugin objects, we might need two separate sort helper functions; one for the form submit handler, and one for the FilterBag. Ideally, we'd only need one, and always work on objects.
I wonder whether the plugin manager's class phpDoc is the appropriate place for architectural/plugin documentation.
Alas, a class doesn't return anything. ;)
And yeah, this totally belongs onto FilterInterface instead.
Why do we have both default_settings and settings for plugin definitions?
settings only exist for instantiated plugins, so that should be superfluous.
Prior comments in this issue strongly argued for replacing this with FilterBag.
Still need to be removed.
.
Comment #48
sunSummary of changes:
Relocated ::tips() to come last in all classes and interfaces.
Less important methods should come last.
Reworked FilterFormat::$filters to always operate on FilterBag.
The $filters property became protected. Any outside code/callers need to use the ::filters() method instead. The method returns the FilterBag. ::filters($instance_id) returns the requested filter.
This was an important change from an architectural perspective, since I really did not feel comfortable with the possibility of a potential disparity between FilterFormat::$filters (the configuration, as contained in the text format config file) and the actual configuration of a filter plugin instance. Therefore, all code that retrieves or calls into filters is guaranteed to work on the actual filter plugins and their configuration now.
Alas, I did not really intend it, but apparently, this change also allowed to remove some larger chunks of code that previously dealt with synchronizing the two data sets (primarily in
FilterFormatStorageController::preSave()
). :)Reworked FilterInterface and FilterBase to have proper properties and methods.
As mentioned before, it took me quite some time to step through the new plugin architecture. The definition was not properly separated from the configuration, and the configuration was not properly separated from a filter plugin's $settings array. Apparently, my repeated questions in earlier patch reviews about the magic __get(), __set(), and __isset() methods on FilterBase actually turned out to be the key for resolving the problem space. ;)
FilterInterface now defines proper methods for getting the type, label, and description of a filter plugin (which are all based on the definition, not configuration).
FilterBase now defines proper class properties for the actual "configuration" properties of a filter plugin instance; i.e., $plugin_id, $module, $status, $weight, $cache, and $settings. In other words, exactly the properties you see in the text format configuration file.
With the two aforementioned changes combined, I also had to quickly invent a facility for "exporting" the configuration of all filter plugin instances in a FilterBag. That is, because FilterFormat::$filters only ever contains the initial configuration, as loaded from config. Any changes to the configuration happen on the filter plugin instances themselves. Therefore, the filter plugin instances need to be exported, in order to resemble back the complete FilterFormat::$filters data to be stored in configuration.
In short:
FilterBag::export()
calls into all plugin instances in the bag, which implement a correspondingFilterInterface::export()
.Of course, I don't know whether the concept I'm proposing is completely out of line with the rest of the plugin system or any prior art. (Well, it's definitely "out of line", because there doesn't seem to be a facility for this yet :P) If there is anything and I happened to miss it, then I'd love to know. :)
The idea here essentially was to "inherit" the facility-wise identical functionality of
Entity::getExportProperties()
to the PluginBag, and from there to all plugin instances in the bag/collection.I hope this makes sense. Let me know what you think! :)
I didn't run any tests, but manual testing worked fine, so let's see what the bot thinks.
Comment #50
sunWeird. Not sure why earlier patches didn't fail on that, too.
Fixed $filters['all'] is undefined if there are no formats.
Comment #51
sunFixed configured filters are not instantiated.
Comment #53
sunHrm. Figuring out the test failures, and how to change the implementation, took me a range of hours...
I'm still not happy with the massive complexity being introduced. However, I'm slowly able to make more sense of the FilterBag.
Comment #54
tim.plunkettI didn't fully review the changes in #48-51 yet, this is just of the interdiff in #53.
Most of this looks good, some is a little odd. I'm glad you're warming up to PluginBag.
Wouldn't this then need to call $this->remove($id);
What does this gain us over just relying on the CacheDecorator static caching?
Er, okay.
Comment #56
sunThe FilterAdminTest failure is most likely caused by the @todo I added very late to
FilterBag::sort()
— as of now, the sorting only affects the order of plugin instances, but the FilterBag is actually Iterable, so we actually need to sort the $instanceIDs array (which is the data base of the Iterable), AND the order in both $instanceIDs as well as $pluginInstances has to be *always* identical.Apparently, this SHOULD include the situation when new filters are added to a format (because you can add a filter with a custom weight). However, that's really non-trivial to figure out, because we don't want to trigger the sorting function on every single plugin instantiation (performance). It should only be triggered when the configuration of a filter is changed, or when a new filter is added.
Comment #57
tim.plunkettThe changes to FilterPluginManager look a lot like #1903346: Establish a new DefaultPluginManager to encapsulate best practices (which was actually written after, and with no influence from this issue, amazing!), can we punt on that here?
Comment #58
sunHm. I looked at that issue/patch, but I'm not able to see any kind of similarities? (Nevertheless, I commented over there. :))
Comment #59
sunMerged HEAD, resolved conflicts, and corrected
FilterBag::sort()
as mentioned previously.Changes:
Please note:
Comment #61
sunComment #63
sunI studied TextSummaryTest, text_summary(), the default plain_text format, as well as the default filtered_html format of Standard profile, for two hours now, but I literally have no idea how the summary length test is able to pass in HEAD.
If I get it correctly, the existing code in HEAD merely checks for
if (isset($filters['filter_htmlcorrector']))
— but as we all know or should know by now, text formats contain all filters, regardless of their status. Consequently, the mere existence of a filter in $filters implies no meaning at all.And indeed, with that conclusion, I just found #1235062: text_summary() ignores filter status .....meh, will pedantry force us to fix that first?
Comment #65
tim.plunkett#63: filter.plugins.63.patch queued for re-testing.
Comment #67
tim.plunkettRerolled. Still haven't groked all the changes since my passing patch.
Comment #69
tim.plunkett!!
Somewhere along the way, the above patches started rearranging filters in core formats, not test ones. And with the addition of the WYSIYG formats, the tests broke.
So this interdiff reverts the core formats to the way they are in HEAD, and fixes the test checking them.
It's possible that we're done here...
Comment #70
tim.plunkettThis seems like premature optimization. The CacheDecorator provides static (property-based) caching itself, in addition to cache() calls.
This is obsolete now, I'll remove it in the next patch (waiting for tests results first)
This, and possibly elsewhere, should use \Drupal now
Er, this is $pluginId in PluginBase, not sure how this works. Or is it never called?
Comment #72
tim.plunkett#69: filters-1868772-69.patch queued for re-testing.
Comment #74
tim.plunkettOkay, there were a couple upstream changes to filter.module.
Also, adjusted to use a custom @Filter annotation.
Comment #76
tim.plunkettMisnamed the annotation on the PHP filter.
Comment #78
tim.plunkettWell that passes locally, run-tests.sh and GUI. Might have to enlist jthorson's help.
Latest is in http://drupalcode.org/sandbox/heyrocker/1145636.git/shortlog/refs/heads/...
Comment #79
tim.plunkettRerolled.
Comment #81
tim.plunkettReroll for various commits.
Comment #82
tim.plunkettOkay, this interdiff may look like its cheating, but its actually reverting the order back to the way it is in HEAD now.
Comment #84
tim.plunkettOkay, so I retested each of those twice, and each one passed once and failed once... So that's not good.
Let's settle this.
Comment #86
andypostConfirm this trouble, seems it's related to entity loading or other "internals" of manager/controller
EDIT tested on ubuntu+zend server+php 5.3.14
This ordering troubles beets me in #1799600: Add test of sorting for configuration entities once I tried to add taxonomy vocabularies from #1981418: Drop taxonomy_vocabulary_sort()
Comment #87
tim.plunkettWow. Turns out this is actually caused by a bug in PHP's uasort.
That's why the test is unreliable.
But why are they undefined?
Because #1911884: Enable CKEditor in the Standard install profile changed the test. Before that issue, this tested two enabled filters on a format, and their sorting. But for no apparent reason, it switched formats, and was comparing the weight of two disabled filters. Because of the way filters weights were previously stored, the test obediently gave the result expected, without actually testing anything.
Once the sort was switched, the two disabled filters were assigned "undefined relative orders", causing the random failures.
I'm now testing the same two filters, but on a format they actually are used on.
In addition, the default formats do not match their state when imported. They are pared down to the bare minimum, which is not how we've been handling other default config. I've rexported them to get all of the default values in them, and in the right order.
Finally, getAll() needs to be called *before* sort(), or else there are notices due to try/catch. See https://bugs.php.net/bug.php?id=50688.
The interdiff is against #81.
Comment #89
tim.plunkettWell, that was unfortunate. We do need the full list of definitions, not just what's passed in.
Comment #91
tim.plunkettAh. That failing assertion (added by this issue) is just not how the CMI system works. Every setting is exported, whether or not it is being used.
Okay. We should finally be done here!
Comment #92
Eric_A CreditAttribution: Eric_A commentedThere is an issue for Plain Text: #1942122: Make Filter module active config save format match the default yml file.
And a meta: #1938580: [META] Make active config save format match the default yml file (order and quotes).
Comment #94
BerdirHere's a, hopefully useful, review. Looks great generally, just a bunch of questions and minor things...
Hm, this doesn't really seem to be simpler that way? Why not just access $format->filters['filter_html']->settings['allowed_html'] directly, is there a reason that doesn't work?
Is there a reason this is changed? Doesn't look like this was the case before?
I'm not 100% convinced about removing entity_load() wrappers. save/delete absolutely, but load I'm not sure. Doesn't seem to hurt to have them and you don't need to use them if you don't want to.
Or does this mean that the implementation should use entity_load()? :)
Probably off-topic anyway ;)
Why is this changed? There was a recent discussion on twitter/planet that functions that return a list/collection should always return a list/collection and not NULL. field_get_items() was recently changed to return an array(), this seems backward? And unrelated, or am I missing something? If this doesn't return an array anymore, then @return needs to be updated. That still says array.
Those are the parts about plugin conversions that I love :)
What should be done with this then? Maybe the @todo should say that? Saving this seems to make sense as it's the fastest way to get it again?
As mentioned in the Drupal::pluginManager() issue, $owner == $type seems to confuse people (why repeat, what's the difference). But I don't have a better idea, owner is obviously given and it is a filter...
@inheritdoc ;)
I assume this is just taken from the existing definition? Seems to be a strange class name, especially because it doesn't just convert to p but also br. AutoLineBreak seems like a better name but I'm not sure how involving it would be to change this.
I assume there are a lot more of those below but you already started using it above so it should probably be consistent? And if we don't do it now then we'll have to do it later.
Noticed a $entity while skimming through the code which confused me for a moment. Nothing wrong with it obviously :)
:)
I assume this function is used in other places as well?
I know this was done in other places as well but having the interface within the plugin directory still seems a bit weird. Among other things, it is now in the middle of actual implementations, so while reading through the patch, there's a mix of plugins, the interface and base class.
Makes sense but somewhat off-topic :)
Hm, shouldn't be necessary, assertTrue is essentially a assert((bool) $value), so will be exactly the same?
I think the that needs a docblock according to our current standards (don't ask me why getInfo() doesn't need one but this does...)
Wondering if that should be the default implementation :) Or is it already?
We should be careful with making large patches even larger with such conversions but double-yay for converting standard web tests to dubt ;)
I think there's a $this->installConfig() now?
Why is this changed from explicit calls to a loop here? EDIT: The other way round I mean obviously.
Is this moved to another class?
Comment #95
tim.plunkettPretending that each dreditor block is numbered:
1) Fixed
2) This was changed by sun.
3) I think it means use it inside the function. Otherwise it would be @deprecated, not @todo
4) Fixed
5) :)
6) sun added the @todo, I'm not worried about it either way
7) Incorporated part of #1987298: Shorten directory structure and PSR-0 namespacing for plugins here and made the switch, this will need a reroll once that is in
8) Fixed :)
9) If we want to rename these, we can in a follow-up, but I'm okay with matching the pre-existing name for now.
10) Fixed
11) Heh
12) @todo
13) Yes, _filter_htmlcorrector is used in many other places
14) Moved down to \Drupal\filter\Plugin
15) I defer to sun
16) Actually, this is just for debugging sanity, in some cases it was an object, and not casting it to a bool meant it was var_dump'd for the assertion message, which hit recursive nesting
17) Fixed
18) Since this is the whole reason to implement a filter, I'd prefer it not have a default. Then OO will kick in and remind you to implement it
19) *points at sun*
20) Fixed
21) Yeah, the Filter maintainer made this change.
22) See #1235062: text_summary() ignores filter status. Sun asked to not require this to be split out.
23) Apparently it is unneeded, see ^
Comment #97
BerdirJust installConfig(array('text')).
That should fix the first fail, the second is a random one, there's an issue for it.
Comment #98
tim.plunkettlol, whoops.
Comment #99
BerdirI guess this needs a re-roll now after the plugin directory change?
Looks good to me otherwise.
Comment #100
tim.plunkettComment #101
BerdirWas about to RTBC this yesterday but then noticed that there are still ~8 @todo. class docblocks in there which should be fixed.
Comment #102
tim.plunkettFinally. Sorry.
Comment #103
BerdirGreat. Thank you.
I've reviewed this a few times and while I'm not a filter.module nor plugin system maintainer, the sole filter.module maintainer worked quite a bit of this and I've RTBC'd a few plugin conversion issues and so far the world hasn't ended ;)
So...
Comment #104
tim.plunkett#102: filter-1868772-102.patch queued for re-testing.
Comment #105
alexpottCommitted 9f57b6f and pushed to 8.x. Thanks!
Lets get a followup to add document the variables...
Comment #106
tim.plunkettThanks! Opened #2001006: Document the Filter annotation class
Comment #107
tim.plunkettSeems like writing change notices is the cool thing to do today. I'll work on this.
Comment #108
tim.plunkettOkay, posted https://drupal.org/node/2015901
Comment #109
BerdirLooks good to me!
Comment #111
yukare CreditAttribution: yukare commentedA question about this: what we do with filters that are no files/classes? I am working with the module customfilter(porting it do d8) but now if must be a real file for the filter there is not a way to this module and other like this works.
Comment #112
BerdirAs soon as the filter plugin manager is converted to extend from the default plugin manager, you can use derivatives for this. This means you add one class (which you need anyway to actually do things), specify a derivative class which basically exposes that same class as many times as you want.
See #2039521: Convert FilterPluginManager to extend DefaultPluginManager and MenuBlock and similar block plugins for an example.
Comment #112.0
BerdirUpdated issue summary