Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow steps to be limited to specific classes #15

Merged
merged 4 commits into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Facades/Onboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Spatie\Onboard\OnboardingSteps;

/**
* @method OnboardingStep addStep(string $title)
* @method OnboardingStep addStep(string $title, string $model = null)
* @method Collection<OnboardingStep> steps(Onboardable $model)
*/
class Onboard extends Facade
Expand Down
26 changes: 22 additions & 4 deletions src/OnboardingSteps.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,35 @@ class OnboardingSteps
/** @var array<OnboardingStep> */
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);

return $step;
if ($model && new $model() instanceof Onboardable) {
return $this->steps[$model][] = $step;
}

return $this->steps['default'][] = $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'] ?? [];
}
}
90 changes: 90 additions & 0 deletions tests/OnboardTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand All @@ -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();

Expand All @@ -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');
Expand Down Expand Up @@ -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')
Expand Down
12 changes: 12 additions & 0 deletions tests/Team.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Spatie\Onboard\Tests;

use Illuminate\Database\Eloquent\Model;
use Spatie\Onboard\Concerns\GetsOnboarded;
use Spatie\Onboard\Concerns\Onboardable;

class Team extends Model implements Onboardable
{
use GetsOnboarded;
}