feature #14058 [VarDumper] Add filters to casters (nicolas-grekas)
This PR was merged into the 2.7 branch.
Discussion
----------
[VarDumper] Add filters to casters
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | -
| License | MIT
| Doc PR | -
Commits
-------
84a80d1
[VarDumper] Add filters to casters
This commit is contained in:
commit
bdb50965f0
81
src/Symfony/Component/VarDumper/Caster/Caster.php
Normal file
81
src/Symfony/Component/VarDumper/Caster/Caster.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Caster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for filtering out properties in casters.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class Caster
|
||||||
|
{
|
||||||
|
const EXCLUDE_VERBOSE = 1;
|
||||||
|
const EXCLUDE_VIRTUAL = 2;
|
||||||
|
const EXCLUDE_DYNAMIC = 4;
|
||||||
|
const EXCLUDE_PUBLIC = 8;
|
||||||
|
const EXCLUDE_PROTECTED = 16;
|
||||||
|
const EXCLUDE_PRIVATE = 32;
|
||||||
|
const EXCLUDE_NULL = 64;
|
||||||
|
const EXCLUDE_EMPTY = 128;
|
||||||
|
const EXCLUDE_NOT_IMPORTANT = 256;
|
||||||
|
const EXCLUDE_STRICT = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters out the specified properties.
|
||||||
|
*
|
||||||
|
* By default, a single match in the $filter bit field filters properties out, following an "or" logic.
|
||||||
|
* When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
|
||||||
|
*
|
||||||
|
* @param array $a The array containing the properties to filter.
|
||||||
|
* @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out.
|
||||||
|
* @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set.
|
||||||
|
*
|
||||||
|
* @return array The filtered array
|
||||||
|
*/
|
||||||
|
public static function filter(array $a, $filter, array $listedProperties = array())
|
||||||
|
{
|
||||||
|
foreach ($a as $k => $v) {
|
||||||
|
$type = self::EXCLUDE_STRICT & $filter;
|
||||||
|
|
||||||
|
if (null === $v) {
|
||||||
|
$type |= self::EXCLUDE_NULL & $filter;
|
||||||
|
}
|
||||||
|
if (empty($v)) {
|
||||||
|
$type |= self::EXCLUDE_EMPTY & $filter;
|
||||||
|
}
|
||||||
|
if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !in_array($k, $listedProperties, true)) {
|
||||||
|
$type |= self::EXCLUDE_NOT_IMPORTANT;
|
||||||
|
}
|
||||||
|
if ((self::EXCLUDE_VERBOSE & $filter) && in_array($k, $listedProperties, true)) {
|
||||||
|
$type |= self::EXCLUDE_VERBOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($k[1]) || "\0" !== $k[0]) {
|
||||||
|
$type |= self::EXCLUDE_PUBLIC & $filter;
|
||||||
|
} elseif ('~' === $k[1]) {
|
||||||
|
$type |= self::EXCLUDE_VIRTUAL & $filter;
|
||||||
|
} elseif ('+' === $k[1]) {
|
||||||
|
$type |= self::EXCLUDE_DYNAMIC & $filter;
|
||||||
|
} elseif ('*' === $k[1]) {
|
||||||
|
$type |= self::EXCLUDE_PROTECTED & $filter;
|
||||||
|
} else {
|
||||||
|
$type |= self::EXCLUDE_PRIVATE & $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
|
||||||
|
unset($a[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
}
|
||||||
|
}
|
@ -40,15 +40,17 @@ class ExceptionCaster
|
|||||||
E_STRICT => 'E_STRICT',
|
E_STRICT => 'E_STRICT',
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function castException(\Exception $e, array $a, Stub $stub, $isNested)
|
public static function castException(\Exception $e, array $a, Stub $stub, $isNested, $filter = 0)
|
||||||
{
|
{
|
||||||
$trace = $a["\0Exception\0trace"];
|
$trace = $a["\0Exception\0trace"];
|
||||||
unset($a["\0Exception\0trace"]); // Ensures the trace is always last
|
unset($a["\0Exception\0trace"]); // Ensures the trace is always last
|
||||||
|
|
||||||
static::filterTrace($trace, static::$traceArgs);
|
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
|
||||||
|
static::filterTrace($trace, static::$traceArgs);
|
||||||
|
|
||||||
if (null !== $trace) {
|
if (null !== $trace) {
|
||||||
$a["\0Exception\0trace"] = $trace;
|
$a["\0Exception\0trace"] = $trace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (empty($a["\0Exception\0previous"])) {
|
if (empty($a["\0Exception\0previous"])) {
|
||||||
unset($a["\0Exception\0previous"]);
|
unset($a["\0Exception\0previous"]);
|
||||||
|
@ -96,6 +96,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
private $casters = array();
|
private $casters = array();
|
||||||
private $prevErrorHandler;
|
private $prevErrorHandler;
|
||||||
private $classInfo = array();
|
private $classInfo = array();
|
||||||
|
private $filter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable[]|null $casters A map of casters.
|
* @param callable[]|null $casters A map of casters.
|
||||||
@ -149,10 +150,16 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* Clones a PHP variable.
|
||||||
|
*
|
||||||
|
* @param mixed $var Any PHP variable.
|
||||||
|
* @param int $filter A bit field of Caster::EXCLUDE_* constants.
|
||||||
|
*
|
||||||
|
* @return Data The cloned variable represented by a Data object.
|
||||||
*/
|
*/
|
||||||
public function cloneVar($var)
|
public function cloneVar($var, $filter = 0)
|
||||||
{
|
{
|
||||||
|
$this->filter = $filter;
|
||||||
$this->prevErrorHandler = set_error_handler(array($this, 'handleError'));
|
$this->prevErrorHandler = set_error_handler(array($this, 'handleError'));
|
||||||
try {
|
try {
|
||||||
if (!function_exists('iconv')) {
|
if (!function_exists('iconv')) {
|
||||||
@ -270,7 +277,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
private function callCaster($callback, $obj, $a, $stub, $isNested)
|
private function callCaster($callback, $obj, $a, $stub, $isNested)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$cast = call_user_func($callback, $obj, $a, $stub, $isNested);
|
$cast = call_user_func($callback, $obj, $a, $stub, $isNested, $this->filter);
|
||||||
|
|
||||||
if (is_array($cast)) {
|
if (is_array($cast)) {
|
||||||
$a = $cast;
|
$a = $cast;
|
||||||
|
147
src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php
Normal file
147
src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\VarDumper\Tests\Caster;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Caster\Caster;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class CasterTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
private $referenceArray = array(
|
||||||
|
'null' => null,
|
||||||
|
'empty' => false,
|
||||||
|
'public' => 'pub',
|
||||||
|
"\0~\0virtual" => 'virt',
|
||||||
|
"\0+\0dynamic" => 'dyn',
|
||||||
|
"\0*\0protected" => 'prot',
|
||||||
|
"\0Foo\0private" => 'priv',
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @dataProvider provideFilter */
|
||||||
|
public function testFilter($filter, $expectedDiff, $listedProperties = null)
|
||||||
|
{
|
||||||
|
if (null === $listedProperties) {
|
||||||
|
$filteredArray = Caster::filter($this->referenceArray, $filter);
|
||||||
|
} else {
|
||||||
|
$filteredArray = Caster::filter($this->referenceArray, $filter, $listedProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertSame($expectedDiff, array_diff_assoc($this->referenceArray, $filteredArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideFilter()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
0,
|
||||||
|
array(),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_PUBLIC,
|
||||||
|
array(
|
||||||
|
'null' => null,
|
||||||
|
'empty' => false,
|
||||||
|
'public' => 'pub',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_NULL,
|
||||||
|
array(
|
||||||
|
'null' => null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_EMPTY,
|
||||||
|
array(
|
||||||
|
'null' => null,
|
||||||
|
'empty' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_VIRTUAL,
|
||||||
|
array(
|
||||||
|
"\0~\0virtual" => 'virt',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_DYNAMIC,
|
||||||
|
array(
|
||||||
|
"\0+\0dynamic" => 'dyn',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_PROTECTED,
|
||||||
|
array(
|
||||||
|
"\0*\0protected" => 'prot',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_PRIVATE,
|
||||||
|
array(
|
||||||
|
"\0Foo\0private" => 'priv',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_VERBOSE,
|
||||||
|
array(
|
||||||
|
'public' => 'pub',
|
||||||
|
"\0*\0protected" => 'prot',
|
||||||
|
),
|
||||||
|
array('public', "\0*\0protected"),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_NOT_IMPORTANT,
|
||||||
|
array(
|
||||||
|
'null' => null,
|
||||||
|
'empty' => false,
|
||||||
|
"\0~\0virtual" => 'virt',
|
||||||
|
"\0+\0dynamic" => 'dyn',
|
||||||
|
"\0Foo\0private" => 'priv',
|
||||||
|
),
|
||||||
|
array('public', "\0*\0protected"),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_VIRTUAL | Caster::EXCLUDE_DYNAMIC,
|
||||||
|
array(
|
||||||
|
"\0~\0virtual" => 'virt',
|
||||||
|
"\0+\0dynamic" => 'dyn',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_VERBOSE,
|
||||||
|
$this->referenceArray,
|
||||||
|
array('public', "\0*\0protected"),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_EMPTY,
|
||||||
|
array(
|
||||||
|
'null' => null,
|
||||||
|
'empty' => false,
|
||||||
|
"\0~\0virtual" => 'virt',
|
||||||
|
"\0+\0dynamic" => 'dyn',
|
||||||
|
"\0*\0protected" => 'prot',
|
||||||
|
"\0Foo\0private" => 'priv',
|
||||||
|
),
|
||||||
|
array('public', 'empty'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Caster::EXCLUDE_VERBOSE | Caster::EXCLUDE_EMPTY | Caster::EXCLUDE_STRICT,
|
||||||
|
array(
|
||||||
|
'empty' => false,
|
||||||
|
),
|
||||||
|
array('public', 'empty'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user