|
55 | 55 | use Kint\Value\Representation\ContainerRepresentation;
|
56 | 56 | use Kint\Value\StringValue;
|
57 | 57 | use LogicException;
|
| 58 | +use ReflectionClass; |
58 | 59 |
|
59 | 60 | class DomPlugin extends AbstractPlugin implements PluginBeginInterface
|
60 | 61 | {
|
61 | 62 | /**
|
62 |
| - * Reflection doesn't work below 8.1, also it won't show readonly status. |
| 63 | + * Reflection doesn't show readonly status. |
63 | 64 | *
|
64 | 65 | * In order to ensure this is stable enough we're only going to provide
|
65 | 66 | * properties for element and node. If subclasses like attr or document
|
@@ -104,10 +105,7 @@ class DomPlugin extends AbstractPlugin implements PluginBeginInterface
|
104 | 105 | 'innerHTML' => false,
|
105 | 106 | 'outerHTML' => true,
|
106 | 107 | 'substitutedNodeValue' => false,
|
107 |
| - ]; |
108 |
| - |
109 |
| - public const DOM_NS_VERSIONS = [ |
110 |
| - 'outerHTML' => KINT_PHP85, |
| 108 | + 'children' => true, |
111 | 109 | ];
|
112 | 110 |
|
113 | 111 | /**
|
@@ -208,6 +206,9 @@ class DomPlugin extends AbstractPlugin implements PluginBeginInterface
|
208 | 206 | */
|
209 | 207 | public static bool $verbose = false;
|
210 | 208 |
|
| 209 | + /** @psalm-var array<class-string, array<string, bool>> cache of properties for getKnownProperties */ |
| 210 | + protected static array $property_cache = []; |
| 211 | + |
211 | 212 | protected ClassMethodsPlugin $methods_plugin;
|
212 | 213 | protected ClassStaticsPlugin $statics_plugin;
|
213 | 214 |
|
@@ -259,12 +260,14 @@ public function parseBegin(&$var, ContextInterface $c): ?AbstractValue
|
259 | 260 | /** @psalm-param Node|DOMNode $var */
|
260 | 261 | private function parseProperty(object $var, string $prop, ContextInterface $c): AbstractValue
|
261 | 262 | {
|
262 |
| - if (!isset($var->{$prop})) { |
| 263 | + // Suppress deprecation message |
| 264 | + if (@!isset($var->{$prop})) { |
263 | 265 | return new FixedWidthValue($c, null);
|
264 | 266 | }
|
265 | 267 |
|
266 | 268 | $parser = $this->getParser();
|
267 |
| - $value = $var->{$prop}; |
| 269 | + // Suppress deprecation message |
| 270 | + @$value = $var->{$prop}; |
268 | 271 |
|
269 | 272 | if (\is_scalar($value)) {
|
270 | 273 | return $parser->parse($value, $c);
|
@@ -450,25 +453,42 @@ private function parseNode(object $var, ContextInterface $c): DomNodeValue
|
450 | 453 | */
|
451 | 454 | public static function getKnownProperties(object $var): array
|
452 | 455 | {
|
453 |
| - if ($var instanceof Node) { |
454 |
| - $known_properties = self::NODE_PROPS; |
455 |
| - if ($var instanceof Element) { |
456 |
| - $known_properties += self::ELEMENT_PROPS; |
457 |
| - } |
458 |
| - |
459 |
| - if ($var instanceof Document) { |
460 |
| - $known_properties['textContent'] = true; |
461 |
| - } |
| 456 | + if (KINT_PHP81) { |
| 457 | + $r = new ReflectionClass($var); |
| 458 | + $classname = $r->getName(); |
| 459 | + |
| 460 | + if (!isset(self::$property_cache[$classname])) { |
| 461 | + self::$property_cache[$classname] = []; |
| 462 | + |
| 463 | + foreach ($r->getProperties() as $prop) { |
| 464 | + if ($prop->isStatic()) { |
| 465 | + continue; |
| 466 | + } |
| 467 | + |
| 468 | + $declaring = $prop->getDeclaringClass()->getName(); |
| 469 | + $name = $prop->name; |
| 470 | + |
| 471 | + if (\in_array($declaring, [Node::class, Element::class], true)) { |
| 472 | + $readonly = self::NODE_PROPS[$name] ?? self::ELEMENT_PROPS[$name]; |
| 473 | + } elseif (\in_array($declaring, [DOMNode::class, DOMElement::class], true)) { |
| 474 | + $readonly = self::DOMNODE_PROPS[$name] ?? self::DOMELEMENT_PROPS[$name]; |
| 475 | + } else { |
| 476 | + continue; |
| 477 | + } |
| 478 | + |
| 479 | + self::$property_cache[$classname][$prop->name] = $readonly; |
| 480 | + } |
462 | 481 |
|
463 |
| - if ($var instanceof Attr || $var instanceof CharacterData) { |
464 |
| - $known_properties['nodeValue'] = false; |
465 |
| - } |
| 482 | + if ($var instanceof Document) { |
| 483 | + self::$property_cache[$classname]['textContent'] = true; |
| 484 | + } |
466 | 485 |
|
467 |
| - foreach (self::DOM_NS_VERSIONS as $key => $val) { |
468 |
| - if (false === $val) { |
469 |
| - unset($known_properties[$key]); // @codeCoverageIgnore |
| 486 | + if ($var instanceof Attr || $var instanceof CharacterData) { |
| 487 | + self::$property_cache[$classname]['nodeValue'] = false; |
470 | 488 | }
|
471 | 489 | }
|
| 490 | + |
| 491 | + $known_properties = self::$property_cache[$classname]; |
472 | 492 | } else {
|
473 | 493 | $known_properties = self::DOMNODE_PROPS;
|
474 | 494 | if ($var instanceof DOMElement) {
|
|
0 commit comments