1 | <?php |
||
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() |
|
112 | |||
113 | |||
114 | /** |
||
115 | * @return boolean |
||
116 | */ |
||
117 | 99 | public function isExtraFieldsAllowed() |
|
121 | |||
122 | /** |
||
123 | * @param boolean $extraFieldsAllowed |
||
124 | * |
||
125 | * @return ConfigValidator |
||
126 | */ |
||
127 | 1 | public function setExtraFieldsAllowed($extraFieldsAllowed) |
|
133 | |||
134 | } |
||
135 |