Skip to content

Commit

Permalink
first attempt at custom dumper
Browse files Browse the repository at this point in the history
  • Loading branch information
NiclasvanEyk committed Apr 25, 2023
1 parent c6476f8 commit 334f4d4
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ const render = (properties) =>
<!-- <h3>Other Properties</h3> -->
<!-- <pre>{{ render(categorizedProps.other) }}</pre> -->

<pre>{{ selectedComponent?.data_serialized }}</pre>

<div v-html="selectedComponent?.data_dumped"></div>
</template>
2 changes: 2 additions & 0 deletions packages/blade-devtools-ui/src/lib/blade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export interface BladeComponentTreeNode {
data: BladeComponentAttributes

data_dumped: any
data_serialized: string

/**
* The closest DOM node rendered by the component.
Expand Down Expand Up @@ -189,6 +190,7 @@ export function getAllComments(
id: componentTag.id,
data: cleanData(componentTag.data.data),
data_dumped: componentTag.data.data_dumped,
data_serialized: componentTag.data.data_serialized,
children: [],
parent: current,
dynamic: currentIsDynamic
Expand Down
4 changes: 2 additions & 2 deletions packages/blade-devtools/src/CustomViewFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,19 @@ private function withComponentMarkers(string $content, array $data, string $name
// }

if (array_key_exists('attributes', $data)) {
$data = $data['attributes'];
$data = $data['attributes']->getAttributes();
}
unset($data['__laravel_slots']);
unset($data['slot']);

$cloned = (new VarCloner())->cloneVar($data);
$dumper = new HtmlDumper();
$dumper->setTheme('light');
// $dumper = new JsonDumper();

$data = json_encode([
'data' => $data,
'data_dumped' => $dumper->dump($cloned, output: true),
'data_serialized' => (new Serializer)->serialize($data),
'name' => $name,
]);

Expand Down
52 changes: 16 additions & 36 deletions packages/blade-devtools/src/JsonDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace NiclasvanEyk\BladeDevtools;

use Symfony\Component\VarDumper\Cloner\Cursor;
use Symfony\Component\VarDumper\Cloner\Stub;
use Symfony\Component\VarDumper\Dumper\AbstractDumper;

class JsonDumper extends AbstractDumper
Expand Down Expand Up @@ -268,22 +267,27 @@ public function enterHash(Cursor $cursor, int $type, string|int|null $class, boo

$class = $this->utf8Encode($class);
if (Cursor::HASH_OBJECT === $type) {
$prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{';
$prefix = $class && 'stdClass' !== $class
? $class
: '{';
} elseif (Cursor::HASH_RESOURCE === $type) {
$prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' ');
$prefix = $class.' resource'.($hasChild ? ' {' : ' ');
} else {
$prefix = $class && ! (self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '[';
$prefix = '[';
}

if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) {
$prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]);
// $foo = (Cursor::HASH_RESOURCE === $type ? '@' : '#');
// $bar = (0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo);

// $prefix .= $foo;
} elseif ($cursor->hardRefTo && ! $cursor->refIndex && $class) {
$prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]);
} elseif (! $hasChild && Cursor::HASH_RESOURCE === $type) {
$prefix = substr($prefix, 0, -1);
}

$this->line .= $prefix;
$this->line .= '{"type": "'.$class.'", "value": ';

if ($hasChild) {
$this->dumpLine($cursor->depth);
Expand All @@ -294,7 +298,7 @@ public function leaveHash(Cursor $cursor, int $type, string|int|null $class, boo
{
if (empty($cursor->attr['cut_hash'])) {
$this->dumpEllipsis($cursor, $hasChild, $cut);
$this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : ''));
$this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? '}' : ($hasChild ? '}' : ''));
}

$this->endValue($cursor);
Expand Down Expand Up @@ -341,19 +345,14 @@ protected function dumpKey(Cursor $cursor)
// no break
case Cursor::HASH_ASSOC:
$this->line .= "\"$key\": ";
// if (\is_int($key)) {
// $this->line .= $this->style($style, $key).': ';
// } else {
// $this->line .= $bin.'"'.$this->style($style, $key).'" => ';
// }
break;

case Cursor::HASH_RESOURCE:
$key = "\0~\0".$key;
// no break
case Cursor::HASH_OBJECT:
if (! isset($key[0]) || "\0" !== $key[0]) {
$this->line .= '+'.$bin.$this->style('public', $key).': ';
$this->line .= "+\"$key\": ";
} elseif (0 < strpos($key, "\0", 1)) {
$key = explode("\0", substr($key, 1), 2);

Expand All @@ -380,17 +379,12 @@ protected function dumpKey(Cursor $cursor)
break;
}

if (isset($attr['collapse'])) {
if ($attr['collapse']) {
$this->collapseNextHash = true;
} else {
$this->expandNextHash = true;
}
}
$this->line .= '{"type": "'.$style.'", "name": "'.$key[1].'", "value": ';

$this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': ');
// $this->line .= $bin.$key[1].': ';
} else {
// This case should not happen
throw new \Exception('This case should not happen');
$this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": ';
}
break;
Expand All @@ -402,13 +396,6 @@ protected function dumpKey(Cursor $cursor)
}
}

/**
* Decorates a value with some style.
*
* @param string $style The type of style being applied
* @param string $value The value being styled
* @param array $attr Optional context information
*/
protected function style(string $style, string $value, array $attr = []): string
{
return $value;
Expand All @@ -425,14 +412,7 @@ protected function endValue(Cursor $cursor)
return;
}

if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) {
if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) {
$this->line .= ',';
} elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) {
$this->line .= ',';
}
}

