Add data for conditions
continuous-integration/drone/push Build is passing Details

This commit is contained in:
philipp lang 2024-07-12 00:16:50 +02:00
parent a0038bb5e2
commit cb8bfae182
10 changed files with 115 additions and 27 deletions

View File

@ -3,6 +3,7 @@
namespace App\Form\Editor; namespace App\Form\Editor;
use App\Form\Models\Participant; use App\Form\Models\Participant;
use App\Lib\Editor\Condition;
use App\Lib\Editor\ConditionResolver; use App\Lib\Editor\ConditionResolver;
class FormConditionResolver extends ConditionResolver class FormConditionResolver extends ConditionResolver
@ -20,24 +21,24 @@ class FormConditionResolver extends ConditionResolver
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function filterCondition(string $mode, array $ifs): bool public function filterCondition(Condition $condition): bool
{ {
if (count($ifs) === 0) { if (!$condition->hasStatements()) {
return true; return true;
} }
foreach ($ifs as $if) { foreach ($condition->ifs as $if) {
$field = $this->participant->getFields()->findByKey($if['field']); $field = $this->participant->getFields()->findByKey($if->field);
$matches = $field->matches($if['comparator'], $if['value']); $matches = $field->matches($if->comparator, $if->value);
if ($matches && $mode === 'any') { if ($matches && $condition->isAny()) {
return true; return true;
} }
if (!$matches && $mode === 'all') { if (!$matches && $condition->isAll()) {
return false; return false;
} }
} }
if ($mode === 'any') { if ($condition->isAny()) {
return false; return false;
} }

View File

@ -11,6 +11,7 @@ use App\Form\Models\Form;
use App\Form\Models\Participant; use App\Form\Models\Participant;
use App\Form\Presenters\DefaultPresenter; use App\Form\Presenters\DefaultPresenter;
use App\Form\Presenters\Presenter; use App\Form\Presenters\Presenter;
use App\Lib\Editor\Comparator;
use Faker\Generator; use Faker\Generator;
use Spatie\LaravelData\Data; use Spatie\LaravelData\Data;
use Spatie\LaravelData\Attributes\MapInputName; use Spatie\LaravelData\Attributes\MapInputName;
@ -170,7 +171,7 @@ abstract class Field extends Data
return $this->key . '_display'; return $this->key . '_display';
} }
public function matches(string $comparator, mixed $value): bool public function matches(Comparator $comparator, mixed $value): bool
{ {
return $this->getMatcher()->setValue($this->value)->matches($comparator, $value); return $this->getMatcher()->setValue($this->value)->matches($comparator, $value);
} }

View File

@ -5,6 +5,7 @@ namespace App\Form\Mails;
use App\Form\Data\FormConfigData; use App\Form\Data\FormConfigData;
use App\Form\Editor\FormConditionResolver; use App\Form\Editor\FormConditionResolver;
use App\Form\Models\Participant; use App\Form\Models\Participant;
use App\Lib\Editor\Condition;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Mail\Attachment; use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
@ -71,10 +72,7 @@ class ConfirmRegistrationMail extends Mailable
$conditionResolver = app(FormConditionResolver::class)->forParticipant($this->participant); $conditionResolver = app(FormConditionResolver::class)->forParticipant($this->participant);
return $this->participant->form->getMedia('mailattachments') return $this->participant->form->getMedia('mailattachments')
->filter(fn ($media) => $conditionResolver->filterCondition( ->filter(fn ($media) => $conditionResolver->filterCondition(Condition::fromMedia($media)))
data_get($media->getCustomProperty('conditions'), 'mode', 'all'),
data_get($media->getCustomProperty('conditions'), 'ifs', []),
))
->map(fn ($media) => Attachment::fromStorageDisk($media->disk, $media->getPathRelativeToRoot())) ->map(fn ($media) => Attachment::fromStorageDisk($media->disk, $media->getPathRelativeToRoot()))
->all(); ->all();
} }

View File

