Feature: Project filter selections have a URL
Description
The filter, sorting and active state form of both project list plugins submits by POST, and a filtered list used to be the answer to that POST: it had no URL of its own. It could not be bookmarked or shared, a reload asked to send the form again, and no link rendered inside the list could carry the selection.
Both plugins now answer the submission with a 303 See Other to the same page
and plugin, carrying the selection as GET arguments:
?tx_academicprojects_projectlist[action]=list
&tx_academicprojects_projectlist[controller]=Project
&tx_academicprojects_projectlist[demand][activeState]=completed
&tx_academicprojects_projectlist[demand][filterCollection][categories]=3,6
&tx_academicprojects_projectlist[demand][sortingDirection]=asc
&tx_academicprojects_projectlist[demand][sortingField]=title
&cHash=…
- The URL is built from what the plugin accepted, not from the request: a
category of another group, a uid no category has, an active state the list
does not offer and the referrer and request hash fields of the form never
appear in it; an unknown active state becomes
all. - The categories of every category type are one comma separated list, in ascending order, so one selection has exactly one URL.
- The sorting and the active state are always part of the URL. The content element's preset categories, sorting and active state apply only to the page URL without any list argument, so a visitor who clears a preset category keeps it cleared.
- A GET request with those arguments renders the list exactly as the POST did before, and the form shows the selection again.
- The selection is read from the submitted form alone. A form that posts to the URL of a filtered list replaces its selection rather than adding to it, and a POST carrying no demand of the plugin - another plugin's form on the page - is not redirected.
Nothing changes in the templates, so overridden filter templates keep working as long as they submit fields the demand knows: the redirect carries the selection the plugin accepted and nothing else. A field a project adds to its filter partial, read by a listener from the request, is lost on the redirect. The list action stays non-cacheable, and the demand is not part of the cache hash, so every filter URL of a list shares one page cache entry, see Important: The list demand is not part of the cache hash.
Impact
- A filter or sorting submission answers
303instead of200. Browsers andfetchfollow it by default; JavaScript that posts the form and reads the HTML of the response itself has to follow the redirect. The redirect target carries the plugin's own arguments only: a page type, arguments of other plugins and campaign parameters of the submitted URL are not kept, so a form posted to a page type endpoint lands on the full page.() - A project that added its own redirect after a POST, in a subclass of the
controller, can drop it together with the subclass, which no longer loads
in 3.0, see Breaking: The project controller is final. The URLs that redirect produced
change their
c, see Important: The list demand is not part of the cache hash.Hash - A route enhancer for these plugins must not declare
defaultsfor the sorting: a default is left out of a generated path, so the redirect for the default sorting would end on the page URL without arguments, where the preset applies again.