From 52ff0c6d289fc4875411e8c6d46dcd6c5b3d4b9d Mon Sep 17 00:00:00 2001 From: Rhys Lees <43909932+RhysLees@users.noreply.github.com> Date: Sat, 24 Sep 2022 01:59:20 +0100 Subject: [PATCH 1/4] Allow steps to be limited to a class --- src/Facades/Onboard.php | 2 +- src/OnboardingSteps.php | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Facades/Onboard.php b/src/Facades/Onboard.php index 1bd0ab5..8f9a972 100644 --- a/src/Facades/Onboard.php +++ b/src/Facades/Onboard.php @@ -9,7 +9,7 @@ use Spatie\Onboard\OnboardingSteps; /** - * @method OnboardingStep addStep(string $title) + * @method OnboardingStep addStep(string $title, string $model = null) * @method Collection steps(Onboardable $model) */ class Onboard extends Facade diff --git a/src/OnboardingSteps.php b/src/OnboardingSteps.php index fa52d6a..18f8069 100644 --- a/src/OnboardingSteps.php +++ b/src/OnboardingSteps.php @@ -10,17 +10,37 @@ class OnboardingSteps /** @var array */ protected array $steps = []; - public function addStep(string $title): OnboardingStep + public function addStep(string $title, string $model = null): OnboardingStep { - $this->steps[] = $step = new OnboardingStep($title); + $step = new OnboardingStep($title); + + if ($model && new $model() instanceof Onboardable) { + $this->steps[$model][] = $step; + } else { + $this->steps['default'][] = $step; + } return $step; } public function steps(Onboardable $model): Collection { - return collect($this->steps) + return collect($this->getStepsArray($model)) ->map(fn (OnboardingStep $step) => $step->initiate($model)) ->filter(fn (OnboardingStep $step) => $step->notExcluded()); } + + private function getStepsArray(Onboardable $model): array + { + $key = get_class($model); + + if (key_exists($key, $this->steps)) { + return array_merge( + $this->steps[$key], + $this->steps['default'] ?? [] + ); + } + + return $this->steps['default'] ?? []; + } } From f80f9650868395f0ede57110f0c25ee7b40620bc Mon Sep 17 00:00:00 2001 From: Rhys Lees <43909932+RhysLees@users.noreply.github.com> Date: Sat, 24 Sep 2022 01:59:52 +0100 Subject: [PATCH 2/4] Add tests for limited steps --- tests/OnboardTest.php | 90 +++++++++++++++++++++++++++++++++++++++++++ tests/Team.php | 12 ++++++ 2 files changed, 102 insertions(+) create mode 100644 tests/Team.php diff --git a/tests/OnboardTest.php b/tests/OnboardTest.php index 1e05c97..934a013 100644 --- a/tests/OnboardTest.php +++ b/tests/OnboardTest.php @@ -3,10 +3,12 @@ use Spatie\Onboard\OnboardingManager; use Spatie\Onboard\OnboardingSteps; +use Spatie\Onboard\Tests\Team; use Spatie\Onboard\Tests\User; beforeEach(function () { $this->user = new User(); + $this->team = new Team(); }); test('steps can be defined and configured', function () { @@ -21,6 +23,35 @@ }); $this->assertEquals(1, $onboardingSteps->steps(new User())->count()); + $this->assertEquals(1, $onboardingSteps->steps(new Team())->count()); + + $userStep = $onboardingSteps->steps(new User())->first(); + $teamStep = $onboardingSteps->steps(new Team())->first(); + + expect($userStep->link)->toBe('/some/url') + ->and($userStep->cta)->toBe('Test This!') + ->and($userStep->title)->toBe('Test Step') + ->and($userStep->another)->toBe('attribute'); + + expect($teamStep->link)->toBe('/some/url') + ->and($teamStep->cta)->toBe('Test This!') + ->and($teamStep->title)->toBe('Test Step') + ->and($teamStep->another)->toBe('attribute'); +}); + +test('limited steps can be defined and configured', function () { + $onboardingSteps = new OnboardingSteps(); + + $onboardingSteps->addStep('Test Step', User::class) + ->link('/some/url') + ->cta('Test This!') + ->attributes(['another' => 'attribute']) + ->completeIf(function () { + return true; + }); + + $this->assertEquals(1, $onboardingSteps->steps(new User())->count()); + $this->assertEquals(0, $onboardingSteps->steps(new Team())->count()); $step = $onboardingSteps->steps(new User())->first(); @@ -30,6 +61,40 @@ ->and($step->another)->toBe('attribute'); }); +test('limited steps can be defined with normal steps', function () { + $onboardingSteps = new OnboardingSteps(); + + $onboardingSteps->addStep('Test Step', User::class); + + $onboardingSteps->addStep('Test Step Normal'); + + $this->assertEquals(2, $onboardingSteps->steps(new User())->count()); +}); + +test('multipe limited step models can be defined', function () { + $onboardingSteps = new OnboardingSteps(); + + $onboardingSteps->addStep('Test Step', User::class); + + $onboardingSteps->addStep('Test Step Team', Team::class); + + $this->assertEquals(1, $onboardingSteps->steps(new User())->count()); + $this->assertEquals(1, $onboardingSteps->steps(new Team())->count()); +}); + +test('multipe limited step models can be defined with normal steps', function () { + $onboardingSteps = new OnboardingSteps(); + + $onboardingSteps->addStep('Test Step', User::class); + + $onboardingSteps->addStep('Test Step Normal', Team::class); + + $onboardingSteps->addStep('Test Step Normal'); + + $this->assertEquals(2, $onboardingSteps->steps(new User())->count()); + $this->assertEquals(2, $onboardingSteps->steps(new Team())->count()); +}); + test('is in progress when all steps are incomplete', function () { $onboardingSteps = new OnboardingSteps(); $onboardingSteps->addStep('Test Step'); @@ -62,6 +127,31 @@ ->and($onboarding->inProgress())->toBeFalse(); }); +test('is finished when all steps are complete for limited models steps', function () { + $onboardingSteps = new OnboardingSteps(); + $onboardingSteps->addStep('Test Step', User::class) + ->completeIf(function () { + return true; + }); + $onboardingSteps->addStep('Test Step', Team::class) + ->completeIf(function () { + return false; + }); + + $onboardingSteps->addStep('Excluded Step') + ->excludeIf(function () { + return true; + }) + ->completeIf(function () { + return false; + }); + + $onboarding = new OnboardingManager($this->user, $onboardingSteps); + + expect($onboarding->finished())->toBeTrue() + ->and($onboarding->inProgress())->toBeFalse(); +}); + test('it returns the correct next unfinished step', function () { $onboardingSteps = new OnboardingSteps(); $onboardingSteps->addStep('Step 1') diff --git a/tests/Team.php b/tests/Team.php new file mode 100644 index 0000000..3d77b78 --- /dev/null +++ b/tests/Team.php @@ -0,0 +1,12 @@ + Date: Sat, 24 Sep 2022 02:07:49 +0100 Subject: [PATCH 3/4] Add readme for Limited Steps --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index 8b82292..a371941 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,41 @@ Onboard::addStep('Excluded Step') }); ``` +Limiting steps to a specific class: + +```php +Onboard::addStep('Limited Step', User::class) + ->link('/post/create'); + +// or + +Onboard::addStep('Limited Step', 'App\Models\User') + ->link('/post/create'); +``` + +When using limited steps, steps that are not limited will be available to all classes. For example: + +```php +// Defining User steps +Onboard::addStep('Limited User Step', User::class) + ->link('/post/create'); + +// Defining Team steps +Onboard::addStep('Limited Team Step', Team::class) + ->link('/post/create'); + +// Defining a step that is available to all classes +Onboard::addStep('Normal Step') + ->link('/post/create'); +``` + +The above will result in 1 step being available to all classes, and 2 steps being available to the `User` and `Team` classes: + +`Other` classes will only see the `Normal Step`. +`User` classes will both see the `Normal Step` and `Limited User Step`. +`Team` classes will both see the `Normal Step` and `Limited Team Step`. + + Definining custom attributes and accessing them: ```php From f8a02ecf697138f80e2ee9389f4bb83d5b892471 Mon Sep 17 00:00:00 2001 From: Rhys Lees <43909932+RhysLees@users.noreply.github.com> Date: Sat, 24 Sep 2022 13:51:01 +0100 Subject: [PATCH 4/4] Refactor else statment --- src/OnboardingSteps.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/OnboardingSteps.php b/src/OnboardingSteps.php index 18f8069..09369c0 100644 --- a/src/OnboardingSteps.php +++ b/src/OnboardingSteps.php @@ -15,12 +15,10 @@ public function addStep(string $title, string $model = null): OnboardingStep $step = new OnboardingStep($title); if ($model && new $model() instanceof Onboardable) { - $this->steps[$model][] = $step; - } else { - $this->steps['default'][] = $step; + return $this->steps[$model][] = $step; } - return $step; + return $this->steps['default'][] = $step; } public function steps(Onboardable $model): Collection