Skip to content

Commit 32e3b37

Browse files
Merge branch 'archtechx:3.x' into 3.x
2 parents 90272bc + d98a170 commit 32e3b37

File tree

10 files changed

+114
-19
lines changed

10 files changed

+114
-19
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ jobs:
1616
strategy:
1717
matrix:
1818
include:
19-
- laravel: 9
20-
php: "8.0"
2119
- laravel: 10
2220
php: "8.1"
2321
- laravel: 11
2422
php: "8.3"
23+
- laravel: 12
24+
php: "8.3"
25+
# Ideally we'd run at least one of these on PHP 8.4, however the Dockerfile seems to require some changes for that
2526

2627
steps:
2728
- uses: actions/checkout@v2

.github/workflows/queue.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Queue tests
2+
3+
on:
4+
- push
5+
6+
jobs:
7+
queue:
8+
name: Queue application tests
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Prepare composer version constraint prefix
12+
run: |
13+
if [[ $GITHUB_REF == refs/tags/* ]]; then
14+
# For refs like "refs/tags/v3.9.0", remove "refs/tags/v" prefix to get just "3.9.0"
15+
VERSION=${GITHUB_REF#refs/tags/v}
16+
echo "VERSION_PREFIX=${VERSION}" >> $GITHUB_ENV
17+
else
18+
BRANCH=${GITHUB_REF#refs/heads/}
19+
if [[ $BRANCH =~ ^[0-9]\.x$ ]]; then
20+
# Branches starting with %d.x need to use -dev suffix
21+
echo "VERSION_PREFIX=${BRANCH}-dev" >> $GITHUB_ENV
22+
else
23+
# All other branches use dev-${branch} prefix
24+
echo "VERSION_PREFIX=dev-${BRANCH}" >> $GITHUB_ENV
25+
fi
26+
fi
27+
28+
- name: Clone test suite
29+
run: git clone https://github.com/archtechx/tenancy-queue-tester
30+
31+
- name: Run tests
32+
run: |
33+
cd tenancy-queue-tester
34+
TENANCY_VERSION=${VERSION_PREFIX}#${GITHUB_SHA} ./setup.sh
35+
TENANCY_VERSION=${VERSION_PREFIX}#${GITHUB_SHA} ./test.sh

assets/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,6 @@
194194
*/
195195
'seeder_parameters' => [
196196
'--class' => 'DatabaseSeeder', // root seeder class
197-
// '--force' => true,
197+
// '--force' => true, // This needs to be true to seed tenant databases in production
198198
],
199199
];

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
"require": {
1313
"php": "^8.0",
1414
"ext-json": "*",
15-
"illuminate/support": "^9.0|^10.0|^11.0",
15+
"illuminate/support": "^10.0|^11.0|^12.0",
1616
"facade/ignition-contracts": "^1.0.2",
1717
"ramsey/uuid": "^4.7.3",
18-
"stancl/jobpipeline": "^1.6.2",
19-
"stancl/virtualcolumn": "^1.3.1"
18+
"stancl/jobpipeline": "^1.8.0",
19+
"stancl/virtualcolumn": "^1.5.0"
2020
},
2121
"require-dev": {
22-
"laravel/framework": "^9.0|^10.0|^11.0",
23-
"orchestra/testbench": "^7.0|^8.0|^9.0",
22+
"laravel/framework": "^10.0|^11.0|^12.0",
23+
"orchestra/testbench": "^8.0|^9.0|^10.0",
2424
"league/flysystem-aws-s3-v3": "^3.12.2",
2525
"doctrine/dbal": "^3.6.0",
2626
"spatie/valuestore": "^1.3.2"

src/Database/Concerns/InvalidatesResolverCache.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ trait InvalidatesResolverCache
1818

1919
public static function bootInvalidatesResolverCache()
2020
{
21-
static::saved(function (Tenant $tenant) {
21+
$invalidateCache = static function (Tenant $tenant) {
2222
foreach (static::$resolvers as $resolver) {
2323
/** @var CachedTenantResolver $resolver */
2424
$resolver = app($resolver);
2525

2626
$resolver->invalidateCache($tenant);
2727
}
28-
});
28+
};
29+
30+
static::saved($invalidateCache);
31+
static::deleting($invalidateCache);
2932
}
3033
}

src/Database/Concerns/InvalidatesTenantsResolverCache.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ trait InvalidatesTenantsResolverCache
2121

2222
public static function bootInvalidatesTenantsResolverCache()
2323
{
24-
static::saved(function (Model $model) {
24+
$invalidateCache = static function (Model $model) {
2525
foreach (static::$resolvers as $resolver) {
2626
/** @var CachedTenantResolver $resolver */
2727
$resolver = app($resolver);
2828

2929
$resolver->invalidateCache($model->tenant);
3030
}
31-
});
31+
};
32+
33+
static::saved($invalidateCache);
34+
static::deleting($invalidateCache);
3235
}
3336
}

