Passed
Push — refactoring ( eae241...68edd5 )
by Sergei
02:21
created

DefinitionParser::filterMeta()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Di;
6
7
use Yiisoft\Factory\Definition\ArrayDefinition;
8
use Yiisoft\Factory\Exception\InvalidConfigException;
9
10
use function in_array;
11
use function is_array;
12
use function is_string;
13
14
/**
15
 * @internal Split metadata and defintion
16
 *
17
 * Support configuration:
18
 *
19
 * 1) With a dedicated definition:
20
 *
21
 * ```php
22
 * Engine::class => [
23
 *     'definition' => [
24
 *         '__class' => BigEngine::class,
25
 *         'setNumber()' => [42],
26
 *     ],
27
 *     'tags' => ['a', 'b'],
28
 *     'reset' => function () {
29
 *         $this->number = 42;
30
 *      },
31
 * ]
32
 * ```
33
 *
34
 * 2) Mixed in array definition:
35
 *
36
 * ```php
37
 * Engine::class => [
38
 *     '__class' => BigEngine::class,
39
 *     'setNumber()' => [42],
40
 *     'tags' => ['a', 'b'],
41
 *     'reset' => function () {
42
 *         $this->number = 42;
43
 *      },
44
 * ]
45
 * ```
46
 */
47
final class DefinitionParser
48
{
49
    private const DEFINITION_META = 'definition';
50
51
    private array $allowedMeta;
52
53 98
    public function __construct(array $allowedMeta)
54
    {
55 98
        $this->allowedMeta = $allowedMeta;
56 98
    }
57
58
    /**
59
     * @param mixed $definition
60
     *
61
     * @throws InvalidConfigException
62
     */
63 98
    public function parse($definition): array
64
    {
65 98
        if (!is_array($definition)) {
66 93
            return [$definition, []];
67
        }
68
69
        // Dedicated definition
70 40
        if (isset($definition[self::DEFINITION_META])) {
71 3
            $newDefinition = $definition[self::DEFINITION_META];
72 3
            unset($definition[self::DEFINITION_META]);
73 3
            return [$newDefinition, $this->filterMeta($definition)];
74
        }
75
76 37
        $meta = [];
77 37
        foreach ($definition as $key => $value) {
78
            // It is not array definition
79 37
            if (!is_string($key)) {
80 3
                break;
81
            }
82
83
            // Array definition keys
84
            if (
85 34
                $key === ArrayDefinition::CLASS_NAME ||
86 31
                $key === ArrayDefinition::CONSTRUCTOR ||
87 23
                substr($key, -2) === '()' ||
88 34
                strncmp($key, '$', 1) === 0
89
            ) {
90 34
                continue;
91
            }
92
93 15
            if (!in_array($key, $this->allowedMeta, true)) {
94 2
                throw new InvalidConfigException(
95 2
                    sprintf(
96 2
                        'Invalid definition: metadata "%s" is not allowed. Did you mean "%s()" or "$%s"?',
97
                        $key,
98
                        $key,
99
                        $key,
100
                    )
101
                );
102
            }
103
104 13
            $meta[$key] = $value;
105 13
            unset($definition[$key]);
106
        }
107
108 35
        return [$definition, $meta];
109
    }
110
111 3
    private function filterMeta(array $meta): array
112
    {
113 3
        return array_filter(
114 3
            $meta,
115
            /** @param mixed $key */
116 3
            function ($key) {
117 3
                return in_array($key, $this->allowedMeta, true);
118 3
            },
119 3
            ARRAY_FILTER_USE_KEY
120
        );
121
    }
122
}
123