• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

heimrichhannot / contao-utils-bundle / 6106487958

07 Sep 2023 07:01AM UTC coverage: 22.169% (-0.01%) from 22.181%
6106487958

push

github

web-flow
Merge pull request #68 from heimrichhannot/fix/php8-warning

Fixed: PHP8 warning and minor refactoring

22 of 22 new or added lines in 2 files covered. (100.0%)

1196 of 5395 relevant lines covered (22.17%)

1.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

14.61
/src/Classes/ClassUtil.php
1
<?php
2

3
/*
4
 * Copyright (c) 2022 Heimrich & Hannot GmbH
5
 *
6
 * @license LGPL-3.0-or-later
7
 */
8

9
namespace HeimrichHannot\UtilsBundle\Classes;
10

11
use HeimrichHannot\UtilsBundle\Arrays\ArrayUtil;
12
use HeimrichHannot\UtilsBundle\Util\Type\StringUtil;
13

14
class ClassUtil
15
{
16
    /**
17
     * @var ArrayUtil
18
     */
19
    protected $arrayUtil;
20
    /**
21
     * @var StringUtil
22
     */
23
    protected $stringUtil;
24

25
    /**
26
     * ClassUtil constructor.
27
     */
28
    public function __construct(ArrayUtil $arrayUtil, StringUtil $stringUtil)
29
    {
30
        $this->arrayUtil = $arrayUtil;
2✔
31
        $this->stringUtil = $stringUtil;
2✔
32
    }
33

34
    /**
35
     * @return array
36
     */
37
    public function getParentClasses(string $class, array $parents = [])
38
    {
39
        $strParent = get_parent_class($class);
1✔
40

41
        if ($strParent) {
1✔
42
            $parents[] = $strParent;
1✔
43

44
            $parents = $this->getParentClasses($strParent, $parents);
1✔
45
        }
46

47
        return $parents;
1✔
48
    }
49

50
    /**
51
     * Filter class constants by given prefixes and return the extracted constants.
52
     *
53
     * @param string $class            the class that should be searched for constants in
54
     * @param array  $prefixes         an array of prefixes that should be used to filter the class constants
55
     * @param bool   $returnValueAsKey boolean Return the extracted array keys from its value, if true
56
     *
57
     * @throws \ReflectionException
58
     *
59
     * @return array the extracted constants as array
60
     */
61
    public function getConstantsByPrefixes(string $class, array $prefixes = [], bool $returnValueAsKey = true)
62
    {
63
        $arrExtract = [];
×
64

65
        if (!class_exists($class)) {
×
66
            return $arrExtract;
×
67
        }
68

69
        $objReflection = new \ReflectionClass($class);
×
70
        $arrConstants = $objReflection->getConstants();
×
71

72
        if (!\is_array($arrConstants)) {
×
73
            return $arrExtract;
×
74
        }
75

76
        $arrExtract = $this->arrayUtil->filterByPrefixes($arrConstants, $prefixes);
×
77

78
        return $returnValueAsKey ? array_combine($arrExtract, $arrExtract) : $arrExtract;
×
79
    }
80

81
    /**
82
     * Returns all classes in the given namespace.
83
     *
84
     * @return array
85
     */
86
    public function getClassesInNamespace(string $namespace)
87
    {
88
        $arrOptions = [];
1✔
89

90
        foreach (get_declared_classes() as $strName) {
1✔
91
            if ($this->stringUtil->startsWith($strName, $namespace)) {
1✔
92
                $arrOptions[$strName] = $strName;
1✔
93
            }
94
        }
95

96
        asort($arrOptions);
1✔
97

98
        return $arrOptions;
1✔
99
    }
100

101
    /**
102
     * Returns all children of a given class.
103
     *
104
     * @param string $strNamespace
105
     *
106
     * @return array
107
     */
108
    public function getChildClasses(string $qualifiedClassName)
109
    {
110
        $arrOptions = [];
×
111

112
        foreach (get_declared_classes() as $strName) {
×
113
            if (\in_array($qualifiedClassName, $this->getParentClasses($strName))) {
×
114
                $arrOptions[$strName] = $strName;
×
115
            }
116
        }
117

118
        asort($arrOptions);
×
119

120
        return $arrOptions;
×
121
    }
122

123
    /**
124
     * @param $method
125
     * @param \ReflectionClass $rc
126
     * @return int|null
127
     */
128
    private static function getMethodNameStartIndex($method, \ReflectionClass $rc): ?int
129
    {
130
        $len = 3;
×
131
        $prefix = substr($method->name, 0, $len);
×
132

133
        /** vvv Prefixes with length 3. vvv */
134

135
        // get{MethodName}()
136
        if ('get' === $prefix)
×
137
            return $len;
×
138

139
        // has{MethodName}()
140
        if ('has' === $prefix) {
×
141
            $name = ucfirst(substr($method->name, 3, strlen($method->name)));
×
142
            if ($rc->hasMethod("is$name") || $rc->hasMethod("get$name"))
×
143
                return 0;
×
144
            return $len;
×
145
        }
146

147
        /** vvv Prefixes with length 2. vvv */
148

149
        $len = 2;
×
150
        $prefix = substr($method->name, 0, $len);
×
151

152
        // is{MethodName}()
153
        if ('is' === $prefix) {
×
154
            $name = ucfirst(substr($method->name, 2, strlen($method->name)));
×
155
            if ($rc->hasMethod("has$name") || $rc->hasMethod("get$name"))
×
156
                return 0;
×
157
            return  $len;
×
158
        }
159

160
        return null;
×
161
    }
162

163
    /**
164
     * Serialize a class object to JSON by iterating over all public getters (get(), is(), ...).
165
     *
166
     * @param       $object
167
     * @param array $data
168
     * @param array $options
169
     *
170
     * @throws \ReflectionException if the class or method does not exist
171
     */
172
    public function jsonSerialize($object, $data = [], $options = []): array
173
    {
174
        $class = \get_class($object);
×
175

176
        $rc = new \ReflectionClass($object);
×
177

178
        // get values of properties
179
        if (isset($options['includeProperties']) && $options['includeProperties']) {
×
180
            foreach ($rc->getProperties() as $reflectionProperty) {
×
181
                $propertyName = $reflectionProperty->getName();
×
182

183
                $property = $rc->getProperty($propertyName);
×
184

185
                if (isset($options['ignorePropertyVisibility']) && $options['ignorePropertyVisibility']) {
×
186
                    $property->setAccessible(true);
×
187
                }
188

189
                $data[$propertyName] = $property->getValue($object);
×
190

191
                if (\is_object($data[$propertyName])) {
×
192
                    if (!($data[$propertyName] instanceof \JsonSerializable)) {
×
193
                        unset($data[$propertyName]);
×
194

195
                        continue;
×
196
                    }
197

198
                    $data[$propertyName] = $this->jsonSerialize($data[$propertyName]);
×
199
                }
200
            }
201
        }
202

203
        if (isset($options['ignoreMethods']) && $options['ignoreMethods']) {
×
204
            return $data;
×
205
        }
206

207
        // get values of methods
208
        if (isset($options['ignoreMethodVisibility']) && $options['ignoreMethodVisibility']) {
×
209
            $methods = $rc->getMethods();
×
210
        } else {
211
            $methods = $rc->getMethods(\ReflectionMethod::IS_PUBLIC);
×
212
        }
213

214
        // add all public getter Methods
215
        foreach ($methods as $method) {
×
216

217
            $start = self::getMethodNameStartIndex($method, $rc);
×
218
            if ($start === null) continue;
×
219

220
            // skip methods with parameters
221
            $rm = new \ReflectionMethod($class, $method->name);
×
222

223
            if ($rm->getNumberOfRequiredParameters() > 0) {
×
224
                continue;
×
225
            }
226

227
            if (isset($options['skippedMethods']) && \is_array($options['skippedMethods']) && \in_array($method->name, $options['skippedMethods'])) {
×
228
                continue;
×
229
            }
230

231
            $property = lcfirst(substr($method->name, $start));
×
232

233
            if (!$method->isPublic()) {
×
234
                $method->setAccessible(true);
×
235
                $data[$property] = $method->invoke($object);
×
236
            } else {
237
                $data[$property] = $object->{$method->name}();
×
238
            }
239

240
            if (\is_object($data[$property])) {
×
241
                if (!($data[$property] instanceof \JsonSerializable)) {
×
242
                    unset($data[$property]);
×
243

244
                    continue;
×
245
                }
246
                $data[$property] = $this->jsonSerialize($data[$property]);
×
247
            }
248
        }
249

250
        return $data;
×
251
    }
252

253
    /**
254
     * Calls an object's method which is inaccessible.
255
     *
256
     * @param $entity
257
     *
258
     * @throws \ReflectionException
259
     *
260
     * @return mixed|null
261
     */
262
    public function callInaccessibleMethod($entity, string $method)
263
    {
264
        $rc = new \ReflectionClass($entity);
×
265

266
        if ($rc->hasMethod($method)) {
×
267
            $method = $rc->getMethod($method);
×
268
            $method->setAccessible(true);
×
269

270
            return $method->invoke($entity);
×
271
        }
272

273
        return null;
×
274
    }
275
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc