Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ echo Respect\Stringifier\stringify($value);
### Using as an object

```php
$stringify = Respect\Stringifier\Stringify::createDefault();
use Respect\Stringifier\HandlerStringifier;

// with the `value` method
echo $stringify->value($value);
$stringifier = HandlerStringifier::create();

// with the `__invoke` method
echo $stringify($value);
echo $stringifier->stringify($value);
```

### Examples
Expand Down
4 changes: 2 additions & 2 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<exclude-pattern>tests/fixtures/</exclude-pattern>
</rule>
<rule ref="Squiz.Arrays.ArrayDeclaration.ValueNoNewline">
<exclude-pattern>tests/unit/Stringifiers/CallableStringifierTest.php</exclude-pattern>
<exclude-pattern>tests/unit/Handlers/CallableHandlerTest.php</exclude-pattern>
</rule>
<rule ref="Squiz.Functions.GlobalFunction">
<exclude-pattern>tests/integration/lib/helpers.php</exclude-pattern>
Expand All @@ -34,6 +34,6 @@
</rule>
<rule ref="SlevomatCodingStandard.Functions.StaticClosure.ClosureNotStatic">
<exclude-pattern>tests/integration</exclude-pattern>
<exclude-pattern>tests/unit/Stringifiers/CallableStringifierTest.php</exclude-pattern>
<exclude-pattern>tests/unit/Handlers/CallableHandlerTest.php</exclude-pattern>
</rule>
</ruleset>
21 changes: 21 additions & 0 deletions src/DumpStringifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of Respect/Stringifier.
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

namespace Respect\Stringifier;

use function print_r;

final class DumpStringifier implements Stringifier
{
public function stringify(mixed $raw): string
{
return print_r($raw, true);
}
}
21 changes: 21 additions & 0 deletions src/Handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of Respect/Stringifier.
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

namespace Respect\Stringifier;

interface Handler
{
/**
* Attempts to stringify the given value.
*
* @return string|null The stringified value, or null if this handler cannot handle the type
*/
public function handle(mixed $raw, int $depth): string|null;
}
32 changes: 32 additions & 0 deletions src/HandlerStringifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of Respect/Stringifier.
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

namespace Respect\Stringifier;

use Respect\Stringifier\Handlers\CompositeHandler;

