Skip to content

Commit

Permalink
More SimpleXMLElementPlugin fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jnvsor committed Aug 23, 2024
1 parent c534c9e commit f503403
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 57 deletions.
Binary file modified build/kint.phar
Binary file not shown.
31 changes: 9 additions & 22 deletions src/Parser/SimpleXMLElementPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public function parse(&$var, Value &$o, int $trigger): void

$x = new SimpleXMLElementValue($o->name, \get_class($var), \spl_object_hash($var), \spl_object_id($var));
$x->transplant($o);
$x->size = null;

if (!self::$verbose) {
$x->removeRepresentation('properties');
Expand All @@ -78,7 +79,6 @@ public function parse(&$var, Value &$o, int $trigger): void
// An invalid SimpleXMLElement can gum up the works with
// warnings if we call stuff children/attributes on it.
if (!$var) {
$x->size = null;
$o = $x;

return;
Expand All @@ -98,36 +98,23 @@ public function parse(&$var, Value &$o, int $trigger): void

// Even in DEPTH_LIMIT we need to check strings. With size === 0 we'll
// have no children or attributes so we can go ahead and replace Contents
if (!isset($a) && !isset($c) && \strlen((string) $var) && [(string) $var] === (array) $var) {
if (!isset($c) && \strlen((string) $var)) {
$x->hints = \array_diff($x->hints, ['depth_limit']);

$base_obj = new Value($x->name);
$base_obj->depth = $x->depth + 1;
if (null !== $x->access_path) {
$base_obj->access_path = '(string) '.$x->access_path;
$x->access_path = '(string) '.$x->access_path;
$base_obj->access_path = $x->access_path;
}

$value = (string) $var;
$string = (string) $var;

$s = $this->getParser()->parse($value, $base_obj);
$r = new Representation('toString');
$r->implicit_label = true;
$r->contents = $this->getParser()->parse($string, $base_obj);

$srep = $s->getRepresentation('contents');
$svalrep = $s->value && 'contents' == $s->value->getName() ? $s->value : null;

if ($srep || $svalrep) {
$x->is_string_value = true;
$x->value = $srep ?: $svalrep;

if ($srep) {
$x->replaceRepresentation($srep, 0);
}
}

$reps = \array_reverse($s->getRepresentations());

foreach ($reps as $rep) {
$x->addRepresentation($rep, 0);
}
$x->addRepresentation($r, 0);
}

$o = $x;
Expand Down
11 changes: 7 additions & 4 deletions src/Renderer/Rich/SimpleXMLElementPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@ public function renderValue(Value $o): ?string
return null;
}

if (!$o->is_string_value || (bool) ($o->getRepresentation('attributes')->contents ?? false)) {
$r = $o->getRepresentation('tostring');

if (!isset($r->contents) || !$r->contents instanceof BlobValue) {
return null;
}

$b = new BlobValue($o->name);
$b->transplant($o);
$b->type = 'string';
$b = clone $r->contents;
if ($r = $o->getRepresentation('attributes')) {
$b->addRepresentation($r, 1);
}

$children = $this->renderer->renderChildren($b);
$header = $this->renderer->renderHeader($o);
Expand Down
17 changes: 13 additions & 4 deletions src/Zval/SimpleXMLElementValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,23 @@ class SimpleXMLElementValue extends InstanceValue
{
public array $hints = ['object', 'simplexml_element'];

public bool $is_string_value = false;

public function getValueShort(): ?string
{
if ($this->is_string_value && ($rep = $this->value) && 'contents' === $rep->getName() && 'string' === \gettype($rep->contents)) {
return '"'.$rep->contents.'"';
if ($r = $this->getRepresentation('tostring')) {
/** @psalm-var object{contents: BlobValue, ...} $r */
return $r->contents->getValueShort();
}

return null;
}

public function getSize(): ?string
{
if ($r = $this->getRepresentation('tostring')) {
/** @psalm-var object{contents: BlobValue, ...} $r */
return $r->contents->getSize();
}

return parent::getSize();
}
}
115 changes: 88 additions & 27 deletions tests/Parser/SimpleXMLElementPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class SimpleXMLElementPluginTest extends KintTestCase
<g />
String value
<wrap><wrap><text>String element</text></wrap></wrap>
<both attribs="exist">And string</both>
</x>
END;

Expand Down Expand Up @@ -79,21 +80,25 @@ public function testParse()

// Properties
$this->assertSame('$v', $o->name);
$this->assertFalse($o->is_string_value);
$this->assertNull($o->getRepresentation('tostring'));
$this->assertSame(4, $o->size);
$this->assertSame('@attributes', $o->value->contents[0]->name);
$this->assertSame('viewBox', $o->value->contents[0]->value->contents[0]->name);
$this->assertSame('0 0 30 150', $o->value->contents[0]->value->contents[0]->value->contents);
$this->assertSame('$v->{\'@attributes\'}[\'viewBox\']', $o->value->contents[0]->value->contents[0]->access_path);
$this->assertSame(1, $o->value->contents[0]->size);

$g = $o->value->contents[1];
$this->assertSame('g', $g->name);
$this->assertSame('array', $g->type);
$this->assertSame('$v->g', $g->access_path);
$this->assertSame(2, $g->size);

$attribs = $g->value->contents[0]->value->contents[0];
$this->assertSame('@attributes', $attribs->name);
$this->assertSame('fill', $attribs->value->contents[1]->name);
$this->assertSame('$v->g[0]->{\'@attributes\'}[\'fill\']', $attribs->value->contents[1]->access_path);
$attrib = $g->value->contents[0]->value->contents[0];
$this->assertSame('@attributes', $attrib->name);
$this->assertSame('fill', $attrib->value->contents[1]->name);
$this->assertSame('$v->g[0]->{\'@attributes\'}[\'fill\']', $attrib->value->contents[1]->access_path);
$this->assertSame(2, $attrib->size);

$inner = $g->value->contents[0]->value->contents[1];
$this->assertSame('inner', $inner->name);
Expand All @@ -102,71 +107,127 @@ public function testParse()
// custom code around casting them to arrays so idc
$this->assertInstanceOf(BlobValue::class, $inner);
$this->assertSame('Text', $inner->value->contents);
$this->assertSame(4, $inner->size);

$this->assertEmpty($g->value->contents[1]->value->contents);
$this->assertSame('$v->g[1]', $g->value->contents[1]->access_path);
$this->assertNull($g->value->contents[1]->size);

$wrap = $o->value->contents[2];
$this->assertInstanceOf(SimpleXMLElementValue::class, $wrap);
$this->assertSame('wrap', $wrap->name);
$this->assertSame('$v->wrap', $wrap->access_path);
$this->assertSame(1, $wrap->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $wrap->value->contents[0]);
$this->assertSame('wrap', $wrap->value->contents[0]->name);
$this->assertSame('$v->wrap->wrap', $wrap->value->contents[0]->access_path);
$this->assertSame(1, $wrap->value->contents[0]->size);
$this->assertInstanceOf(BlobValue::class, $wrap->value->contents[0]->value->contents[0]);
$this->assertSame('text', $wrap->value->contents[0]->value->contents[0]->name);
$this->assertSame('String element', $wrap->value->contents[0]->value->contents[0]->value->contents);
$this->assertSame('$v->wrap->wrap->text', $wrap->value->contents[0]->value->contents[0]->access_path);
$this->assertSame(14, $wrap->value->contents[0]->value->contents[0]->size);

$both = $o->value->contents[3];
$this->assertSame('both', $both->name);
$this->assertSame('$v->both', $both->access_path);
$this->assertSame('string', $both->type);
$this->assertSame(10, $both->size);

// Children
$r = $o->getRepresentation('children');
$g1child = $r->contents[0];
$this->assertInstanceOf(Representation::class, $r);
$this->assertCount(3, $r->contents);
$this->assertCount(4, $r->contents);
$this->assertSame('g', $r->contents[0]->name);
$this->assertSame('$v->children()->g', $r->contents[0]->access_path);
$this->assertSame(1, $r->contents[0]->size);
$this->assertSame('g', $r->contents[1]->name);
$this->assertSame('$v->children()->g[1]', $r->contents[1]->access_path);
$this->assertNull($r->contents[1]->size);
$this->assertSame('wrap', $r->contents[2]->name);
$this->assertSame('$v->children()->wrap', $r->contents[2]->access_path);
$this->assertFalse($r->contents[2]->is_string_value);
$this->assertNull($r->contents[2]->getRepresentation('tostring'));
$this->assertSame(1, $r->contents[2]->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[2]);
$text = $r->contents[2]
->getRepresentation('children')->contents[0]
->getRepresentation('children')->contents[0];
$this->assertSame('text', $text->name);
$this->assertSame('$v->children()->wrap->children()->wrap->children()->text', $text->access_path);
$this->assertTrue($text->is_string_value);
$this->assertSame('(string) $v->children()->wrap->children()->wrap->children()->text', $text->access_path);
$this->assertInstanceOf(Representation::class, $text->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $text->getRepresentation('tostring')->contents);
$this->assertNull($text->size);
$this->assertSame('14', $text->getSize());
$this->assertSame(14, $text->getRepresentation('tostring')->contents->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $text);
$both = $r->contents[3];
$this->assertSame('both', $both->name);
$this->assertSame('(string) $v->children()->both', $both->access_path);
$this->assertInstanceOf(Representation::class, $both->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $both->getRepresentation('tostring')->contents);
$this->assertNull($both->size);
$this->assertSame('10', $both->getSize());
$this->assertSame(10, $both->getRepresentation('tostring')->contents->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $both);

// Attributes
$r = $o->value->contents[1]->value->contents[0]->getRepresentation('attributes');
$this->assertInstanceOf(Representation::class, $r);
$this->assertCount(2, $r->contents);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[0]);
$this->assertSame('stroke-width', $r->contents[0]->name);
$this->assertSame('$v->g[0]->attributes()[\'stroke-width\']', $r->contents[0]->access_path);
$this->assertSame('2', $r->contents[0]->value->contents);
$this->assertTrue($r->contents[0]->is_string_value);
$this->assertSame('(string) $v->g[0]->attributes()[\'stroke-width\']', $r->contents[0]->access_path);
$this->assertSame('2', $r->contents[0]->getRepresentation('tostring')->contents->value->contents);
$this->assertInstanceOf(Representation::class, $r->contents[0]->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $r->contents[0]->getRepresentation('tostring')->contents);
$this->assertNull($r->contents[0]->size);
$this->assertSame('1', $r->contents[0]->getSize());
$this->assertSame(1, $r->contents[0]->getRepresentation('tostring')->contents->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[1]);
$this->assertSame('fill', $r->contents[1]->name);
$this->assertSame('$v->g[0]->attributes()[\'fill\']', $r->contents[1]->access_path);
$this->assertSame('#FFF', $r->contents[1]->value->contents);
$this->assertTrue($r->contents[1]->is_string_value);
$this->assertSame('(string) $v->g[0]->attributes()[\'fill\']', $r->contents[1]->access_path);
$this->assertSame('#FFF', $r->contents[1]->getRepresentation('tostring')->contents->value->contents);
$this->assertInstanceOf(Representation::class, $r->contents[1]->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $r->contents[1]->getRepresentation('tostring')->contents);
$this->assertNull($r->contents[1]->size);
$this->assertSame('4', $r->contents[1]->getSize());
$this->assertSame(4, $r->contents[1]->getRepresentation('tostring')->contents->size);

$r = $g1child->getRepresentation('attributes');
$this->assertInstanceOf(Representation::class, $r);
$this->assertCount(2, $r->contents);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[0]);
$this->assertSame('stroke-width', $r->contents[0]->name);
$this->assertSame('$v->children()->g->attributes()[\'stroke-width\']', $r->contents[0]->access_path);
$this->assertSame('2', $r->contents[0]->value->contents);
$this->assertTrue($r->contents[0]->is_string_value);
$this->assertSame('(string) $v->children()->g->attributes()[\'stroke-width\']', $r->contents[0]->access_path);
$this->assertSame('2', $r->contents[0]->getRepresentation('tostring')->contents->value->contents);
$this->assertInstanceOf(Representation::class, $r->contents[0]->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $r->contents[0]->getRepresentation('tostring')->contents);
$this->assertNull($r->contents[0]->size);
$this->assertSame('1', $r->contents[0]->getSize());
$this->assertSame(1, $r->contents[0]->getRepresentation('tostring')->contents->size);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[1]);
$this->assertSame('fill', $r->contents[1]->name);
$this->assertSame('$v->children()->g->attributes()[\'fill\']', $r->contents[1]->access_path);
$this->assertSame('#FFF', $r->contents[1]->value->contents);
$this->assertTrue($r->contents[1]->is_string_value);
$this->assertSame('(string) $v->children()->g->attributes()[\'fill\']', $r->contents[1]->access_path);
$this->assertSame('#FFF', $r->contents[1]->getRepresentation('tostring')->contents->value->contents);
$this->assertInstanceOf(Representation::class, $r->contents[1]->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $r->contents[1]->getRepresentation('tostring')->contents);
$this->assertNull($r->contents[1]->size);
$this->assertSame('4', $r->contents[1]->getSize());
$this->assertSame(4, $r->contents[1]->getRepresentation('tostring')->contents->size);

$r = $both->getRepresentation('attributes');
$this->assertInstanceOf(Representation::class, $r);
$this->assertCount(1, $r->contents);
$this->assertInstanceOf(SimpleXMLElementValue::class, $r->contents[0]);
$this->assertSame('attribs', $r->contents[0]->name);
$this->assertSame('(string) $v->children()->both->attributes()[\'attribs\']', $r->contents[0]->access_path);
$this->assertSame('exist', $r->contents[0]->getRepresentation('tostring')->contents->value->contents);
$this->assertInstanceOf(Representation::class, $r->contents[0]->getRepresentation('tostring'));
$this->assertInstanceOf(BlobValue::class, $r->contents[0]->getRepresentation('tostring')->contents);
$this->assertNull($r->contents[0]->size);
$this->assertSame('5', $r->contents[0]->getSize());
$this->assertSame(5, $r->contents[0]->getRepresentation('tostring')->contents->size);
}

