Slugless canonical for singletons + clean listing canonical#3735
Open
Vondry wants to merge 2 commits into
Open
Slugless canonical for singletons + clean listing canonical#3735Vondry wants to merge 2 commits into
Vondry wants to merge 2 commits into
Conversation
…ing query params
Singletons are served at their slugless listing URL (ListingController
forwards a singleton listing to the record), but getCanonicalRouteAndParams
returned the record-detail route, exposing two URLs for identical content
(/{singularSlug} and /{singularSlug}/{slug}). Canonicalize singletons to the
slugless /{singularSlug} URL instead.
Also stop merging listing query params (order/status/filters) into the
listing canonical, where they appeared as ?order=-createdAt&status=published.
… canonical Unit tests for ContentHelper canonical route resolution: - singleton -> slugless listing route (no slugOrId) - non-singleton -> record route with slug (regression guard) - homepage singleton -> homepage route, not listing (precedence) - non-Content input is ignored Functional tests: - listing canonical omits volatile query params (order/status/filters) - a singleton's slugged record URL canonicalizes to its slugless URL, and the slugless URL is self-referential (end-to-end) Support changes: - add an 'about' non-homepage singleton to the test-scaffolding content types so the end-to-end singleton test has a record to exercise - ContentTypesParserTest: demo content-type count 9 -> 10, assert 'about' key - phpunit.xml.dist: set BOLT_CANONICAL so the Canonical service bootstraps in the test environment (otherwise it fatals on an empty value)
ed159a1 to
f966cb9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A singleton content type ends up with two indexable URLs serving identical content, and the on-page canonical points at the "ugly" one:
ListingControllerforwards a singleton "listing" to the record), e.g./about.ContentHelper::getCanonicalRouteAndParams()returns the record-detail route, so the<link rel="canonical">becomes/about/{slug}— where{slug}is an auto-generated record slug (e.g.about-2) that carries no meaning for a one-record type.Separately, listing canonicals leak volatile query params:
ListingControllermerges the parsed query params (order,status, filters) into the canonical, producing URLs like/showcases?order=-createdAt&status=published.Fix
/{singularSlug}) instead of the record-detail route. The homepage (also a singleton) keeps resolving to the homepage route — its early-return precedence is preserved.Because
getLink()(record|link) andsetCanonicalPath()sharegetCanonicalRouteAndParams(), internal links and the canonical tag now agree for singletons.Changes
src/Utils/ContentHelper.php— add a singleton branch togetCanonicalRouteAndParams().src/Controller/Frontend/ListingController.php— stop merging query params into the listing canonical.Tests
tests/php/Utils/ContentHelperTest.php): singleton → slugless listing route (noslugOrId); non-singleton → record route + slug (regression guard); homepage singleton → homepage route,not listing; non-
Contentinput ignored.tests/php/Controller/Frontend/ListingCanonicalTest.php): a listing canonical omits query params.tests/php/Controller/Frontend/SingletonCanonicalTest.php): a singleton's slugged record URL canonicalizes to its slugless URL, and the slugless URL is self-referential.Each test was mutation-verified — it fails when its corresponding fix is reverted.
Supporting test changes
config/bolt/contenttypes.yaml— add anaboutnon-homepage singleton to the test-scaffolding content types so the end-to-end test has a record to exercise (the only existing singleton,homepage, is special-cased).tests/php/Configuration/Parser/ContentTypesParserTest.php— demo content-type count 9 → 10, assert theaboutkey.phpunit.xml.dist— setBOLT_CANONICALso theCanonicalservice bootstraps in the test environment (it otherwise fatals on the empty default value).Test screenshots
1. Homepage singleton test case (This already works -> nothing changes)
2. Contact page singleton test cases (This did not work -> now works as homepage singleton)
Notes
RelationFactoryTestis occasionally flaky due to unseeded Faker fixtures; unrelated to this change.