ex
Fork of mbed-os-example-mbed5-blinky by
dumi_doc-master/schema/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php@44:c1d8923072ba, 2017-07-18 (annotated)
- Committer:
- TMBOY
- Date:
- Tue Jul 18 16:27:22 2017 +0800
- Revision:
- 44:c1d8923072ba
?
Who changed what in which revision?
| User | Revision | Line number | New 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\Rfc3339; |
| TMBOY | 44:c1d8923072ba | 13 | use JsonSchema\Entity\JsonPointer; |
| TMBOY | 44:c1d8923072ba | 14 | |
| TMBOY | 44:c1d8923072ba | 15 | /** |
| TMBOY | 44:c1d8923072ba | 16 | * Validates against the "format" property |
| TMBOY | 44:c1d8923072ba | 17 | * |
| TMBOY | 44:c1d8923072ba | 18 | * @author Justin Rainbow <justin.rainbow@gmail.com> |
| TMBOY | 44:c1d8923072ba | 19 | * @link http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23 |
| TMBOY | 44:c1d8923072ba | 20 | */ |
| TMBOY | 44:c1d8923072ba | 21 | class FormatConstraint extends Constraint |
| TMBOY | 44:c1d8923072ba | 22 | { |
| TMBOY | 44:c1d8923072ba | 23 | /** |
| TMBOY | 44:c1d8923072ba | 24 | * {@inheritDoc} |
| TMBOY | 44:c1d8923072ba | 25 | */ |
| TMBOY | 44:c1d8923072ba | 26 | public function check($element, $schema = null, JsonPointer $path = null, $i = null) |
| TMBOY | 44:c1d8923072ba | 27 | { |
| TMBOY | 44:c1d8923072ba | 28 | if (!isset($schema->format)) { |
| TMBOY | 44:c1d8923072ba | 29 | return; |
| TMBOY | 44:c1d8923072ba | 30 | } |
| TMBOY | 44:c1d8923072ba | 31 | |
| TMBOY | 44:c1d8923072ba | 32 | switch ($schema->format) { |
| TMBOY | 44:c1d8923072ba | 33 | case 'date': |
| TMBOY | 44:c1d8923072ba | 34 | if (!$date = $this->validateDateTime($element, 'Y-m-d')) { |
| TMBOY | 44:c1d8923072ba | 35 | $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 36 | } |
| TMBOY | 44:c1d8923072ba | 37 | break; |
| TMBOY | 44:c1d8923072ba | 38 | |
| TMBOY | 44:c1d8923072ba | 39 | case 'time': |
| TMBOY | 44:c1d8923072ba | 40 | if (!$this->validateDateTime($element, 'H:i:s')) { |
| TMBOY | 44:c1d8923072ba | 41 | $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 42 | } |
| TMBOY | 44:c1d8923072ba | 43 | break; |
| TMBOY | 44:c1d8923072ba | 44 | |
| TMBOY | 44:c1d8923072ba | 45 | case 'date-time': |
| TMBOY | 44:c1d8923072ba | 46 | if (null === Rfc3339::createFromString($element)) { |
| TMBOY | 44:c1d8923072ba | 47 | $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element)), 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 48 | } |
| TMBOY | 44:c1d8923072ba | 49 | break; |
| TMBOY | 44:c1d8923072ba | 50 | |
| TMBOY | 44:c1d8923072ba | 51 | case 'utc-millisec': |
| TMBOY | 44:c1d8923072ba | 52 | if (!$this->validateDateTime($element, 'U')) { |
| TMBOY | 44:c1d8923072ba | 53 | $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 54 | } |
| TMBOY | 44:c1d8923072ba | 55 | break; |
| TMBOY | 44:c1d8923072ba | 56 | |
| TMBOY | 44:c1d8923072ba | 57 | case 'regex': |
| TMBOY | 44:c1d8923072ba | 58 | if (!$this->validateRegex($element)) { |
| TMBOY | 44:c1d8923072ba | 59 | $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 60 | } |
| TMBOY | 44:c1d8923072ba | 61 | break; |
| TMBOY | 44:c1d8923072ba | 62 | |
| TMBOY | 44:c1d8923072ba | 63 | case 'color': |
| TMBOY | 44:c1d8923072ba | 64 | if (!$this->validateColor($element)) { |
| TMBOY | 44:c1d8923072ba | 65 | $this->addError($path, "Invalid color", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 66 | } |
| TMBOY | 44:c1d8923072ba | 67 | break; |
| TMBOY | 44:c1d8923072ba | 68 | |
| TMBOY | 44:c1d8923072ba | 69 | case 'style': |
| TMBOY | 44:c1d8923072ba | 70 | if (!$this->validateStyle($element)) { |
| TMBOY | 44:c1d8923072ba | 71 | $this->addError($path, "Invalid style", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 72 | } |
| TMBOY | 44:c1d8923072ba | 73 | break; |
| TMBOY | 44:c1d8923072ba | 74 | |
| TMBOY | 44:c1d8923072ba | 75 | case 'phone': |
| TMBOY | 44:c1d8923072ba | 76 | if (!$this->validatePhone($element)) { |
| TMBOY | 44:c1d8923072ba | 77 | $this->addError($path, "Invalid phone number", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 78 | } |
| TMBOY | 44:c1d8923072ba | 79 | break; |
| TMBOY | 44:c1d8923072ba | 80 | |
| TMBOY | 44:c1d8923072ba | 81 | case 'uri': |
| TMBOY | 44:c1d8923072ba | 82 | if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) { |
| TMBOY | 44:c1d8923072ba | 83 | $this->addError($path, "Invalid URL format", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 84 | } |
| TMBOY | 44:c1d8923072ba | 85 | break; |
| TMBOY | 44:c1d8923072ba | 86 | |
| TMBOY | 44:c1d8923072ba | 87 | case 'email': |
| TMBOY | 44:c1d8923072ba | 88 | if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) { |
| TMBOY | 44:c1d8923072ba | 89 | $this->addError($path, "Invalid email", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 90 | } |
| TMBOY | 44:c1d8923072ba | 91 | break; |
| TMBOY | 44:c1d8923072ba | 92 | |
| TMBOY | 44:c1d8923072ba | 93 | case 'ip-address': |
| TMBOY | 44:c1d8923072ba | 94 | case 'ipv4': |
| TMBOY | 44:c1d8923072ba | 95 | if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) { |
| TMBOY | 44:c1d8923072ba | 96 | $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 97 | } |
| TMBOY | 44:c1d8923072ba | 98 | break; |
| TMBOY | 44:c1d8923072ba | 99 | |
| TMBOY | 44:c1d8923072ba | 100 | case 'ipv6': |
| TMBOY | 44:c1d8923072ba | 101 | if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) { |
| TMBOY | 44:c1d8923072ba | 102 | $this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 103 | } |
| TMBOY | 44:c1d8923072ba | 104 | break; |
| TMBOY | 44:c1d8923072ba | 105 | |
| TMBOY | 44:c1d8923072ba | 106 | case 'host-name': |
| TMBOY | 44:c1d8923072ba | 107 | case 'hostname': |
| TMBOY | 44:c1d8923072ba | 108 | if (!$this->validateHostname($element)) { |
| TMBOY | 44:c1d8923072ba | 109 | $this->addError($path, "Invalid hostname", 'format', array('format' => $schema->format,)); |
| TMBOY | 44:c1d8923072ba | 110 | } |
| TMBOY | 44:c1d8923072ba | 111 | break; |
| TMBOY | 44:c1d8923072ba | 112 | |
| TMBOY | 44:c1d8923072ba | 113 | default: |
| TMBOY | 44:c1d8923072ba | 114 | // Empty as it should be: |
| TMBOY | 44:c1d8923072ba | 115 | // The value of this keyword is called a format attribute. It MUST be a string. |
| TMBOY | 44:c1d8923072ba | 116 | // A format attribute can generally only validate a given set of instance types. |
| TMBOY | 44:c1d8923072ba | 117 | // If the type of the instance to validate is not in this set, validation for |
| TMBOY | 44:c1d8923072ba | 118 | // this format attribute and instance SHOULD succeed. |
| TMBOY | 44:c1d8923072ba | 119 | // http://json-schema.org/latest/json-schema-validation.html#anchor105 |
| TMBOY | 44:c1d8923072ba | 120 | break; |
| TMBOY | 44:c1d8923072ba | 121 | } |
| TMBOY | 44:c1d8923072ba | 122 | } |
| TMBOY | 44:c1d8923072ba | 123 | |
| TMBOY | 44:c1d8923072ba | 124 | protected function validateDateTime($datetime, $format) |
| TMBOY | 44:c1d8923072ba | 125 | { |
| TMBOY | 44:c1d8923072ba | 126 | $dt = \DateTime::createFromFormat($format, $datetime); |
| TMBOY | 44:c1d8923072ba | 127 | |
| TMBOY | 44:c1d8923072ba | 128 | if (!$dt) { |
| TMBOY | 44:c1d8923072ba | 129 | return false; |
| TMBOY | 44:c1d8923072ba | 130 | } |
| TMBOY | 44:c1d8923072ba | 131 | |
| TMBOY | 44:c1d8923072ba | 132 | if ($datetime === $dt->format($format)) { |
| TMBOY | 44:c1d8923072ba | 133 | return true; |
| TMBOY | 44:c1d8923072ba | 134 | } |
| TMBOY | 44:c1d8923072ba | 135 | |
| TMBOY | 44:c1d8923072ba | 136 | // handles the case where a non-6 digit microsecond datetime is passed |
| TMBOY | 44:c1d8923072ba | 137 | // which will fail the above string comparison because the passed |
| TMBOY | 44:c1d8923072ba | 138 | // $datetime may be '2000-05-01T12:12:12.123Z' but format() will return |
| TMBOY | 44:c1d8923072ba | 139 | // '2000-05-01T12:12:12.123000Z' |
| TMBOY | 44:c1d8923072ba | 140 | if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) { |
| TMBOY | 44:c1d8923072ba | 141 | return true; |
| TMBOY | 44:c1d8923072ba | 142 | } |
| TMBOY | 44:c1d8923072ba | 143 | |
| TMBOY | 44:c1d8923072ba | 144 | return false; |
| TMBOY | 44:c1d8923072ba | 145 | } |
| TMBOY | 44:c1d8923072ba | 146 | |
| TMBOY | 44:c1d8923072ba | 147 | protected function validateRegex($regex) |
| TMBOY | 44:c1d8923072ba | 148 | { |
| TMBOY | 44:c1d8923072ba | 149 | return false !== @preg_match('/' . $regex . '/', ''); |
| TMBOY | 44:c1d8923072ba | 150 | } |
| TMBOY | 44:c1d8923072ba | 151 | |
| TMBOY | 44:c1d8923072ba | 152 | protected function validateColor($color) |
| TMBOY | 44:c1d8923072ba | 153 | { |
| TMBOY | 44:c1d8923072ba | 154 | if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia', |
| TMBOY | 44:c1d8923072ba | 155 | 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', |
| TMBOY | 44:c1d8923072ba | 156 | 'red', 'silver', 'teal', 'white', 'yellow'))) { |
| TMBOY | 44:c1d8923072ba | 157 | return true; |
| TMBOY | 44:c1d8923072ba | 158 | } |
| TMBOY | 44:c1d8923072ba | 159 | |
| TMBOY | 44:c1d8923072ba | 160 | return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color); |
| TMBOY | 44:c1d8923072ba | 161 | } |
| TMBOY | 44:c1d8923072ba | 162 | |
| TMBOY | 44:c1d8923072ba | 163 | protected function validateStyle($style) |
| TMBOY | 44:c1d8923072ba | 164 | { |
| TMBOY | 44:c1d8923072ba | 165 | $properties = explode(';', rtrim($style, ';')); |
| TMBOY | 44:c1d8923072ba | 166 | $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT); |
| TMBOY | 44:c1d8923072ba | 167 | |
| TMBOY | 44:c1d8923072ba | 168 | return empty($invalidEntries); |
| TMBOY | 44:c1d8923072ba | 169 | } |
| TMBOY | 44:c1d8923072ba | 170 | |
| TMBOY | 44:c1d8923072ba | 171 | protected function validatePhone($phone) |
| TMBOY | 44:c1d8923072ba | 172 | { |
| TMBOY | 44:c1d8923072ba | 173 | return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone); |
| TMBOY | 44:c1d8923072ba | 174 | } |
| TMBOY | 44:c1d8923072ba | 175 | |
| TMBOY | 44:c1d8923072ba | 176 | protected function validateHostname($host) |
| TMBOY | 44:c1d8923072ba | 177 | { |
| TMBOY | 44:c1d8923072ba | 178 | $hostnameRegex = '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i'; |
| TMBOY | 44:c1d8923072ba | 179 | return preg_match($hostnameRegex, $host); |
| TMBOY | 44:c1d8923072ba | 180 | } |
| TMBOY | 44:c1d8923072ba | 181 | } |
