Passed
Push — feature/second-release ( 3d3b5e...855c58 )
by Andrea Marco
14:24
created

commonType()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 15
rs 9.9666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cerbero\LaravelEnum;
6
7
use Generator;
8
9
/**
10
 * Determine whether the given namespace exists.
11
 */
12
function namespaceExists(string $target): bool
13
{
14
    return class_exists($target) || interface_exists($target);
15
}
16
17
/**
18
 * Yield the content of the given path line by line.
19
 *
20
 * @return Generator<int, string>
21
 */
22
function yieldLines(string $path): Generator
23
{
24
    $stream = fopen($path, 'rb');
25
26
    try {
27
        while (($line = fgets($stream, 1024)) !== false) {
28
            yield $line;
29
        }
30
    } finally {
31
        is_resource($stream) && fclose($stream);
32
    }
33
}
34
35
/**
36
 * Retrieve the common type among the given types.
37
 */
38
function commonType(string ...$types): string
39
{
40
    $null = '';
41
    $types = array_unique($types);
42
43
    if (($index = array_search('null', $types)) !== false) {
44
        $null = '?';
45
46
        unset($types[$index]);
47
    }
48
49
    return match (true) {
50
        ! is_null($common = commonInterfaceOrParent(...$types)) => $null . $common,
51
        count($types) == 1 => $null . reset($types),
52
        default => implode('|', $types) . ($null ? '|null' : ''),
53
    };
54
}
55
56
/**
57
 * Retrieve the first interface or parent class in common with the given classes.
58
 *
59
 * @return ?class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment ?class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in ?class-string.
Loading history...
60
 */
61
function commonInterfaceOrParent(string ...$classes): ?string
62
{
63
    if ($classes !== array_filter($classes, namespaceExists(...))) {
64
        return null;
65
    }
66
67
    foreach (['class_implements', 'class_parents'] as $callback) {
68
        /** @var array<class-string, class-string> $common */
69
        if ($common = array_intersect(...array_map($callback, $classes))) {
70
            return reset($common);
71
        }
72
    }
73
74
    return null;
75
}
76