From 35d314a4aff23ab6932b98b297284577b38053b5 Mon Sep 17 00:00:00 2001 From: Mustafa Kerem CANSEV Date: Tue, 3 Dec 2024 21:52:06 +0300 Subject: [PATCH 1/3] add fallback locale support and additional query support to `HasSlug@findBySlug` method --- src/HasSlug.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/HasSlug.php b/src/HasSlug.php index 137525b..cfb30c4 100644 --- a/src/HasSlug.php +++ b/src/HasSlug.php @@ -190,15 +190,31 @@ protected function generateSubstring($slugSourceString) return substr($slugSourceString, 0, $this->slugOptions->maximumLength); } - public static function findBySlug(string $slug, array $columns = ['*']) + public static function findBySlug(string $slug, array $columns = ['*'], callable $additionalQuery = null) { $modelInstance = new static(); $field = $modelInstance->getSlugOptions()->slugField; - $field = in_array(HasTranslatableSlug::class, class_uses_recursive(static::class)) - ? "{$field}->{$modelInstance->getLocale()}" - : $field; + $currentLocale = $modelInstance->getLocale(); + $fallbackLocale = config('app.fallback_locale'); - return static::where($field, $slug)->first($columns); + $query = static::query(); + + if (in_array(HasTranslatableSlug::class, class_uses_recursive(static::class))) { + $currentField = "{$field}->{$currentLocale}"; + $fallbackField = "{$field}->{$fallbackLocale}"; + + $query->where($currentField, $slug); + + $query->orWhere($fallbackField, $slug); + } else { + $query->where($field, $slug); + } + + if (is_callable($additionalQuery)) { + $additionalQuery($query); + } + + return $query->first($columns); } } From 340407fdda22a695e8e77ecc0d8f5f2c1a2f688c Mon Sep 17 00:00:00 2001 From: Mustafa Kerem CANSEV Date: Tue, 3 Dec 2024 22:08:54 +0300 Subject: [PATCH 2/3] update `HasSlug@findBySlug` for moved variables in supported trait condition --- src/HasSlug.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/HasSlug.php b/src/HasSlug.php index cfb30c4..d28f6ff 100644 --- a/src/HasSlug.php +++ b/src/HasSlug.php @@ -195,12 +195,12 @@ public static function findBySlug(string $slug, array $columns = ['*'], callable $modelInstance = new static(); $field = $modelInstance->getSlugOptions()->slugField; - $currentLocale = $modelInstance->getLocale(); - $fallbackLocale = config('app.fallback_locale'); - $query = static::query(); if (in_array(HasTranslatableSlug::class, class_uses_recursive(static::class))) { + $currentLocale = $modelInstance->getLocale(); + $fallbackLocale = config('app.fallback_locale'); + $currentField = "{$field}->{$currentLocale}"; $fallbackField = "{$field}->{$fallbackLocale}"; From 613c87649fabecb0c5e4fe0d746315b6d34aee99 Mon Sep 17 00:00:00 2001 From: Mustafa Kerem CANSEV Date: Tue, 3 Dec 2024 22:20:14 +0300 Subject: [PATCH 3/3] add new tests for `findBySlug` method in `HasSlug` trait --- tests/HasSlugTest.php | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/HasSlugTest.php b/tests/HasSlugTest.php index 593dd85..96dcf84 100644 --- a/tests/HasSlugTest.php +++ b/tests/HasSlugTest.php @@ -4,6 +4,7 @@ use Spatie\Sluggable\SlugOptions; use Spatie\Sluggable\Tests\TestSupport\TestModel; use Spatie\Sluggable\Tests\TestSupport\TestModelSoftDeletes; +use Spatie\Sluggable\Tests\TestSupport\TranslatableModel; it('will save a slug when saving a model', function () { $model = TestModel::create(['name' => 'this is a test']); @@ -349,3 +350,61 @@ public function getSlugOptions(): SlugOptions expect($savedModel->id)->toEqual($model->id); }); + +it('can customize query using additionalQuery parameter in findBySlug', function () { + $model = new class () extends TestModel { + public function getSlugOptions(): SlugOptions + { + return parent::getSlugOptions()->saveSlugsTo('url'); + } + }; + + $model->url = 'custom-slug'; + $model->other_field = 'active'; + $model->save(); + + $savedModel = $model::findBySlug('custom-slug', ['*'], function ($query) { + $query->where('other_field', 'active'); + }); + + expect($savedModel) + ->not->toBeNull() + ->and($savedModel->id) + ->toEqual($model->id); + + $noMatch = $model::findBySlug('custom-slug', ['*'], function ($query) { + $query->where('status', 'inactive'); + }); + + expect($noMatch)->toBeNull(); +}); + +it('can find models using findBySlug with fallback locale', function () { + config()->set('app.fallback_locale', 'en'); + app()->setLocale('tr'); + + $model = new class () extends TranslatableModel { + public function getSlugOptions(): SlugOptions + { + return parent::getSlugOptions()->saveSlugsTo('slug'); + } + }; + + $model->slug = ['en' => 'english-slug', 'tr' => 'turkish-slug']; + $model->name = ['en' => 'English Name', 'tr' => 'Turkish Name']; + $model->save(); + + $foundModelInCurrentLocale = $model::findBySlug('turkish-slug'); + + expect($foundModelInCurrentLocale) + ->not->toBeNull() + ->and($foundModelInCurrentLocale->id) + ->toEqual($model->id); + + $foundModelInFallbackLocale = $model::findBySlug('english-slug'); + + expect($foundModelInFallbackLocale) + ->not->toBeNull() + ->and($foundModelInFallbackLocale->id) + ->toEqual($model->id); +});