mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 08:04:03 +00:00
* Make universal route logic part of tbe early ID trait * Add requstHasTenant to prevent access MW, add todo@samuel * Delete PathIdentificationManager, move the used methods appropriately * Correct and refactor code related to the deleted PathIdentificationManager class * Add docblock * Fix code style (php-cs-fixer) * refactor globalStackMiddleware() * remove todos [ci skip] * refactor routeMiddleware() * revert bool assertions * revert more changes --------- Co-authored-by: PHP CS Fixer <phpcsfixer@example.com> Co-authored-by: Samuel Štancl <samuel@archte.ch>
123 lines
4.7 KiB
PHP
123 lines
4.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Stancl\Tenancy\Overrides;
|
||
|
||
use Illuminate\Routing\UrlGenerator;
|
||
use Illuminate\Support\Arr;
|
||
use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
||
|
||
/**
|
||
* This class is used in place of the default UrlGenerator when UrlGeneratorBootstrapper is enabled.
|
||
*
|
||
* TenancyUrlGenerator does two extra things:
|
||
* 1. Autofill the {tenant} parameter in the tenant context with the current tenant if $passTenantParameterToRoutes is enabled (enabled by default)
|
||
* 2. Prepend the route name with `tenant.` (or the configured prefix) if $prefixRouteNames is enabled (disabled by default)
|
||
*
|
||
* Both of these can be skipped by passing the $bypassParameter (`['central' => true]` by default)
|
||
*/
|
||
class TenancyUrlGenerator extends UrlGenerator
|
||
{
|
||
/**
|
||
* Parameter which bypasses the behavior modification of route() and temporarySignedRoute().
|
||
*
|
||
* E.g. route('tenant') => app.test/{tenant}/tenant (or app.test/tenant?tenant=tenantKey if the route doesn't accept the tenant parameter)
|
||
* route('tenant', [$bypassParameter => true]) => app.test/tenant.
|
||
*/
|
||
public static string $bypassParameter = 'central';
|
||
|
||
/**
|
||
* Determine if the route names passed to `route()` or `temporarySignedRoute()`
|
||
* should get prefixed with the tenant route name prefix.
|
||
*
|
||
* This is useful when using path identification with packages that generate URLs,
|
||
* like Jetstream, so that you don't have to manually prefix route names passed to each route() call.
|
||
*/
|
||
public static bool $prefixRouteNames = false;
|
||
|
||
/**
|
||
* Determine if the tenant parameter should get passed
|
||
* to the links generated by `route()` or `temporarySignedRoute()` whenever available
|
||
* (enabled by default – works with both path and query string identification).
|
||
*
|
||
* With path identification, you can disable this and use URL::defaults() instead (as an alternative solution).
|
||
*/
|
||
public static bool $passTenantParameterToRoutes = true;
|
||
|
||
/**
|
||
* Override the route() method so that the route name gets prefixed
|
||
* and the tenant parameter gets added when in tenant context.
|
||
*/
|
||
public function route($name, $parameters = [], $absolute = true)
|
||
{
|
||
[$name, $parameters] = $this->prepareRouteInputs($name, Arr::wrap($parameters));
|
||
|
||
return parent::route($name, $parameters, $absolute);
|
||
}
|
||
|
||
/**
|
||
* Override the temporarySignedRoute() method so that the route name gets prefixed
|
||
* and the tenant parameter gets added when in tenant context.
|
||
*/
|
||
public function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true)
|
||
{
|
||
[$name, $parameters] = $this->prepareRouteInputs($name, Arr::wrap($parameters));
|
||
|
||
return parent::temporarySignedRoute($name, $expiration, $parameters, $absolute);
|
||
}
|
||
|
||
/**
|
||
* Return bool indicating if the bypass parameter was in $parameters.
|
||
*/
|
||
protected function routeBehaviorModificationBypassed(mixed $parameters): bool
|
||
{
|
||
if (isset($parameters[static::$bypassParameter])) {
|
||
return (bool) $parameters[static::$bypassParameter];
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Takes a route name and an array of parameters to return the prefixed route name
|
||
* and the route parameters with the tenant parameter added.
|
||
*
|
||
* To skip these modifications, pass the bypass parameter in route parameters.
|
||
* Before returning the modified route inputs, the bypass parameter is removed from the parameters.
|
||
*/
|
||
protected function prepareRouteInputs(string $name, array $parameters): array
|
||
{
|
||
if (! $this->routeBehaviorModificationBypassed($parameters)) {
|
||
$name = $this->prefixRouteName($name);
|
||
$parameters = $this->addTenantParameter($parameters);
|
||
}
|
||
|
||
// Remove bypass parameter from the route parameters
|
||
unset($parameters[static::$bypassParameter]);
|
||
|
||
return [$name, $parameters];
|
||
}
|
||
|
||
/**
|
||
* If $prefixRouteNames is true, prefix the passed route name.
|
||
*/
|
||
protected function prefixRouteName(string $name): string
|
||
{
|
||
$tenantPrefix = PathTenantResolver::tenantRouteNamePrefix();
|
||
|
||
if (static::$prefixRouteNames && ! str($name)->startsWith($tenantPrefix)) {
|
||
$name = str($name)->after($tenantPrefix)->prepend($tenantPrefix)->toString();
|
||
}
|
||
|
||
return $name;
|
||
}
|
||
|
||
/**
|
||
* If `tenant()` isn't null, add tenant paramter to the passed parameters.
|
||
*/
|
||
protected function addTenantParameter(array $parameters): array
|
||
{
|
||
return tenant() && static::$passTenantParameterToRoutes ? array_merge($parameters, [PathTenantResolver::tenantParameterName() => tenant()->getTenantKey()]) : $parameters;
|
||
}
|
||
}
|