Skip to content

Fix URL parameter type for filter rules without frontend filter widget - #1585

Merged
zonky2 merged 3 commits into
hotfix/2.4.25from
hotfix/fix_slugget_parameter_detail_page
Aug 6, 2026
Merged

Fix URL parameter type for filter rules without frontend filter widget#1585
zonky2 merged 3 commits into
hotfix/2.4.25from
hotfix/fix_slugget_parameter_detail_page

Conversation

@zonky2

@zonky2 zonky2 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

The URL parameter type ("URL type for the parameter") introduced with #1558 and fixed up in #1563 was only honoured for filter rules that render a frontend filter widget. ListControllerTrait::getFilterParameters() obtained the type from getParameterFilterWidgets(), which returns nothing for rules without widget - the usual detail page rules. Those parameters fell back to "slugNget" and were accepted as slug as well as GET, no matter what was configured.

The type is now obtained from the filter settings themselves:

  • Simple::getParameterTypes() reports the configured param_type for all parameters of a setting, WithChildren and ExpressionRule merge the types of their children and Collection::getParameterTypes() aggregates all settings of the collection.
  • ParameterTypes::fromSetting() provides the backwards compatibility layer for filter settings not implementing getParameterTypes(). They are treated as "slugNget" and trigger a deprecation. The method becomes part of ISimple in MetaModels 3.0 - adding it now would break implementations not extending Simple.

Render\Setting\Collection::buildJumpToUrlFor() builds the jumpTo URL of the detail page as slug or as GET according to the configured type - it always used slug before, so a rule configured as GET produced links that did not match its own configuration.

A parameter passed via another type than the configured one now results in a 404 instead of silently rendering the unfiltered list under an URL that looks like it is filtered. This is limited to rules without frontend filter widget; for widgets the frontend filter handles the URL (see #1563) and a value of the wrong type stays unused as before.

As a side effect the expensive getParameterFilterWidgets() call is gone from the regular rendering path. It is only performed when a mismatch was detected, that is on the path ending in a 404 anyway.

The URL parameter type ("URL type for the parameter") introduced with #1558 and
fixed up in #1563 was only honoured for filter rules that render a frontend filter
widget. ListControllerTrait::getFilterParameters() obtained the type from
getParameterFilterWidgets(), which returns nothing for rules without widget - the
usual detail page rules. Those parameters fell back to "slugNget" and were accepted
as slug as well as GET, no matter what was configured.

The type is now obtained from the filter settings themselves:

* Simple::getParameterTypes() reports the configured param_type for all parameters
  of a setting, WithChildren and ExpressionRule merge the types of their children
  and Collection::getParameterTypes() aggregates all settings of the collection.
* ParameterTypes::fromSetting() provides the backwards compatibility layer for
  filter settings not implementing getParameterTypes(). They are treated as
  "slugNget" and trigger a deprecation. The method becomes part of ISimple in
  MetaModels 3.0 - adding it now would break implementations not extending Simple.

Render\Setting\Collection::buildJumpToUrlFor() builds the jumpTo URL of the detail
page as slug or as GET according to the configured type - it always used slug
before, so a rule configured as GET produced links that did not match its own
configuration.

A parameter passed via another type than the configured one now results in a 404
instead of silently rendering the unfiltered list under an URL that looks like it
is filtered. This is limited to rules without frontend filter widget; for widgets
the frontend filter handles the URL (see #1563) and a value of the wrong type stays
unused as before.

As a side effect the expensive getParameterFilterWidgets() call is gone from the
regular rendering path. It is only performed when a mismatch was detected, that is
on the path ending in a 404 anyway.
@zonky2
zonky2 requested a review from discordier August 4, 2026 17:58
@zonky2 zonky2 self-assigned this Aug 4, 2026
@zonky2 zonky2 added this to the 2.4.x milestone Aug 4, 2026
zonky2 added 2 commits August 6, 2026 10:37
Adding a method to ICollection - like to any other interface - is a BC break and has
to wait for the next major release. ICollection therefore keeps its previous method
list and both, ICollection and ISimple, announce getParameterTypes() via a "@method"
annotation plus a note that not implementing it is deprecated. The backwards
compatibility layer ParameterTypes::fromSetting() now takes collections as well, so
implementations not providing the method keep working and are treated as "slugNget".

A filter parameter passed via another URL type than the configured one no longer
results in a 404. The value is not read and the parameter stays unused, just like any
other unknown parameter - the 404 was too harsh for a mistyped or outdated URL. As the
outcome no longer differs between rules with and without frontend filter widget, the
special casing of widgets and its additional getParameterFilterWidgets() call are gone
again, together with the tests of the removed guard.
A get-only filter parameter accessed via slug resulted in a PageNotFoundException
(#1563). This is too harsh for a mistyped or outdated URL and it is no longer in line
with the list controllers, which ignore a value passed via the wrong URL type.

The value was never used for filtering anyway: buildParameters() routes a slug that is
not wanted as slug into the "other" parameters, so it never becomes part of the widget
values. Only the exception is gone therefore.

To not have the 404 come back in through the back door, all wanted parameter names are
now marked as used in the Input class. Previously this was only done for the ones
present as slug in the "all" parameters, so a get-only parameter passed via slug stayed
unconsumed and Contao raised an UnusedArgumentsException - a 404 as well - whenever no
list on the same page marked it.
@zonky2
zonky2 force-pushed the hotfix/fix_slugget_parameter_detail_page branch from aafa30c to d8cc677 Compare August 6, 2026 08:56
@zonky2
zonky2 merged commit a58f2aa into hotfix/2.4.25 Aug 6, 2026
8 checks passed
@zonky2
zonky2 deleted the hotfix/fix_slugget_parameter_detail_page branch August 6, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant