ILIAS  release_7 Revision v7.30-3-g800a261c036
AbstractLayoutModification.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
21
22use Closure;
23use LogicException;
24use ReflectionFunction;
25use ReflectionException;
26
32{
36 private $priority;
41
42 public function isFinal() : bool
43 {
44 return false;
45 }
46
50 public function getPriority() : int
51 {
52 return $this->priority ?? LayoutModification::PRIORITY_LOW;
53 }
54
58 final public function withPriority(int $priority) : LayoutModification
59 {
60 if ((self::PRIORITY_LOW > $priority) || ($priority > self::PRIORITY_HIGH)) {
61 throw new LogicException("\$priority MUST be between LayoutModification::PRIORITY_LOW, LayoutModification::PRIORITY_MEDIUM or LayoutModification::PRIORITY_HIGH");
62 }
63 $clone = clone $this;
64 $clone->priority = $priority;
65
66 return $clone;
67 }
68
72 final public function withHighPriority() : LayoutModification
73 {
74 $clone = clone $this;
75 $clone->priority = LayoutModification::PRIORITY_HIGH;
76
77 return $clone;
78 }
79
83 final public function withLowPriority() : LayoutModification
84 {
85 $clone = clone $this;
86 $clone->priority = LayoutModification::PRIORITY_LOW;
87
88 return $clone;
89 }
90
95 final public function withModification(Closure $closure) : LayoutModification
96 {
97 $clone = clone $this;
98 $clone->modification = $closure;
99
100 return $clone;
101 }
102
106 final public function getModification() : Closure
107 {
108 return $this->modification;
109 }
110
114 final public function hasValidModification() : bool
115 {
116 try {
117 return $this->checkClosure();
118 } catch (\Throwable $e) {
119 if (defined('DEVMODE') && ((bool) DEVMODE) === true) {
120 throw $e;
121 }
122 return false;
123 }
124 }
125
129 private function checkClosure() : bool
130 {
131 $closure = $this->modification;
132 if (!$closure instanceof Closure) {
133 return false;
134 //throw new InvalidModification($this, "Modification is not a Closure");
135 }
136
137 try {
138 $r = new ReflectionFunction($closure);
139
140 $requested_return_type = $this->getClosureReturnType();
141 $requested_first_argument_type = $this->getClosureFirstArgumentType();
142
143 // First Argument
144 $param = $r->getParameters()[0] ?? null;
145 // No first argument
146 if ($param === null) {
147 throw new InvalidModification($this, "Modification has no first parameter");
148 }
149 // First argument has no type
150 if (!$param->hasType()) {
151 throw new InvalidModification($this, "Modification's first parameter has no type");
152 }
153 // First argument has wrong type
154 if ($param->getType()->getName() !== $requested_first_argument_type) {
155 throw new InvalidModification($this, "Modification's first parameter does not match the requested type");
156 }
157 // First argument nullable
158 if ($this->firstArgumentAllowsNull() && !$param->allowsNull()) {
159 throw new InvalidModification($this, "Modification's first parameter must be nullable");
160 }
161
162 // Return type
163
164 // Return type not available
165 if (!$r->hasReturnType()) {
166 throw new InvalidModification($this, "Modification has no return type");
167 }
168 // return type check
169 if ($r->getReturnType()->getName() !== $requested_return_type) {
170 throw new InvalidModification($this, "Modification's return type does not match the requested type");
171 }
172
173 // Return type nullable
174 if ($this->returnTypeAllowsNull() && !$r->getReturnType()->allowsNull()) {
175 throw new InvalidModification($this, "Modification's return type must be nullable");
176 }
177 } catch (ReflectionException $e) {
178 throw new InvalidModification($this, "Modification threw an exception while checking the closure");
179 }
180
181 return true;
182 }
183}
An exception for terminatinating execution or to throw for unit testing.
$param
Definition: xapitoken.php:29