From e1aefe07434125257bc1ba4b9d1bfa18b5ef5ec2 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 16 Aug 2023 13:24:08 +0100 Subject: [PATCH 1/3] Add the ability to auto-determine the presenter --- README.md | 2 +- src/Concerns/UsesPresenters.php | 58 ++++++++++++++++--- tests/Models/Item.php | 14 +++++ tests/Presenters/ItemPresenter.php | 15 +++++ tests/Presenters/ItemSubdomainPresenter.php | 15 +++++ tests/PresentersTest.php | 19 ++++++ .../migrations/create_items_table.php.stub | 32 ++++++++++ 7 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 tests/Models/Item.php create mode 100644 tests/Presenters/ItemPresenter.php create mode 100644 tests/Presenters/ItemSubdomainPresenter.php create mode 100644 tests/database/migrations/create_items_table.php.stub diff --git a/README.md b/README.md index 5c24807..eb8791b 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ If you want to change the directory, you have two options. First options is to set the full namespace while you're creating the presenter class ```bash -php artisna presneter:make App\Models\Presenter\UserPresenter +php artisan presneter:make App\Models\Presenter\UserPresenter ``` Or change `presenter_namespace` from `config/laravel-presenter` file. diff --git a/src/Concerns/UsesPresenters.php b/src/Concerns/UsesPresenters.php index 4b1c3a5..066d214 100644 --- a/src/Concerns/UsesPresenters.php +++ b/src/Concerns/UsesPresenters.php @@ -9,18 +9,62 @@ */ trait UsesPresenters { + /* + |-------------------------------------------------------------------------- + | Presenters + |-------------------------------------------------------------------------- + | + | Presenters can be defined as a single item in $this->presenter or + | as an array of $this->presenters. If neither are set, then we will + | generate a default based on the Model and type (if set). + | + */ + /** - * Check the given presenters value exists or not - * - * @param string $type - * @return mixed + * @throws PresenterException */ - public function present(string $type = 'default') + public function present(string $type = 'default'): mixed { - if (array_key_exists($type, $this->presenters)) { - return new $this->presenters[$type]($this); + $presenter = $this->getDefaultPresenterName($type); + + if (! is_null($this->presenters) && is_array($this->presenters)) { + if (array_key_exists($type, $this->presenters)) { + $presenter = $this->presenters[$type]; + } else { + throw new PresenterException(); + } + + } elseif (isset($this->presenter) && is_string($this->presenter)) { + $presenter = $this->presenter; + } + + if (class_exists($presenter)) { + return new $presenter($this); } throw new PresenterException(); } + + /* + |-------------------------------------------------------------------------- + | Default Presenter Names + |-------------------------------------------------------------------------- + | + | By default, the presenter name is defined based on the name of the + | Model class. The default namespace is \App\Presenters. So, the Model + | Day has Presenter DayPresenter. However, if you supply a type, e.g. then it + | would be DayTypePresenter. + | + */ + + private function getDefaultPresenterName($type) + { + $modelNameModifier = $type === 'default' ? '' : $type; + + return str(get_class()) + ->replace('Models', 'Presenters') + ->append(str($modelNameModifier)->ucfirst()) + ->append('Presenter') + ->toString(); + } } diff --git a/tests/Models/Item.php b/tests/Models/Item.php new file mode 100644 index 0000000..064978b --- /dev/null +++ b/tests/Models/Item.php @@ -0,0 +1,14 @@ +model->title)->slug()->toString(); + } +} diff --git a/tests/Presenters/ItemSubdomainPresenter.php b/tests/Presenters/ItemSubdomainPresenter.php new file mode 100644 index 0000000..f467b04 --- /dev/null +++ b/tests/Presenters/ItemSubdomainPresenter.php @@ -0,0 +1,15 @@ +model->title)->upper()->toString(); + } +} diff --git a/tests/PresentersTest.php b/tests/PresentersTest.php index 06d511b..379745a 100644 --- a/tests/PresentersTest.php +++ b/tests/PresentersTest.php @@ -1,5 +1,6 @@ group('Presenter Implementation'); + +it('can automatically load the presenter', function () { + $item = new Item([ + 'title' => 'An item title', + ]); + + expect($item->present()->slug) + ->toEqual('an-item-title'); +}); + +it('can automatically load a non-default presenter', function () { + $item = new Item([ + 'title' => 'An item title', + ]); + + expect($item->present('subdomain')->caps) + ->toEqual('AN ITEM TITLE'); +}); diff --git a/tests/database/migrations/create_items_table.php.stub b/tests/database/migrations/create_items_table.php.stub new file mode 100644 index 0000000..12adbd4 --- /dev/null +++ b/tests/database/migrations/create_items_table.php.stub @@ -0,0 +1,32 @@ +id(); + $table->string('title'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('users'); + } +}; From b991e30b4e6f58366de8b82d31fce84eec107703 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 17 Oct 2023 16:58:29 +0100 Subject: [PATCH 2/3] Use Str facade --- src/Concerns/UsesPresenters.php | 3 ++- tests/Presenters/ItemPresenter.php | 3 ++- tests/Presenters/ItemSubdomainPresenter.php | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Concerns/UsesPresenters.php b/src/Concerns/UsesPresenters.php index 066d214..eadc785 100644 --- a/src/Concerns/UsesPresenters.php +++ b/src/Concerns/UsesPresenters.php @@ -3,6 +3,7 @@ namespace Coderflex\LaravelPresenter\Concerns; use Coderflex\LaravelPresenter\Exceptions\PresenterException; +use Illuminate\Support\Str; /** * Uses Presenters Trait @@ -61,7 +62,7 @@ private function getDefaultPresenterName($type) { $modelNameModifier = $type === 'default' ? '' : $type; - return str(get_class()) + return Str::of(get_class()) ->replace('Models', 'Presenters') ->append(str($modelNameModifier)->ucfirst()) ->append('Presenter') diff --git a/tests/Presenters/ItemPresenter.php b/tests/Presenters/ItemPresenter.php index ed02aa1..852d09a 100644 --- a/tests/Presenters/ItemPresenter.php +++ b/tests/Presenters/ItemPresenter.php @@ -5,11 +5,12 @@ ; use Coderflex\LaravelPresenter\Presenter; +use Illuminate\Support\Str; class ItemPresenter extends Presenter { public function slug() { - return str($this->model->title)->slug()->toString(); + return Str::of($this->model->title)->slug()->toString(); } } diff --git a/tests/Presenters/ItemSubdomainPresenter.php b/tests/Presenters/ItemSubdomainPresenter.php index f467b04..bd5edba 100644 --- a/tests/Presenters/ItemSubdomainPresenter.php +++ b/tests/Presenters/ItemSubdomainPresenter.php @@ -5,11 +5,12 @@ ; use Coderflex\LaravelPresenter\Presenter; +use Illuminate\Support\Str; class ItemSubdomainPresenter extends Presenter { public function caps() { - return str($this->model->title)->upper()->toString(); + return Str::of($this->model->title)->upper()->toString(); } } From d1412694b5a4956285a277ce9cf2ce937870a1b3 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 17 Oct 2023 16:58:35 +0100 Subject: [PATCH 3/3] Fix code-smell --- src/Concerns/UsesPresenters.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Concerns/UsesPresenters.php b/src/Concerns/UsesPresenters.php index eadc785..440a985 100644 --- a/src/Concerns/UsesPresenters.php +++ b/src/Concerns/UsesPresenters.php @@ -28,14 +28,14 @@ public function present(string $type = 'default'): mixed { $presenter = $this->getDefaultPresenterName($type); - if (! is_null($this->presenters) && is_array($this->presenters)) { - if (array_key_exists($type, $this->presenters)) { - $presenter = $this->presenters[$type]; - } else { - throw new PresenterException(); - } + if ( + is_array($this->presenters) && + array_key_exists($type, $this->presenters ?? []) + ) { + $presenter = $this->presenters[$type]; + } - } elseif (isset($this->presenter) && is_string($this->presenter)) { + if (is_string($this->presenter ?? null)) { $presenter = $this->presenter; }