8000 [ValueExporter] extracted ValueExporter in its own component · symfony/symfony@2f0461b · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f0461b

Browse files
committed
[ValueExporter] extracted ValueExporter in its own component
1 parent 45b557a commit 2f0461b

17 files changed

+696
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
composer.lock
2+
phpunit.xml
3+
vendor/
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
3.2.0
5+
-----
6+
7+
* introducing the component
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Exception;
13+
14+
/**
15+
* Thrown when a {@link \Symfony\Component\ValueExporter\Formatter\FormatterInterface}
16+
* is not supported by the {@link \Symfony\Component\ValueExporter\Exporter\ValueExporterInterface}.
17+
*
18+
* @author Jules Pietri <jules@heahprod.com>
19+
*/
20+
class InvalidFormatterException extends \InvalidArgumentException
21+
{
22+
/**
23+
* @param string $formatterClass The invalid formatter class
24+
* @param string $exporterClass The exporter class
25+
* @param string $expectedInterface The expected formatter interface
26+
*/
27+
public function __construct($formatterClass, $exporterClass, $expectedInterface)
28+
{
29+
parent::__construct(sprintf('The exporter "%s" expects formatters implementing "%", but was given "%s" class.', $exporterClass, $expectedInterface, $formatterClass));
30+
}
31+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Exporter;
13+
14+
use Symfony\Component\ValueExporter\Exception\InvalidFormatterException;
15+
use Symfony\Component\ValueExporter\Exporter;
16+
use Symfony\Component\ValueExporter\Formatter\FormatterInterface;
17+
18+
/**
19+
* ValueExporterInterface implementations export PHP values.
20+
*
21+
* @author Jules Pietri <jules@heahprod.com>
22+
*/
23+
abstract class AbstractValueExporter implements ValueExporterInterface
24+
{
25+
/**
26+
* An array of formatters.
27+
*
28+
* @var FormatterInterface[]
29+
*/
30+
protected $formatters = array();
31+
32+
/**
33+
* The supported formatter interface.
34+
*
35+
* @var string
36+
*/
37+
protected $formatterInterface = FormatterInterface::class;
38+
39+
final public function __construct()
40+
{
41+
$this->addFormatters(func_get_args());
42+
}
43+
44+
/**
45+
* Adds {@link FormatterInterface} that will be called in the given order.
10000
46+
*
47+
* @param FormatterInterface[] $appends The formatters to execute at last
48+
* @param FormatterInterface[] $prepends The formatters to execute first
49+
*
50+
* @throws InvalidFormatterException If the exporter does not supporta given formatter
51+
*/
52+
final public function addFormatters(array $appends, array $prepends = array())
53+
{
54+
foreach ($appends as $append) {
55+
if (!$append instanceof $this->formatterInterface) {
56+
throw new InvalidFormatterException(get_class($append), self::class, $this->formatterInterface);
57+
}
58+
$this->formatters[] = $append;
59+
}
60+
foreach ($prepends as $prepend) {
61+
if (!$prepend instanceof $this->formatterInterface) {
62+
throw new InvalidFormatterException(get_class($prepend), self::class, $this->formatterInterface);
63+
}
64+
array_unshift($this->formatters, $prepend);
65+
}
66+
}
67+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Exporter;
13+
14+
use Symfony\Component\ValueExporter\Exception\InvalidFormatterException;
15+
use Symfony\Component\ValueExporter\Exporter;
16+
use Symfony\Component\ValueExporter\Formatter\FormatterInterface;
17+
18+
/**
19+
* ValueExporterInterface implementations export PHP values.
20+
*
21+
* An implementation can rely on {@link FormatterInterface} implementations
22+
* to handle specific types of value.
23+
*
24+
* @author Jules Pietri <jules@heahprod.com>
25+
*/
26+
interface ValueExporterInterface
27+
{
28+
/**
29+
* Exports a PHP value.
30+
*
31+
* ValueExporter instance should always deal with array or \Traversable
32+
* values first in order to handle depth and expand arguments.
33+
*
34+
* Usually you don't need to define the depth but it will be incremented
35+
* in recursive calls. When expand is false any expandable values such as
36+
* arrays or objects should be inline in their exported representation.
37+
*
38+
* @param mixed $value The PHP value to export
39+
* @param int $depth The level of indentation
40+
* @param bool $expand Whether to inline or expand nested values
41+
*/
42+
public function exportValue($value, $depth, $expand);
43+
44+
/**
45+
* Adds {@link FormatterInterface} that will be called in the given order.
46+
*
47+
* @param FormatterInterface[] $appends The formatters to execute at last
48+
* @param FormatterInterface[] $prepends The formatters to execute first
49+
*
50+
* @return self
51+
*
52+
* @throws InvalidFormatterException If the exporter does not supporta given formatter
53+
*/
54+
public function addFormatters(array $appends, array $prepends);
55+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Exporter;
13+
14+
use Symfony\Component\ValueExporter\Formatter\StringFormatterInterface;
15+
16+
/**
17+
* @author Fabien Potencier <fabien@symfony.com>
18+
* @author Bernhard Schussek <bschussek@gmail.com>
19+
* @author Quentin Schuler <qschuler@neosyne.com>
20+
* @author Jules Pietri <jules@heahprod.com>
21+
*/
22+
class ValueToStringExporter extends AbstractValueExporter
23+
{
24+
protected $formatterInterface = StringFormatterInterface::class;
25+
26+
public function exportValue($value, $depth = 1, $expand = false)
27+
{
28+
// Arrays have to be handled first to deal with nested level and depth,
29+
// this implementation intentionally ignores \Traversable values.
30+
// Therefor, \Traversable instances might be treated as objects unless
31+
// implementing a {@link StringFormatterInterface} and passing it to
32+
// the exporter in order to support them.
33+
if (is_array($value)) {
34+
if (empty($value)) {
35+
return 'array()';
36+
}
37+
$indent = str_repeat(' ', $depth);
38+
39+
$a = array();
40+
foreach ($value as $k => $v) {
41+
if (is_array($v) && !empty($v)) {
42+
$expand = true;
43+
}
44+
$a[] = sprintf('%s => %s', $this->exportValue($k), $this->exportValue($v, $depth + 1, $expand));
45+
}
46+
if ($expand) {
47+
return sprintf("array(\n%s%s\n%s)", $indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1));
48+
}
49+
50+
$s = sprintf('array(%s)', implode(', ', $a));
51+
52+
if (80 > strlen($s)) {
53+
return $s;
54+
}
55+
56+
return sprintf("array(\n%s%s\n)", $indent, implode(sprintf(",\n%s", $indent), $a));
57+
}
58+
// Not an array, test each formatter
59+
foreach ($this->formatters as $formatter) {
60+
/** @var StringFormatterInterface $formatter */
61+
if ($formatter->supports($value)) {
62+
return $formatter->formatToString($value);
63+
}
64+
}
65+
// Fallback on default
66+
if (is_object($value)) {
67+
return sprintf('object(%s)', get_class($value));
68+
}
69+
if (is_resource($value)) {
70+
return sprintf('resource(%s#%d)', get_resource_type($value), $value);
71+
}
72+
if (is_float($value)) {
73+
return sprintf('%s', floatval($value));
74+
}
75+
if (is_string($value)) {
76+
return sprintf('"%s"', $value);
77+
}
78+
if (null === $value) {
79+
return 'null';
80+
}
81+
if (false === $value) {
82+
return 'false';
83+
}
84+
if (true === $value) {
85+
return 'true';
86+
}
87+
88+
return (string) $value;
89+
}
90+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Formatter;
13+
14+
/**
15+
* Returns a string representation of a DateTimeInterface instance.
16+
*
17+
* Based on the contribution by @scuben (https://github.com/scuben)
18+
* https://github.com/symfony/symfony/commit/a1762fb65423dc94d69c5fb6abaed37f2ad576e6
19+
*
20+
* @author Jules Pietri <jules@heahprod.com>
21+
*/
22+
class DateTimeToStringFormatter implements StringFormatterInterface
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function supports($value)
28+
{
29+
return $value instanceof \DateTimeInterface;
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function formatToString($value)
36+
{
37+
return sprintf('object(%s) - %s', get_class($value), $value->format(\DateTime::ISO8601));
38+
}
39+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Formatter;
13+
14+
/**
15+
* FormatterInterface.
16+
*
17+
* Returns a formatted representation of (a) supported type(s) of PHP value.
18+
*
19+
* @author Jules Pietri <jules@heahprod.com>
20+
*/
21+
interface FormatterInterface
22+
{
23+
/**
24+
* Returns whether the formatter can format the type(s) of the given value.
25+
*
26+
* @param mixed $value The given value to format
27+
*
28+
* @return bool Whether the given value can be formatted
29+
*/
30+
public function supports($value);
31+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ValueExporter\Formatter;
13+
14+
/**
15+
* Returns a string representation of a __PHP_Incomplete_Class instance.
16+
*
17+
* @author Yonel Ceruto González <yonelceruto@gmail.com>
18+
* @author Jules Pietri <jules@heahprod.com>
19+
*/
20+
class PhpIncompleteClassToStringFormatter implements StringFormatterInterface
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function supports($value)
26+
{
27+
return $value instanceof \__PHP_Incomplete_Class;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function formatToString($value)
34+
{
35+
return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value));
36+
}
37+
38+
private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
39+
{
40+
$array = new \ArrayObject($value);
41+
42+
return $array['__PHP_Incomplete_Class_Name'];
43+
}
44+
}

0 commit comments

Comments
 (0)
0