8000 feature #14058 [VarDumper] Add filters to casters (nicolas-grekas) · symfony/symfony@bdb5096 · GitHub
[go: up one dir, main page]

Skip to content

Commit bdb5096

Browse files
committed
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
2 parents 2533d8f + 84a80d1 commit bdb5096

File tree

4 files changed

+244
-7
lines changed

4 files changed

+244
-7
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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\VarDumper\Caster;
13+
14+
/**
15+
* Helper for filtering out properties in casters.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class Caster
20+
{
21+
const EXCLUDE_VERBOSE = 1;
22+
const EXCLUDE_VIRTUAL = 2;
23+
const EXCLUDE_DYNAMIC = 4;
24+
const EXCLUDE_PUBLIC = 8;
25+
const EXCLUDE_PROTECTED = 16;
26+
const EXCLUDE_PRIVATE = 32;
27+
const EXCLUDE_NULL = 64;
28+
const EXCLUDE_EMPTY = 128;
29+
const EXCLUDE_NOT_IMPORTANT = 256;
30+
const EXCLUDE_STRICT = 512;
31+
32+
/**
33+
* Filters out the specified properties.
34+
*
35+
* By default, a single match in the $filter bit field filters properties out, following an "or" logic.
36+
* When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
37+
*
38+
* @param array $a The array containing the properties to filter.
39+
* @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out.
40+
* @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set.
41+
*
42+
* @return array The filtered array
43+
*/
44+
public static function filter(array $a, $filter, array $listedProperties = array())
45+
{
46+
foreach ($a as $k => $v) {
47+
$type = self::EXCLUDE_STRICT & $filter;
48+
49+
if (null === $v) {
50+
$type |= self::EXCLUDE_NULL & $filter;
51+
}
52+
if (empty($v)) {
53+
$type |= self::EXCLUDE_EMPTY & $filter;
54+
}
55+
if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !in_array($k, $listedProperties, true)) {
56+
$type |= self::EXCLUDE_NOT_IMPORTANT;
57+
}
58+
if ((self::EXCLUDE_VERBOSE & $filter) && in_array($k, $listedProperties, true)) {
59+
$type |= self::EXCLUDE_VERBOSE;
60+
}
61+
62+
if (!isset($k[1]) || "\0" !== $k[0]) {
63+
$type |= self::EXCLUDE_PUBLIC & $filter;
64+
} elseif ('~' === $k[1]) {
65+
$type |= self::EXCLUDE_VIRTUAL & $filter;
66+
} elseif ('+' === $k[1]) {
67+
$type |= self::EXCLUDE_DYNAMIC & $filter;
68+
} elseif ('*' === $k[1]) {
69+
$type |= self::EXCLUDE_PROTECTED & $filter;
70+
} else {
71+
$type |= self::EXCLUDE_PRIVATE & $filter;
72+
}
73+
74+
if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
75+
unset($a[$k]);
76+
}
77+
}
78+
79+
return $a;
80+
}
81+
}

src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,17 @@ class ExceptionCaster
4040
E_STRICT => 'E_STRICT',
4141
);
4242

