Completed
Push — feature/issue-165 ( d66719...7c61ef )
by Mikaël
29:34
created

UnionRule::addValidationMethod()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 53
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 38
nc 6
nop 2
dl 0
loc 53
ccs 44
cts 44
cp 1
crap 7
rs 8.3786
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace WsdlToPhp\PackageGenerator\File\Validation;
4
5
use WsdlToPhp\PackageGenerator\Model\StructAttribute;
6
use WsdlToPhp\PhpGenerator\Element\PhpFunctionParameter;
7
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
8
9
class UnionRule extends AbstractRule
10
{
11
12
    /**
13
     * @return string
14
     */
15 6
    public function name()
16
    {
17 6
        return 'union';
18
    }
19
20
    /**
21
     * @param string $parameterName
22
     * @param mixed $value
23
     * @param bool $itemType
24
     * @return string
25
     */
26 6
    public function testConditions($parameterName, $value, $itemType = false)
27
    {
28 6
        $test = '';
29 6
        if (is_array($value) && 0 < count($value)) {
30 6
            $this->addValidationMethod($parameterName, $value);
31 6
            $test = sprintf('\'\' !== ($message = self::%s($%s))', $this->getValidationMethodName($parameterName), $parameterName);
32 3
        }
33 6
        return $test;
34
    }
35
36
    /**
37
     * @param string $parameterName
38
     * @param mixed $value
39
     * @param bool $itemType
40
     * @return string
41
     */
42 6
    public function exceptionMessageOnTestFailure($parameterName, $value, $itemType = false)
43
    {
44 6
        return '$message';
45
    }
46
47
    /**
48
     * @param $parameterName
49
     * @param mixed $unionValues
50
     */
51 6
    protected function addValidationMethod($parameterName, array $unionValues)
52
    {
53 6
        $method = new PhpMethod('temp');
54 6
        $rules = clone $this->getRules();
55 6
        $rules->setMethod($method);
56
57
        // gather validation rules
58 6
        foreach ($unionValues as $unionValue) {
59 6
            $rules->setAttribute(new StructAttribute($this->getGenerator(), 'any', $unionValue));
60 6
            $rules->applyRules('value');
61 3
        }
62
63
        // adapt content, remove duplicated rules
64
        // duplicated rules is base don the fact that validation rules are composed by 4 lines so we check existing rule every 4-line block of text
65 6
        $exceptions = 0;
66 6
        $exceptionsTests = [];
67 6
        $exceptionsArray = [];
68 6
        $children = [];
69 6
        $methodChildren = $method->getChildren();
70 6
        $chilrenCount = count($methodChildren);
71 6
        $existingValidationRules = [];
72 6
        for ($i = 0;$i < $chilrenCount;$i += 4) {
73 6
            $validationRules = array_slice($methodChildren, ((int) $i / 4) * 4, 4);
74 6
            if (!in_array($validationRules, $existingValidationRules)) {
75 6
                foreach ($validationRules as $validationRule) {
76 6
                    if (is_string($validationRule) && false !== strpos($validationRule, 'throw new')) {
77 6
                        $exceptionName = sprintf('$exception%d', $exceptions++);
78 6
                        $validationRule = str_replace('throw new', sprintf('%s = new', $exceptionName), $validationRule);
79 6
                        $exceptionsTests[] = sprintf('isset(%s)', $exceptionName);
80 6
                        $exceptionsArray[] = $exceptionName;
81 3
                    }
82 6
                    $children[] = $validationRule;
83 3
                }
84 3
            }
85 6
            $existingValidationRules[] = $validationRules;
86 3
        }
87
88
        // populate final validation method
89 6
        $method = new PhpMethod($this->getValidationMethodName($parameterName), [
90 6
            new PhpFunctionParameter('value', PhpFunctionParameter::NO_VALUE),
91 6
        ], PhpMethod::ACCESS_PUBLIC, false, true);
92 6
        $method->addChild('$message = \'\';');
93 6
        array_walk($children, [
94 6
            $method,
95 6
            'addChild',
96 3
        ]);
97
        $method
98 6
            ->addChild(sprintf('if (%s) {', implode(' && ', $exceptionsTests)))
99 6
            ->addChild($method->getIndentedString(sprintf('$message = sprintf("The value %%s does not match any of the union rules: %s. See following errors:\n%%s", var_export($value, true), implode("\n", array_map(function(\InvalidArgumentException $e) { return sprintf(\' - %%s\', $e->getMessage()); }, [%s])));', implode(', ', $unionValues), implode(', ', $exceptionsArray)), 1))
100 6
            ->addChild('}')
101 6
            ->addChild(sprintf('unset(%s);', implode(', ', $exceptionsArray)))
102 6
            ->addChild('return $message;');
103 6
        $this->getMethods()->add($method);
104 6
    }
105
106
    /**
107
     * @param string $parameterName
108
     * @return string
109
     */
110 6
    protected function getValidationMethodName($parameterName)
111
    {
112 6
        return sprintf('validate%sForUnionConstraintsFrom%s', ucfirst($parameterName), ucFirst($this->getMethod()->getName()));
113
    }
114
}
115