1<?php 2 3/* 4 * This file is part of the JsonSchema package. 5 * 6 * For the full copyright and license information, please view the LICENSE 7 * file that was distributed with this source code. 8 */ 9 10namespace JsonSchema\Constraints; 11 12use JsonSchema\Entity\JsonPointer; 13use JsonSchema\Exception\InvalidArgumentException; 14use JsonSchema\Exception\ValidationException; 15use JsonSchema\Validator; 16 17/** 18 * A more basic constraint definition - used for the public 19 * interface to avoid exposing library internals. 20 */ 21class BaseConstraint 22{ 23 /** 24 * @var array Errors 25 */ 26 protected $errors = array(); 27 28 /** 29 * @var int All error types which have occurred 30 */ 31 protected $errorMask = Validator::ERROR_NONE; 32 33 /** 34 * @var Factory 35 */ 36 protected $factory; 37 38 /** 39 * @param Factory $factory 40 */ 41 public function __construct(Factory $factory = null) 42 { 43 $this->factory = $factory ?: new Factory(); 44 } 45 46 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null) 47 { 48 $error = array( 49 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')), 50 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'), 51 'message' => $message, 52 'constraint' => $constraint, 53 'context' => $this->factory->getErrorContext(), 54 ); 55 56 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) { 57 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message'])); 58 } 59 60 if (is_array($more) && count($more) > 0) { 61 $error += $more; 62 } 63 64 $this->errors[] = $error; 65 $this->errorMask |= $error['context']; 66 } 67 68 public function addErrors(array $errors) 69 { 70 if ($errors) { 71 $this->errors = array_merge($this->errors, $errors); 72 $errorMask = &$this->errorMask; 73 array_walk($errors, function ($error) use (&$errorMask) { 74 if (isset($error['context'])) { 75 $errorMask |= $error['context']; 76 } 77 }); 78 } 79 } 80 81 public function getErrors($errorContext = Validator::ERROR_ALL) 82 { 83 if ($errorContext === Validator::ERROR_ALL) { 84 return $this->errors; 85 } 86 87 return array_filter($this->errors, function ($error) use ($errorContext) { 88 if ($errorContext & $error['context']) { 89 return true; 90 } 91 }); 92 } 93 94 public function numErrors($errorContext = Validator::ERROR_ALL) 95 { 96 if ($errorContext === Validator::ERROR_ALL) { 97 return count($this->errors); 98 } 99 100 return count($this->getErrors($errorContext)); 101 } 102 103 public function isValid() 104 { 105 return !$this->getErrors(); 106 } 107 108 /** 109 * Clears any reported errors. Should be used between 110 * multiple validation checks. 111 */ 112 public function reset() 113 { 114 $this->errors = array(); 115 $this->errorMask = Validator::ERROR_NONE; 116 } 117 118 /** 119 * Get the error mask 120 * 121 * @return int 122 */ 123 public function getErrorMask() 124 { 125 return $this->errorMask; 126 } 127 128 /** 129 * Recursively cast an associative array to an object 130 * 131 * @param array $array 132 * 133 * @return object 134 */ 135 public static function arrayToObjectRecursive($array) 136 { 137 $json = json_encode($array); 138 if (json_last_error() !== \JSON_ERROR_NONE) { 139 $message = 'Unable to encode schema array as JSON'; 140 if (function_exists('json_last_error_msg')) { 141 $message .= ': ' . json_last_error_msg(); 142 } 143 throw new InvalidArgumentException($message); 144 } 145 146 return (object) json_decode($json); 147 } 148} 149