This commit is contained in:
Enoch
2024-08-09 22:16:39 +08:00
commit d78b38e80f
3984 changed files with 416946 additions and 0 deletions
@@ -0,0 +1,114 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function array_keys;
use function implode;
use function is_array;
use function is_int;
use function sprintf;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts an array value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class ArrayStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* @var int
*/
private $maximumDepth;
/**
* @var int
*/
private $itemsLimit;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
* @param int $maximumDepth
* @param int $itemsLimit
*/
public function __construct(Stringifier $stringifier, Quoter $quoter, int $maximumDepth, int $itemsLimit)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
$this->maximumDepth = $maximumDepth;
$this->itemsLimit = $itemsLimit;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_array($raw)) {
return null;
}
if (empty($raw)) {
return $this->quoter->quote('{ }', $depth);
}
if ($depth >= $this->maximumDepth) {
return '...';
}
$items = [];
$itemsCount = 0;
$isSequential = $this->isSequential($raw);
foreach ($raw as $key => $value) {
if (++$itemsCount > $this->itemsLimit) {
$items[$itemsCount] = '...';
break;
}
$items[$itemsCount] = '';
if (false === $isSequential) {
$items[$itemsCount] .= sprintf('%s: ', $this->stringifier->stringify($key, $depth + 1));
}
$items[$itemsCount] .= $this->stringifier->stringify($value, $depth + 1);
}
return $this->quoter->quote(sprintf('{ %s }', implode(', ', $items)), $depth);
}
/**
* Returns whether the array is sequential or not.
*
* @param array $array
*
* @return bool
*/
private function isSequential(array $array): bool
{
return array_keys($array) === range(0, count($array) - 1);
}
}
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function is_bool;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts a boolean value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class BoolStringifier implements Stringifier
{
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Quoter $quoter
*/
public function __construct(Quoter $quoter)
{
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_bool($raw)) {
return null;
}
return $this->quoter->quote($raw ? 'TRUE' : 'FALSE', $depth);
}
}
@@ -0,0 +1,117 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use Respect\Stringifier\Quoters\CodeQuoter;
use Respect\Stringifier\Quoters\StringQuoter;
use Respect\Stringifier\Stringifier;
/**
* Converts a value into a string using the defined Stringifiers.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class ClusterStringifier implements Stringifier
{
/**
* @var Stringifier[]
*/
private $stringifiers;
/**
* Initializes the stringifier.
*
* @param Stringifier[] ...$stringifiers
*/
public function __construct(Stringifier ...$stringifiers)
{
$this->setStringifiers($stringifiers);
}
/**
* Create a default instance of the class.
*
* This instance includes all possible stringifiers.
*
* @return ClusterStringifier
*/
public static function createDefault(): self
{
$quoter = new CodeQuoter();
$stringifier = new self();
$stringifier->setStringifiers([
new TraversableStringifier($stringifier, $quoter),
new DateTimeStringifier($stringifier, $quoter, 'c'),
new ThrowableStringifier($stringifier, $quoter),
new StringableObjectStringifier($stringifier),
new JsonSerializableStringifier($stringifier, $quoter),
new ObjectStringifier($stringifier, $quoter),
new ArrayStringifier($stringifier, $quoter, 3, 5),
new InfiniteStringifier($quoter),
new NanStringifier($quoter),
new ResourceStringifier($quoter),
new BoolStringifier($quoter),
new NullStringifier($quoter),
new JsonParsableStringifier(),
]);
return $stringifier;
}
/**
* Set stringifiers.
*
* @param array $stringifiers
*
* @return void
*/
public function setStringifiers(array $stringifiers): void
{
$this->stringifiers = [];
foreach ($stringifiers as $stringifier) {
$this->addStringifier($stringifier);
}
}
/**
* Add a stringifier to the chain
*
* @param Stringifier $stringifier
*
* @return void
*/
public function addStringifier(Stringifier $stringifier): void
{
$this->stringifiers[] = $stringifier;
}
/**
* {@inheritdoc}
*/
public function stringify($value, int $depth): ?string
{
foreach ($this->stringifiers as $stringifier) {
$string = $stringifier->stringify($value, $depth);
if (null === $string) {
continue;
}
return $string;
}
return null;
}
}
@@ -0,0 +1,76 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use DateTimeInterface;
use function get_class;
use function sprintf;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts an instance of DateTimeInterface into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class DateTimeStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* @var string
*/
private $format;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
* @param string $format
*/
public function __construct(Stringifier $stringifier, Quoter $quoter, string $format)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
$this->format = $format;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!$raw instanceof DateTimeInterface) {
return null;
}
return $this->quoter->quote(
sprintf(
'[date-time] (%s: %s)',
get_class($raw),
$this->stringifier->stringify($raw->format($this->format), $depth + 1)
),
$depth
);
}
}
@@ -0,0 +1,58 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function is_float;
use function is_infinite;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts an infinite float value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class InfiniteStringifier implements Stringifier
{
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Quoter $quoter
*/
public function __construct(Quoter $quoter)
{
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_float($raw)) {
return null;
}
if (!is_infinite($raw)) {
return null;
}
return $this->quoter->quote(($raw > 0 ? '' : '-').'INF', $depth);
}
}
@@ -0,0 +1,40 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use const JSON_UNESCAPED_UNICODE;
use const JSON_UNESCAPED_SLASHES;
use function json_encode;
use Respect\Stringifier\Stringifier;
/**
* Converts any value into JSON parsable string representation.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class JsonParsableStringifier implements Stringifier
{
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
$string = json_encode($raw, (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION));
if (false === $string) {
return null;
}
return $string;
}
}
@@ -0,0 +1,67 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
use JsonSerializable;
/**
* Converts an instance of JsonSerializable into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class JsonSerializableStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
*/
public function __construct(Stringifier $stringifier, Quoter $quoter)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!$raw instanceof JsonSerializable) {
return null;
}
return $this->quoter->quote(
sprintf(
'[json-serializable] (%s: %s)',
get_class($raw),
$this->stringifier->stringify($raw->jsonSerialize(), $depth + 1)
),
$depth
);
}
}
@@ -0,0 +1,58 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function is_float;
use function is_nan;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts a NaN value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class NanStringifier implements Stringifier
{
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Quoter $quoter
*/
public function __construct(Quoter $quoter)
{
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_float($raw)) {
return null;
}
if (!is_nan($raw)) {
return null;
}
return $this->quoter->quote('NaN', $depth);
}
}
@@ -0,0 +1,52 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts a NULL value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class NullStringifier implements Stringifier
{
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Quoter $quoter
*/
public function __construct(Quoter $quoter)
{
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (null !== $raw) {
return null;
}
return $this->quoter->quote('NULL', $depth);
}
}
@@ -0,0 +1,70 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function get_class;
use function get_object_vars;
use function is_object;
use function sprintf;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts an object into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class ObjectStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
*/
public function __construct(Stringifier $stringifier, Quoter $quoter)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_object($raw)) {
return null;
}
return $this->quoter->quote(
sprintf(
'[object] (%s: %s)',
get_class($raw),
$this->stringifier->stringify(get_object_vars($raw), $depth + 1)
),
$depth
);
}
}
@@ -0,0 +1,61 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function get_resource_type;
use function is_resource;
use function sprintf;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
/**
* Converts a resource value into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class ResourceStringifier implements Stringifier
{
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Quoter $quoter
*/
public function __construct(Quoter $quoter)
{
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_resource($raw)) {
return null;
}
return $this->quoter->quote(
sprintf(
'[resource] (%s)',
get_resource_type($raw)
),
$depth
);
}
}
@@ -0,0 +1,57 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function is_object;
use function method_exists;
use Respect\Stringifier\Stringifier;
/**
* Converts a object that implements the __toString() magic method into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class StringableObjectStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
*/
public function __construct(Stringifier $stringifier)
{
$this->stringifier = $stringifier;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!is_object($raw)) {
return null;
}
if (!method_exists($raw, '__toString')) {
return null;
}
return $this->stringifier->stringify($raw->__toString(), $depth);
}
}
@@ -0,0 +1,84 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function get_class;
use function getcwd;
use function sprintf;
use function str_replace;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
use Throwable;
/**
* Converts an instance of Throwable into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class ThrowableStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
*/
public function __construct(Stringifier $stringifier, Quoter $quoter)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!$raw instanceof Throwable) {
return null;
}
return $this->quoter->quote(
sprintf(
'[throwable] (%s: %s)',
get_class($raw),
$this->stringifier->stringify($this->getData($raw), $depth + 1)
),
$depth
);
}
private function getData(Throwable $throwable): array
{
return [
'message' => $throwable->getMessage(),
'code' => $throwable->getCode(),
'file' => sprintf(
'%s:%d',
str_replace(getcwd().'/', '', $throwable->getFile()),
$throwable->getLine()
),
];
}
}
@@ -0,0 +1,69 @@
<?php
/*
* This file is part of Respect/Stringifier.
*
* (c) Henrique Moody <henriquemoody@gmail.com>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Stringifier\Stringifiers;
use function get_class;
use function iterator_to_array;
use Respect\Stringifier\Quoter;
use Respect\Stringifier\Stringifier;
use Traversable;
/**
* Converts an instance of Traversable into a string.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*/
final class TraversableStringifier implements Stringifier
{
/**
* @var Stringifier
*/
private $stringifier;
/**
* @var Quoter
*/
private $quoter;
/**
* Initializes the stringifier.
*
* @param Stringifier $stringifier
* @param Quoter $quoter
*/
public function __construct(Stringifier $stringifier, Quoter $quoter)
{
$this->stringifier = $stringifier;
$this->quoter = $quoter;
}
/**
* {@inheritdoc}
*/
public function stringify($raw, int $depth): ?string
{
if (!$raw instanceof Traversable) {
return null;
}
return $this->quoter->quote(
sprintf(
'[traversable] (%s: %s)',
get_class($raw),
$this->stringifier->stringify(iterator_to_array($raw), $depth + 1)
),
$depth
);
}
}