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 Psy Shell.
5
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 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 Psy\Command\ListCommand;
13
 
14
use Symfony\Component\Console\Input\InputInterface;
15
 
16
/**
17
 * Property Enumerator class.
18
 */
19
class PropertyEnumerator extends Enumerator
20
{
21
    /**
22
     * {@inheritdoc}
23
     */
24
    protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null): array
25
    {
26
        // only list properties when a Reflector is present.
27
 
28
        if ($reflector === null) {
29
            return [];
30
        }
31
 
32
        // We can only list properties on actual class (or object) reflectors.
33
        if (!$reflector instanceof \ReflectionClass) {
34
            return [];
35
        }
36
 
37
        // only list properties if we are specifically asked
38
        if (!$input->getOption('properties')) {
39
            return [];
40
        }
41
 
42
        $showAll = $input->getOption('all');
43
        $noInherit = $input->getOption('no-inherit');
44
        $properties = $this->prepareProperties($this->getProperties($showAll, $reflector, $noInherit), $target);
45
 
46
        if (empty($properties)) {
47
            return [];
48
        }
49
 
50
        $ret = [];
51
        $ret[$this->getKindLabel($reflector)] = $properties;
52
 
53
        return $ret;
54
    }
55
 
56
    /**
57
     * Get defined properties for the given class or object Reflector.
58
     *
200 lars 59
     * @param bool             $showAll   Include private and protected properties
60
     * @param \ReflectionClass $reflector
61
     * @param bool             $noInherit Exclude inherited properties
148 lars 62
     *
63
     * @return array
64
     */
200 lars 65
    protected function getProperties(bool $showAll, \ReflectionClass $reflector, bool $noInherit = false): array
148 lars 66
    {
67
        $className = $reflector->getName();
68
 
69
        $properties = [];
70
        foreach ($reflector->getProperties() as $property) {
71
            if ($noInherit && $property->getDeclaringClass()->getName() !== $className) {
72
                continue;
73
            }
74
 
75
            if ($showAll || $property->isPublic()) {
76
                $properties[$property->getName()] = $property;
77
            }
78
        }
79
 
80
        \ksort($properties, \SORT_NATURAL | \SORT_FLAG_CASE);
81
 
82
        return $properties;
83
    }
84
 
85
    /**
86
     * Prepare formatted property array.
87
     *
88
     * @param array $properties
89
     *
90
     * @return array
91
     */
92
    protected function prepareProperties(array $properties, $target = null): array
93
    {
94
        // My kingdom for a generator.
95
        $ret = [];
96
 
97
        foreach ($properties as $name => $property) {
98
            if ($this->showItem($name)) {
99
                $fname = '$'.$name;
100
                $ret[$fname] = [
101
                    'name'  => $fname,
102
                    'style' => $this->getVisibilityStyle($property),
103
                    'value' => $this->presentValue($property, $target),
104
                ];
105
            }
106
        }
107
 
108
        return $ret;
109
    }
110
 
111
    /**
112
     * Get a label for the particular kind of "class" represented.
113
     *
114
     * @param \ReflectionClass $reflector
115
     */
116
    protected function getKindLabel(\ReflectionClass $reflector): string
117
    {
118
        if (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
119
            return 'Trait Properties';
120
        } else {
121
            return 'Class Properties';
122
        }
123
    }
124
 
125
    /**
126
     * Get output style for the given property's visibility.
127
     *
128
     * @param \ReflectionProperty $property
129
     */
130
    private function getVisibilityStyle(\ReflectionProperty $property): string
131
    {
132
        if ($property->isPublic()) {
133
            return self::IS_PUBLIC;
134
        } elseif ($property->isProtected()) {
135
            return self::IS_PROTECTED;
136
        } else {
137
            return self::IS_PRIVATE;
138
        }
139
    }
140
 
141
    /**
142
     * Present the $target's current value for a reflection property.
143
     *
144
     * @param \ReflectionProperty $property
145
     * @param mixed               $target
146
     */
147
    protected function presentValue(\ReflectionProperty $property, $target): string
148
    {
149
        if (!$target) {
150
            return '';
151
        }
152
 
153
        // If $target is a class or trait (try to) get the default
154
        // value for the property.
155
        if (!\is_object($target)) {
156
            try {
157
                $refl = new \ReflectionClass($target);
158
                $props = $refl->getDefaultProperties();
159
                if (\array_key_exists($property->name, $props)) {
160
                    $suffix = $property->isStatic() ? '' : ' <aside>(default)</aside>';
161
 
162
                    return $this->presentRef($props[$property->name]).$suffix;
163
                }
164
            } catch (\Throwable $e) {
165
                // Well, we gave it a shot.
166
            }
167
 
168
            return '';
169
        }
170
 
171
        $property->setAccessible(true);
172
        $value = $property->getValue($target);
173
 
174
        return $this->presentRef($value);
175
    }
176
}