Completed
Push — master ( 1049ef...ba8cbe )
by Portey
7s
created

ConfigValidator   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 118
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Test Coverage

Coverage 77.78%

Importance

Changes 4
Bugs 1 Features 2
Metric Value
wmc 21
c 4
b 1
f 2
lcom 2
cbo 4
dl 0
loc 118
ccs 35
cts 45
cp 0.7778
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A isValid() 0 4 1
A isExtraFieldsAllowed() 0 4 1
A __construct() 0 4 1
A initializeRules() 0 4 1
A addRule() 0 4 1
A setExtraFieldsAllowed() 0 6 1
A getInstance() 0 10 2
C validate() 0 46 13
1
<?php
2
/*
3
* This file is a part of graphql-youshido project.
4
*
5
* @author Alexandr Viniychuk <[email protected]>
6
* created: 11/28/15 2:25 AM
7
*/
8
9
namespace Youshido\GraphQL\Validator\ConfigValidator;
10
11
12
use Youshido\GraphQL\Validator\ConfigValidator\Rules\TypeValidationRule;
13
use Youshido\GraphQL\Validator\ConfigValidator\Rules\ValidationRuleInterface;
14
use Youshido\GraphQL\Validator\ErrorContainer\ErrorContainerTrait;
15
use Youshido\GraphQL\Validator\Exception\ValidationException;
16
17
class ConfigValidator implements ConfigValidatorInterface
18
{
19
20
    use ErrorContainerTrait;
21
22
    protected $rules = [];
23
24
    protected $extraFieldsAllowed = false;
25
26
    /** @var ValidationRuleInterface[] */
27
    protected $validationRules = [];
28
29
    /** @var  ConfigValidator */
30
    protected static $instance;
31
32
    private function __construct()
33
    {
34
        $this->initializeRules();
35
    }
36
37
    /**
38
     * @return ConfigValidator
39
     */
40 125
    public static function getInstance()
41
    {
42 125
        if (empty(self::$instance)) {
43
            self::$instance = new self();
44
        }
45
46 125
        self::$instance->clearErrors();
47
48 125
        return self::$instance;
49
    }
50
51 99
    public function validate($data, $rules = [], $extraFieldsAllowed = null)
52
    {
53 99
        if ($extraFieldsAllowed !== null) $this->setExtraFieldsAllowed($extraFieldsAllowed);
54
55 99
        $processedFields = [];
56 99
        foreach ($rules as $fieldName => $fieldRules) {
57 99
            $processedFields[] = $fieldName;
58
59
            /** Custom validation of 'required' property */
60 99
            if (array_key_exists('required', $fieldRules)) {
61 86
                unset($fieldRules['required']);
62
63 86
                if (!array_key_exists($fieldName, $data)) {
64 12
                    $this->addError(new ValidationException(sprintf('Field "%s" is required', $fieldName)));
65
66 86
                    continue;
67
                }
68 98
            } elseif (!array_key_exists($fieldName, $data)) {
69 94
                continue;
70
            }
71 98
            if (!empty($fieldRules['final'])) unset($fieldRules['final']);
72
73
            /** Validation of all other rules*/
74 98
            foreach ($fieldRules as $ruleName => $ruleInfo) {
75 98
                if (!array_key_exists($ruleName, $this->validationRules)) {
76 1
                    $this->addError(new ValidationException(sprintf('Field "%s" has invalid rule "%s"', $fieldName, $ruleInfo)));
77
78 1
                    continue;
79
                }
80
81 98
                if (!$this->validationRules[$ruleName]->validate($data[$fieldName], $ruleInfo)) {
82 98
                    $this->addError(new ValidationException(sprintf('Field "%s" expected to be "%s" but got "%s"', $fieldName, $ruleName, gettype($data[$fieldName]))));
83
                }
84
            }
85
        }
86
87 99
        if (!$this->isExtraFieldsAllowed()) {
88 3
            foreach (array_keys($data) as $fieldName) {
89 3
                if (!in_array($fieldName, $processedFields)) {
90 3
                    $this->addError(new ValidationException(sprintf('Field "%s" is not expected', $fieldName)));
91
                }
92
            }
93
        }
94
95 99
        return $this->isValid();
96
    }
97
98
    protected function initializeRules()
99
    {
100
        $this->validationRules['type'] = new TypeValidationRule($this);
101
    }
102
103
    public function addRule($name, ValidationRuleInterface $rule)
104
    {
105
        $this->validationRules[$name] = $rule;
106
    }
107
108 99
    public function isValid()
109
    {
110 99
        return !$this->hasErrors();
111
    }
112
113
114
    /**
115
     * @return boolean
116
     */
117 99
    public function isExtraFieldsAllowed()
118
    {
119 99
        return $this->extraFieldsAllowed;
120
    }
121
122
    /**
123
     * @param boolean $extraFieldsAllowed
124
     *
125
     * @return ConfigValidator
126
     */
127 1
    public function setExtraFieldsAllowed($extraFieldsAllowed)
128
    {
129 1
        $this->extraFieldsAllowed = $extraFieldsAllowed;
130
131 1
        return $this;
132
    }
133
134
}
135