ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
Input.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2017 Richard Klees <richard.klees@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4
6
7use ILIAS\Data\Factory as DataFactory;
19
23abstract class Input implements C\Input\Field\Input, InputInternal
24{
27 use Triggerer;
31 protected $data_factory;
35 protected $refinery;
39 protected $label;
43 protected $byline;
47 protected $is_required = false;
51 protected $is_disabled = false;
58 protected $value = null;
64 protected $error = null;
68 private $name = null;
76 protected $content = null;
80 private $operations;
81
82
91 public function __construct(
92 DataFactory $data_factory,
93 Factory $refinery,
94 $label,
95 $byline
96 ) {
97 $this->data_factory = $data_factory;
98 $this->refinery = $refinery;
99 $this->checkStringArg("label", $label);
100 if ($byline !== null) {
101 $this->checkStringArg("byline", $byline);
102 }
103 $this->label = $label;
104 $this->byline = $byline;
105 $this->operations = [];
106 }
107
108 // Observable properties of the input as it is shown to the client.
109
110
114 public function getLabel()
115 {
116 return $this->label;
117 }
118
119
123 public function withLabel($label)
124 {
125 $this->checkStringArg("label", $label);
126 $clone = clone $this;
127 $clone->label = $label;
128
129 return $clone;
130 }
131
132
136 public function getByline()
137 {
138 return $this->byline;
139 }
140
141
145 public function withByline($byline)
146 {
147 $this->checkStringArg("byline", $byline);
148 $clone = clone $this;
149 $clone->byline = $byline;
150
151 return $clone;
152 }
153
154
158 public function isRequired()
159 {
160 return $this->is_required;
161 }
162
163
167 public function withRequired($is_required)
168 {
169 $this->checkBoolArg("is_required", $is_required);
170 $clone = clone $this;
171 $clone->is_required = $is_required;
172
173 return $clone;
174 }
175
176
183 abstract protected function getConstraintForRequirement();
184
185
189 public function isDisabled()
190 {
191 return $this->is_disabled;
192 }
193
194
198 public function withDisabled($is_disabled)
199 {
200 $this->checkBoolArg("is_disabled", $is_disabled);
201 $clone = clone $this;
202 $clone->is_disabled = $is_disabled;
203
204 return $clone;
205 }
206
207
213 public function getValue()
214 {
215 return $this->value;
216 }
217
218
228 public function withValue($value)
229 {
230 $this->checkArg("value", $this->isClientSideValueOk($value), "Display value does not match input type.");
231 $clone = clone $this;
232 $clone->value = $value;
233
234 return $clone;
235 }
236
237
245 abstract protected function isClientSideValueOk($value) : bool;
246
247
253 public function getError()
254 {
255 return $this->error;
256 }
257
258
266 public function withError($error)
267 {
268 $clone = clone $this;
269 $clone->setError($error);
270
271 return $clone;
272 }
273
274
282 private function setError($error)
283 {
284 $this->checkStringArg("error", $error);
285 $this->error = $error;
286 }
287
296 {
297 $clone = clone $this;
298 $clone->setAdditionalTransformation($trafo);
299
300 return $clone;
301 }
302
303
315 {
316 $this->operations[] = $trafo;
317 if ($this->content !== null) {
318 if (!$this->content->isError()) {
319 $this->content = $trafo->applyTo($this->content);
320 }
321 if ($this->content->isError()) {
322 $this->setError($this->content->error());
323 }
324 }
325 }
326
327 // Implementation of InputInternal
328
329 // This is the machinery to be used to process the input from the client side.
330 // This should not be exposed to the consumers of the inputs. These methods
331 // should instead only be used by the forms wrapping the input.
332
336 final public function getName()
337 {
338 return $this->name;
339 }
340
341
346 {
347 $clone = clone $this;
348 $clone->name = $source->getNewName();
349
350 return $clone;
351 }
352
353
360 public function withInput(InputData $input)
361 {
362 if ($this->getName() === null) {
363 throw new \LogicException("Can only collect if input has a name.");
364 }
365
366 //TODO: Discuss, is this correct here. If there is no input contained in this post
367 //We assign null. Note that unset checkboxes are not contained in POST.
368 if (!$this->isDisabled()) {
369 $value = $input->getOr($this->getName(), null);
370 // ATTENTION: There was a special case for the Filter Input Container here,
371 // which lead to #27909. The issue will most certainly appear again in. If
372 // you are the one debugging it and came here: Please don't put knowledge
373 // of the special case for the filter in this general class. Have a look
374 // into https://mantis.ilias.de/view.php?id=27909 for the according discussion.
375 $clone = $this->withValue($value);
376 } else {
377 $clone = $this;
378 }
379
380 $clone->content = $this->applyOperationsTo($clone->getValue());
381 if ($clone->content->isError()) {
382 return $clone->withError("" . $clone->content->error());
383 }
384
385 return $clone;
386 }
387
388
396 protected function applyOperationsTo($res)
397 {
398 if ($res === null && !$this->isRequired()) {
399 return $this->data_factory->ok($res);
400 }
401
402 $res = $this->data_factory->ok($res);
403 foreach ($this->getOperations() as $op) {
404 if ($res->isError()) {
405 return $res;
406 }
407
408 $res = $op->applyTo($res);
409 }
410
411 return $res;
412 }
413
414
420 private function getOperations()
421 {
422 if ($this->isRequired()) {
423 $op = $this->getConstraintForRequirement();
424 if ($op !== null) {
425 yield $op;
426 }
427 }
428
429 foreach ($this->operations as $op) {
430 yield $op;
431 }
432 }
433
434
438 public function getContent()
439 {
440 if (is_null($this->content)) {
441 throw new \LogicException("No content of this field has been evaluated yet. Seems withRequest was not called.");
442 }
443 return $this->content;
444 }
445
449 public function withOnUpdate(Signal $signal)
450 {
451 return $this->withTriggeredSignal($signal, 'update');
452 }
453
457 public function appendOnUpdate(Signal $signal)
458 {
459 return $this->appendTriggeredSignal($signal, 'update');
460 }
461}
An exception for terminatinating execution or to throw for unit testing.
Builds data types.
Definition: Factory.php:20
getByline()
Get the byline of the input.string|null
Definition: Input.php:136
withLabel($label)
Get an input like this, but with a replaced label.Input
Definition: Input.php:123
withError($error)
Get an input like this one, with a different error.
Definition: Input.php:266
withOnUpdate(Signal $signal)
Trigger a signal of another component on update.$this
Definition: Input.php:449
getName()
The name of the input as used in HTML.string
Definition: Input.php:336
isRequired()
Is this field required?bool
Definition: Input.php:158
getContent()
Get the current content of the input.Result
Definition: Input.php:438
withNameFrom(NameSource $source)
Get an input like this one, with a different name.Input
Definition: Input.php:345
getOperations()
Get the operations that should be performed on the input.
Definition: Input.php:420
appendOnUpdate(Signal $signal)
Get a component like this, triggering a signal of another component on update.In contrast to withOnUp...
Definition: Input.php:457
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Input.php:228
withInput(InputData $input)
Collects the input, applies trafos on the input and returns a new input reflecting the data that was ...
Definition: Input.php:360
getConstraintForRequirement()
This may return a constraint that will be checked first if the field is required.
withDisabled($is_disabled)
Get an input like this, but set it to a disabled state.Input
Definition: Input.php:198
withRequired($is_required)
Get an input like this, but set the field to be required (or not).Input
Definition: Input.php:167
getError()
The error of the input as used in HTML.
Definition: Input.php:253
getValue()
Get the value that is displayed in the input client side.
Definition: Input.php:213
isDisabled()
Is this input disabled?bool
Definition: Input.php:189
__construct(DataFactory $data_factory, Factory $refinery, $label, $byline)
Input constructor.
Definition: Input.php:91
applyOperationsTo($res)
Applies the operations in this instance to the value.
Definition: Input.php:396
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:314
withAdditionalTransformation(Transformation $trafo)
Apply a transformation to the current or future content.
Definition: Input.php:295
setError($error)
Set an error on this input.
Definition: Input.php:282
withByline($byline)
Get an input like this, but with an additional/replaced label.Input
Definition: Input.php:145
getLabel()
Get the label of the input.string
Definition: Input.php:114
error($a_errmsg)
set error message @access public
A constraint encodes some resrtictions on values.
Definition: Constraint.php:15
A transformation is a function from one datatype to another.
applyTo(Result $data)
Perform the transformation and reify possible failures.
This describes commonalities between all inputs.
Definition: Input.php:32
withValue($value)
Get an input like this with another value displayed on the client side.
isDisabled()
Is this input disabled?
isRequired()
Is this field required?
Describes the interface of inputs that is used for internal processing of data from the client.
Describes how Input-Elements want to interact with posted data.
Definition: InputData.php:13
getOr($name, $default)
Get a named value from the data and fallback to default if that name does not exist.
Describes a source for input names.
Definition: NameSource.php:11
if($format !==null) $name
Definition: metadata.php:230
$source
Definition: metadata.php:76
withTriggeredSignal(Component\Signal $signal, $event)
Add a triggered signal, replacing any other signals registered on the same event.
Definition: Triggerer.php:48
checkStringArg($which, $value)
Throw an InvalidArgumentException if $value is no string.
checkArg($which, $check, $message)
/** Throw an InvalidArgumentException containing the message if $check is false.
appendTriggeredSignal(Component\Signal $signal, $event)
Append a triggered signal to other signals of the same event.
Definition: Triggerer.php:31
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
checkBoolArg($which, $value)
Throw an InvalidArgumentException if $value is not a bool.
trait ComponentHelper
Provides common functionality for component implementations.
foreach($_POST as $key=> $value) $res