ConfigList::getDeltas()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 3
nop 2
dl 0
loc 18
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace Sunnysideup\ConfigManager\Api;
4
5
use ReflectionClass;
6
use SilverStripe\Config\Collections\DeltaConfigCollection;
7
use SilverStripe\Control\Director;
8
use SilverStripe\Core\ClassInfo;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\Core\Config\Configurable;
11
use SilverStripe\Core\Extensible;
12
use SilverStripe\Core\Extension;
13
use SilverStripe\Core\Injector\Injectable;
14
15
class ConfigList
16
{
17
    use Extensible;
18
    use Injectable;
19
    use Configurable;
20
21
    private static $exceptional_classes = [
22
        Extension::class,
23
    ];
24
25
    private static $do_not_show = [
26
        'extra_methods',
27
        'built_in_methods',
28
    ];
29
30
    // protected $locationIncludes = [];
31
    //
32
    // protected $classNameIncludes = [];
33
    //
34
    // public function setLocationIncludes($a)
35
    // {
36
    //     $this->locationIncludes = $a;
37
    //
38
    //     return $this;
39
    // }
40
    //
41
    // public function setClassNameIncludes($a)
42
    // {
43
    //     $this->classNameIncludes = $a;
44
    //
45
    //     return $this;
46
    // }
47
48
    public function getListOfConfigs(): array
49
    {
50
        $resultArray = [];
51
52
        $doNotShow = $this->Config()->get('do_not_show');
53
54
        $config = Config::inst();
55
        $alsoSet = $config->getAll();
56
        $base = Director::baseFolder();
57
58
        $classes = $this->configurableClasses();
59
        foreach ($classes as $class) {
60
            $reflector = new ReflectionClass($class);
61
            $fileName = $reflector->getFilename();
62
            $fileName = str_replace($base, '', $fileName);
63
64
            //lists
65
            $staticListDelta = $this->getDeltas($config, $class);
0 ignored issues
show
Bug introduced by
$config of type SilverStripe\Config\Coll...nfigCollectionInterface is incompatible with the type SilverStripe\Core\Config\Config expected by parameter $config of Sunnysideup\ConfigManage...ConfigList::getDeltas(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            $staticListDelta = $this->getDeltas(/** @scrutinizer ignore-type */ $config, $class);
Loading history...
66
            $staticListDynamic = array_keys($alsoSet[strtolower($class)]);
67
            $defaultLists = $this->getDefaultLists($reflector, $doNotShow);
68
            $originalValues = $defaultLists['OriginalValues'];
69
70
            $lists = [
71
                //do first so that they will always show up
72
                'runtime' => $staticListDelta,
73
                'system' => $defaultLists['Caching'],
74
                'caching' => $defaultLists['System'],
75
                'property' => $defaultLists['Property'],
76
                //needs to be last so that only dynamic ones that are
77
                //not set as property are included
78
                'dynamic' => $staticListDynamic,
79
            ];
80
81
            foreach ($lists as $type => $list) {
82
                foreach ($list as $property) {
83
                    $key = str_replace('/', '-', $fileName . '-' . $property);
84
                    if (! isset($resultArray[$key])) {
85
                        $value = $config->get($class, $property, Config::UNINHERITED);
86
                        $hasValue = (bool) $value;
87
                        $originalValue = isset($originalValues[$property]) ? $originalValues[$property] : '';
88
                        if (is_object($value)) {
89
                            $value = 'object';
90
                        }
91
                        $isDefault = true;
92
                        $default = '';
93
                        if ($originalValue !== $value) {
94
                            $isDefault = false;
95
                            if ($value && $originalValue) {
96
                                $default = $originalValue;
97
                            }
98
                        }
99
                        $hasDefault = (bool) $originalValue;
100
                        $resultArray[$key] = array_merge(
101
                            $this->getClassIntel($class),
102
                            [
103
                                'FileLocation' => $fileName,
104
                                'Property' => $property,
105
                                'Type' => $type,
106
                                'IsDefault' => $isDefault,
107
                                'HasDefault' => $hasDefault,
108
                                'HasValue' => $hasValue,
109
                                'Default' => $default,
110
                                'Value' => $value,
111
                            ]
112
                        );
113
                    }
114
                }
115
            }
116
        }
117
118
        return $resultArray;
119
    }
120
121
    /**
122
     * info about static.
123
     *
124
     * @param ReflectionClass $reflector
125
     * @param array            $doNotShow
126
     */
127
    protected function getDefaultLists($reflector, array $doNotShow): array
128
    {
129
        //vars
130
        $staticListSystem = [];
131
        $staticListCaching = [];
132
        $staticListProperty = [];
133
        $originalValues = [];
134
        //start loop
135
        $statics = $reflector->getStaticProperties();
136
        foreach (array_keys($statics) as $property) {
137
            $propertyObject = $reflector->getProperty($property);
138
            if ($propertyObject->isPrivate()) {
139
                $propertyObject->setAccessible(true);
140
                $originalValues[$property] = $propertyObject->getValue($reflector);
141
142
                if (in_array($property, $doNotShow, true)) {
143
                    $staticListSystem[$property] = $property;
144
                } elseif ('_' === substr($property, 0, 1) ||
145
                    false !== strpos($property, 'cache')
146
                ) {
147
                    $staticListCaching[$property] = $property;
148
                } else {
149
                    $staticListProperty[$property] = $property;
150
                }
151
            }
152
        }
153
154
        return [
155
            'System' => $staticListSystem,
156
            'Caching' => $staticListCaching,
157
            'Property' => $staticListProperty,
158
            'OriginalValues' => $originalValues,
159
        ];
160
    }
161
162
    /**
163
     * info about class.
164
     */
165
    protected function getClassIntel(string $class): array
166
    {
167
        $vendor = 'n/a';
168
        $package = 'n/a';
169
        $shorterClassname = $class;
170
        $classNameArray = explode('\\', $class);
171
        $shortClassName = ClassInfo::shortName($class);
172
        $ancestry = ClassInfo::ancestry($class);
173
        $childClasses = ClassInfo::subclassesFor($class, false);
174
        if (count($classNameArray) > 1) {
175
            $vendor = $classNameArray[0];
176
            $package = $classNameArray[1];
177
            array_shift($classNameArray);
178
            array_shift($classNameArray);
179
            $shorterClassname = implode(' / ', $classNameArray);
180
        }
181
182
        return [
183
            'Vendor' => $vendor,
184
            'Package' => $package,
185
            'ClassName' => $class,
186
            'ShorterClassName' => $shorterClassname,
187
            'ShortClassName' => $shortClassName,
188
            'ParentClasses' => $ancestry,
189
            'ChildClasses' => $childClasses,
190
        ];
191
    }
192
193
    /**
194
     * get values set at run time (deltas / changed ones).
195
     *
196
     * @param Config $config
197
     * @param string $className
198
     */
199
    protected function getDeltas($config, $className): array
200
    {
201
        $deltaList = [];
202
        if ($config instanceof DeltaConfigCollection) {
0 ignored issues
show
introduced by
$config is never a sub-type of SilverStripe\Config\Coll...s\DeltaConfigCollection.
Loading history...
203
            $deltas = $config->getDeltas($className);
204
            if (count($deltas)) {
205
                foreach ($deltas as $deltaInners) {
206
                    if (isset($deltaInners['config'])) {
207
                        $deltaList = array_merge(
208
                            $deltaList,
209
                            array_keys($deltaInners['config'])
210
                        );
211
                    }
212
                }
213
            }
214
        }
215
216
        return $deltaList;
217
    }
218
219
    /**
220
     * get a list of class with the Configurable Trait.
221
     */
222
    protected function configurableClasses(): array
223
    {
224
        $definedClasses = ClassInfo::allClasses();
225
226
        return array_filter(
227
            $definedClasses,
228
            function ($className) {
229
                if (class_exists($className)) {
230
                    $autoload = true;
231
                    $traits = [];
232
                    $class = $className;
233
                    // Get traits of all parent classes
234
                    do {
235
                        $traits = array_merge(class_uses($class, $autoload), $traits);
236
                        $class = get_parent_class($class);
237
                        if (in_array($class, $this->Config()->get('exceptional_classes'), true)) {
238
                            $traits[Configurable::class] = Configurable::class;
239
                        }
240
                    } while ($class);
241
242
                    // Get traits of all parent traits
243
                    $traitsToSearch = $traits;
244
                    while (! empty($traitsToSearch)) {
245
                        $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
246
                        $traits = array_merge($newTraits, $traits);
247
                        $traitsToSearch = array_merge($newTraits, $traitsToSearch);
248
                    }
249
250
                    foreach (array_keys($traits) as $trait) {
251
                        $traits = array_merge(class_uses($trait, $autoload), $traits);
252
                    }
253
254
                    return isset($traits[Configurable::class]);
255
                }
256
            }
257
        );
258
    }
259
}
260