ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
Input.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use ILIAS\Data\Factory as DataFactory;
26use ILIAS\Refinery\Factory as Refinery;
29use ILIAS\UI\Implementation\Component\ComponentHelper;
34use LogicException;
35use Generator;
36use InvalidArgumentException;
38
42abstract class Input implements InputInternal
43{
44 use ComponentHelper;
45
52 protected $value = null;
53
57 protected ?string $error = null;
58
59 private ?string $name = null;
60
61 protected ?string $dedicated_name = null;
62
68 protected ?Result $content = null;
69
73 protected array $operations = [];
74
78 public function __construct(
79 protected DataFactory $data_factory,
80 protected Refinery $refinery,
81 ) {
82 }
83
89 public function getValue()
90 {
91 return $this->value;
92 }
93
101 public function withValue($value): self
102 {
103 $this->checkArg("value", null === $value || $this->isClientSideValueOk($value), "Display value does not match input type.");
104 $clone = clone $this;
105 $clone->value = $value;
106 return $clone;
107 }
108
117 abstract protected function isClientSideValueOk($value): bool;
118
122 public function getError(): ?string
123 {
124 return $this->error;
125 }
126
130 public function withError(string $error): self
131 {
132 $clone = clone $this;
133 $clone->setError($error);
134 return $clone;
135 }
136
140 private function setError(string $error): void
141 {
142 $this->error = $error;
143 }
144
148 public function withAdditionalTransformation(Transformation $trafo): self
149 {
150 $clone = clone $this;
151 $clone->setAdditionalTransformation($trafo);
152 return $clone;
153 }
154
161 protected function setAdditionalTransformation(Transformation $trafo): void
162 {
163 $this->operations[] = $trafo;
164 if ($this->content !== null) {
165 if (!$this->content->isError()) {
166 $this->content = $trafo->applyTo($this->content);
167 }
168 if ($this->content->isError()) {
169 $this->setError($this->content->error());
170 }
171 }
172 }
173
177 final public function getDedicatedName(): ?string
178 {
179 return $this->dedicated_name;
180 }
181
185 final public function withDedicatedName(string $dedicated_name): self
186 {
187 $clone = clone $this;
188 $clone->dedicated_name = $dedicated_name;
189 return $clone;
190 }
191
195 final public function getName(): ?string
196 {
197 return $this->name;
198 }
199
203 public function withNameFrom(NameSource $source, ?string $parent_name = null): self
204 {
205 $clone = clone $this;
206 if ($source instanceof DynamicInputsNameSource) {
207 $clone->name = '';
208 } else {
209 $clone->name = ($parent_name !== null) ? $parent_name . '/' : '';
210 }
211 $clone->name .= ($clone->dedicated_name !== null)
212 ? $source->getNewDedicatedName($clone->dedicated_name)
213 : $source->getNewName();
214 return $clone;
215 }
216
223 public function withInput(InputData $input): self
224 {
225 if ($this->getName() === null) {
226 throw new LogicException("Can only collect if input has a name.");
227 }
228
229
230 //TODO: Discuss, is this correct here. If there is no input contained in this post
231 //We assign null. Note that unset checkboxes are not contained in POST.
232 $value = $input->getOr($this->getName(), null);
233 // ATTENTION: There was a special case for the Filter Input Container here,
234 // which lead to #27909. The issue will most certainly appear again in. If
235 // you are the one debugging it and came here: Please don't put knowledge
236 // of the special case for the filter in this general class. Have a look
237 // into https://mantis.ilias.de/view.php?id=27909 for the according discussion.
238 $clone = $this->withValue($value);
239
240 $clone->content = $this->applyOperationsTo($clone->getValue());
241 if ($clone->content->isError()) {
242 $error = $clone->content->error();
243 if ($error instanceof \Exception) {
245 }
246 return $clone->withError("" . $error);
247 }
248
249 return $clone;
250 }
251
257 protected function applyOperationsTo($res): Result
258 {
259 $res = $this->data_factory->ok($res);
260 foreach ($this->getOperations() as $op) {
261 if ($res->isError()) {
262 return $res;
263 }
264 $res = $op->applyTo($res);
265 }
266
267 return $res;
268 }
269
275 protected function getOperations(): Generator
276 {
277 foreach ($this->operations as $op) {
278 yield $op;
279 }
280 }
281
285 public function getContent(): Result
286 {
287 if (is_null($this->content)) {
288 throw new LogicException("No content of this field has been evaluated yet. Seems withRequest was not called.");
289 }
290 return $this->content;
291 }
292}
Builds data types.
Definition: Factory.php:36
Other than the FormInputNameSource this name source is for inputs that can be dynamically added multi...
getName()
The name of the input as used in HTML.
Definition: Input.php:195
withInput(InputData $input)
Collects the input, applies trafos on the input and returns a new input reflecting the data that was ...
Definition: Input.php:223
setError(string $error)
Set an error on this input.
Definition: Input.php:140
applyOperationsTo($res)
Applies the operations in this instance to the value.
Definition: Input.php:257
withDedicatedName(string $dedicated_name)
Sets an optional dedicated name for this input which is used in the NAME attribute of the rendered in...
Definition: Input.php:185
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Input.php:101
withAdditionalTransformation(Transformation $trafo)
Apply a transformation to the current or future content.
Definition: Input.php:148
getValue()
Get the value that is displayed in the input client side.
Definition: Input.php:89
withNameFrom(NameSource $source, ?string $parent_name=null)
Definition: Input.php:203
getOperations()
Get the operations that should be performed on the input.
Definition: Input.php:275
__construct(protected DataFactory $data_factory, protected Refinery $refinery,)
Input constructor.
Definition: Input.php:78
withError(string $error)
Get an input like this one, with a different error.
Definition: Input.php:130
getError()
The error of the input as used in HTML.
Definition: Input.php:122
isClientSideValueOk($value)
Check if the value is good to be displayed client side.
setAdditionalTransformation(Transformation $trafo)
Apply a transformation to the current or future content.
Definition: Input.php:161
getContent()
Get the current content of the input.
Definition: Input.php:285
Result $content
This is the current content of the input in the abstraction.
Definition: Input.php:68
ilErrorHandling $error
Definition: class.ilias.php:69
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:29
A constraint encodes some resrtictions on values.
Definition: Constraint.php:32
A transformation is a function from one datatype to another.
applyTo(Result $result)
Perform the transformation and reify possible failures.
Describes how Input-Elements want to interact with posted data.
Definition: InputData.php:30
getOr(string $name, $default)
Get a named value from the data and fallback to default if that name does not exist.
This describes commonalities between all inputs.
Definition: Input.php:47
withValue($value)
Get an input like this with another value displayed on the client side.
Describes the interface of inputs that is used for internal processing of data from the client.
Describes a source for input names.
Definition: NameSource.php:27
getNewName()
Generates a unique name on every call.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setError(string $error)
This setter will be used by withInput() to set possible errors.
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
foreach($_POST as $key=> $value) $res