@ -2,6 +2,8 @@
namespace App\Form\Matchers; namespace App\Form\Matchers;
use App\Lib\Editor\Comparator;
abstract class Matcher abstract class Matcher
{ {
@ -14,5 +16,5 @@ abstract class Matcher
return $this; return $this;
} }
abstract public function matches(string $comparator, mixed $value): bool; abstract public function matches(Comparator $comparator, mixed $value): bool;
} }

View File

@ -2,24 +2,26 @@
namespace App\Form\Matchers; namespace App\Form\Matchers;
use App\Lib\Editor\Comparator;
class SingleValueMatcher extends Matcher class SingleValueMatcher extends Matcher
{ {
public function matches(string $comparator, mixed $value): bool public function matches(Comparator $comparator, mixed $value): bool
{ {
if ($comparator === 'isEqual' && $value === $this->value) { if ($comparator === Comparator::EQUAL && $value === $this->value) {
return true; return true;
} }
if ($comparator === 'isNotEqual' && $value !== $this->value) { if ($comparator === Comparator::NOTEQUAL && $value !== $this->value) {
return true; return true;
} }
if ($comparator === 'isIn' && in_array($this->value, $value)) { if ($comparator === Comparator::IN && in_array($this->value, $value)) {
return true; return true;
} }
if ($comparator === 'isNotIn' && !in_array($this->value, $value)) { if ($comparator === Comparator::NOTIN && !in_array($this->value, $value)) {
return true; return true;
} }

View File

@ -0,0 +1,12 @@
<?php
namespace App\Lib\Editor;
enum Comparator: string
{
case EQUAL = 'isEqual';
case NOTEQUAL = 'isNotEqual';
case IN = 'isIn';
case NOTIN = 'isNotIn';
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Lib\Editor;
use Illuminate\Database\Eloquent\Model;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\LaravelData\Attributes\DataCollectionOf;
class Condition extends Data
{
/** @param DataCollection<int, Statement> $ifs */
public function __construct(
public ConditionMode $mode,
#[DataCollectionOf(Statement::class)]
public DataCollection $ifs,
) {
}
public static function fromMedia(Media $media): self
{
return static::withoutMagicalCreationFrom($media->getCustomProperty('conditions') ?: [
'mode' => 'any',
'ifs' => [],
]);
}
/**
* @param array<string, mixed> $block
*/
public static function fromBlock(array $block): self
{
return static::withoutMagicalCreationFrom([
'mode' => data_get($block, 'tunes.condition.mode', 'any'),
'ifs' => data_get($block, 'tunes.condition.ifs', []),
]);
}
public function hasStatements(): bool
{
return count($this->ifs) > 0;
}
public function isAny(): bool
{
return $this->mode === ConditionMode::ANY;
}
public function isAll(): bool
{
return $this->mode === ConditionMode::ALL;
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Lib\Editor;
enum ConditionMode: string
{
case ALL = 'all';
case ANY = 'any';
}

View File

@ -5,10 +5,7 @@ namespace App\Lib\Editor;
abstract class ConditionResolver abstract class ConditionResolver
{ {
/** abstract public function filterCondition(Condition $condition): bool;
* @param array<string, mixed> $ifs
*/
abstract public function filterCondition(string $mode, array $ifs): bool;
/** /**
* @param array<string, mixed> $content * @param array<string, mixed> $content
@ -24,9 +21,6 @@ abstract class ConditionResolver
*/ */
public function filterBlock(array $block): bool public function filterBlock(array $block): bool
{ {
$mode = data_get($block, 'tunes.condition.mode', 'any'); return $this->filterCondition(Condition::fromBlock($block));
$ifs = data_get($block, 'tunes.condition.ifs', []);
return $this->filterCondition($mode, $ifs);
} }
} }

View File

@ -0,0 +1,13 @@
<?php
namespace App\Lib\Editor;
use Spatie\LaravelData\Data;
class Statement extends Data
{
/** @param mixed $value */
public function __construct(public string $field, public $value, public Comparator $comparator)
{
}
}