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

systemsdk / docker-symfony-api / #74

pending completion
#74

push

DKravtsov
Php 8.2, symfony 6.2, updated RabbitMQ, updated composer dependencies, refactoring.

51 of 51 new or added lines in 44 files covered. (100.0%)

1479 of 2668 relevant lines covered (55.43%)

23.59 hits per line

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

0.0
/src/General/Application/Utils/Tests/PhpUnitUtil.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\General\Application\Utils\Tests;
6

7
use App\Role\Domain\Entity\Role;
8
use DateTime;
9
use DateTimeImmutable;
10
use Doctrine\DBAL\Types\Type;
11
use Exception;
12
use LogicException;
13
use Ramsey\Uuid\UuidInterface;
14
use RecursiveDirectoryIterator;
15
use RecursiveIteratorIterator;
16
use ReflectionClass;
17
use ReflectionException;
18
use ReflectionMethod;
19
use RegexIterator;
20
use stdClass;
21
use Symfony\Bundle\FrameworkBundle\Console\Application;
22
use Symfony\Component\Console\Input\ArrayInput;
23
use Symfony\Component\Console\Output\ConsoleOutput;
24
use Symfony\Component\HttpKernel\KernelInterface;
25
use Throwable;
26

27
use function array_key_exists;
28
use function explode;
29
use function sprintf;
30
use function str_contains;
31
use function substr_count;
32

33
/**
34
 * Class PHPUnitUtil
35
 *
36
 * @package App\General
37
 */
