marcosh /
php-validation-dsl
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Marcosh\PhpValidationDSL\Result; |
||
| 6 | |||
| 7 | use Marcosh\PhpValidationDSL\Equality; |
||
| 8 | |||
| 9 | final class ValidationResult |
||
| 10 | { |
||
| 11 | /** |
||
| 12 | * @var bool |
||
| 13 | */ |
||
| 14 | private $isValid; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * @var mixed |
||
| 18 | */ |
||
| 19 | private $validContent; |
||
| 20 | |||
| 21 | /** |
||
| 22 | * @var array |
||
| 23 | */ |
||
| 24 | private $messages; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * @param bool $isValid |
||
| 28 | * @param mixed $validContent |
||
| 29 | * @param array $messages |
||
| 30 | */ |
||
| 31 | private function __construct( |
||
| 32 | bool $isValid, |
||
| 33 | $validContent, |
||
| 34 | array $messages |
||
| 35 | ) { |
||
| 36 | $this->isValid = $isValid; |
||
| 37 | $this->validContent = $validContent; |
||
| 38 | $this->messages = $messages; |
||
| 39 | } |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @param mixed $validContent |
||
| 43 | * @return self |
||
| 44 | */ |
||
| 45 | public static function valid($validContent): self |
||
| 46 | { |
||
| 47 | return new self(true, $validContent, []); |
||
| 48 | } |
||
| 49 | |||
| 50 | public static function errors(array $messages): self |
||
| 51 | { |
||
| 52 | return new self(false, null, $messages); |
||
| 53 | } |
||
| 54 | |||
| 55 | public function join(self $that, callable $joinValid, callable $joinErrors): self |
||
| 56 | { |
||
| 57 | if (! $this->isValid || ! $that->isValid) { |
||
| 58 | return self::errors($joinErrors($this->messages, $that->messages)); |
||
| 59 | } |
||
| 60 | |||
| 61 | return self::valid($joinValid($this->validContent, $that->validContent)); |
||
| 62 | } |
||
| 63 | |||
| 64 | public function meet(self $that, callable $joinErrors): self |
||
| 65 | { |
||
| 66 | if ($this->isValid) { |
||
| 67 | return $this; |
||
| 68 | } |
||
| 69 | |||
| 70 | if ($that->isValid) { |
||
| 71 | return $that; |
||
| 72 | } |
||
| 73 | |||
| 74 | return self::errors($joinErrors($this->messages, $that->messages)); |
||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * @param callable $processValid : validContent -> mixed |
||
| 79 | * @param callable $processErrors : messages -> mixed |
||
| 80 | * @return mixed |
||
| 81 | */ |
||
| 82 | public function process( |
||
| 83 | callable $processValid, |
||
| 84 | callable $processErrors |
||
| 85 | ) { |
||
| 86 | if (! $this->isValid) { |
||
| 87 | return $processErrors($this->messages); |
||
| 88 | } |
||
| 89 | |||
| 90 | return $processValid($this->validContent); |
||
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * @param callable $map : validContent -> newValidContent |
||
| 95 | * @return ValidationResult |
||
| 96 | */ |
||
| 97 | public function map(callable $map): self |
||
| 98 | { |
||
| 99 | return $this->process( |
||
| 100 | /** @param mixed $validContent */ |
||
| 101 | function ($validContent) use ($map): self { |
||
| 102 | return self::valid($map($validContent)); |
||
| 103 | }, |
||
| 104 | function (array $messages): self { |
||
| 105 | return self::errors($messages); |
||
| 106 | } |
||
| 107 | ); |
||
| 108 | } |
||
| 109 | |||
| 110 | public function mapErrors(callable $map): self |
||
| 111 | { |
||
| 112 | return $this->process( |
||
| 113 | /** @param mixed $validContent */ |
||
| 114 | function ($validContent): self { |
||
| 115 | return self::valid($validContent); |
||
| 116 | }, |
||
| 117 | function (array $messages) use ($map): self { |
||
| 118 | return self::errors($map($messages)); |
||
| 119 | } |
||
| 120 | ); |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * @param ValidationResult $apply contains a callable |
||
| 125 | * @return self |
||
| 126 | */ |
||
| 127 | public function apply(ValidationResult $apply): self |
||
| 128 | { |
||
| 129 | return $apply->process( |
||
| 130 | function (callable $validApply): self { |
||
| 131 | return $this->map($validApply); |
||
| 132 | }, |
||
| 133 | /** @return mixed */ |
||
| 134 | function (array $applyMessages) { |
||
| 135 | return $this->process( |
||
| 136 | /** @param mixed $validContent */ |
||
| 137 | function ($validContent) use ($applyMessages): self { |
||
|
0 ignored issues
–
show
|
|||
| 138 | return self::errors($applyMessages); |
||
| 139 | }, |
||
| 140 | function (array $messages) use ($applyMessages): self { |
||
| 141 | return self::errors(array_merge($applyMessages, $messages)); |
||
| 142 | } |
||
| 143 | ); |
||
| 144 | } |
||
| 145 | ); |
||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * @param callable $bind : validContent -> ValidationResult |
||
| 150 | * @return self |
||
| 151 | */ |
||
| 152 | public function bind(callable $bind): self |
||
| 153 | { |
||
| 154 | return $this->process( |
||
| 155 | /** @param mixed $validContent */ |
||
| 156 | function ($validContent) use ($bind): self { |
||
| 157 | return $bind($validContent); |
||
| 158 | }, |
||
| 159 | function (array $messages): self { |
||
| 160 | return self::errors($messages); |
||
| 161 | } |
||
| 162 | ); |
||
| 163 | } |
||
| 164 | |||
| 165 | public function equals(self $that): bool |
||
| 166 | { |
||
| 167 | if (is_object($this->validContent) && is_object($that->validContent) && |
||
| 168 | get_class($this->validContent) === get_class($that->validContent) && |
||
| 169 | $this->validContent instanceof Equality) { |
||
| 170 | $contentEquality = $this->validContent->equals($that->validContent); |
||
| 171 | } else { |
||
| 172 | $contentEquality = $this->validContent === $that->validContent; |
||
| 173 | } |
||
| 174 | |||
| 175 | return ($this->isValid && $that->isValid && $contentEquality) || |
||
| 176 | (!$this->isValid && !$that->isValid && $this->messages === $that->messages); |
||
| 177 | } |
||
| 178 | } |
||
| 179 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.