ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Committer:
TMBOY
Date:
Tue Jul 18 16:27:22 2017 +0800
Revision:
44:c1d8923072ba
?

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TMBOY 44:c1d8923072ba 1 <?php
TMBOY 44:c1d8923072ba 2
TMBOY 44:c1d8923072ba 3 /*
TMBOY 44:c1d8923072ba 4 * This file is part of the JsonSchema package.
TMBOY 44:c1d8923072ba 5 *
TMBOY 44:c1d8923072ba 6 * For the full copyright and license information, please view the LICENSE
TMBOY 44:c1d8923072ba 7 * file that was distributed with this source code.
TMBOY 44:c1d8923072ba 8 */
TMBOY 44:c1d8923072ba 9
TMBOY 44:c1d8923072ba 10 namespace JsonSchema\Constraints;
TMBOY 44:c1d8923072ba 11
TMBOY 44:c1d8923072ba 12 use JsonSchema\Entity\JsonPointer;
TMBOY 44:c1d8923072ba 13
TMBOY 44:c1d8923072ba 14 /**
TMBOY 44:c1d8923072ba 15 * The ObjectConstraint Constraints, validates an object against a given schema
TMBOY 44:c1d8923072ba 16 *
TMBOY 44:c1d8923072ba 17 * @author Robert Schönthal <seroscho@googlemail.com>
TMBOY 44:c1d8923072ba 18 * @author Bruno Prieto Reis <bruno.p.reis@gmail.com>
TMBOY 44:c1d8923072ba 19 */
TMBOY 44:c1d8923072ba 20 class ObjectConstraint extends Constraint
TMBOY 44:c1d8923072ba 21 {
TMBOY 44:c1d8923072ba 22 /**
TMBOY 44:c1d8923072ba 23 * {@inheritDoc}
TMBOY 44:c1d8923072ba 24 */
TMBOY 44:c1d8923072ba 25 public function check($element, $definition = null, JsonPointer $path = null, $additionalProp = null, $patternProperties = null)
TMBOY 44:c1d8923072ba 26 {
TMBOY 44:c1d8923072ba 27 if ($element instanceof UndefinedConstraint) {
TMBOY 44:c1d8923072ba 28 return;
TMBOY 44:c1d8923072ba 29 }
TMBOY 44:c1d8923072ba 30
TMBOY 44:c1d8923072ba 31 $matches = array();
TMBOY 44:c1d8923072ba 32 if ($patternProperties) {
TMBOY 44:c1d8923072ba 33 $matches = $this->validatePatternProperties($element, $path, $patternProperties);
TMBOY 44:c1d8923072ba 34 }
TMBOY 44:c1d8923072ba 35
TMBOY 44:c1d8923072ba 36 if ($definition) {
TMBOY 44:c1d8923072ba 37 // validate the definition properties
TMBOY 44:c1d8923072ba 38 $this->validateDefinition($element, $definition, $path);
TMBOY 44:c1d8923072ba 39 }
TMBOY 44:c1d8923072ba 40
TMBOY 44:c1d8923072ba 41 // additional the element properties
TMBOY 44:c1d8923072ba 42 $this->validateElement($element, $matches, $definition, $path, $additionalProp);
TMBOY 44:c1d8923072ba 43 }
TMBOY 44:c1d8923072ba 44
TMBOY 44:c1d8923072ba 45 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
TMBOY 44:c1d8923072ba 46 {
TMBOY 44:c1d8923072ba 47 $try = array('/','#','+','~','%');
TMBOY 44:c1d8923072ba 48 $matches = array();
TMBOY 44:c1d8923072ba 49 foreach ($patternProperties as $pregex => $schema) {
TMBOY 44:c1d8923072ba 50 $delimiter = '/';
TMBOY 44:c1d8923072ba 51 // Choose delimiter. Necessary for patterns like ^/ , otherwise you get error
TMBOY 44:c1d8923072ba 52 foreach ($try as $delimiter) {
TMBOY 44:c1d8923072ba 53 if (strpos($pregex, $delimiter) === false) { // safe to use
TMBOY 44:c1d8923072ba 54 break;
TMBOY 44:c1d8923072ba 55 }
TMBOY 44:c1d8923072ba 56 }
TMBOY 44:c1d8923072ba 57
TMBOY 44:c1d8923072ba 58 // Validate the pattern before using it to test for matches
TMBOY 44:c1d8923072ba 59 if (@preg_match($delimiter. $pregex . $delimiter, '') === false) {
TMBOY 44:c1d8923072ba 60 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex,));
TMBOY 44:c1d8923072ba 61 continue;
TMBOY 44:c1d8923072ba 62 }
TMBOY 44:c1d8923072ba 63 foreach ($element as $i => $value) {
TMBOY 44:c1d8923072ba 64 if (preg_match($delimiter . $pregex . $delimiter, $i)) {
TMBOY 44:c1d8923072ba 65 $matches[] = $i;
TMBOY 44:c1d8923072ba 66 $this->checkUndefined($value, $schema ? : new \stdClass(), $path, $i);
TMBOY 44:c1d8923072ba 67 }
TMBOY 44:c1d8923072ba 68 }
TMBOY 44:c1d8923072ba 69 }
TMBOY 44:c1d8923072ba 70 return $matches;
TMBOY 44:c1d8923072ba 71 }
TMBOY 44:c1d8923072ba 72
TMBOY 44:c1d8923072ba 73 /**
TMBOY 44:c1d8923072ba 74 * Validates the element properties
TMBOY 44:c1d8923072ba 75 *
TMBOY 44:c1d8923072ba 76 * @param \stdClass $element Element to validate
TMBOY 44:c1d8923072ba 77 * @param array $matches Matches from patternProperties (if any)
TMBOY 44:c1d8923072ba 78 * @param \stdClass $objectDefinition ObjectConstraint definition
TMBOY 44:c1d8923072ba 79 * @param JsonPointer|null $path Path to test?
TMBOY 44:c1d8923072ba 80 * @param mixed $additionalProp Additional properties
TMBOY 44:c1d8923072ba 81 */
TMBOY 44:c1d8923072ba 82 public function validateElement($element, $matches, $objectDefinition = null, JsonPointer $path = null, $additionalProp = null)
TMBOY 44:c1d8923072ba 83 {
TMBOY 44:c1d8923072ba 84 $this->validateMinMaxConstraint($element, $objectDefinition, $path);
TMBOY 44:c1d8923072ba 85
TMBOY 44:c1d8923072ba 86 foreach ($element as $i => $value) {
TMBOY 44:c1d8923072ba 87 $definition = $this->getProperty($objectDefinition, $i);
TMBOY 44:c1d8923072ba 88
TMBOY 44:c1d8923072ba 89 // no additional properties allowed
TMBOY 44:c1d8923072ba 90 if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
TMBOY 44:c1d8923072ba 91 $this->addError($path, "The property " . $i . " is not defined and the definition does not allow additional properties", 'additionalProp');
TMBOY 44:c1d8923072ba 92 }
TMBOY 44:c1d8923072ba 93
TMBOY 44:c1d8923072ba 94 // additional properties defined
TMBOY 44:c1d8923072ba 95 if (!in_array($i, $matches) && $additionalProp && !$definition) {
TMBOY 44:c1d8923072ba 96 if ($additionalProp === true) {
TMBOY 44:c1d8923072ba 97 $this->checkUndefined($value, null, $path, $i);
TMBOY 44:c1d8923072ba 98 } else {
TMBOY 44:c1d8923072ba 99 $this->checkUndefined($value, $additionalProp, $path, $i);
TMBOY 44:c1d8923072ba 100 }
TMBOY 44:c1d8923072ba 101 }
TMBOY 44:c1d8923072ba 102
TMBOY 44:c1d8923072ba 103 // property requires presence of another
TMBOY 44:c1d8923072ba 104 $require = $this->getProperty($definition, 'requires');
TMBOY 44:c1d8923072ba 105 if ($require && !$this->getProperty($element, $require)) {
TMBOY 44:c1d8923072ba 106 $this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires');
TMBOY 44:c1d8923072ba 107 }
TMBOY 44:c1d8923072ba 108
TMBOY 44:c1d8923072ba 109 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
TMBOY 44:c1d8923072ba 110 if (is_object($property)) {
TMBOY 44:c1d8923072ba 111 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
TMBOY 44:c1d8923072ba 112 }
TMBOY 44:c1d8923072ba 113 }
TMBOY 44:c1d8923072ba 114 }
TMBOY 44:c1d8923072ba 115
TMBOY 44:c1d8923072ba 116 /**
TMBOY 44:c1d8923072ba 117 * Validates the definition properties
TMBOY 44:c1d8923072ba 118 *
TMBOY 44:c1d8923072ba 119 * @param \stdClass $element Element to validate
TMBOY 44:c1d8923072ba 120 * @param \stdClass $objectDefinition ObjectConstraint definition
TMBOY 44:c1d8923072ba 121 * @param JsonPointer|null $path Path?
TMBOY 44:c1d8923072ba 122 */
TMBOY 44:c1d8923072ba 123 public function validateDefinition($element, $objectDefinition = null, JsonPointer $path = null)
TMBOY 44:c1d8923072ba 124 {
TMBOY 44:c1d8923072ba 125 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
TMBOY 44:c1d8923072ba 126
TMBOY 44:c1d8923072ba 127 foreach ($objectDefinition as $i => $value) {
TMBOY 44:c1d8923072ba 128 $property = $this->getProperty($element, $i, $undefinedConstraint);
TMBOY 44:c1d8923072ba 129 $definition = $this->getProperty($objectDefinition, $i);
TMBOY 44:c1d8923072ba 130
TMBOY 44:c1d8923072ba 131 if($this->factory->getCheckMode() & Constraint::CHECK_MODE_TYPE_CAST){
TMBOY 44:c1d8923072ba 132 if(!($property instanceof Constraint)) {
TMBOY 44:c1d8923072ba 133 $property = $this->coerce($property, $definition);
TMBOY 44:c1d8923072ba 134
TMBOY 44:c1d8923072ba 135 if($this->factory->getCheckMode() & Constraint::CHECK_MODE_COERCE) {
TMBOY 44:c1d8923072ba 136 if (is_object($element)) {
TMBOY 44:c1d8923072ba 137 $element->{$i} = $property;
TMBOY 44:c1d8923072ba 138 } else {
TMBOY 44:c1d8923072ba 139 $element[$i] = $property;
TMBOY 44:c1d8923072ba 140 }
TMBOY 44:c1d8923072ba 141 }
TMBOY 44:c1d8923072ba 142 }
TMBOY 44:c1d8923072ba 143 }
TMBOY 44:c1d8923072ba 144
TMBOY 44:c1d8923072ba 145 if (is_object($definition)) {
TMBOY 44:c1d8923072ba 146 // Undefined constraint will check for is_object() and quit if is not - so why pass it?
TMBOY 44:c1d8923072ba 147 $this->checkUndefined($property, $definition, $path, $i);
TMBOY 44:c1d8923072ba 148 }
TMBOY 44:c1d8923072ba 149 }
TMBOY 44:c1d8923072ba 150 }
TMBOY 44:c1d8923072ba 151
TMBOY 44:c1d8923072ba 152 /**
TMBOY 44:c1d8923072ba 153 * Converts a value to boolean. For example, "true" becomes true.
TMBOY 44:c1d8923072ba 154 * @param $value The value to convert to boolean
TMBOY 44:c1d8923072ba 155 * @return bool|mixed
TMBOY 44:c1d8923072ba 156 */
TMBOY 44:c1d8923072ba 157 protected function toBoolean($value)
TMBOY 44:c1d8923072ba 158 {
TMBOY 44:c1d8923072ba 159 if($value === "true"){
TMBOY 44:c1d8923072ba 160 return true;
TMBOY 44:c1d8923072ba 161 }
TMBOY 44:c1d8923072ba 162
TMBOY 44:c1d8923072ba 163 if($value === "false"){
TMBOY 44:c1d8923072ba 164 return false;
TMBOY 44:c1d8923072ba 165 }
TMBOY 44:c1d8923072ba 166
TMBOY 44:c1d8923072ba 167 return $value;
TMBOY 44:c1d8923072ba 168 }
TMBOY 44:c1d8923072ba 169
TMBOY 44:c1d8923072ba 170 /**
TMBOY 44:c1d8923072ba 171 * Converts a numeric string to a number. For example, "4" becomes 4.
TMBOY 44:c1d8923072ba 172 *
TMBOY 44:c1d8923072ba 173 * @param mixed $value The value to convert to a number.
TMBOY 44:c1d8923072ba 174 * @return int|float|mixed
TMBOY 44:c1d8923072ba 175 */
TMBOY 44:c1d8923072ba 176 protected function toNumber($value)
TMBOY 44:c1d8923072ba 177 {
TMBOY 44:c1d8923072ba 178 if(is_numeric($value)) {
TMBOY 44:c1d8923072ba 179 return $value + 0; // cast to number
TMBOY 44:c1d8923072ba 180 }
TMBOY 44:c1d8923072ba 181
TMBOY 44:c1d8923072ba 182 return $value;
TMBOY 44:c1d8923072ba 183 }
TMBOY 44:c1d8923072ba 184
TMBOY 44:c1d8923072ba 185 protected function toInteger($value)
TMBOY 44:c1d8923072ba 186 {
TMBOY 44:c1d8923072ba 187 if(is_numeric($value) && (int)$value == $value) {
TMBOY 44:c1d8923072ba 188 return (int)$value; // cast to number
TMBOY 44:c1d8923072ba 189 }
TMBOY 44:c1d8923072ba 190
TMBOY 44:c1d8923072ba 191 return $value;
TMBOY 44:c1d8923072ba 192 }
TMBOY 44:c1d8923072ba 193
TMBOY 44:c1d8923072ba 194 /**
TMBOY 44:c1d8923072ba 195 * Given a value and a definition, attempts to coerce the value into the
TMBOY 44:c1d8923072ba 196 * type specified by the definition's 'type' property.
TMBOY 44:c1d8923072ba 197 *
TMBOY 44:c1d8923072ba 198 * @param mixed $value Value to coerce.
TMBOY 44:c1d8923072ba 199 * @param \stdClass $definition A definition with information about the expected type.
TMBOY 44:c1d8923072ba 200 * @return bool|int|string
TMBOY 44:c1d8923072ba 201 */
TMBOY 44:c1d8923072ba 202 protected function coerce($value, $definition)
TMBOY 44:c1d8923072ba 203 {
TMBOY 44:c1d8923072ba 204 $types = isset($definition->type)?$definition->type:null;
TMBOY 44:c1d8923072ba 205 if($types){
TMBOY 44:c1d8923072ba 206 foreach((array)$types as $type) {
TMBOY 44:c1d8923072ba 207 switch ($type) {
TMBOY 44:c1d8923072ba 208 case "boolean":
TMBOY 44:c1d8923072ba 209 $value = $this->toBoolean($value);
TMBOY 44:c1d8923072ba 210 break;
TMBOY 44:c1d8923072ba 211 case "integer":
TMBOY 44:c1d8923072ba 212 $value = $this->toInteger($value);
TMBOY 44:c1d8923072ba 213 break;
TMBOY 44:c1d8923072ba 214 case "number":
TMBOY 44:c1d8923072ba 215 $value = $this->toNumber($value);
TMBOY 44:c1d8923072ba 216 break;
TMBOY 44:c1d8923072ba 217 }
TMBOY 44:c1d8923072ba 218 }
TMBOY 44:c1d8923072ba 219 }
TMBOY 44:c1d8923072ba 220 return $value;
TMBOY 44:c1d8923072ba 221 }
TMBOY 44:c1d8923072ba 222
TMBOY 44:c1d8923072ba 223 /**
TMBOY 44:c1d8923072ba 224 * retrieves a property from an object or array
TMBOY 44:c1d8923072ba 225 *
TMBOY 44:c1d8923072ba 226 * @param mixed $element Element to validate
TMBOY 44:c1d8923072ba 227 * @param string $property Property to retrieve
TMBOY 44:c1d8923072ba 228 * @param mixed $fallback Default value if property is not found
TMBOY 44:c1d8923072ba 229 *
TMBOY 44:c1d8923072ba 230 * @return mixed
TMBOY 44:c1d8923072ba 231 */
TMBOY 44:c1d8923072ba 232 protected function getProperty($element, $property, $fallback = null)
TMBOY 44:c1d8923072ba 233 {
TMBOY 44:c1d8923072ba 234 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) {
TMBOY 44:c1d8923072ba 235 return $element[$property];
TMBOY 44:c1d8923072ba 236 } elseif (is_object($element) && property_exists($element, $property)) {
TMBOY 44:c1d8923072ba 237 return $element->$property;
TMBOY 44:c1d8923072ba 238 }
TMBOY 44:c1d8923072ba 239
TMBOY 44:c1d8923072ba 240 return $fallback;
TMBOY 44:c1d8923072ba 241 }
TMBOY 44:c1d8923072ba 242
TMBOY 44:c1d8923072ba 243 /**
TMBOY 44:c1d8923072ba 244 * validating minimum and maximum property constraints (if present) against an element
TMBOY 44:c1d8923072ba 245 *
TMBOY 44:c1d8923072ba 246 * @param \stdClass $element Element to validate
TMBOY 44:c1d8923072ba 247 * @param \stdClass $objectDefinition ObjectConstraint definition
TMBOY 44:c1d8923072ba 248 * @param JsonPointer|null $path Path to test?
TMBOY 44:c1d8923072ba 249 */
TMBOY 44:c1d8923072ba 250 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null) {
TMBOY 44:c1d8923072ba 251 // Verify minimum number of properties
TMBOY 44:c1d8923072ba 252 if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
TMBOY 44:c1d8923072ba 253 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
TMBOY 44:c1d8923072ba 254 $this->addError($path, "Must contain a minimum of " . $objectDefinition->minProperties . " properties", 'minProperties', array('minProperties' => $objectDefinition->minProperties,));
TMBOY 44:c1d8923072ba 255 }
TMBOY 44:c1d8923072ba 256 }
TMBOY 44:c1d8923072ba 257 // Verify maximum number of properties
TMBOY 44:c1d8923072ba 258 if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
TMBOY 44:c1d8923072ba 259 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
TMBOY 44:c1d8923072ba 260 $this->addError($path, "Must contain no more than " . $objectDefinition->maxProperties . " properties", 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties,));
TMBOY 44:c1d8923072ba 261 }
TMBOY 44:c1d8923072ba 262 }
TMBOY 44:c1d8923072ba 263 }
TMBOY 44:c1d8923072ba 264 }