ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
12 use ILIAS\UI\Component as C;
19 
23 abstract class Input implements C\Input\Field\Input, InputInternal
24 {
25  use ComponentHelper;
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 
314  protected function setAdditionalTransformation(Transformation $trafo)
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 
345  public function withNameFrom(NameSource $source)
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 }
isDisabled()
Is this input disabled?
getLabel()
Get the label of the input.string
Definition: Input.php:114
setError($error)
Set an error on this input.
Definition: Input.php:282
withLabel($label)
Get an input like this, but with a replaced label.Input
Definition: Input.php:123
__construct(DataFactory $data_factory, Factory $refinery, $label, $byline)
Input constructor.
Definition: Input.php:91
getName()
The name of the input as used in HTML.string
Definition: Input.php:336
applyTo(Result $data)
Perform the transformation and reify possible failures.
applyOperationsTo($res)
Applies the operations in this instance to the value.
Definition: Input.php:396
Describes the interface of inputs that is used for internal processing of data from the client...
checkArg($which, $check, $message)
/** Throw an InvalidArgumentException containing the message if $check is false.
withAdditionalTransformation(Transformation $trafo)
Apply a transformation to the current or future content.
Definition: Input.php:295
getOperations()
Get the operations that should be performed on the input.
Definition: Input.php:420
withRequired($is_required)
Get an input like this, but set the field to be required (or not).Input
Definition: Input.php:167
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
trait ComponentHelper
Provides common functionality for component implementations.
getOr($name, $default)
Get a named value from the data and fallback to default if that name does not exist.
checkStringArg($which, $value)
Throw an InvalidArgumentException if $value is no string.
Describes how Input-Elements want to interact with posted data.
Definition: InputData.php:12
if($format !==null) $name
Definition: metadata.php:230
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
withOnUpdate(Signal $signal)
Trigger a signal of another component on update.A signal of another component$this ...
Definition: Input.php:449
checkBoolArg($which, $value)
Throw an InvalidArgumentException if $value is not a bool.
foreach($_POST as $key=> $value) $res
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Input.php:228
appendTriggeredSignal(Component\Signal $signal, $event)
Append a triggered signal to other signals of the same event.
Definition: Triggerer.php:31
isRequired()
Is this field required?
setAdditionalTransformation(Transformation $trafo)
Apply a transformation to the current or future content.
Definition: Input.php:314
getByline()
Get the byline of the input.string|null
Definition: Input.php:136
Builds data types.
Definition: Factory.php:19
getError()
The error of the input as used in HTML.
Definition: Input.php:253
isDisabled()
Is this input disabled?bool
Definition: Input.php:189
withValue($value)
Get an input like this with another value displayed on the client side.
getNewName()
Generates a unique name on every call.
getContent()
Get the current content of the input.Result
Definition: Input.php:438
A transformation is a function from one datatype to another.
withByline($byline)
Get an input like this, but with an additional/replaced label.Input
Definition: Input.php:145
Describes a source for input names.
Definition: NameSource.php:10
appendOnUpdate(Signal $signal)
Get a component like this, triggering a signal of another component on update.In contrast to withOnUp...
Definition: Input.php:457
withNameFrom(NameSource $source)
Get an input like this one, with a different name.Input
Definition: Input.php:345
isRequired()
Is this field required?bool
Definition: Input.php:158
$source
Definition: metadata.php:76
withError($error)
Get an input like this one, with a different error.
Definition: Input.php:266
getValue()
Get the value that is displayed in the input client side.
Definition: Input.php:213
withDisabled($is_disabled)
Get an input like this, but set it to a disabled state.Input
Definition: Input.php:198
withTriggeredSignal(Component\Signal $signal, $event)
Add a triggered signal, replacing any other signals registered on the same event. ...
Definition: Triggerer.php:48