MethodNodeParser::setter()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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