ILIAS  release_7 Revision v7.30-3-g800a261c036
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
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 FormInputInternal
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 $error = $clone->content->error();
383 if ($error instanceof \Exception) {
384 $error = $error->getMessage();
385 }
386 return $clone->withError("" . $error);
387 }
388
389 return $clone;
390 }
391
392
400 protected function applyOperationsTo($res)
401 {
402 if ($res === null && !$this->isRequired()) {
403 return $this->data_factory->ok($res);
404 }
405
406 $res = $this->data_factory->ok($res);
407 foreach ($this->getOperations() as $op) {
408 if ($res->isError()) {
409 return $res;
410 }
411
412 $res = $op->applyTo($res);
413 }
414
415 return $res;
416 }
417
418
424 private function getOperations()
425 {
426 if ($this->isRequired()) {
427 $op = $this->getConstraintForRequirement();
428 if ($op !== null) {
429 yield $op;
430 }
431 }
432
433 foreach ($this->operations as $op) {
434 yield $op;
435 }
436 }
437
438
442 public function getContent()
443 {
444 if (is_null($this->content)) {
445 throw new \LogicException("No content of this field has been evaluated yet. Seems withRequest was not called.");
446 }
447 return $this->content;
448 }
449
453 public function withOnUpdate(Signal $signal)
454 {
455 return $this->withTriggeredSignal($signal, 'update');
456 }
457
461 public function appendOnUpdate(Signal $signal)
462 {
463 return $this->appendTriggeredSignal($signal, 'update');
464 }
465}
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:453
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:442
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:424
appendOnUpdate(Signal $signal)
Get a component like this, triggering a signal of another component on update.In contrast to withOnUp...
Definition: Input.php:461
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:400
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.
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