Skip to content

Commit

Permalink
allow enable/disable actions
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagof committed Mar 15, 2024
1 parent 8db2ded commit 5e56c5f
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ phpstan.neon
testbench.yaml
vendor
node_modules
.DS_Store
4 changes: 2 additions & 2 deletions database/factories/ActionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ public function definition(): array
{
return [
'rule_id' => fn () => RuleFactory::new()->forObject(TestObject::class)->create()->id,
'active' => true,
'enabled' => true,
];
}

public function inactive(): ActionFactory
{
return $this->state(fn (array $attributes) => [
'active' => false,
'enabled' => false,
]);
}

Expand Down
4 changes: 2 additions & 2 deletions database/factories/ConditionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ public function definition(): array
{
return [
'rule_id' => fn () => RuleFactory::new()->forObject(TestObject::class)->create()->id,
'active' => true,
'enabled' => true,
];
}

public function inactive(): ConditionFactory
{
return $this->state(fn (array $attributes) => [
'active' => false,
'enabled' => false,
]);
}

Expand Down
8 changes: 4 additions & 4 deletions database/migrations/create_laravel-volition_tables.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ return new class extends Migration {

Schema::create('volition_conditions', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Rule::class)->constrained('volition_rules');
$table->boolean('active')->default(true);
$table->foreignIdFor(Rule::class)->constrained('volition_rules')->cascadeOnDelete();
$table->boolean('enabled')->default(true);
$table->string('class');
$table->text('payload');

Expand All @@ -30,8 +30,8 @@ return new class extends Migration {

Schema::create('volition_actions', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Rule::class)->constrained('volition_rules');
$table->boolean('active')->default(true);
$table->foreignIdFor(Rule::class)->constrained('volition_rules')->cascadeOnDelete();
$table->boolean('enabled')->default(true);
$table->string('class');
$table->text('payload');

Expand Down
3 changes: 0 additions & 3 deletions src/Models/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
use Squarebit\Volition\Traits\BelongToRule;

/**
* @property string $class
* @property IsAction $payload
*
* @method static Builder<static> forClass(string $class)
*/
class Action extends Element
Expand Down
4 changes: 0 additions & 4 deletions src/Models/Condition.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
use Squarebit\Volition\Contracts\Volitional;
use Squarebit\Volition\Traits\BelongToRule;

/**
* @property string $class
* @property IsCondition $payload
*/
class Condition extends Element
{
use HasFactory;
Expand Down
9 changes: 9 additions & 0 deletions src/Models/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
* @property int $id
* @property class-string $class
* @property object $payload
* @property bool $enabled
*/
abstract class Element extends Model
{
protected $guarded = ['id'];

protected $casts = [
'payload' => Serialize::class,
'enabled' => 'bool',
];

public static function boot(): void
Expand All @@ -25,4 +27,11 @@ public static function boot(): void
$model->class = ($model->payload)::class;
});
}

public function disabled(bool $disabled = true): static
{
$this->enabled = ! $disabled;

return $this;
}
}
16 changes: 10 additions & 6 deletions src/Models/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,24 @@ public function scopeForClass(Builder $query, string $className): Builder

public function passes(Volitional $object): bool
{
return $this->conditions
->reduce(fn (bool $carry, Condition $condition): bool => $carry && $condition->passes($object), true);
return $this->conditions->count() > 0 &&
$this->conditions
->filter(fn (Condition $condition) => $condition->enabled)
->reduce(fn (bool $carry, Condition $condition): bool => $carry && $condition->passes($object), true);
}

public function addCondition(IsCondition $condition): static
public function addCondition(IsCondition $condition, bool $enabled = true): static
{
$this->conditions()->save((new Condition())->condition($condition));
$this->conditions()
->save((new Condition())->condition($condition)->disabled(! $enabled));

return $this;
}

public function addAction(IsAction $action): static
public function addAction(IsAction $action, bool $enabled = true): static
{
$this->actions()->save((new Action())->action($action));
$this->actions()
->save((new Action())->action($action)->disabled(! $enabled));

return $this;
}
Expand Down
20 changes: 13 additions & 7 deletions src/Traits/HasVolition.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\Collection;
use Squarebit\Volition\Contracts\IsAction;
use Squarebit\Volition\Exception\ActionMissingException;
use Squarebit\Volition\Models\Action;
use Squarebit\Volition\Models\Rule;

trait HasVolition
Expand Down Expand Up @@ -43,9 +44,14 @@ public function rule(string|Rule $rule): ?Rule
*/
public function actions(string|Rule $forRule = null): Collection
{
return $forRule
? $this->rule($forRule)?->actions->pluck('payload') ?? collect()
: $this->rules()->pluck('actions')->flatten()->pluck('payload')->unique() ?? collect();
$actions = $forRule
? $this->rule($forRule)?->actions
: $this->rules()->pluck('actions')->flatten();

return $actions
?->filter(fn (Action $action): bool => $action->enabled)
->pluck('payload')
->unique() ?? collect();
}

/**
Expand All @@ -54,9 +60,9 @@ public function actions(string|Rule $forRule = null): Collection
* @param class-string<TActionClass> $ofClass
* @return TActionClass|null
*/
public function action(string $ofClass, bool $throw = false): ?IsAction
public function action(string $ofClass, string $forRule = null, bool $throw = false): ?IsAction
{
$action = $this->actions()->firstWhere(fn (IsAction $action) => $action instanceof $ofClass);
$action = $this->actions($forRule)->firstWhere(fn (IsAction $action) => $action instanceof $ofClass);

throw_if(
$action === null && $throw,
Expand All @@ -70,8 +76,8 @@ public function action(string $ofClass, bool $throw = false): ?IsAction
/**
* @param class-string<\Squarebit\Volition\Contracts\IsAction> $actionClass
*/
public function executeAction(string $actionClass, bool $throw = false): mixed
public function executeAction(string $actionClass, string $forRule = null, bool $throw = false): mixed
{
return $this->action($actionClass, $throw)?->execute($this);
return $this->action($actionClass, $forRule, $throw)?->execute($this);
}
}
14 changes: 13 additions & 1 deletion tests/Feature/RuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
->addAction($prefixAction)
->addAction($suffixAction);

RuleFactory::new(['name' => 'ruleB'])
$this->ruleB = RuleFactory::new(['name' => 'ruleB'])
->forObject(TestObject::class)
->create()
->addCondition($condition)
Expand Down Expand Up @@ -98,6 +98,18 @@
->toThrow(ActionMissingException::class);
});

test('it ignores disabled actions', function () {
$this->ruleB
->addAction(new PrefixAction(prefix: 'Squarebit'), enabled: false);

$testObj = new TestObject(property: 'prop_value');

expect($testObj->action(PrefixAction::class, forRule: 'ruleB'))
->toBeNull()
->and(fn () => $testObj->action(PrefixAction::class, forRule: 'ruleB', throw: true))
->toThrow(ActionMissingException::class);
});

test('it executes actions', function () {
$testObj = new TestObject(property: 'prop_value');
$testObj2 = new TestObject(property: 'some_other_prop_value');
Expand Down

0 comments on commit 5e56c5f

Please sign in to comment.