Passed
Push — develop ( 9b8c4e...79e7ae )
by Andrea Marco
03:34 queued 14s
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 UnitEnum;
8
9
/**
10
 * Retrieve the type in common with the given types.
11
 */
12
function commonType(string ...$types): string
13
{
14
    $null = '';
15
    $types = array_unique($types);
16
17
    if (($index = array_search('null', $types)) !== false) {
18
        $null = '?';
19
20
        unset($types[$index]);
21
    }
22
23
    return match (true) {
24
        ! is_null($common = commonInterfaceOrParent(...$types)) => $null . $common,
25
        count($types) == 1 => $null . reset($types),
26
        default => implode('|', $types) . ($null ? '|null' : ''),
27
    };
28
}
29
30
/**
31
 * Retrieve the first interface or parent class in common with the given classes.
32
 *
33
 * @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...
34
 */
35
function commonInterfaceOrParent(string ...$classes): ?string
36
{
37
    if ($classes !== array_filter($classes, namespaceExists(...))) {
38
        return null;
39
    }
40
41
    foreach (['class_implements', 'class_parents'] as $callback) {
42
        /** @var array<class-string, class-string> $common */
43
        if ($common = array_intersect(...array_map($callback, $classes))) {
44
            return reset($common);
45
        }
46
    }
47
48
    return null;
49
}
50
51
/**
52
 * Determine whether the given namespace exists.
53
 */
54
function namespaceExists(string $namespace): bool
55
{
56
    return class_exists($namespace) || interface_exists($namespace);
57
}
58
59
/**
60
 * Retrieve the return type of the given meta for the provided cases.
61
 *
62
 * @param list<UnitEnum> $cases
63
 */
64
function metaReturnType(string $meta, array $cases): string
65
{
66
    $returnTypes = array_map(function (UnitEnum $case) use ($meta) {
67
        $value = $case->resolveMetaAttribute($meta);
68
69
        return is_string($value) && namespaceExists($value) ? $value : get_debug_type($value);
70
    }, $cases);
71
72
    return commonType(...$returnTypes);
73
}
74