/**
Expand Down Expand Up @@ -194,14 +255,14 @@ public function testParseDepthLimit()
$this->assertSame('inner', $inner->name);
$this->assertSame(2, $inner->depth);
$this->assertNotContains('depth_limit', $inner->hints);
$this->assertTrue($inner->is_string_value);
$this->assertInstanceOf(Representation::class, $inner->getRepresentation('tostring'));

$attr = $g1->getRepresentation('attributes')->contents[0];
$this->assertInstanceOf(SimpleXMLElementValue::class, $attr);
$this->assertSame('stroke-width', $attr->name);
$this->assertSame(2, $attr->depth);
$this->assertNotContains('depth_limit', $attr->hints);
$this->assertTrue($attr->is_string_value);
$this->assertInstanceOf(Representation::class, $attr->getRepresentation('tostring'));

$wrap = $o
->getRepresentation('children')->contents[2]
Expand All @@ -210,7 +271,7 @@ public function testParseDepthLimit()
$this->assertSame('wrap', $wrap->name);
$this->assertSame(2, $wrap->depth);
$this->assertNotContains('depth_limit', $wrap->hints);
$this->assertFalse($wrap->is_string_value);
$this->assertNull($wrap->getRepresentation('tostring'));

$p->setDepthLimit(2);
$o = $p->parse($v, clone $b);
Expand All @@ -221,14 +282,14 @@ public function testParseDepthLimit()
$this->assertSame('inner', $inner->name);
$this->assertSame(2, $inner->depth);
$this->assertNotContains('depth_limit', $inner->hints);
$this->assertTrue($inner->is_string_value);
$this->assertInstanceOf(Representation::class, $inner->getRepresentation('tostring'));

$attr = $g1->getRepresentation('attributes')->contents[0];
$this->assertInstanceOf(SimpleXMLElementValue::class, $attr);
$this->assertSame('stroke-width', $attr->name);
$this->assertSame(2, $attr->depth);
$this->assertNotContains('depth_limit', $attr->hints);
$this->assertTrue($attr->is_string_value);
$this->assertInstanceOf(Representation::class, $attr->getRepresentation('tostring'));

$wrap = $o
->getRepresentation('children')->contents[2]
Expand All @@ -237,7 +298,7 @@ public function testParseDepthLimit()
$this->assertSame('wrap', $wrap->name);
$this->assertSame(2, $wrap->depth);
$this->assertContains('depth_limit', $wrap->hints);
$this->assertFalse($wrap->is_string_value);
$this->assertNull($wrap->getRepresentation('tostring'));
}

/**
Expand Down

0 comments on commit f503403

Please sign in to comment.