Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | 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
 *
6
 * (c) 2012-2022 Justin Hileman
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
     *
59
     * @param bool       $showAll   Include private and protected properties
60
     * @param \Reflector $reflector
61
     * @param bool       $noInherit Exclude inherited properties
62
     *
63
     * @return array
64
     */
65
    protected function getProperties(bool $showAll, \Reflector $reflector, bool $noInherit = false): array
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
     * @return string
117
     */
118
    protected function getKindLabel(\ReflectionClass $reflector): string
119
    {
120
        if (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
121
            return 'Trait Properties';
122
        } else {
123
            return 'Class Properties';
124
        }
125
    }
126
 
127
    /**
128
     * Get output style for the given property's visibility.
129
     *
130
     * @param \ReflectionProperty $property
131
     *
132
     * @return string
133
     */
134
    private function getVisibilityStyle(\ReflectionProperty $property): string
135
    {
136
        if ($property->isPublic()) {
137
            return self::IS_PUBLIC;
138
        } elseif ($property->isProtected()) {
139
            return self::IS_PROTECTED;
140
        } else {
141
            return self::IS_PRIVATE;
142
        }
143
    }
144
 
145
    /**
146
     * Present the $target's current value for a reflection property.
147
     *
148
     * @param \ReflectionProperty $property
149
     * @param mixed               $target
150
     *
151
     * @return string
152
     */
153
    protected function presentValue(\ReflectionProperty $property, $target): string
154
    {
155
        if (!$target) {
156
            return '';
157
        }
158
 
159
        // If $target is a class or trait (try to) get the default
160
        // value for the property.
161
        if (!\is_object($target)) {
162
            try {
163
                $refl = new \ReflectionClass($target);
164
                $props = $refl->getDefaultProperties();
165
                if (\array_key_exists($property->name, $props)) {
166
                    $suffix = $property->isStatic() ? '' : ' <aside>(default)</aside>';
167
 
168
                    return $this->presentRef($props[$property->name]).$suffix;
169
                }
170
            } catch (\Throwable $e) {
171
                // Well, we gave it a shot.
172
            }
173
 
174
            return '';
175
        }
176
 
177
        $property->setAccessible(true);
178
        $value = $property->getValue($target);
179
 
180
        return $this->presentRef($value);
181
    }
182
}