Passed
Push — 2.x ( bef6c0...34f135 )
by Mikaël
03:54
created

UnionRule::addValidationMethod()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 53
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 38
nc 6
nop 2
dl 0
loc 53
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
    public function name()
16
    {
17
        return 'union';
18
    }
19
20
    /**
21
     * @param string $parameterName
22
     * @param mixed $value
23
     * @param bool $itemType
24
     * @return string
25
     */
26
    public function testConditions($parameterName, $value, $itemType = false)
27
    {
28
        $test = '';
29
        if (is_array($value) && 0 < count($value)) {
30
            $this->addValidationMethod($parameterName, $value);
31
            $test = sprintf('\'\' !== (%s = self::%s($%s))', self::getErrorMessageVariableName($parameterName), $this->getValidationMethodName($parameterName), $parameterName);
32
        }
33
        return $test;
34
    }
35
36
    /**
37
     * @param string $parameterName
38
     * @param mixed $value
39
     * @param bool $itemType
40
     * @return string
41
     */
42
    public function exceptionMessageOnTestFailure($parameterName, $value, $itemType = false)
43
    {
44
        return self::getErrorMessageVariableName($parameterName);
45
    }
46
47
    /**
48
     * @param string $parameterName
49
     * @param string[] $unionValues
50
     */
51
    protected function addValidationMethod($parameterName, array $unionValues)
52
    {
53
        $method = new PhpMethod('temp');
54
        $rules = clone $this->getRules();
55
        $rules->setMethod($method);
56
57
        // gather validation rules
58
        foreach ($unionValues as $unionValue) {
59
            $rules->setAttribute(new StructAttribute($this->getGenerator(), 'any', $unionValue));
60
            $rules->applyRules('value');
61
        }
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
        $exceptions = 0;
66
        $exceptionsTests = [];
67
        $exceptionsArray = [];
68
        $children = [];
69
        $methodChildren = $method->getChildren();
70
        $chilrenCount = count($methodChildren);
71
        $existingValidationRules = [];
72
        for ($i = 0;$i < $chilrenCount;$i += 4) {
73
            $validationRules = array_slice($methodChildren, ((int) $i / 4) * 4, 4);
74
            if (!in_array($validationRules, $existingValidationRules)) {
75
                foreach ($validationRules as $validationRule) {
76
                    if (is_string($validationRule) && false !== strpos($validationRule, 'throw new')) {
77
                        $exceptionName = sprintf('$exception%d', $exceptions++);
78
                        $validationRule = str_replace('throw new', sprintf('%s = new', $exceptionName), $validationRule);
79
                        $exceptionsTests[] = sprintf('isset(%s)', $exceptionName);
80
                        $exceptionsArray[] = $exceptionName;
81
                    }
82
                    $children[] = $validationRule;
83
                }
84
            }
85
            $existingValidationRules[] = $validationRules;
86
        }
87
88
        // populate final validation method
89
        $method = new PhpMethod($this->getValidationMethodName($parameterName), [
90
            new PhpFunctionParameter('value', PhpFunctionParameter::NO_VALUE),
91
        ], PhpMethod::ACCESS_PUBLIC, false, true);
92
        $method->addChild('$message = \'\';');
93
        array_walk($children, [
94
            $method,
95
            'addChild',
96
        ]);
97
        $method
98
            ->addChild(sprintf('if (%s) {', implode(' && ', $exceptionsTests)))
99
            ->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
            ->addChild('}')
101
            ->addChild(sprintf('unset(%s);', implode(', ', $exceptionsArray)))
102
            ->addChild('return $message;');
103
        $this->getMethods()->add($method);
104
    }
105
106
    /**
107
     * @param string $parameterName
108
     * @return string
109
     */
110
    protected function getValidationMethodName($parameterName)
111
    {
112
        return sprintf('validate%sForUnionConstraintsFrom%s', ucfirst($parameterName), ucFirst($this->getMethod()->getName()));
113
    }
114
115
    /**
116
     * @param string $parameterName
117
     * @return string
118
     */
119
    public static function getErrorMessageVariableName($parameterName)
120
    {
121
        return sprintf('$%sUnionErrorMessage', $parameterName);
122
    }
123
}
124