ConstructAnnotation::compile()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 17
nc 5
nop 0
dl 0
loc 29
rs 9.3888
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of PhpUnitGen.
5
 *
6
 * (c) 2017-2018 Paul Thébaud <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace PhpUnitGen\Annotation;
13
14
use PhpUnitGen\Annotation\AnnotationInterface\AnnotationInterface;
15
use PhpUnitGen\Exception\AnnotationParseException;
16
use PhpUnitGen\Exception\JsonException;
17
use PhpUnitGen\Parser\NodeParserUtil\RootRetrieverHelper;
18
use PhpUnitGen\Util\Json;
19
use Respect\Validation\Validator;
20
21
/**
22
 * Class ConstructAnnotation.
23
 *
24
 * @author     Paul Thébaud <[email protected]>.
25
 * @copyright  2017-2018 Paul Thébaud <[email protected]>.
26
 * @license    https://opensource.org/licenses/MIT The MIT license.
27
 * @link       https://github.com/paul-thebaud/phpunit-generator
28
 * @since      Class available since Release 2.0.0.
29
 */
30
class ConstructAnnotation extends AbstractAnnotation
31
{
32
    /**
33
     * @var string|null $class The class name to use to construct the instance, null if none.
34
     */
35
    private $class;
36
37
    /**
38
     * @var string[] $parameters The constructor parameters.
39
     */
40
    private $parameters;
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function getType(): int
46
    {
47
        return AnnotationInterface::TYPE_CONSTRUCT;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function compile(): void
54
    {
55
        // Decode JSON content
56
        try {
57
            $decoded = Json::decode('[' . $this->getStringContent() . ']');
58
        } catch (JsonException $exception) {
59
            throw new AnnotationParseException('"construct" annotation content is invalid (invalid JSON content)');
60
        }
61
        $this->validate($decoded);
62
63
        $index = 0;
64
        // If there is a custom constructor class
65
        if (Validator::stringType()->validate($decoded[$index])) {
66
            $phpFile = RootRetrieverHelper::getRoot($this);
67
            // If class to use is not from global namespace
68
            if (! Validator::regex('/^\\\\/')->validate($decoded[$index])) {
69
                // Add the current namespace to it
70
                $namespace       = $phpFile->getNamespaceString();
71
                $decoded[$index] = ($namespace !== null? ($namespace . '\\') : '') . $decoded[$index];
72
            }
73
            // Get the last name part
74
            $nameArray = explode('\\', $decoded[$index]);
75
            $lastPart  = end($nameArray);
76
            // Add use to PhpFile
77
            $phpFile->addConcreteUse($decoded[$index], $lastPart);
78
            $this->class = $lastPart;
79
            $index++;
80
        }
81
        $this->parameters = $decoded[$index];
82
    }
83
84
    /**
85
     * Validate the content of annotation.
86
     *
87
     * @param mixed $decoded The annotation content.
88
     *
89
     * @throws AnnotationParseException If the content is invalid.
90
     */
91
    private function validate($decoded): void
92
    {
93
        // Validate it is an array
94
        if (! Validator::arrayType()->length(1, 2)->validate($decoded)) {
95
            throw new AnnotationParseException(
96
                '"construct" annotation content is invalid (must contains parameters array, and maybe a class)'
97
            );
98
        }
99
100
        $size = count($decoded);
101
102
        // Validate that if size is 2, first value is a string
103
        if ($size === 2 && ! Validator::stringType()->validate($decoded[0])) {
104
            throw new AnnotationParseException(
105
                '"construct" annotation content is invalid (constructor class must be a string)'
106
            );
107
        }
108
        // Validate that last value is an array
109
        if (! Validator::arrayVal()
110
            ->each(Validator::stringType(), Validator::intType())->validate($decoded[$size - 1])) {
111
            throw new AnnotationParseException(
112
                '"construct" annotation content is invalid (constructor parameters must be a array of string)'
113
            );
114
        }
115
    }
116
117
    /**
118
     * @return string|null The class name, null if none.
119
     */
120
    public function getClass(): ?string
121
    {
122
        return $this->class;
123
    }
124
125
    /**
126
     * @return string[] The constructor parameters.
127
     */
128
    public function getParameters(): array
129
    {
130
        return $this->parameters;
131
    }
132
}
133