38
class PhpUnitUtil
39
{
40
    public const TYPE_INT = 'int';
41
    public const TYPE_INTEGER = 'integer';
42
    public const TYPE_STRING = 'string';
43
    public const TYPE_ARRAY = 'array';
44
    public const TYPE_JSON = 'json';
45
    public const TYPE_BOOL = 'bool';
46
    public const TYPE_BOOLEAN = 'boolean';
47
    public const TYPE_CUSTOM_CLASS = 'CustomClass';
48

49
    /**
50
     * @var array<string, mixed>
51
     */
52
    private static array $validValueCache = [];
53

54
    /**
55
     * @var array<string, stdClass|DateTime|string>
56
     */
57
    private static array $invalidValueCache = [];
58

59
    /**
60
     * @codeCoverageIgnore
61
     *
62
     * @throws Exception
63
     */
64
    public static function loadFixtures(KernelInterface $kernel): void
65
    {
66
        $application = new Application($kernel);
67
        $application->setAutoExit(false);
68
        $input = new ArrayInput([
69
            'command' => 'doctrine:fixtures:load',
70
            '--no-interaction' => true,
71
            '--quiet' => true,
72
        ]);
73
        $input->setInteractive(false);
74
        $application->run($input, new ConsoleOutput(ConsoleOutput::VERBOSITY_QUIET));
75
    }
76

77
    /**
78
     * @codeCoverageIgnore
79
     *
80
     * @return array<int, string>
81
     */
82
    public static function recursiveFileSearch(string $folder, string $pattern): array
83
    {
84
        $dir = new RecursiveDirectoryIterator($folder);
85
        $ite = new RecursiveIteratorIterator($dir);
86
        /** @var array<int, string> $files */
87
        $files = new RegexIterator($ite, $pattern, RegexIterator::GET_MATCH);
88
        $fileList = [];
89

90
        foreach ($files as $file) {
91
            $fileList[] = $file[0];
92
        }
93

94
        return $fileList;
95
    }
96

97
    /**
98
     * Method to call specified 'protected' or 'private' method on given class.
99
     *
100
     * @param object $object The instantiated instance of your class
101
     * @param string $name The name of your private/protected method
102
     * @param array<int, mixed> $args Method arguments
103
     *
104
     * @throws ReflectionException
105
     */
106
    public static function callMethod(object $object, string $name, array $args): mixed
107
    {
108
        return self::getMethod($object, $name)->invokeArgs($object, $args);
×
109
    }
110

111
    /**
112
     * Get a private or protected method for testing/documentation purposes.
113
     * How to use for MyClass->foo():
114
     *      $cls = new MyClass();
115
     *      $foo = PHPUnitUtil::getPrivateMethod($cls, 'foo');
116
     *      $foo->invoke($cls, $...);
117
     *
118
     * @param object $object The instantiated instance of your class
119
     * @param string $name The name of your private/protected method
120
     *
121
     * @throws ReflectionException
122
     *
123
     * @return ReflectionMethod The method you asked for
124
     */
125
    public static function getMethod(object $object, string $name): ReflectionMethod
126
    {
127
        // Get reflection and make specified method accessible
128
        $class = new ReflectionClass($object);
×
129
        $method = $class->getMethod($name);
×
130
        $method->setAccessible(true);
×
131

132
        return $method;
×
133
    }
134

135
    /**
136
     * Helper method to get any property value from given class.
137
     *
138
     * @throws ReflectionException
139
     */
140
    public static function getProperty(string $property, object $object): mixed
141
    {
142
        $clazz = new ReflectionClass($object::class);
×
143
        $property = $clazz->getProperty($property);
×
144
        $property->setAccessible(true);
×
145

146
        return $property->getValue($object);
×
147
    }
148

149
    public static function getType(Type | string | null $type): string
150
    {
151
        $exception = new LogicException(
×
152
            sprintf(
×
153
                "Currently type '%s' is not supported within type normalizer",
×
154
                $type instanceof Type ? $type::class : (string)$type,
×
155
            ),
×
156
        );
×
157

158
        return match ($type) {
×
159
            'time', 'date', 'datetime' => DateTime::class,
×
160
            'time_immutable', 'date_immutable', 'datetime_immutable' => DateTimeImmutable::class,
×
161
            self::TYPE_INT, self::TYPE_INTEGER, 'bigint' => self::TYPE_INT,
×
162
            self::TYPE_STRING, 'text', 'EnumLanguage', 'EnumLocale', 'EnumLogLogin' => self::TYPE_STRING,
×
163
            self::TYPE_JSON => self::TYPE_JSON,
×
164
            self::TYPE_ARRAY => self::TYPE_ARRAY,
×
165
            self::TYPE_BOOL, self::TYPE_BOOLEAN => self::TYPE_BOOL,
×
166
            default => throw $exception,
×
167
        };
×
168
    }
169

170
    /**
171
     * Helper method to override any property value within given class.
172
     *
173
     * @param UuidInterface|array<array-key, string>|null $value
174
     *
175
     * @throws ReflectionException
176
     */
177
    public static function setProperty(string $property, UuidInterface | array | null $value, object $object): void
178
    {
179
        $clazz = new ReflectionClass($object::class);
×
180
        $property = $clazz->getProperty($property);
×
181
        $property->setAccessible(true);
×
182
        $property->setValue($object, $value);
×
183
    }
184

185
    /**
186
     * Helper method to get valid value for specified type.
187
     *
188
     * @param array<string, string>|null $meta
189
     *
190
     * @throws Throwable
191
     */
192
    public static function getValidValueForType(string $type, ?array $meta = null): mixed
193
    {
194
        $cacheKey = $type . serialize($meta);
×
195

196
        if (!array_key_exists($cacheKey, self::$validValueCache)) {
×
197
            self::$validValueCache[$cacheKey] = self::getValidValue($meta, $type);
×
198
        }
199

200
        return self::$validValueCache[$cacheKey];
×
201
    }
202

203
    /**
204
     * Helper method to get invalid value for specified type.
205
     *
206
     * @throws Throwable
207
     */
208
    public static function getInvalidValueForType(string $type): DateTime | stdClass | string
209
    {
210
        if ($type !== stdClass::class && substr_count($type, '\\') > 1) {
×
211
            $type = self::TYPE_CUSTOM_CLASS;
×
212
        }
213

214
        if (!array_key_exists($type, self::$invalidValueCache)) {
×
215
            if (str_contains($type, '|')) {
×
216
                $output = self::getInvalidValueForType(explode('|', $type)[0]);
×
217
            } elseif (str_contains($type, '[]')) {
×
218
                $output = self::getInvalidValueForType(self::TYPE_ARRAY);
×
219
            } else {
220
                $output = match ($type) {
×
221
                    stdClass::class, DateTimeImmutable::class => new DateTime(),
×
222
                    self::TYPE_CUSTOM_CLASS, self::TYPE_INT, self::TYPE_INTEGER, self::TYPE_STRING, self::TYPE_ARRAY,
×
223
                    self::TYPE_BOOL, self::TYPE_BOOLEAN, DateTime::class, 'enumLanguage', 'enumLocale', 'enumLogLogin'
×
224
                        => new stdClass(),
×
225
                    default => throw new LogicException(sprintf("Cannot create invalid value for type '%s'.", $type)),
×
226
                };
×
227
            }
228

229
            self::$invalidValueCache[$type] = $output;
×
230
        }
231

232
        return self::$invalidValueCache[$type];
×
233
    }
234

235
    /**
236
     * @param array<string, string>|null $meta
237
     *
238
     * @throws Throwable
239
     */
240
    private static function getValidValue(
241
        ?array $meta,
242
        string $type
243
    ): mixed {
244
        $meta ??= [];
×
245

246
        $class = stdClass::class;
×
247
        $params = [null];
×
248

249
        if (substr_count($type, '\\') > 1 && !str_contains($type, '|')) {
×
250
            /** @var class-string $class */
251
            $class = $meta !== [] ? $meta['targetEntity'] : $type;
×
252

253
            $type = self::TYPE_CUSTOM_CLASS;
×
254

255
            $cleanClass = $class[0] === '\\' ? ltrim($class, '\\') : $class;
×
256

257
            if ($cleanClass === Role::class) {
×
258
                $params = ['Some Role'];
×
259
            }
260
        }
261

262
        $output = match ($type) {
×
263
            self::TYPE_CUSTOM_CLASS => new $class(...$params),
×
264
            self::TYPE_INT, self::TYPE_INTEGER => 666,
×
265
            self::TYPE_STRING => 'Some text here',
×
266
            self::TYPE_ARRAY => ['some', self::TYPE_ARRAY, 'here'],
×
267
            self::TYPE_BOOL, self::TYPE_BOOLEAN => true,
×
268
            DateTime::class => new DateTime(),
×
269
            DateTimeImmutable::class => new DateTimeImmutable(),
×
270
            default => null,
×
271
        };
×
272

273
        if (str_contains($type, '|')) {
×
274
            $output = self::getValidValueForType(explode('|', $type)[0], $meta);
×
275
        } elseif (str_contains($type, '[]')) {
×
276
            /** @var array<mixed, object> $output */
277
            $output = self::getValidValueForType(self::TYPE_ARRAY, $meta);
×
278
        }
279

280
        return $output ?? throw new LogicException(sprintf("Cannot create valid value for type '%s'.", $type));
×
281
    }
282
}
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