opnform/app/Service/Forms/FormLogicConditionChecker.php

406 lines
15 KiB
PHP
Raw Permalink Normal View History

2022-09-20 19:59:52 +00:00
<?php
namespace App\Service\Forms;
class FormLogicConditionChecker
{
public function __construct(private ?array $conditions, private ?array $formData)
{
}
2024-02-23 10:54:12 +00:00
public static function conditionsMet(?array $conditions, array $formData): bool
{
2022-09-20 19:59:52 +00:00
return (new self($conditions, $formData))->conditionsAreMet($conditions, $formData);
}
2024-02-23 10:54:12 +00:00
private function conditionsAreMet(?array $conditions, array $formData): bool
{
if (! $conditions) {
2022-09-20 19:59:52 +00:00
return false;
}
// If it's not a group, just a single condition
2024-02-23 10:54:12 +00:00
if (! isset($conditions['operatorIdentifier'])) {
return $this->propertyConditionMet($conditions['value'], $formData[$conditions['value']['property_meta']['id']] ?? null);
2022-09-20 19:59:52 +00:00
}
if ($conditions['operatorIdentifier'] === 'and') {
$isvalid = true;
2024-02-23 10:54:12 +00:00
foreach ($conditions['children'] as $childrenCondition) {
if (! $this->conditionsMet($childrenCondition, $formData)) {
2022-09-20 19:59:52 +00:00
$isvalid = false;
break;
}
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return $isvalid;
2024-02-23 10:54:12 +00:00
} elseif ($conditions['operatorIdentifier'] === 'or') {
2022-09-20 19:59:52 +00:00
$isvalid = false;
2024-02-23 10:54:12 +00:00
foreach ($conditions['children'] as $childrenCondition) {
2022-09-20 19:59:52 +00:00
if ($this->conditionsMet($childrenCondition, $formData)) {
$isvalid = true;
break;
}
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return $isvalid;
}
2024-02-23 10:54:12 +00:00
throw new \Exception('Unexcepted operatorIdentifier:'.$conditions['operatorIdentifier']);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function propertyConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['property_meta']['type']) {
case 'text':
case 'url':
case 'email':
case 'phone_number':
2024-02-23 10:54:12 +00:00
return $this->textConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'number':
2024-02-23 10:54:12 +00:00
return $this->numberConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'checkbox':
2024-02-23 10:54:12 +00:00
return $this->checkboxConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'select':
2024-02-23 10:54:12 +00:00
return $this->selectConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'date':
2024-02-23 10:54:12 +00:00
return $this->dateConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'multi_select':
2024-02-23 10:54:12 +00:00
return $this->multiSelectConditionMet($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
case 'files':
2024-02-23 10:54:12 +00:00
return $this->filesConditionMet($propertyCondition, $value);
}
return false;
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkEquals($condition, $fieldValue): bool
{
2022-09-20 19:59:52 +00:00
return $condition['value'] === $fieldValue;
}
2024-02-23 10:54:12 +00:00
private function checkContains($condition, $fieldValue): bool
{
2022-09-20 19:59:52 +00:00
return ($fieldValue && is_array($fieldValue)) ? in_array($condition['value'], $fieldValue) : false;
}
2024-02-23 10:54:12 +00:00
private function checkListContains($condition, $fieldValue): bool
{
if (is_null($fieldValue)) {
return false;
}
2024-02-23 10:54:12 +00:00
if (! is_array($fieldValue)) {
2024-01-17 13:26:31 +00:00
return $this->checkEquals($condition, $fieldValue);
}
if (is_array($condition['value'])) {
return count(array_intersect($condition['value'], $fieldValue)) === count($condition['value']);
} else {
return in_array($condition['value'], $fieldValue);
}
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkStartsWith($condition, $fieldValue): bool
{
2022-09-20 19:59:52 +00:00
return str_starts_with($fieldValue, $condition['value']);
}
2024-02-23 10:54:12 +00:00
private function checkEndsWith($condition, $fieldValue): bool
{
2022-09-20 19:59:52 +00:00
return str_ends_with($fieldValue, $condition['value']);
}
2024-02-23 10:54:12 +00:00
private function checkIsEmpty($condition, $fieldValue): bool
{
if (is_array($fieldValue)) {
2022-09-20 19:59:52 +00:00
return count($fieldValue) === 0;
}
2024-02-23 10:54:12 +00:00
return $fieldValue == '' || $fieldValue == null || ! $fieldValue;
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkGreaterThan($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && (float) $fieldValue > (float) $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkGreaterThanEqual($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && (float) $fieldValue >= (float) $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkLessThan($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && (float) $fieldValue < (float) $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkLessThanEqual($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && (float) $fieldValue <= (float) $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkBefore($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && $fieldValue > $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkAfter($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && $fieldValue < $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkOnOrBefore($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && $fieldValue >= $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkOnOrAfter($condition, $fieldValue): bool
{
return $condition['value'] && $fieldValue && $fieldValue <= $condition['value'];
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkPastWeek($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subDays(7)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkPastMonth($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subMonths(1)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkPastYear($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate <= now()->toDateString() && $fieldDate >= now()->subYears(1)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkNextWeek($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addDays(7)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkNextMonth($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addMonths(1)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkNextYear($condition, $fieldValue): bool
{
if (! $fieldValue) {
return false;
}
2022-09-20 19:59:52 +00:00
$fieldDate = date('Y-m-d', strtotime($fieldValue));
2024-02-23 10:54:12 +00:00
return $fieldDate >= now()->toDateString() && $fieldDate <= now()->addYears(1)->toDateString();
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
private function checkLength($condition, $fieldValue, $operator = '==='): bool
{
if (! $fieldValue || strlen($fieldValue) === 0) {
return false;
}
2023-01-21 11:58:01 +00:00
switch ($operator) {
2024-02-23 10:54:12 +00:00
case '===':
return strlen($fieldValue) === (int) $condition['value'];
case '!==':
return strlen($fieldValue) !== (int) $condition['value'];
case '>':
return strlen($fieldValue) > (int) $condition['value'];
case '>=':
return strlen($fieldValue) >= (int) $condition['value'];
case '<':
return strlen($fieldValue) < (int) $condition['value'];
case '<=':
return strlen($fieldValue) <= (int) $condition['value'];
2023-01-21 11:58:01 +00:00
}
2024-02-23 10:54:12 +00:00
2023-01-21 11:58:01 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function textConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'equals':
return $this->checkEquals($propertyCondition, $value);
case 'does_not_equal':
return ! $this->checkEquals($propertyCondition, $value);
case 'contains':
return $this->checkContains($propertyCondition, $value);
case 'does_not_contain':
return ! $this->checkContains($propertyCondition, $value);
case 'starts_with':
return $this->checkStartsWith($propertyCondition, $value);
case 'ends_with':
return $this->checkEndsWith($propertyCondition, $value);
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'is_not_empty':
return ! $this->checkIsEmpty($propertyCondition, $value);
case 'content_length_equals':
return $this->checkLength($propertyCondition, $value, '===');
case 'content_length_does_not_equal':
return $this->checkLength($propertyCondition, $value, '!==');
case 'content_length_greater_than':
return $this->checkLength($propertyCondition, $value, '>');
case 'content_length_greater_than_or_equal_to':
return $this->checkLength($propertyCondition, $value, '>=');
case 'content_length_less_than':
return $this->checkLength($propertyCondition, $value, '<');
case 'content_length_less_than_or_equal_to':
return $this->checkLength($propertyCondition, $value, '<=');
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function numberConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'equals':
return $this->checkEquals($propertyCondition, $value);
case 'does_not_equal':
return ! $this->checkEquals($propertyCondition, $value);
case 'greater_than':
return $this->checkGreaterThan($propertyCondition, $value);
case 'less_than':
return $this->checkLessThan($propertyCondition, $value);
case 'greater_than_or_equal_to':
return $this->checkGreaterThanEqual($propertyCondition, $value);
case 'less_than_or_equal_to':
return $this->checkLessThanEqual($propertyCondition, $value);
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'is_not_empty':
return ! $this->checkIsEmpty($propertyCondition, $value);
case 'content_length_equals':
return $this->checkLength($propertyCondition, $value, '===');
case 'content_length_does_not_equal':
return $this->checkLength($propertyCondition, $value, '!==');
case 'content_length_greater_than':
return $this->checkLength($propertyCondition, $value, '>');
case 'content_length_greater_than_or_equal_to':
return $this->checkLength($propertyCondition, $value, '>=');
case 'content_length_less_than':
return $this->checkLength($propertyCondition, $value, '<');
case 'content_length_less_than_or_equal_to':
return $this->checkLength($propertyCondition, $value, '<=');
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function checkboxConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'equals':
return $this->checkEquals($propertyCondition, $value);
case 'does_not_equal':
return ! $this->checkEquals($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function selectConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'equals':
return $this->checkEquals($propertyCondition, $value);
case 'does_not_equal':
return ! $this->checkEquals($propertyCondition, $value);
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'is_not_empty':
return ! $this->checkIsEmpty($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function dateConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'equals':
return $this->checkEquals($propertyCondition, $value);
case 'before':
return $this->checkBefore($propertyCondition, $value);
case 'after':
return $this->checkAfter($propertyCondition, $value);
case 'on_or_before':
return $this->checkOnOrBefore($propertyCondition, $value);
case 'on_or_after':
return $this->checkOnOrAfter($propertyCondition, $value);
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'past_week':
return $this->checkPastWeek($propertyCondition, $value);
case 'past_month':
return $this->checkPastMonth($propertyCondition, $value);
case 'past_year':
return $this->checkPastYear($propertyCondition, $value);
case 'next_week':
return $this->checkNextWeek($propertyCondition, $value);
case 'next_month':
return $this->checkNextMonth($propertyCondition, $value);
case 'next_year':
return $this->checkNextYear($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function multiSelectConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'contains':
return $this->checkListContains($propertyCondition, $value);
case 'does_not_contain':
return ! $this->checkListContains($propertyCondition, $value);
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'is_not_empty':
return ! $this->checkIsEmpty($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
2024-02-23 10:54:12 +00:00
private function filesConditionMet(array $propertyCondition, $value): bool
{
2022-09-20 19:59:52 +00:00
switch ($propertyCondition['operator']) {
2024-02-23 10:54:12 +00:00
case 'is_empty':
return $this->checkIsEmpty($propertyCondition, $value);
case 'is_not_empty':
return ! $this->checkIsEmpty($propertyCondition, $value);
2022-09-20 19:59:52 +00:00
}
2024-02-23 10:54:12 +00:00
2022-09-20 19:59:52 +00:00
return false;
}
}