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