Completed
Pull Request — master (#30)
by
unknown
02:40
created

EnumProvider::ensureEnumClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of the "elao/enum" package.
5
 *
6
 * Copyright (C) 2016 Elao
7
 *
8
 * @author Elao <[email protected]>
9
 */
10
11
namespace Elao\Enum\Bridge\Faker\Provider;
12
13
use Elao\Enum\EnumInterface;
14
use Elao\Enum\Exception\InvalidArgumentException;
15
use Elao\Enum\FlaggedEnum;
16
17
class EnumProvider
18
{
19
    /**
20
     * Enum mapping as an array with :
21
     *
22
     * - alias for Enum class as key
23
     * - Enum FQCN as value
24
     *
25
     * Example :
26
     *
27
     * ```
28
     * [
29
     *   'Civility' => Civility::class,
30
     *   'Gender'   => Gender::class,
31
     * ]
32
     * ```
33
     *
34
     * @var array
35
     */
36
    private $enumMapping = [];
37
38
    public function __construct(array $enumMapping)
39
    {
40
        foreach ($enumMapping as $enumAlias => $enumClass) {
41
            $this->ensureEnumClass($enumClass);
42
            $this->enumMapping[$enumAlias] = $enumClass;
43
        }
44
    }
45
46
    /**
47
     * @param string $enumValueShortcut As <ENUM_CLASS_ALIAS>::<ENUM_VALUE_CONSTANT>
48
     *                                  Examples: 'Gender::MALE', 'Gender::FEMALE', 'Permissions::READ|WRITE', etc.
49
     *
50
     * @throws InvalidArgumentException When the alias part of $enumValueShortcut is not a valid alias
51
     *
52
     * @return EnumInterface
53
     */
54
    public function enum(string $enumValueShortcut): EnumInterface
55
    {
56
        list($enumClassAlias, $constants) = explode('::', $enumValueShortcut);
57
58
        if (!array_key_exists($enumClassAlias, $this->enumMapping)) {
59
            throw new InvalidArgumentException("$enumClassAlias is not a valid alias");
60
        }
61
62
        /** @var EnumInterface $class */
63
        $class = $this->enumMapping[$enumClassAlias];
64
65
        $constants = explode('|', $constants);
66
67
        // Flagged Enum if $constants count is greater than one:
68
        if (count($constants) > 1) {
69
            if (!is_a($class, FlaggedEnum::class, true)) {
70
                throw new InvalidArgumentException("$class is not a valid FlaggedEnum");
71
            }
72
            $value = 0;
73
            foreach ($constants as $constant) {
74
                $value |= constant($class . '::' . $constant);
75
            }
76
        } else {
77
            $value = constant($class . '::' . current($constants));
78
        }
79
80
        return $class::get($value);
81
    }
82
83
    /**
84
     * @param string $enumClassAlias
85
     *
86
     * @throws InvalidArgumentException When $enumClassAlias is not a valid alias
87
     *
88
     * @return EnumInterface
89
     */
90
    public function randomEnum(string $enumClassAlias): EnumInterface
91
    {
92
        if (!array_key_exists($enumClassAlias, $this->enumMapping)) {
93
            throw new InvalidArgumentException("$enumClassAlias is not a valid alias");
94
        }
95
96
        /** @var EnumInterface $class */
97
        $class = $this->enumMapping[$enumClassAlias];
98
99
        $instances = $class::instances();
100
        $randomRank = rand(0, count($instances) - 1);
101
102
        return $instances[$randomRank];
103
    }
104
105
    /**
106
     * Make sure that $enumClass is a proper Enum class. Throws exception otherwise.
107
     *
108
     * @param string $enumClass
109
     *
110
     * @throws InvalidArgumentException When $enumClass is not a class or is not a proper Enum
111
     */
112
    private function ensureEnumClass(string $enumClass)
113
    {
114
        if (!is_a($enumClass, EnumInterface::class, true)) {
115
            throw new InvalidArgumentException("$enumClass is not a proper enum class");
116
        }
117
    }
118
}
119