$this->line .= ',';
$this->dumpLine($cursor->depth, true);
}

Expand Down
110 changes: 110 additions & 0 deletions packages/blade-devtools/src/Serializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

namespace NiclasvanEyk\BladeDevtools;

class Serializer
{
private $depth = 0;

public function __construct(
private array $dontSerialize = [
'Illuminate\\Foundation\\Application',
],
private int $maxDepth = 5,
) {
}

public function serialize($value): array
{
$serialized = ['type' => 'aborted'];
if ($this->depth > 2) {
return $serialized;
}

if (is_array($value)) {
return $this->serializeArray($value);
} elseif (is_null($value)) {
return ['type' => 'null', 'value' => null];
} elseif (is_scalar($value)) {
return ['type' => $this->serializeScalar($value), 'value' => $value];
}

return $this->serializeClass($value);

// throw new Exception("I don't know how to serialize this: " . $value);
}

private function serializeArray(array $attributes): array
{

$serialized = [];

foreach ($attributes as $name => $value) {
$serialized[$name] = $this->serialize($value);
}

return $serialized;
}

private function serializeScalar($scalar): string
{
if (is_string($scalar)) {
return 'string';
}
if (is_int($scalar)) {
return 'int';
}
if (is_float($scalar)) {
return 'float';
}
if (is_null($scalar)) {
return 'null';
}
if (is_bool($scalar)) {
return 'bool';
}

throw new \Exception('Unknown scalar type!');
}

private function serializeClass(object $object): array
{
$this->depth += 1;

$serialized = [];

$reflected = new \ReflectionClass($object);
$serialized['type'] = 'class';
$serialized['class'] = $reflected->getName();

if ($this->ignores($reflected)) {
$serialized['ignored'] = true;
}

$properties = [];
foreach ($reflected->getProperties() as $property) {
if ($property->isStatic()) {
continue;
}
try {
$properties[] = [
'name' => $property->getName(),
'value' => $this->serialize($property->getValue($object)),
];
} catch (\Throwable $exception) {

}

}
$serialized['properties'] = $properties;

$this->depth -= 1;

return $serialized;
}

private function ignores(\ReflectionClass $class): bool
{
return in_array($class->getName(), $this->dontSerialize);
}
}

0 comments on commit 334f4d4

Please sign in to comment.