Passed
Push — main ( fe5adf...e99a91 )
by Thierry
01:50
created

ContainerAnnotation::validateAttrName()   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 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * ContainerAnnotation.php
5
 *
6
 * Jaxon annotation for DI injection.
7
 *
8
 * @package jaxon-annotations
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2022 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-annotations
13
 */
14
15
namespace Jaxon\Annotations\Annotation;
16
17
use mindplay\annotations\AnnotationException;
18
use mindplay\annotations\AnnotationFile;
19
use mindplay\annotations\IAnnotationFileAware;
20
21
use function count;
22
use function is_array;
23
use function is_string;
24
use function ltrim;
25
use function preg_match;
26
use function preg_split;
27
use function rtrim;
28
29
/**
30
 * Specifies attributes to inject into a callable object.
31
 *
32
 * @usage('class' => true, 'method'=>true, 'multiple'=>true, 'inherited'=>true)
33
 */
34
class ContainerAnnotation extends AbstractAnnotation implements IAnnotationFileAware
35
{
36
    /**
37
     * The attribute name
38
     *
39
     * @var string
40
     */
41
    protected $sAttr = '';
42
43
    /**
44
     * The attribute class
45
     *
46
     * @var string
47
     */
48
    protected $sClass = '';
49
50
    /**
51
     * @var AnnotationFile
52
     */
53
    protected $xClassFile;
54
55
    /**
56
     * @inheritDoc
57
     */
58
    public function setAnnotationFile(AnnotationFile $file)
59
    {
60
        $this->xClassFile = $file;
61
    }
62
63
    /**
64
     * @inheritDoc
65
     */
66
    public static function parseAnnotation($value)
67
    {
68
        $aParams = preg_split("/[\s]+/", $value, 3);
69
        $nParamCount = count($aParams);
70
        if($nParamCount === 1)
71
        {
72
            return ['attr' => rtrim($aParams[0])];
73
        }
74
        if($nParamCount === 2)
75
        {
76
            return ['attr' => rtrim($aParams[0]), 'class' => $aParams[1]];
77
        }
78
        return ['attr' => rtrim($aParams[0]), 'class' => $aParams[1], 'extra' => $aParams[2]];
79
    }
80
81
    /**
82
     * @param string $sClassName
83
     *
84
     * @return bool
85
     */
86
    protected function validateClassName(string $sClassName): bool
87
    {
88
        return preg_match('/^(\\\)?([a-zA-Z][a-zA-Z0-9_]*)(\\\[a-zA-Z][a-zA-Z0-9_]*)*$/', $sClassName) > 0;
89
    }
90
91
    /**
92
     * @param string $sAttrName
93
     *
94
     * @return bool
95
     */
96
    protected function validateAttrName(string $sAttrName): bool
97
    {
98
        return preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $sAttrName) > 0;
99
    }
100
101
    /**
102
     * @inheritDoc
103
     * @throws AnnotationException
104
     */
105
    public function initAnnotation(array $properties)
106
    {
107
        if(count($properties) != 2 ||
108
            !isset($properties['attr']) || !is_string($properties['attr']) ||
109
            !isset($properties['class']) || !is_string($properties['class']))
110
        {
111
            throw new AnnotationException('The @di annotation requires a property "attr" of type string ' .
112
                'and a property "class" of type string');
113
        }
114
        if(!$this->validateAttrName($properties['attr']))
115
        {
116
            throw new AnnotationException($properties['attr'] . ' is not a valid "attr" value for the @di annotation');
117
        }
118
        if(!$this->validateClassName($properties['class']))
119
        {
120
            throw new AnnotationException($properties['class'] . ' is not a valid "class" value for the @di annotation');
121
        }
122
        $this->sAttr = $properties['attr'];
123
        $this->sClass = ltrim($this->xClassFile->resolveType($properties['class']), '\\');
124
    }
125
126
    /**
127
     * @inheritDoc
128
     */
129
    public function getName(): string
130
    {
131
        return '__di';
132
    }
133
134
    /**
135
     * @inheritDoc
136
     */
137
    public function getValue()
138
    {
139
        if(is_array($this->xPrevValue))
140
        {
141
            $this->xPrevValue[$this->sAttr] = $this->sClass; // Append the current value to the array
142
            return $this->xPrevValue;
143
        }
144
        return [$this->sAttr => $this->sClass]; // Return the current value in an array
145
    }
146
}
147