Skip to content

Optional extra arguments for custom error messages #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/JsonSchema/Constraints/CollectionConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public function check($value, $schema = null, $path = null, $i = null)
{
// Verify minItems
if (isset($schema->minItems) && count($value) < $schema->minItems) {
$this->addError($path, "There must be a minimum of " . $schema->minItems . " items in the array");
$this->addError($path, "There must be a minimum of " . $schema->minItems . " items in the array", 'minItems', array('minItems' => $schema->minItems,));
}

// Verify maxItems
if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
$this->addError($path, "There must be a maximum of " . $schema->maxItems . " items in the array");
$this->addError($path, "There must be a maximum of " . $schema->maxItems . " items in the array", 'maxItems', array('maxItems' => $schema->maxItems,));
}

// Verify uniqueItems
Expand All @@ -39,7 +39,7 @@ public function check($value, $schema = null, $path = null, $i = null)
$unique = array_map(function($e) { return var_export($e, true); }, $value);
}
if (count(array_unique($unique)) != count($value)) {
$this->addError($path, "There are no duplicates allowed in the array");
$this->addError($path, "There are no duplicates allowed in the array", 'uniqueItems');
}
}

Expand Down Expand Up @@ -92,7 +92,7 @@ protected function validateItems($value, $schema = null, $path = null, $i = null
$this->checkUndefined($v, $schema->additionalItems, $path, $k);
} else {
$this->addError(
$path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items');
$path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems,));
}
} else {
// Should be valid against an empty schema
Expand Down
14 changes: 11 additions & 3 deletions src/JsonSchema/Constraints/Constraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,20 @@ public function setUriRetriever(UriRetriever $uriRetriever)
/**
* {@inheritDoc}
*/
public function addError($path, $message)
public function addError($path, $message, $constraint='', array $more=null)
{
$this->errors[] = array(
$error = array(
'property' => $path,
'message' => $message
'message' => $message,
'constraint' => $constraint,
);

if (is_array($more) && count($more) > 0)
{
$error += $more;
}

$this->errors[] = $error;
}

/**
Expand Down
8 changes: 5 additions & 3 deletions src/JsonSchema/Constraints/ConstraintInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ public function addErrors(array $errors);
/**
* adds an error
*
* @param $path
* @param $message
* @param string $path
* @param string $message
* @param string $constraint the constraint/rule that is broken, e.g.: 'minLength'
* @param array $more more array elements to add to the error
*/
public function addError($path, $message);
public function addError($path, $message, $constraint='', array $more=null);

/**
* checks if the validator has not raised errors
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/EnumConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ public function check($element, $schema = null, $path = null, $i = null)
}
}

$this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true));
$this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true), 'enum', array('enum' => $schema->enum,));
}
}
33 changes: 19 additions & 14 deletions src/JsonSchema/Constraints/FormatConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public function check($element, $schema = null, $path = null, $i = null)
switch ($schema->format) {
case 'date':
if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
$this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)));
$this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format,));
}
break;

case 'time':
if (!$this->validateDateTime($element, 'H:i:s')) {
$this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)));
$this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format,));
}
break;

Expand All @@ -45,74 +45,79 @@ public function check($element, $schema = null, $path = null, $i = null)
!$this->validateDateTime($element, 'Y-m-d\TH:i:sP') &&
!$this->validateDateTime($element, 'Y-m-d\TH:i:sO')
) {
$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)));
$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,));
}
break;

case 'utc-millisec':
if (!$this->validateDateTime($element, 'U')) {
$this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)));
$this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format,));
}
break;

case 'regex':
if (!$this->validateRegex($element)) {
$this->addError($path, 'Invalid regex format ' . $element);
$this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format,));
}
break;

case 'color':
if (!$this->validateColor($element)) {
$this->addError($path, "Invalid color");
$this->addError($path, "Invalid color", 'format', array('format' => $schema->format,));
}
break;

case 'style':
if (!$this->validateStyle($element)) {
$this->addError($path, "Invalid style");
$this->addError($path, "Invalid style", 'format', array('format' => $schema->format,));
}
break;

case 'phone':
if (!$this->validatePhone($element)) {
$this->addError($path, "Invalid phone number");
$this->addError($path, "Invalid phone number", 'format', array('format' => $schema->format,));
}
break;

case 'uri':
if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
$this->addError($path, "Invalid URL format");
$this->addError($path, "Invalid URL format", 'format', array('format' => $schema->format,));
}
break;

case 'email':
if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) {
$this->addError($path, "Invalid email");
$this->addError($path, "Invalid email", 'format', array('format' => $schema->format,));
}
break;

case 'ip-address':
case 'ipv4':
if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
$this->addError($path, "Invalid IP address");
$this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
}
break;

case 'ipv6':
if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
$this->addError($path, "Invalid IP address");
$this->addError($path, "Invalid IP address", 'format', array('format' => $schema->format,));
}
break;

case 'host-name':
case 'hostname':
if (!$this->validateHostname($element)) {
$this->addError($path, "Invalid hostname");
$this->addError($path, "Invalid hostname", 'format', array('format' => $schema->format,));
}
break;

default:
// Do nothing so that custom formats can be used.
// Empty as it should be:
// The value of this keyword is called a format attribute. It MUST be a string.
// A format attribute can generally only validate a given set of instance types.
// If the type of the instance to validate is not in this set, validation for
// this format attribute and instance SHOULD succeed.
// http://json-schema.org/latest/json-schema-validation.html#anchor105
break;
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/JsonSchema/Constraints/NumberConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,40 @@ public function check($element, $schema = null, $path = null, $i = null)
if (isset($schema->exclusiveMinimum)) {
if (isset($schema->minimum)) {
if ($schema->exclusiveMinimum && $element === $schema->minimum) {
$this->addError($path, "Must have a minimum value greater than boundary value of " . $schema->minimum);
$this->addError($path, "Must have a minimum value greater than boundary value of " . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum,));
} else if ($element < $schema->minimum) {
$this->addError($path, "Must have a minimum value of " . $schema->minimum);
$this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
}
} else {
$this->addError($path, "Use of exclusiveMinimum requires presence of minimum");
$this->addError($path, "Use of exclusiveMinimum requires presence of minimum", 'missingMinimum');
}
} else if (isset($schema->minimum) && $element < $schema->minimum) {
$this->addError($path, "Must have a minimum value of " . $schema->minimum);
$this->addError($path, "Must have a minimum value of " . $schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
}

// Verify maximum
if (isset($schema->exclusiveMaximum)) {
if (isset($schema->maximum)) {
if ($schema->exclusiveMaximum && $element === $schema->maximum) {
$this->addError($path, "Must have a maximum value less than boundary value of " . $schema->maximum);
$this->addError($path, "Must have a maximum value less than boundary value of " . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum,));
} else if ($element > $schema->maximum) {
$this->addError($path, "Must have a maximum value of " . $schema->maximum);
$this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
}
} else {
$this->addError($path, "Use of exclusiveMaximum requires presence of maximum");
$this->addError($path, "Use of exclusiveMaximum requires presence of maximum", 'missingMinimum');
}
} else if (isset($schema->maximum) && $element > $schema->maximum) {
$this->addError($path, "Must have a maximum value of " . $schema->maximum);
$this->addError($path, "Must have a maximum value of " . $schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
}

// Verify divisibleBy - Draft v3
if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
$this->addError($path, "Is not divisible by " . $schema->divisibleBy);
$this->addError($path, "Is not divisible by " . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy,));
}

// Verify multipleOf - Draft v4
if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
$this->addError($path, "Must be a multiple of " . $schema->multipleOf);
$this->addError($path, "Must be a multiple of " . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf,));
}

$this->checkFormat($element, $schema, $path, $i);
Expand Down
6 changes: 3 additions & 3 deletions src/JsonSchema/Constraints/ObjectConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function validatePatternProperties($element, $path, $patternProperties)
foreach ($patternProperties as $pregex => $schema) {
// Validate the pattern before using it to test for matches
if (@preg_match('/'. $pregex . '/', '') === false) {
$this->addError($path, 'The pattern "' . $pregex . '" is invalid');
$this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex,));
continue;
}
foreach ($element as $i => $value) {
Expand Down Expand Up @@ -77,7 +77,7 @@ public function validateElement($element, $matches, $objectDefinition = null, $p

// no additional properties allowed
if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
$this->addError($path, "The property - " . $i . " - is not defined and the definition does not allow additional properties");
$this->addError($path, "The property " . $i . " is not defined and the definition does not allow additional properties", 'additionalProp');
}

// additional properties defined
Expand All @@ -92,7 +92,7 @@ public function validateElement($element, $matches, $objectDefinition = null, $p
// property requires presence of another
$require = $this->getProperty($definition, 'requires');
if ($require && !$this->getProperty($element, $require)) {
$this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present");
$this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires');
}

if (!$definition) {
Expand Down
12 changes: 9 additions & 3 deletions src/JsonSchema/Constraints/StringConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ public function check($element, $schema = null, $path = null, $i = null)
{
// Verify maxLength
if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
$this->addError($path, "Must be at most " . $schema->maxLength . " characters long");
$this->addError($path, "Must be at most " . $schema->maxLength . " characters long", 'maxLength', array(
'maxLength' => $schema->maxLength,
));
}

//verify minLength
if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
$this->addError($path, "Must be at least " . $schema->minLength . " characters long");
$this->addError($path, "Must be at least " . $schema->minLength . " characters long", 'minLength', array(
'minLength' => $schema->minLength,
));
}

// Verify a regex pattern
if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#', $element)) {
$this->addError($path, "Does not match the regex pattern " . $schema->pattern);
$this->addError($path, "Does not match the regex pattern " . $schema->pattern, 'pattern', array(
'pattern' => $schema->pattern,
));
}

$this->checkFormat($element, $schema, $path, $i);
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/TypeConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function check($value = null, $schema = null, $path = null, $i = null)
implode(', ', array_filter(self::$wording)))
);
}
$this->addError($path, gettype($value) . " value found, but " . self::$wording[$type] . " is required");
$this->addError($path, ucwords(gettype($value)) . " value found, but " . self::$wording[$type] . " is required", 'type');
}
}

Expand Down
Loading