DecoratorSpecBuilder::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of the pinepain/js-sandbox PHP library.
5
 *
6
 * Copyright (c) 2016-2017 Bogdan Padalko <[email protected]>
7
 *
8
 * Licensed under the MIT license: http://opensource.org/licenses/MIT
9
 *
10
 * For the full copyright and license information, please view the
11
 * LICENSE file that was distributed with this source or visit
12
 * http://opensource.org/licenses/MIT
13
 */
14
15
16
namespace Pinepain\JsSandbox\Decorators;
17
18
19
use Pinepain\JsSandbox\Specs\Builder\ArgumentValueBuilderInterface;
20
use Pinepain\JsSandbox\Specs\Builder\Exceptions\ArgumentValueBuilderException;
21
22
23
class DecoratorSpecBuilder implements DecoratorSpecBuilderInterface
24
{
25
    private $regexp = '/
26
        ^
27
        \@(?<name>[a-z_]+(?:[\w-]*\w)?)
28
        \s*
29
        (?:
30
            \(
31
            \s*
32
            (?<params>
33
                (
34
                    (?:[^\'\"\(\)\,\s]+)        # literal
35
                    |
36
                    (?:[+-]?[0-9]+\.?[0-9]*)    # numbers (no exponential notation)
37
                    |
38
                    (?:\'[^\']*\')              # single-quoted string
39
                    |
40
                    (?:\"[^\"]*\")              # double-quoted string
41
                    |
42
                    (?:\[\s*\])                 # empty array
43
                    |
44
                    (?:\{\s*\})                 # empty object
45
                    |
46
                    true | false | null
47
                )(?:\s*\,\s*((?-3))*)*
48
            )?
49
            \s*
50
            \)
51
        )?
52
        \s*
53
        $
54
        /xi';
55
    /**
56
     * @var ArgumentValueBuilderInterface
57
     */
58
    private $argument;
59
60
    /**
61
     * @param ArgumentValueBuilderInterface $argument
62
     */
63
    public function __construct(ArgumentValueBuilderInterface $argument)
64
    {
65
        $this->argument = $argument;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function build(string $definition): DecoratorSpecInterface
72
    {
73
        $definition = trim($definition);
74
75
        if (!$definition) {
76
            throw new DecoratorSpecBuilderException('Definition must be non-empty string');
77
        }
78
79
        try {
80
            if (preg_match($this->regexp, $definition, $matches)) {
81
82
                $params    = array_slice($matches, 5);
83
                $decorator = $this->buildDecorator($matches['name'], $params);
84
85
                return $decorator;
86
            }
87
        } catch (ArgumentValueBuilderException $e) {
88
            // We don't care about what specific issue we hit inside,
89
            // for API user it means that the definition is invalid
90
        }
91
92
        throw new DecoratorSpecBuilderException("Unable to parse definition: '{$definition}'");
93
    }
94
95
    /**
96
     * @param string $name
97
     * @param array $raw_args
98
     *
99
     * @return DecoratorSpecInterface
100
     */
101
    protected function buildDecorator(string $name, array $raw_args): DecoratorSpecInterface
102
    {
103
        $arguments = [];
104
        foreach ($raw_args as $raw_arg) {
105
            $arguments[] = $this->argument->build($raw_arg, true);
106
        }
107
108
        return new DecoratorSpec($name, $arguments);
109
    }
110
}
111