src/Exceptions/ModelNotSyncMasterException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ class ModelNotSyncMasterException extends Exception
1010
{
1111
public function __construct(string $class)
1212
{
13-
parent::__construct("Model of $class class is not an SyncMaster model. Make sure you're using the central model to make changes to synced resources when you're in the central context");
13+
parent::__construct("Model of $class class is not a SyncMaster model. Make sure you're using the central model to make changes to synced resources when you're in the central context.");
1414
}
1515
}

src/Features/UserImpersonation.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class UserImpersonation implements Feature
1818

1919
public function bootstrap(Tenancy $tenancy): void
2020
{
21-
$tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, string $authGuard = null): ImpersonationToken {
21+
$tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, ?string $authGuard = null): ImpersonationToken {
2222
return ImpersonationToken::create([
2323
'tenant_id' => $tenant->getTenantKey(),
2424
'user_id' => $userId,
@@ -32,10 +32,10 @@ public function bootstrap(Tenancy $tenancy): void
3232
* Impersonate a user and get an HTTP redirect response.
3333
*
3434
* @param string|ImpersonationToken $token
35-
* @param int $ttl
35+
* @param int|null $ttl
3636
* @return RedirectResponse
3737
*/
38-
public static function makeResponse($token, int $ttl = null): RedirectResponse
38+
public static function makeResponse($token, ?int $ttl = null): RedirectResponse
3939
{
4040
$token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token);
4141

src/Middleware/InitializeTenancyByPath.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ public function handle(Request $request, Closure $next)
4040
return $this->initializeTenancy(
4141
$request, $next, $route
4242
);
43-
} else {
44-
throw new RouteIsMissingTenantParameterException;
4543
}
4644

47-
return $next($request);
45+
throw new RouteIsMissingTenantParameterException;
4846
}
4947
}

tests/CachedTenantResolverTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Stancl\Tenancy\Tests;
66

77
use Illuminate\Support\Facades\DB;
8+
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
89
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
910
use Stancl\Tenancy\Tests\Etc\Tenant;
1011

@@ -80,6 +81,33 @@ public function cache_is_invalidated_when_the_tenant_is_updated()
8081
$this->assertNotEmpty(DB::getQueryLog()); // not empty
8182
}
8283

84+
/** @test */
85+
public function cache_is_invalidated_when_the_tenant_is_deleted()
86+
{
87+
$tenant = Tenant::create();
88+
$tenant->createDomain([
89+
'domain' => 'acme',
90+
]);
91+
92+
DB::enableQueryLog();
93+
94+
DomainTenantResolver::$shouldCache = true;
95+
96+
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
97+
DB::flushQueryLog();
98+
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
99+
$this->assertEmpty(DB::getQueryLog()); // empty
100+
101+
$tenant->delete();
102+
DB::flushQueryLog();
103+
104+
$this->assertThrows(function () {
105+
app(DomainTenantResolver::class)->resolve('acme');
106+
}, TenantCouldNotBeIdentifiedOnDomainException::class);
107+
108+
$this->assertNotEmpty(DB::getQueryLog()); // not empty - cache cleared so the DB was queried
109+
}
110+
83111
/** @test */
84112
public function cache_is_invalidated_when_a_tenants_domain_is_changed()
85113
{
@@ -109,4 +137,31 @@ public function cache_is_invalidated_when_a_tenants_domain_is_changed()
109137
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('bar')));
110138
$this->assertNotEmpty(DB::getQueryLog()); // not empty
111139
}
140+
141+
/** @test */
142+
public function cache_is_invalidated_when_a_tenants_domain_is_deleted()
143+
{
144+
$tenant = Tenant::create();
145+
$tenant->createDomain([
146+
'domain' => 'acme',
147+
]);
148+
149+
DB::enableQueryLog();
150+
151+
DomainTenantResolver::$shouldCache = true;
152+
153+
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
154+
DB::flushQueryLog();
155+
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
156+
$this->assertEmpty(DB::getQueryLog()); // empty
157+
158+
$tenant->domains->first()->delete();
159+
DB::flushQueryLog();
160+
161+
$this->assertThrows(function () {
162+
app(DomainTenantResolver::class)->resolve('acme');
163+
}, TenantCouldNotBeIdentifiedOnDomainException::class);
164+
165+
$this->assertNotEmpty(DB::getQueryLog()); // not empty - cache cleared so the DB was queried
166+
}
112167
}

0 commit comments

Comments
 (0)