43-
public static function castException(\Exception $e, array $a, Stub $stub, $isNested)
43+
public static function castException(\Exception $e, array $a, Stub $stub, $isNested, $filter = 0)
4444
{
4545
$trace = $a["\0Exception\0trace"];
4646
unset($a["\0Exception\0trace"]); // Ensures the trace is always last
4747

48-
static::filterTrace($trace, static::$traceArgs);
48+
if (!($filter & Caster::EXCLUDE_VERBOSE)) {
49+
static::filterTrace($trace, static::$traceArgs);
4950

50-
if (null !== $trace) {
51-
$a["\0Exception\0trace"] = $trace;
51+
if (null !== $trace) {
52+
$a["\0Exception\0trace"] = $trace;
53+
}
5254
}
5355
if (empty($a["\0Exception\0previous"])) {
5456
unset($a["\0Exception\0previous"]);

src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ abstract class AbstractCloner implements ClonerInterface
9696
private $casters = array();
9797
private $prevErrorHandler;
9898
private $classInfo = array();
99+
private $filter = 0;
99100

100101
/**
101102
* @param callable[]|null $casters A map of casters.
@@ -149,10 +150,16 @@ public function setMaxString($maxString)
149150
}
150151

151152
/**
152-
* {@inheritdoc}
153+
* Clones a PHP variable.
154+
*
155+
* @param mixed $var Any PHP variable.
156+
* @param int $filter A bit field of Caster::EXCLUDE_* constants.
157+
*
158+
* @return Data The cloned variable represented by a Data object.
153159
*/
154-
public function cloneVar($var)
160+
public function cloneVar($var, $filter = 0)
155161
{
162+
$this->filter = $filter;
156163
$this->prevErrorHandler = set_error_handler(array($this, 'handleError'));
157164
try {
158165
if (!function_exists('iconv')) {
@@ -270,7 +277,7 @@ protected function castResource(Stub $stub, $isNested)
270277
private function callCaster($callback, $obj, $a, $stub, $isNested)
271278
{
272279
try {
273-
$cast = call_user_func($callback, $obj, $a, $stub, $isNested);
280+
$cast = call_user_func($callback, $obj, $a, $stub, $isNested, $this->filter);
274281

275282
if (is_array($cast)) {
276283
$a = $cast;
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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\VarDumper\Tests\Caster;
13+
14+
use Symfony\Component\VarDumper\Caster\Caster;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class CasterTest extends \PHPUnit_Framework_TestCase
20+
{
21+
private $referenceArray = array(
22+
'null' => null,
23+
'empty' => false,
24+
'public' => 'pub',
25+
"\0~\0virtual" => 'virt',
26+
"\0+\0dynamic" => 'dyn',
27+
"\0*\0protected" => 'prot',
28+
"\0Foo\0private" => 'priv',
29+
);
30+
31+
/** @dataProvider provideFilter */
32+
public function testFilter($filter, $expectedDiff, $listedProperties = null)
33+
{
34+
if (null === $listedProperties) {
35+
$filteredArray = Caster::filter($this->referenceArray, $filter);
36+
} else {
37+
$filteredArray = Caster::filter($this->referenceArray, $filter, $listedProperties);
38+
}
39+
40+
$this->assertSame($expectedDiff, array_diff_assoc($this->referenceArray, $filteredArray));
41+
}
42+
43+
public function provideFilter()
44+
{
45+
return array(
46+
array(
47+
0,
48+
array(),
49+
),
50+
array(
51+
Caster::EXCLUDE_PUBLIC,
52+
array(
53+
'null' => null,
54+
'empty' => false,
55+
'public' => 'pub',
56+
),
57+
),
58+
array(
59+
Caster::EXCLUDE_NULL,
60+
array(
61+
'null' => null,
62+
),
63+
),
64+
array(
65+
Caster::EXCLUDE_EMPTY,
66+
array(
67+
'null' => null,
68+
'empty' => false,
69+
),
70+
),
71+
array(
72+
Caster::EXCLUDE_VIRTUAL,
73+
array(
74+
"\0~\0virtual" => 'virt',
75+
),
76+
),
77+
array(
78+
Caster::EXCLUDE_DYNAMIC,
79+
array(
80+
"\0+\0dynamic" => 'dyn',
81+
),
82+
),
83+
array(
84+
Caster::EXCLUDE_PROTECTED,
85+
array(
86+
"\0*\0protected" => 'prot',
87+
),
88+
),
89+
array(
90+
Caster::EXCLUDE_PRIVATE,
91+
array(
92+
"\0Foo\0private" => 'priv',
93+
),
94+
),
95+
array(
96+
Caster::EXCLUDE_VERBOSE,
97+
array(
98+
'public' => 'pub',
99+
"\0*\0protected" => 'prot',
100+
),
101+
array('public', "\0*\0protected"),
102+
),
103+
array(
104+
Caster::EXCLUDE_NOT_IMPORTANT,
105+
array(
106+
'null' => null,
107+
'empty' => false,
108+
"\0~\0virtual" => 'virt',
109+
"\0+\0dynamic" => 'dyn',
110+
"\0Foo\0private" => 'priv',
111+
),
112+
array('public', "\0*\0protected"),
113+
),
114+
array(
115+
Caster::EXCLUDE_VIRTUAL | Caster::EXCLUDE_DYNAMIC,
116+
array(
117+
"\0~\0virtual" => 'virt',
118+
"\0+\0dynamic" => 'dyn',
119+
),
120+
),
121+
array(
122+
Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_VERBOSE,
123+
$this->referenceArray,
124+
array('public', "\0*\0protected"),
125+
),
126+
array(
127+
Caster::EXCLUDE_NOT_IMPORTANT | Caster::EXCLUDE_EMPTY,
128+
array(
129+
'null' => null,
130+
'empty' => false,
131+
"\0~\0virtual" => 'virt',
132+
"\0+\0dynamic" => 'dyn',
133+
"\0*\0protected" => 'prot',
134+
"\0Foo\0private" => 'priv',
135+
),
136+
array('public', 'empty'),
137+
),
138+
array(
139+
Caster::EXCLUDE_VERBOSE | Caster::EXCLUDE_EMPTY | Caster::EXCLUDE_STRICT,
140+
array(
141+
'empty' => false,
142+
),
143+
array('public', 'empty'),
144+
),
145+
);
146+
}
147+
}

0 commit comments

Comments
 (0)
< 2A2E /div>
0