Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 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
use Symfony\Component\VarDumper\Cloner\Stub;
15
 
16
/**
17
 * Helper for filtering out properties in casters.
18
 *
19
 * @author Nicolas Grekas <p@tchwork.com>
20
 *
21
 * @final
22
 */
23
class Caster
24
{
25
    public const EXCLUDE_VERBOSE = 1;
26
    public const EXCLUDE_VIRTUAL = 2;
27
    public const EXCLUDE_DYNAMIC = 4;
28
    public const EXCLUDE_PUBLIC = 8;
29
    public const EXCLUDE_PROTECTED = 16;
30
    public const EXCLUDE_PRIVATE = 32;
31
    public const EXCLUDE_NULL = 64;
32
    public const EXCLUDE_EMPTY = 128;
33
    public const EXCLUDE_NOT_IMPORTANT = 256;
34
    public const EXCLUDE_STRICT = 512;
35
 
36
    public const PREFIX_VIRTUAL = "\0~\0";
37
    public const PREFIX_DYNAMIC = "\0+\0";
38
    public const PREFIX_PROTECTED = "\0*\0";
39
 
40
    /**
41
     * Casts objects to arrays and adds the dynamic property prefix.
42
     *
43
     * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not
44
     */
45
    public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array
46
    {
47
        if ($hasDebugInfo) {
48
            try {
49
                $debugInfo = $obj->__debugInfo();
50
            } catch (\Throwable) {
51
                // ignore failing __debugInfo()
52
                $hasDebugInfo = false;
53
            }
54
        }
55
 
56
        $a = $obj instanceof \Closure ? [] : (array) $obj;
57
 
58
        if ($obj instanceof \__PHP_Incomplete_Class) {
59
            return $a;
60
        }
61
 
62
        if ($a) {
63
            static $publicProperties = [];
64
            $debugClass ??= get_debug_type($obj);
65
 
66
            $i = 0;
67
            $prefixedKeys = [];
68
            foreach ($a as $k => $v) {
69
                if ("\0" !== ($k[0] ?? '')) {
70
                    if (!isset($publicProperties[$class])) {
71
                        foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
72
                            $publicProperties[$class][$prop->name] = true;
73
                        }
74
                    }
75
                    if (!isset($publicProperties[$class][$k])) {
76
                        $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
77
                    }
78
                } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {
79
                    $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0");
80
                }
81
                ++$i;
82
            }
83
            if ($prefixedKeys) {
84
                $keys = array_keys($a);
85
                foreach ($prefixedKeys as $i => $k) {
86
                    $keys[$i] = $k;
87
                }
88
                $a = array_combine($keys, $a);
89
            }
90
        }
91
 
92
        if ($hasDebugInfo && \is_array($debugInfo)) {
93
            foreach ($debugInfo as $k => $v) {
94
                if (!isset($k[0]) || "\0" !== $k[0]) {
95
                    if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) {
96
                        continue;
97
                    }
98
                    $k = self::PREFIX_VIRTUAL.$k;
99
                }
100
 
101
                unset($a[$k]);
102
                $a[$k] = $v;
103
            }
104
        }
105
 
106
        return $a;
107
    }
108
 
109
    /**
110
     * Filters out the specified properties.
111
     *
112
     * By default, a single match in the $filter bit field filters properties out, following an "or" logic.
113
     * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed.
114
     *
115
     * @param array    $a                The array containing the properties to filter
116
     * @param int      $filter           A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out
117
     * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set
688 lars 118
     * @param int|null &$count           Set to the number of removed properties
148 lars 119
     */
120
    public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array
121
    {
122
        $count = 0;
123
 
124
        foreach ($a as $k => $v) {
125
            $type = self::EXCLUDE_STRICT & $filter;
126
 
127
            if (null === $v) {
128
                $type |= self::EXCLUDE_NULL & $filter;
129
                $type |= self::EXCLUDE_EMPTY & $filter;
130
            } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {
131
                $type |= self::EXCLUDE_EMPTY & $filter;
132
            }
133
            if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) {
134
                $type |= self::EXCLUDE_NOT_IMPORTANT;
135
            }
136
            if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) {
137
                $type |= self::EXCLUDE_VERBOSE;
138
            }
139
 
140
            if (!isset($k[1]) || "\0" !== $k[0]) {
141
                $type |= self::EXCLUDE_PUBLIC & $filter;
142
            } elseif ('~' === $k[1]) {
143
                $type |= self::EXCLUDE_VIRTUAL & $filter;
144
            } elseif ('+' === $k[1]) {
145
                $type |= self::EXCLUDE_DYNAMIC & $filter;
146
            } elseif ('*' === $k[1]) {
147
                $type |= self::EXCLUDE_PROTECTED & $filter;
148
            } else {
149
                $type |= self::EXCLUDE_PRIVATE & $filter;
150
            }
151
 
152
            if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) {
153
                unset($a[$k]);
154
                ++$count;
155
            }
156
        }
157
 
158
        return $a;
159
    }
160
 
161
    public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array
162
    {
163
        if (isset($a['__PHP_Incomplete_Class_Name'])) {
164
            $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')';
165
            unset($a['__PHP_Incomplete_Class_Name']);
166
        }
167
 
168
        return $a;
169
    }
170
}