diff --git a/src/CacheKey.php b/src/CacheKey.php index ef9aaf2..13ddfa1 100644 --- a/src/CacheKey.php +++ b/src/CacheKey.php @@ -16,17 +16,23 @@ class CacheKey protected $macroKey; protected $model; protected $query; + protected $withoutGlobalScopes = []; + protected $withoutAllGlobalScopes = false; public function __construct( array $eagerLoad, $model, $query, - $macroKey + $macroKey, + array $withoutGlobalScopes, + $withoutAllGlobalScopes ) { $this->eagerLoad = $eagerLoad; $this->macroKey = $macroKey; $this->model = $model; $this->query = $query; + $this->withoutGlobalScopes = $withoutGlobalScopes; + $this->withoutAllGlobalScopes = $withoutAllGlobalScopes; } public function make( @@ -57,6 +63,14 @@ protected function getBindingsSlug() : string return ''; } + if ($this->withoutAllGlobalScopes) { + return Arr::query($this->model->query()->withoutGlobalScopes()->getBindings()); + } + + if (count($this->withoutGlobalScopes) > 0) { + return Arr::query($this->model->query()->withoutGlobalScopes($this->withoutGlobalScopes)->getBindings()); + } + return Arr::query($this->model->query()->getBindings()); } diff --git a/src/Traits/BuilderCaching.php b/src/Traits/BuilderCaching.php index 7ef35c1..44dd106 100644 --- a/src/Traits/BuilderCaching.php +++ b/src/Traits/BuilderCaching.php @@ -21,4 +21,25 @@ public function truncate() return parent::truncate(); } + + public function withoutGlobalScope($scope) + { + array_push($this->withoutGlobalScopes, $scope); + + return parent::withoutGlobalScope($scope); + } + + public function withoutGlobalScopes(array $scopes = null) + { + if ($scopes != null) { + $this->withoutGlobalScopes = $scopes; + } + + if ($scopes == null || ($scopes != null && count($scopes) == 0)) { + $this->withoutAllGlobalScopes = true; + } + + return parent::withoutGlobalScopes($scopes); + } + } diff --git a/src/Traits/Caching.php b/src/Traits/Caching.php index e061b83..a615cd6 100644 --- a/src/Traits/Caching.php +++ b/src/Traits/Caching.php @@ -16,6 +16,8 @@ trait Caching protected $isCachable = true; protected $scopesAreApplied = false; protected $macroKey = ""; + protected $withoutGlobalScopes = []; + protected $withoutAllGlobalScopes = false; public function __call($method, $parameters) { @@ -45,12 +47,13 @@ protected function applyScopesToInstance() { if (! property_exists($this, "scopes") || $this->scopesAreApplied + || $this->withoutAllGlobalScopes ) { return; } foreach ($this->scopes as $identifier => $scope) { - if (! isset($this->scopes[$identifier])) { + if (! isset($this->scopes[$identifier]) || isset($this->withoutGlobalScopes[$identifier])) { continue; } @@ -166,7 +169,7 @@ protected function makeCacheKey( $query = $this->query->getQuery(); } - return (new CacheKey($eagerLoad, $model, $query, $this->macroKey)) + return (new CacheKey($eagerLoad, $model, $query, $this->macroKey, $this->withoutGlobalScopes, $this->withoutAllGlobalScopes)) ->make($columns, $idColumn, $keyDifferentiator); } diff --git a/tests/Integration/CachedBuilder/ScopeTest.php b/tests/Integration/CachedBuilder/ScopeTest.php index 30096f3..fb4ba9d 100644 --- a/tests/Integration/CachedBuilder/ScopeTest.php +++ b/tests/Integration/CachedBuilder/ScopeTest.php @@ -156,6 +156,83 @@ public function testGlobalScopesWhenSwitchingContextUsingGetMethod() $this->assertEquals("B", $authorsB->first()); } + public function testGlobalScopesAreNotCachedWhenUsingWithoutGlobalScopes() + { + $user = factory(User::class)->create(["name" => "Abernathy Kings"]); + $this->actingAs($user); + $author = factory(UncachedAuthor::class, 1) + ->create(['name' => 'Alois']) + ->first(); + $authors = (new AuthorBeginsWithScoped) + ->withoutGlobalScopes() + ->get(); + $key = sha1("genealabs:laravel-model-caching:testing:{$this->testingSqlitePath}testing.sqlite:authors:genealabslaravelmodelcachingtestsfixturesauthorbeginswithscoped"); + $tags = ["genealabs:laravel-model-caching:testing:{$this->testingSqlitePath}testing.sqlite:genealabslaravelmodelcachingtestsfixturesauthorbeginswithscoped"]; + + $cachedResults = $this->cache() + ->tags($tags) + ->get($key)['value']; + $liveResults = (new UncachedAuthor) + ->nameStartsWith("A") + ->get(); + + $this->assertTrue($authors->contains($author)); + $this->assertTrue($cachedResults->contains($author)); + $this->assertTrue($liveResults->contains($author)); + } + + public function testWithoutGlobalScopes() + { + factory(Author::class, 200)->create(); + $user = factory(User::class)->create(["name" => "Andrew Junior"]); + $this->actingAs($user); + $authorsA = (new AuthorBeginsWithScoped) + ->withoutGlobalScopes() + ->get() + ->map(function ($author) { + return (new Str)->substr($author->name, 0, 1); + }) + ->unique(); + $user = factory(User::class)->create(["name" => "Barry Barry Barry"]); + $this->actingAs($user); + $authorsB = (new AuthorBeginsWithScoped) + ->withoutGlobalScopes(['GeneaLabs\LaravelModelCaching\Tests\Fixtures\Scopes\NameBeginsWith']) + ->get() + ->map(function ($author) { + return (new Str)->substr($author->name, 0, 1); + }) + ->unique(); + + $this->assertGreaterThan(1, count($authorsA)); + $this->assertGreaterThan(1, count($authorsB)); + } + + public function testWithoutGlobalScope() + { + factory(Author::class, 200)->create(); + $user = factory(User::class)->create(["name" => "Andrew Junior"]); + $this->actingAs($user); + $authorsA = (new AuthorBeginsWithScoped) + ->withoutGlobalScope('GeneaLabs\LaravelModelCaching\Tests\Fixtures\Scopes\NameBeginsWith') + ->get() + ->map(function ($author) { + return (new Str)->substr($author->name, 0, 1); + }) + ->unique(); + $user = factory(User::class)->create(["name" => "Barry Barry Barry"]); + $this->actingAs($user); + $authorsB = (new AuthorBeginsWithScoped) + ->withoutGlobalScope('GeneaLabs\LaravelModelCaching\Tests\Fixtures\Scopes\NameBeginsWith') + ->get() + ->map(function ($author) { + return (new Str)->substr($author->name, 0, 1); + }) + ->unique(); + + $this->assertGreaterThan(1, count($authorsA)); + $this->assertGreaterThan(1, count($authorsB)); + } + public function testLocalScopesInRelationship() { $first = "A";