Skip to content

[4.x] TenancyUrlGenerator: override toRoute()#1439

Open
lukinovec wants to merge 7 commits intomasterfrom
override-toroute
Open

[4.x] TenancyUrlGenerator: override toRoute()#1439
lukinovec wants to merge 7 commits intomasterfrom
override-toroute

Conversation

@lukinovec
Copy link
Copy Markdown
Contributor

@lukinovec lukinovec commented Mar 9, 2026

This PR adds the toRoute() method override to TenancyUrlGenerator. toRoute() now attempts to find a tenant equivalent of the passed route (= a route with the same name as the passed one, but with the tenant prefix) and generates URL for the tenant route. This behavior can be bypassed using the bypass parameter, like with the route() method override TenancyUrlGenerator had until now.

The primary reason for adding this is that Livewire v4 no longer uses the route() helper (which automatically prefixes the passed route name because of the override in TenancyUrlGenerator) in Livewire::getUpdateUri(). Now, it uses toRoute() (livewire/livewire@544aa3d#diff-e7609f8b0a60bde5a85067803d4e2f08f235c7cee9225a51ea67a85ff9a1d694R52), which didn't automatically swap the route for its 'tenant.'-prefixed equivalent in tenant context. So for the Livewire integration to work with path identification, we need to override toRoute() as described.

The temporarySignedRoute() override got removed because temporarySignedRoute() calls route() under the hood, there's no need to specifically override temporarySignedRoute().

Note: Browsing old convos, it seems like the temporarySignedRoute() override was needed to make Livewire file uploads work with path identification, but it's not needed anymore. TenancyUrlGenerator had some changes since then, and now, I can't see the exact reason why we needed the override (temporarySignedRoute() uses route() under the hood, so the only thing that should really matter is overriding route()/toRoute()). It was likely a leftover from some older implementation.

The route() override got simplified. Since route() uses toRoute() under the hood, the route() override only has to have the prefixing logic. The rest gets delegated to toRoute().

Note: Even though we override toRoute() now which route() uses for generating the URLs, we still need to override route() for its $this->routes->getByName($name) call to receive the prefixed name. For example, if route() wasn't overridden, and we only had one route: tenant.foo (no central foo route), and we'd call route('foo'), we'd get an exception saying that route "foo" wasn't found, even if automatic route name prefixing was on and toRoute() was overridden. With the route() override, route('foo') acts as if we passed 'tenant.foo' instead of 'foo'.

Comments in TenancyUrlGenerator and UrlGeneratorBootstrapper got updated to be more accurate. All intentionally affected methods are listed in TenancyUrlGenerator's docblock.

Summary by CodeRabbit

  • Improvements

    • Route-name prefixing and tenant-parameter injection now apply consistently across additional URL-generation entry points; bypass handling is generalized to skip these behaviors when requested.
  • Documentation

    • Clarified docblock wording to more clearly state how tenant parameters are included in generated links.
  • Tests

    • Added tests validating prefixed-route selection, tenant-parameter injection, and bypass behavior.

Also update `route()` override since `parent::route()` calls `toRoute()` under the hood (similarly to how `parent::temporarySignedRoute()` calls `route()`)
@lukinovec lukinovec marked this pull request as ready for review March 9, 2026 12:39
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.06%. Comparing base (c32f52c) to head (61bf6dc).

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1439      +/-   ##
============================================
+ Coverage     86.03%   86.06%   +0.02%     
- Complexity     1156     1157       +1     
============================================
  Files           184      184              
  Lines          3381     3380       -1     
============================================
  Hits           2909     2909              
+ Misses          472      471       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

lukinovec and others added 3 commits March 10, 2026 12:17
The `toRoute()` and `route()` overrides cover `temporarySignedRoute())`, so we don't need to specifically override `temporarySIgnedRoute()` anymore. `route()` override got simplified since everything except for the name prefixing is delegated to the lower-level `toRoute()` method.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c03bc5b9-9ea5-4b39-8ff3-a662d3de99ce

📥 Commits

Reviewing files that changed from the base of the PR and between 60dd522 and bff74c8.

📒 Files selected for processing (3)
  • src/Bootstrappers/UrlGeneratorBootstrapper.php
  • src/Overrides/TenancyUrlGenerator.php
  • tests/Bootstrappers/UrlGeneratorBootstrapperTest.php

📝 Walkthrough

Walkthrough

Centralized route-name prefixing and tenant-parameter handling by introducing a toRoute() override; route() now normalizes input and delegates parameter preparation. Docblock wording adjusted; new tests validate url()->toRoute() prefixing and bypass/tenant-parameter behavior. No runtime API signatures were widened.

Changes

Cohort / File(s) Summary
Bootstrapper docblock
src/Bootstrappers/UrlGeneratorBootstrapper.php
Docblock reworded to clarify that the tenant parameter (from PathTenantResolver::tenantParameterName()) is passed to links produced by URL-generation methods. No executable code changed.
URL generator core
src/Overrides/TenancyUrlGenerator.php
Reworked route handling: removed temporarySignedRoute() public override and added toRoute($route, $parameters, $absolute). route() now validates/normalizes names (e.g., backed enums) and delegates to prepareRouteInputs(); toRoute() derives/possibly swaps in a tenant-prefixed route name before calling parent::toRoute(). prepareRouteInputs() was generalized to accept an optional route name and always perform tenant-parameter injection and bypass-parameter removal, while applying name prefixing only when a name is provided.
Tests
tests/Bootstrappers/UrlGeneratorBootstrapperTest.php
Added Pest tests covering url()->toRoute() behavior: tenant-prefixed route name selection when $prefixRouteNames = true, bypass parameter preventing prefixing, tenant query-parameter injection for unnamed routes when enabled, and bypass preventing tenant-parameter addition.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hop between routes, soft and spry,
I tuck the tenant where queries lie,
toRoute() leads the nimble chase,
Prefixes find their proper place,
A rabbit’s grin trails links nearby.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[4.x] TenancyUrlGenerator: override toRoute()' directly and clearly describes the main change: adding a toRoute() override to TenancyUrlGenerator, which aligns with the PR's primary objective and file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch override-toroute

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Overrides/TenancyUrlGenerator.php`:
- Around line 141-149: The parameter mutation is skipped for unnamed Route
objects because $route->getName() gates the call to prepareRouteInputs; change
the logic in TenancyUrlGenerator::toRoute so you always call
$this->prepareRouteInputs($name, Arr::wrap($parameters)) (or call it with
null/$name when route has no name) to apply tenant-parameter injection and
bypass-parameter removal, but keep the route swap conditional: only replace
$route when $prefixedName !== $name and $this->routes->getByName($prefixedName)
returns a route; ensure prepareRouteInputs and the passTenantParameterToRoutes
behavior run even when $route->getName() is falsy before delegating to
parent::toRoute().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 17d8031d-e2be-43de-9b4c-44e8b71136d2

📥 Commits

Reviewing files that changed from the base of the PR and between 60dd522 and dc2be5b.

📒 Files selected for processing (3)
  • src/Bootstrappers/UrlGeneratorBootstrapper.php
  • src/Overrides/TenancyUrlGenerator.php
  • tests/Bootstrappers/UrlGeneratorBootstrapperTest.php

Comment thread src/Overrides/TenancyUrlGenerator.php
If an unnamed route is passed to url()->toRoute(), the generated URL will receive the tenant parameter as long as the bypass parameter wasn't passed. Also remove the bypass parameter from the generated URL.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Overrides/TenancyUrlGenerator.php`:
- Around line 128-130: The route() method currently calls prepareRouteInputs()
and discards the mutated $parameters, causing duplicate work and potential side
effects; create a small helper (e.g., normalizeRouteName or prepareRouteName) in
the TenancyUrlGenerator class that performs only the name normalization logic
extracted from prepareRouteInputs() and returns the normalized $name without
mutating $parameters, then update route() to call that helper and pass the
original $parameters into parent::route($name, $parameters, $absolute); keep
prepareRouteInputs() and toRoute() unchanged so full parameter resolution still
happens only when needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1ef2ed10-fc71-412c-80f0-c96ee9ac799c

📥 Commits

Reviewing files that changed from the base of the PR and between dc2be5b and bff74c8.

📒 Files selected for processing (2)
  • src/Overrides/TenancyUrlGenerator.php
  • tests/Bootstrappers/UrlGeneratorBootstrapperTest.php

Comment thread src/Overrides/TenancyUrlGenerator.php
@lukinovec
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

✅ Actions performed

Full review triggered.

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.

2 participants