1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 18:44:03 +00:00

[4.x] Improve RootUrl and UrlGenerator bootstrappers (#1294)

* Make RootUrlBootstrapper run ONLY in CLI by default (add $rootUrlOverrideInTests), work with resolved UrlGenerator

* Make resolving 'url' return a pre-created generator instance instead of creating it on every app('url') call

* Take care of doubling tenant keys in TenancyUrlGenerator, add regression test for using UrlGenerator and RootUrl bootstrappers together

* Fix code style (php-cs-fixer)

* refactor RootUrlBootstrapper

* add docblock

* clarify docblock

* simplify test: use concrete values instead of overly dynamic code

* Fix bootstrapper order in test, add url('/') assertion

* Use $this->app instead of app()

* Improve TenancyUrlGenerator and RootUrlBootstrapperTest clarity

* Revert attempt to maintain compatibility between the two bootstrappers

* Delete bootstrapper combining test

* Fix code style (php-cs-fixer)

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
This commit is contained in:
Samuel Štancl 2025-01-16 10:30:06 +01:00 committed by GitHub
parent 8f958d5779
commit 5d3b3d3c21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 28 deletions

View file

@ -7,7 +7,6 @@ namespace Stancl\Tenancy\Bootstrappers;
use Closure; use Closure;
use Illuminate\Config\Repository; use Illuminate\Config\Repository;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Routing\UrlGenerator;
use Stancl\Tenancy\Contracts\TenancyBootstrapper; use Stancl\Tenancy\Contracts\TenancyBootstrapper;
use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Contracts\Tenant;
@ -36,28 +35,46 @@ class RootUrlBootstrapper implements TenancyBootstrapper
protected string|null $originalRootUrl = null; protected string|null $originalRootUrl = null;
/**
* You may want to selectively enable or disable this bootstrapper in specific tests.
* For instance, when using `Livewire::test()` this bootstrapper can cause problems,
* due to an internal Livewire route, so you may want to disable it, while in tests
* that are generating URLs in things like mails, the bootstrapper should be used
* just like in any queued job.
*/
public static bool $rootUrlOverrideInTests = false;
public function __construct( public function __construct(
protected UrlGenerator $urlGenerator,
protected Repository $config, protected Repository $config,
protected Application $app, protected Application $app,
) {} ) {}
public function bootstrap(Tenant $tenant): void public function bootstrap(Tenant $tenant): void
{ {
if ($this->app->runningInConsole() && static::$rootUrlOverride) { if (static::$rootUrlOverride === null) {
$this->originalRootUrl = $this->urlGenerator->to('/'); return;
$newRootUrl = (static::$rootUrlOverride)($tenant, $this->originalRootUrl);
$this->urlGenerator->forceRootUrl($newRootUrl);
$this->config->set('app.url', $newRootUrl);
} }
if (! $this->app->runningInConsole()) {
return;
}
if ($this->app->runningUnitTests() && ! static::$rootUrlOverrideInTests) {
return;
}
$this->originalRootUrl = $this->app['url']->to('/');
$newRootUrl = (static::$rootUrlOverride)($tenant, $this->originalRootUrl);
$this->app['url']->forceRootUrl($newRootUrl);
$this->config->set('app.url', $newRootUrl);
} }
public function revert(): void public function revert(): void
{ {
if ($this->originalRootUrl) { if ($this->originalRootUrl) {
$this->urlGenerator->forceRootUrl($this->originalRootUrl); $this->app['url']->forceRootUrl($this->originalRootUrl);
$this->config->set('app.url', $this->originalRootUrl); $this->config->set('app.url', $this->originalRootUrl);
} }
} }

View file

@ -37,7 +37,7 @@ class UrlGeneratorBootstrapper implements TenancyBootstrapper
public function revert(): void public function revert(): void
{ {
$this->app->bind('url', fn () => $this->originalUrlGenerator); $this->app->extend('url', fn () => $this->originalUrlGenerator);
} }
/** /**
@ -47,24 +47,22 @@ class UrlGeneratorBootstrapper implements TenancyBootstrapper
*/ */
protected function useTenancyUrlGenerator(): void protected function useTenancyUrlGenerator(): void
{ {
$this->app->extend('url', function (UrlGenerator $urlGenerator, Application $app) { $newGenerator = new TenancyUrlGenerator(
$newGenerator = new TenancyUrlGenerator( $this->app['router']->getRoutes(),
$app['router']->getRoutes(), $this->originalUrlGenerator->getRequest(),
$urlGenerator->getRequest(), $this->app['config']->get('app.asset_url'),
$app['config']->get('app.asset_url'), );
);
$newGenerator->defaults($urlGenerator->getDefaultParameters()); $newGenerator->defaults($this->originalUrlGenerator->getDefaultParameters());
$newGenerator->setSessionResolver(function () { $newGenerator->setSessionResolver(function () {
return $this->app['session'] ?? null; return $this->app['session'] ?? null;
});
$newGenerator->setKeyResolver(function () {
return $this->app->make('config')->get('app.key');
});
return $newGenerator;
}); });
$newGenerator->setKeyResolver(function () {
return $this->app->make('config')->get('app.key');
});
$this->app->extend('url', fn () => $newGenerator);
} }
} }

View file

@ -10,18 +10,23 @@ use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper; use Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain; use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain;
use Stancl\Tenancy\Bootstrappers\UrlGeneratorBootstrapper;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Stancl\Tenancy\Overrides\TenancyUrlGenerator;
beforeEach(function () { beforeEach(function () {
Event::listen(TenancyInitialized::class, BootstrapTenancy::class); Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
Event::listen(TenancyEnded::class, RevertToCentralContext::class); Event::listen(TenancyEnded::class, RevertToCentralContext::class);
RootUrlBootstrapper::$rootUrlOverride = null; RootUrlBootstrapper::$rootUrlOverride = null;
RootUrlBootstrapper::$rootUrlOverrideInTests = true;
}); });
afterEach(function () { afterEach(function () {
RootUrlBootstrapper::$rootUrlOverride = null; RootUrlBootstrapper::$rootUrlOverride = null;
RootUrlBootstrapper::$rootUrlOverrideInTests = false;
}); });
test('root url bootstrapper overrides the root url when tenancy gets initialized and reverts the url to the central one after tenancy ends', function() { test('root url bootstrapper overrides the root url when tenancy gets initialized and reverts the url to the central one when ending tenancy', function() {
config(['tenancy.bootstrappers' => [RootUrlBootstrapper::class]]); config(['tenancy.bootstrappers' => [RootUrlBootstrapper::class]]);
Route::group([ Route::group([