final class HandlerStringifier implements Stringifier
{
public function __construct(
private readonly Handler $handler,
private readonly Stringifier $fallback,
) {
}

public static function create(): self
{
return new self(CompositeHandler::create(), new DumpStringifier());
}

public function stringify(mixed $raw): string
{
return $this->handler->handle($raw, 0) ?? $this->fallback->stringify($raw);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

declare(strict_types=1);

namespace Respect\Stringifier\Stringifiers;
namespace Respect\Stringifier\Handlers;

use Respect\Stringifier\Handler;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;

use function array_keys;
use function count;
Expand All @@ -20,19 +20,19 @@
use function range;
use function sprintf;

final class ArrayStringifier implements Stringifier
final class ArrayHandler implements Handler
{
private const string LIMIT_EXCEEDED_PLACEHOLDER = '...';

public function __construct(
private readonly Stringifier $stringifier,
private readonly Handler $handler,
private readonly Quoter $quoter,
private readonly int $maximumDepth,
private readonly int $maximumNumberOfItems,
) {
}

public function stringify(mixed $raw, int $depth): string|null
public function handle(mixed $raw, int $depth): string|null
{
if (!is_array($raw)) {
return null;
Expand Down Expand Up @@ -60,7 +60,7 @@ public function stringify(mixed $raw, int $depth): string|null
continue;
}

$items[] = sprintf('%s: %s', $this->stringifier->stringify($key, $depth + 1), $stringifiedValue);
$items[] = sprintf('%s: %s', $this->handler->handle($key, $depth + 1), $stringifiedValue);
}

return $this->quoter->quote(sprintf('[%s]', implode(', ', $items)), $depth);
Expand All @@ -69,10 +69,10 @@ public function stringify(mixed $raw, int $depth): string|null
private function stringifyKeyValue(mixed $value, int $depth): string|null
{
if (is_array($value)) {
return $this->stringify($value, $depth);
return $this->handle($value, $depth);
}

return $this->stringifier->stringify($value, $depth);
return $this->handler->handle($value, $depth);
}

/** @param mixed[] $array */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,31 @@

declare(strict_types=1);

namespace Respect\Stringifier\Stringifiers;
namespace Respect\Stringifier\Handlers;

use ArrayObject;
use Respect\Stringifier\Handler;
use Respect\Stringifier\Helpers\ObjectHelper;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;

final class ArrayObjectStringifier implements Stringifier
final class ArrayObjectHandler implements Handler
{
use ObjectHelper;

public function __construct(
private readonly Stringifier $stringifier,
private readonly Handler $handler,
private readonly Quoter $quoter,
) {
}

public function stringify(mixed $raw, int $depth): string|null
public function handle(mixed $raw, int $depth): string|null
{
if (!$raw instanceof ArrayObject) {
return null;
}

return $this->quoter->quote(
$this->format($raw, 'getArrayCopy() =>', $this->stringifier->stringify($raw->getArrayCopy(), $depth + 1)),
$this->format($raw, 'getArrayCopy() =>', $this->handler->handle($raw->getArrayCopy(), $depth + 1)),
$depth,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@

declare(strict_types=1);

namespace Respect\Stringifier\Stringifiers;
namespace Respect\Stringifier\Handlers;

use Respect\Stringifier\Handler;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;

use function is_bool;

final class BoolStringifier implements Stringifier
final class BoolHandler implements Handler
{
public function __construct(
private readonly Quoter $quoter,
) {
}

public function stringify(mixed $raw, int $depth): string|null
public function handle(mixed $raw, int $depth): string|null
{
if (!is_bool($raw)) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

declare(strict_types=1);

namespace Respect\Stringifier\Stringifiers;
namespace Respect\Stringifier\Handlers;

use Closure;
use ReflectionFunction;
Expand All @@ -19,9 +19,9 @@
use ReflectionParameter;
use ReflectionType;
use ReflectionUnionType;
use Respect\Stringifier\Handler;
use Respect\Stringifier\Helpers\ObjectHelper;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;

use function array_keys;
use function array_map;
Expand All @@ -37,18 +37,18 @@
use function strstr;
use function substr;

final class CallableStringifier implements Stringifier
final class CallableHandler implements Handler
{
use ObjectHelper;

public function __construct(
private readonly Stringifier $stringifier,
private readonly Handler $handler,
private readonly Quoter $quoter,
private readonly bool $closureOnly = true,
) {
}

public function stringify(mixed $raw, int $depth): string|null
public function handle(mixed $raw, int $depth): string|null
{
if ($raw instanceof Closure) {
return $this->buildFunction(new ReflectionFunction($raw), $depth);
Expand Down Expand Up @@ -170,14 +170,14 @@ private function buildParameter(ReflectionParameter $reflectionParameter, int $d
private function buildValue(ReflectionParameter $reflectionParameter, int $depth): string|null
{
if (!$reflectionParameter->isDefaultValueAvailable()) {
return $this->stringifier->stringify(null, $depth);
return $this->handler->handle(null, $depth);
}

if ($reflectionParameter->isDefaultValueConstant()) {
return $reflectionParameter->getDefaultValueConstantName();
}

return $this->stringifier->stringify($reflectionParameter->getDefaultValue(), $depth);
return $this->handler->handle($reflectionParameter->getDefaultValue(), $depth);
}

private function buildType(ReflectionType $raw, int $depth): string
Expand Down
97 changes: 97 additions & 0 deletions src/Handlers/CompositeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

/*
* This file is part of Respect/Stringifier.
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

namespace Respect\Stringifier\Handlers;

use DateTimeInterface;
use Respect\Stringifier\Handler;
use Respect\Stringifier\Quoters\StandardQuoter;

use function array_unshift;

final class CompositeHandler implements Handler
{
private const int MAXIMUM_DEPTH = 3;
private const int MAXIMUM_NUMBER_OF_ITEMS = 5;
private const int MAXIMUM_NUMBER_OF_PROPERTIES = self::MAXIMUM_NUMBER_OF_ITEMS;
private const int MAXIMUM_LENGTH = 120;

/** @var array<Handler> */
private array $handlers = [];

public function __construct(Handler ...$handlers)
{
$this->handlers = $handlers;
}

public static function create(): self
{
$quoter = new StandardQuoter(self::MAXIMUM_LENGTH);

$handler = new self(
new InfiniteNumberHandler($quoter),
new NotANumberHandler($quoter),
new ResourceHandler($quoter),
new BoolHandler($quoter),
new NullHandler($quoter),
new DeclaredHandler($quoter),
$jsonEncodableHandler = new JsonEncodableHandler(),
);
$handler->prependHandler(
$arrayHandler = new ArrayHandler(
$handler,
$quoter,
self::MAXIMUM_DEPTH,
self::MAXIMUM_NUMBER_OF_ITEMS,
),
);
$handler->prependHandler(
new ObjectHandler(
$handler,
$quoter,
self::MAXIMUM_DEPTH,
self::MAXIMUM_NUMBER_OF_PROPERTIES,
),
);
$handler->prependHandler(new CallableHandler($handler, $quoter));
$handler->prependHandler(
new FiberObjectHandler(new CallableHandler($handler, $quoter, closureOnly: false), $quoter),
);
$handler->prependHandler(new EnumerationHandler($quoter));
$handler->prependHandler(new ObjectWithDebugInfoHandler($arrayHandler, $quoter));
$handler->prependHandler(new ArrayObjectHandler($arrayHandler, $quoter));
$handler->prependHandler(new JsonSerializableObjectHandler($jsonEncodableHandler, $quoter));
$handler->prependHandler(new StringableObjectHandler($jsonEncodableHandler, $quoter));
$handler->prependHandler(new ThrowableObjectHandler($jsonEncodableHandler, $quoter));
$handler->prependHandler(new DateTimeHandler($quoter, DateTimeInterface::ATOM));
$handler->prependHandler(new IteratorObjectHandler($handler, $quoter));

return $handler;
}

public function prependHandler(Handler $handler): void
{
array_unshift($this->handlers, $handler);
}

public function handle(mixed $raw, int $depth): string|null
{
foreach ($this->handlers as $handler) {
$string = $handler->handle($raw, $depth);
if ($string === null) {
continue;
}

return $string;
}

return null;
}
}
Loading