Skip to content

Commit 83fed2f

Browse files
committed
refactoring
1 parent 052c1d1 commit 83fed2f

File tree

1 file changed

+59
-73
lines changed

1 file changed

+59
-73
lines changed

src/Application/UI/ComponentReflection.php

Lines changed: 59 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -33,40 +33,39 @@ final class ComponentReflection extends \ReflectionClass
3333

3434

3535
/**
36-
* Returns array of classes persistent parameters. They have public visibility,
37-
* are non-static and have annotation @persistent.
36+
* Returns array of persistent properties. They are public and have attribute #[Persistent] or annotation @persistent.
3837
*/
39-
public function getPersistentParams(?string $class = null): array
38+
public function getPersistentParams(): array
4039
{
41-
$class = $class ?? $this->getName();
42-
$params = &self::$ppCache[$class];
40+
$params = &self::$ppCache[$this->getName()];
4341
if ($params !== null) {
4442
return $params;
4543
}
4644

4745
$params = [];
48-
if (is_subclass_of($class, Component::class)) {
49-
$isPresenter = is_subclass_of($class, Presenter::class);
50-
$defaults = get_class_vars($class);
51-
foreach ($defaults as $name => $default) {
52-
$rp = new \ReflectionProperty($class, $name);
53-
if (!$rp->isStatic()
54-
&& ((PHP_VERSION_ID >= 80000 && $rp->getAttributes(Nette\Application\Attributes\Persistent::class))
55-
|| self::parseAnnotation($rp, 'persistent'))
56-
) {
57-
$params[$name] = [
58-
'def' => $default,
59-
'type' => self::getPropertyType($rp, $default),
60-
'since' => $isPresenter ? Nette\Utils\Reflection::getPropertyDeclaringClass($rp)->getName() : null,
61-
];
62-
}
46+
$isPresenter = $this->isSubclassOf(Presenter::class);
47+
$defaults = $this->getDefaultProperties();
48+
foreach ($this->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
49+
if (!$prop->isStatic()
50+
&& (self::parseAnnotation($prop, 'persistent')
51+
|| (PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Persistent::class)))
52+
) {
53+
$default = $defaults[$prop->getName()] ?? null;
54+
$params[$prop->getName()] = [
55+
'def' => $default,
56+
'type' => self::getPropertyType($prop, $default),
57+
'since' => $isPresenter ? Nette\Utils\Reflection::getPropertyDeclaringClass($prop)->getName() : null,
58+
];
6359
}
60+
}
6461

65-
foreach ($this->getPersistentParams(get_parent_class($class)) as $name => $param) {
62+
if ($this->getParentClass()->isSubclassOf(Component::class)) {
63+
$parent = new self($this->getParentClass()->getName());
64+
foreach ($parent->getPersistentParams() as $name => $meta) {
6665
if (isset($params[$name])) {
67-
$params[$name]['since'] = $param['since'];
66+
$params[$name]['since'] = $meta['since'];
6867
} else {
69-
$params[$name] = $param;
68+
$params[$name] = $meta;
7069
}
7170
}
7271
}
@@ -75,25 +74,22 @@ public function getPersistentParams(?string $class = null): array
7574
}
7675

7776

78-
public function getPersistentComponents(?string $class = null): array
77+
public function getPersistentComponents(): array
7978
{
80-
$class = $class ?? $this->getName();
79+
$class = $this->getName();
8180
$components = &self::$pcCache[$class];
8281
if ($components !== null) {
8382
return $components;
8483
}
8584

8685
$components = [];
87-
if (is_subclass_of($class, Presenter::class)) {
86+
if ($this->isSubclassOf(Presenter::class)) {
8887
foreach ($class::getPersistentComponents() as $name => $meta) {
89-
if (is_string($meta)) {
90-
$name = $meta;
91-
}
92-
93-
$components[$name] = ['since' => $class];
88+
$components[is_string($meta) ? $meta : $name] = ['since' => $class];
9489
}
9590

96-
$components = $this->getPersistentComponents(get_parent_class($class)) + $components;
91+
$parent = new self($this->getParentClass()->getName());
92+
$components = $parent->getPersistentComponents() + $components;
9793
}
9894

9995
return $components;
@@ -197,12 +193,28 @@ public static function combineArgs(\ReflectionFunctionAbstract $method, array $a
197193

198194

199195
/**
200-
* Non data-loss type conversion.
196+
* Lossless type conversion.
201197
*/
202198
public static function convertType(&$val, string $types): bool
203199
{
200+
$scalars = ['string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'boolean' => 1, 'double' => 1, 'integer' => 1];
201+
$testable = ['iterable' => 1, 'object' => 1, 'array' => 1, 'null' => 1];
202+
204203
foreach (explode('|', $types) as $type) {
205-
if (self::convertSingleType($val, $type)) {
204+
if (isset($scalars[$type])) {
205+
$ok = self::castScalar($val, $type);
206+
} elseif (isset($testable[$type])) {
207+
$ok = "is_$type"($val);
208+
} elseif ($type === 'scalar') { // special type due to historical reasons
209+
$ok = !is_array($val);
210+
} elseif ($type === 'mixed') {
211+
$ok = true;
212+
} elseif ($type === 'callable') { // intentionally disabled for security reasons
213+
$ok = false;
214+
} else {
215+
$ok = $val instanceof $type;
216+
}
217+
if ($ok) {
206218
return true;
207219
}
208220
}
@@ -212,52 +224,26 @@ public static function convertType(&$val, string $types): bool
212224

213225

214226
/**
215-
* Non data-loss type conversion.
227+
* Lossless type casting.
216228
*/
217-
private static function convertSingleType(&$val, string $type): bool
229+
private static function castScalar(&$val, string $type): bool
218230
{
219-
$builtin = [
220-
'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1,
221-
'callable' => 1, 'iterable' => 1, 'void' => 1, 'null' => 1, 'mixed' => 1,
222-
'boolean' => 1, 'integer' => 1, 'double' => 1, 'scalar' => 1,
223-
];
224-
225-
if (empty($builtin[$type])) {
226-
return $val instanceof $type;
227-
228-
} elseif ($type === 'object') {
229-
return is_object($val);
230-
231-
} elseif ($type === 'callable') {
232-
return false;
233-
234-
} elseif ($type === 'scalar') {
235-
return !is_array($val);
236-
237-
} elseif ($type === 'array' || $type === 'iterable') {
238-
return is_array($val);
239-
240-
} elseif ($type === 'mixed') {
241-
return true;
242-
243-
} elseif (!is_scalar($val)) { // array, resource, null, etc.
231+
if (!is_scalar($val)) {
244232
return false;
233+
}
245234

246-
} else {
247-
$tmp = ($val === false ? '0' : (string) $val);
248-
if ($type === 'double' || $type === 'float') {
249-
$tmp = preg_replace('#\.0*$#D', '', $tmp);
250-
}
251-
252-
$orig = $tmp;
253-
settype($tmp, $type);
254-
if ($orig !== ($tmp === false ? '0' : (string) $tmp)) {
255-
return false; // data-loss occurs
256-
}
235+
$tmp = ($val === false ? '0' : (string) $val);
236+
if ($type === 'double' || $type === 'float') {
237+
$tmp = preg_replace('#\.0*$#D', '', $tmp);
238+
}
257239

258-
$val = $tmp;
240+
$orig = $tmp;
241+
settype($tmp, $type);
242+
if ($orig !== ($tmp === false ? '0' : (string) $tmp)) {
243+
return false; // data-loss occurs
259244
}
260245

246+
$val = $tmp;
261247
return true;
262248
}
263249

0 commit comments

Comments
 (0)