Passed
Push — develop ( 8c60cf...7e01a8 )
by Paul
03:38
created

MethodNodeParser::setter()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 3
nop 2
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace PhpUnitGen\Parser\NodeParser;
4
5
use PhpParser\Node;
6
use PhpUnitGen\Annotation\GetAnnotation;
7
use PhpUnitGen\Annotation\SetAnnotation;
8
use PhpUnitGen\Configuration\ConfigurationInterface\ConfigInterface;
9
use PhpUnitGen\Exception\Exception;
10
use PhpUnitGen\Model\FunctionModel;
11
use PhpUnitGen\Model\ModelInterface\InterfaceModelInterface;
12
use PhpUnitGen\Model\ModelInterface\TraitModelInterface;
13
use PhpUnitGen\Model\PropertyInterface\NodeInterface;
14
use PhpUnitGen\Parser\NodeParserUtil\MethodVisibilityHelper;
15
use Respect\Validation\Validator;
16
17
/**
18
 * Class MethodNodeParser.
19
 *
20
 * @author     Paul Thébaud <[email protected]>.
21
 * @copyright  2017-2018 Paul Thébaud <[email protected]>.
22
 * @license    https://opensource.org/licenses/MIT The MIT license.
23
 * @link       https://github.com/paul-thebaud/phpunit-generator
24
 * @since      Class available since Release 2.0.0.
25
 */
26
class MethodNodeParser extends AbstractFunctionNodeParser
27
{
28
    /**
29
     * Parse a node to update the parent node model.
30
     *
31
     * @param mixed         $node   The node to parse.
32
     * @param NodeInterface $parent The parent node.
33
     */
34
    public function invoke($node, NodeInterface $parent): void
35
    {
36
        if (! $node instanceof Node\Stmt\ClassMethod || ! $parent instanceof InterfaceModelInterface) {
37
            throw new Exception('MethodNodeParser is made to parse a method node');
38
        }
39
40
        // Retrieve visibility
41
        $function = new FunctionModel();
42
        $function->setVisibility(MethodVisibilityHelper::getVisibility($node));
43
44
        // If no private / protected methods parsing is required
45
        if (! $function->isPublic() && ! $this->config->hasPrivateParsing()) {
46
            return;
47
        }
48
49
        $function->setParentNode($parent);
50
        $function->setName($node->name);
51
        $function->setIsFinal($node->isFinal());
52
        $function->setIsStatic($node->isStatic());
53
        $function->setIsAbstract($node->isAbstract());
54
55
        $this->parseFunction($node, $function);
56
57
        $parent->addFunction($function);
58
59
        if ($this->autoGetterOrSetter($function, $parent)) {
60
            return;
61
        }
62
        if (($documentation = $node->getDocComment()) !== null) {
63
            $this->documentationNodeParser->invoke($documentation, $function);
64
        }
65
    }
66
67
    /**
68
     * Check if auto generation is enabled, and try to generate getter or setter annotation.
69
     *
70
     * @param FunctionModel           $function The function to check for.
71
     * @param InterfaceModelInterface $parent   The parent to use.
72
     *
73
     * @return bool True if a getter or a setter annotation has been created.
74
     */
75
    private function autoGetterOrSetter(FunctionModel $function, InterfaceModelInterface $parent): bool
76
    {
77
        if ($this->config->hasAuto() && $parent instanceof TraitModelInterface) {
78
            if ($this->getter($function, $parent)) {
79
                return true;
80
            }
81
            if ($this->setter($function, $parent)) {
82
                return true;
83
            }
84
        }
85
        return false;
86
    }
87
88
    /**
89
     * Try to create a getter annotation for function.
90
     *
91
     * @param FunctionModel       $function The function to check for.
92
     * @param TraitModelInterface $parent The parent to use.
93
     *
94
     * @return bool True if a getter annotation has been created.
95
     */
96
    private function getter(FunctionModel $function, TraitModelInterface $parent): bool
97
    {
98
        // Check if function name matches
99
        preg_match('/^get(.+)$/', $function->getName(), $matches);
100
101
        if (Validator::arrayType()->length(2, 2)->validate($matches)) {
102
            // Check if property exists
103
            $property = lcfirst($matches[1]);
104
            if ($parent->hasAttribute($property, $function->isStatic())) {
105
                $annotation = new GetAnnotation();
106
                $annotation->setName('@PhpUnitGen\\getter');
107
                $function->addAnnotation($annotation);
108
                $annotation->setParentNode($function);
109
                $annotation->compile();
110
111
                return true;
112
            }
113
        }
114
115
        return false;
116
    }
117
118
    /**
119
     * Try to create a setter annotation for function.
120
     *
121
     * @param FunctionModel       $function The function to check for.
122
     * @param TraitModelInterface $parent The parent to use.
123
     *
124
     * @return bool True if a setter annotation has been created.
125
     */
126
    private function setter(FunctionModel $function, TraitModelInterface $parent): bool
127
    {
128
        // Check if function name matches
129
        preg_match('/^set(.+)$/', $function->getName(), $matches);
130
131
        if (Validator::arrayType()->length(2, 2)->validate($matches)) {
132
            // Check if property exists
133
            $property = lcfirst($matches[1]);
134
            if ($parent->hasAttribute($property, $function->isStatic())) {
135
                $annotation = new SetAnnotation();
136
                $annotation->setName('@PhpUnitGen\\setter');
137
                $annotation->setParentNode($function);
138
                $function->addAnnotation($annotation);
139
                $annotation->compile();
140
141
                return true;
142
            }
143
        }
144
145
        return false;
146
    }
147
}
148