- Status changed to Postponed: needs info
9 days ago 9:03am 4 April 2025
Views is not consistent between its code, schema, and APIs. Tests confirm what it does, not what it should do.
This issue was created to elaborate on the bug and its solution. Patches were applied to the related issue 2976616 which narrowly focuses on what turns out to be a much bigger problem. Rather than rewrite its issue summary, this issue was added.
Note: Filtering the drupal project issues to search for 'schema' in bug reports on views.module in version 9.* reveals a few issues with problems in the same namespace but of a much narrower scope. Most have been idle for 4+ years. To my knowledge, none proposes what is contained herein other than issue 2836390 proposes to change the stored plugin_id in config.
This bug surfaced while testing aggregation on a view with fields. The config of such a view always fails schema checks because views code:
and the schema.yml says:
so the config items added by 'field' are not included in 'numeric' and vice versa; hence the schema conflicts.
From the views UI, the config changes only occur if the field handler is edited and the view saved. For example, turn on aggregation for the view and save the view. The config items on the fields in the view are not changed (they continue to use 'group together' for aggregation). Edit one of them and save the view. Now the field config includes the items from the 'numeric' field (and the default 'field') handler.
The straightforward solution (used in patches on issue 2976616) was to:
HandlerBase::defineOptions()
methodThis fixed the immediate problem but exposed a host of config, code, and test issues in views.
First, to store only the config items applicable to the handler meant changing the last parameter in the function call to unpackOptions()
in PluginBase::init().
- $this->unpackOptions($this->options, $options);
+ $this->unpackOptions($this->options, $options, $definition, FALSE);
The last parameter (the undocumented $all parameter) is what allows views to accept and retain any options in the handler config (e.g. from import) and never prune those options that do not apply to the handler. For example, one could make up options and add them to a view export, then import the view, and views would retain the bogus items in persistent config (database and export). All because of having $all = TRUE. Changing $all to FALSE prunes the unwanted config items after the handler is edited and the view is saved.
But this change to $all also exposes a lot of errors in code and tests (both assertions and the views being tested).
PluginBase::init()
calls $this->defineOptions() to gather the options applicable to the handler. These methods in EntityField (the class behind the 'field' handler), FieldPluginBase, HandlerBase, and PluginBase essentially duplicate the contents of the schema.yml files. Well, they are supposed to duplicate if there are to be no schema conflicts, but they do not and there are. Examples are:
views/argument/ManyToOne conditionally defines 'break_phrase' yet it should always be present.
views/field/FieldPluginBase
Interestingly, the addition of 'plugin_id' to HandlerBase::defineOptions()
[NOT the reorder in 'views_handler' data type in views.data_types.schema.yml] led to some major test failures. After a view is loaded and the displays are initialized, the plugin_id key is now first in line in the options array of each handler. Some of the tests save the view after initialization and compare it to the original. The tests utilize some rather robust code that checks array identity (the '===' operator) and fails (if I understand this correctly) because the order of keys differ in the input and output. (Note: switching the order in the respective views.yml files made the tests pass.) The output 'plugin_id' key is first on each handler item as opposed to some other position. The 'plugin_id' key had been declared in 5 of the 6 handlers: views_field, views_filter, views_sort, views_area, and views_argument; but not in views_relationship. It is also defined in their common parent, views_handler. This in itself is bad form. To 'fix' the tests necessitated moving the plugin_id key to first place in each view used in tests (which includes all the default views declared in a module config/optional directory).
Several of the test views have incorrect values (yet the tests would pass):
views.view.test_field_get_entity.yml has incorrect values for:
which should be:
views.view.test_display_defaults.yml omits plugin_id: standard
views.view.test_{un,}group_rows.yml includes a field that does not exist
See the patches on the aforementioned issue if you are curious.
Described in detail above. To recap:
None. Tests are updated in the patch on issue 2976616.
None.
None.
None. (Unless you consider bug fixes a model change.)
Not applicable.
Needs review
10.1 β¨
Last updated
Used to track the progress of issues reviewed by the Drupal Needs Review Queue Initiative.
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.