534 lines
17 KiB
PHP
534 lines
17 KiB
PHP
<?php
|
|
|
|
namespace App\Rules;
|
|
|
|
use Illuminate\Contracts\Validation\Rule;
|
|
use Illuminate\Contracts\Validation\DataAwareRule;
|
|
use Illuminate\Support\Str;
|
|
|
|
class FormPropertyLogicRule implements Rule, DataAwareRule {
|
|
|
|
const ACTIONS_VALUES = [
|
|
'show-block',
|
|
'hide-block',
|
|
'make-it-optional',
|
|
'require-answer'
|
|
];
|
|
|
|
const CONDITION_MAPPING = [
|
|
'text' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'contains' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_contain' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'starts_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'ends_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'url' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'contains' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_contain' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'starts_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'ends_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'email' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'contains' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_contain' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'starts_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'ends_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'phone_number' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'contains' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_contain' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'starts_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'ends_with' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'number' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'greater_than' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'less_than' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'greater_than_or_equal_to' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'less_than_or_equal_to' => [
|
|
'expected_type' => 'number',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'checkbox' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
|
|
]
|
|
],
|
|
'select' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'does_not_equal' => [
|
|
'expected_type' => 'string',
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'multi_select' => [
|
|
'comparators' => [
|
|
'contains' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'uuid',
|
|
]
|
|
],
|
|
'does_not_contain' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'uuid',
|
|
]
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'date' => [
|
|
'comparators' => [
|
|
'equals' => [
|
|
'expected_type' => 'string',
|
|
'format' => [
|
|
'type' => 'date'
|
|
]
|
|
],
|
|
'before' => [
|
|
'expected_type' => 'string',
|
|
'format' => [
|
|
'type' => 'date'
|
|
]
|
|
],
|
|
'after' => [
|
|
'expected_type' => 'string',
|
|
'format' => [
|
|
'type' => 'date'
|
|
]
|
|
],
|
|
'on_or_before' => [
|
|
'expected_type' => 'string',
|
|
'format' => [
|
|
'type' => 'date'
|
|
]
|
|
],
|
|
'on_or_after' => [
|
|
'expected_type' => 'string',
|
|
'format' => [
|
|
'type' => 'date'
|
|
]
|
|
],
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'past_week' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
],
|
|
'past_month' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
],
|
|
'past_year' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
],
|
|
'next_week' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
],
|
|
'next_month' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
],
|
|
'next_year' => [
|
|
'expected_type' => 'object',
|
|
'format' => [
|
|
'type' => 'empty',
|
|
'values' => '{}'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
'files' => [
|
|
'comparators' => [
|
|
'is_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
],
|
|
'is_not_empty' => [
|
|
'expected_type' => 'boolean',
|
|
'format' => [
|
|
'type' => 'enum',
|
|
'values' => [true]
|
|
]
|
|
]
|
|
]
|
|
],
|
|
];
|
|
|
|
private $isConditionCorrect = true;
|
|
private $isActionCorrect = true;
|
|
private $field = [];
|
|
private $data = [];
|
|
|
|
private function checkBaseCondition($condtion) {
|
|
|
|
if (!isset($condtion['value'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!isset($condtion['value']['property_meta'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!isset($condtion['value']['property_meta']['type'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!isset($condtion['value']['operator'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!isset($condtion['value']['value'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
$typeField = $condtion['value']['property_meta']['type'];
|
|
$operator = $condtion['value']['operator'];
|
|
$value = $condtion['value']['value'];
|
|
|
|
if (!isset(self::CONDITION_MAPPING[$typeField])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!isset(self::CONDITION_MAPPING[$typeField]['comparators'][$operator])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
$type = self::CONDITION_MAPPING[$typeField]['comparators'][$operator]['expected_type'];
|
|
|
|
// Type d'objet : string, boolean, number, object
|
|
if (
|
|
($type === 'string' && gettype($value) !== 'string') ||
|
|
($type === 'boolean' && !is_bool($value)) ||
|
|
($type === 'number' && !is_numeric($value)) ||
|
|
($type === 'object' && !is_array($value))
|
|
) {
|
|
$this->isConditionCorrect = false;
|
|
}
|
|
}
|
|
|
|
private function checkConditions($conditions) {
|
|
if (isset($conditions['operatorIdentifier'])) {
|
|
if (($conditions['operatorIdentifier'] !== 'and') && ($conditions['operatorIdentifier'] !== 'or')) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (isset($conditions['operatorIdentifier']['children'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
if (!is_array($conditions['children'])) {
|
|
$this->isConditionCorrect = false;
|
|
return;
|
|
}
|
|
|
|
foreach ($conditions['children'] as &$child) {
|
|
$this->checkConditions($child);
|
|
}
|
|
} else if (isset($conditions['identifier'])) {
|
|
$this->checkBaseCondition($conditions);
|
|
}
|
|
}
|
|
|
|
private function checkActions($conditions) {
|
|
if (is_array($conditions) && count($conditions) > 0) {
|
|
foreach($conditions as $val){
|
|
if (!in_array($val, static::ACTIONS_VALUES) ||
|
|
(in_array($this->field["type"], ['nf-text', 'nf-page-break', 'nf-divider', 'nf-image']) && !in_array($val, ['hide-block'])) ||
|
|
(isset($this->field["hidden"]) && $this->field["hidden"] && !in_array($val, ['show-block','require-answer'])) ||
|
|
(isset($this->field["required"]) && $this->field["required"] && !in_array($val, ['make-it-optional','hide-block']))
|
|
) {
|
|
$this->isActionCorrect = false;
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determine if the validation rule passes.
|
|
*
|
|
* @param string $attribute
|
|
* @param mixed $value
|
|
* @return bool
|
|
*/
|
|
public function passes($attribute, $value) {
|
|
$this->setProperty($attribute);
|
|
if(isset($value["conditions"])){
|
|
$this->checkConditions($value["conditions"]);
|
|
}
|
|
if(isset($value["actions"])){
|
|
$this->checkActions($value["actions"]);
|
|
}
|
|
return ($this->isConditionCorrect && $this->isActionCorrect);
|
|
}
|
|
|
|
/**
|
|
* Get the validation error message.
|
|
*
|
|
*/
|
|
public function message() {
|
|
$errorList = [];
|
|
if(!$this->isConditionCorrect){
|
|
$errorList[] = "The logic conditions for ".$this->field['name']." are not complete.";
|
|
}
|
|
if(!$this->isActionCorrect){
|
|
$errorList[] = "The logic actions for ".$this->field['name']." are not valid.";
|
|
}
|
|
return $errorList;
|
|
}
|
|
|
|
/**
|
|
* Set the data under validation.
|
|
*
|
|
* @param array $data
|
|
* @return $this
|
|
*/
|
|
public function setData($data)
|
|
{
|
|
$this->data = $data;
|
|
|
|
return $this;
|
|
}
|
|
|
|
private function setProperty(string $attributeKey)
|
|
{
|
|
$attributeKey = Str::of($attributeKey)->replace('.logic','')->toString();
|
|
$this->field = \Arr::get($this->data, $attributeKey);
|
|
}
|
|
}
|