Completed
Push — develop ( 10d533...fd1d54 )
by Paul
02:00
created

ConstructAnnotation::getClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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