@@ -154,7 +154,7 @@ public function in($data, Context $options = null)
154154 if ($ this ->__booleanSchema ) {
155155 return $ data ;
156156 } elseif (empty ($ options ->skipValidation )) {
157- $ this ->fail (new InvalidValue ('Denied by false schema ' ), '# ' );
157+ $ this ->fail (( new InvalidValue ('Denied by false schema ' ))-> withData ( $ data ), '# ' );
158158 }
159159 }
160160
@@ -213,10 +213,10 @@ private function processType(&$data, Context $options, $path = '#')
213213 $ valid = Type::isValid ($ this ->type , $ data , $ options ->version );
214214 }
215215 if (!$ valid ) {
216- $ this ->fail (new TypeException (ucfirst (
216+ $ this ->fail (( new TypeException (ucfirst (
217217 implode (', ' , is_array ($ this ->type ) ? $ this ->type : array ($ this ->type ))
218218 . ' expected, ' . json_encode ($ data ) . ' received ' )
219- ), $ path );
219+ ))-> withData ( $ data )-> withConstraint ( $ this -> type ) , $ path );
220220 }
221221 }
222222
@@ -250,7 +250,9 @@ private function processEnum($data, $path = '#')
250250 }
251251 }
252252 if (!$ enumOk ) {
253- $ this ->fail (new EnumException ('Enum failed, enum: ' . json_encode ($ this ->enum ) . ', data: ' . json_encode ($ data )), $ path );
253+ $ this ->fail ((new EnumException ('Enum failed, enum: ' . json_encode ($ this ->enum ) . ', data: ' . json_encode ($ data )))
254+ ->withData ($ data )
255+ ->withConstraint ($ this ->enum ), $ path );
254256 }
255257 }
256258
@@ -274,10 +276,14 @@ private function processConst($data, $path)
274276 $ diff = new JsonDiff ($ this ->const , $ data ,
275277 JsonDiff::STOP_ON_DIFF );
276278 if ($ diff ->getDiffCnt () != 0 ) {
277- $ this ->fail (new ConstException ('Const failed ' ), $ path );
279+ $ this ->fail ((new ConstException ('Const failed ' ))
280+ ->withData ($ data )
281+ ->withConstraint ($ this ->const ), $ path );
278282 }
279283 } else {
280- $ this ->fail (new ConstException ('Const failed ' ), $ path );
284+ $ this ->fail ((new ConstException ('Const failed ' ))
285+ ->withData ($ data )
286+ ->withConstraint ($ this ->const ), $ path );
281287 }
282288 }
283289 }
@@ -299,7 +305,8 @@ private function processNot($data, Context $options, $path)
299305 // Expected exception
300306 }
301307 if ($ exception === false ) {
302- $ this ->fail (new LogicException ('Not ' . json_encode ($ this ->not ) . ' expected, ' . json_encode ($ data ) . ' received ' ), $ path . '->not ' );
308+ $ this ->fail ((new LogicException ('Not ' . json_encode ($ this ->not ) . ' expected, ' . json_encode ($ data ) . ' received ' ))
309+ ->withData ($ data ), $ path . '->not ' );
303310 }
304311 }
305312
@@ -312,25 +319,29 @@ private function processString($data, $path)
312319 {
313320 if ($ this ->minLength !== null ) {
314321 if (mb_strlen ($ data , 'UTF-8 ' ) < $ this ->minLength ) {
315- $ this ->fail (new StringException ('String is too short ' , StringException::TOO_SHORT ), $ path );
322+ $ this ->fail ((new StringException ('String is too short ' , StringException::TOO_SHORT ))
323+ ->withData ($ data )->withConstraint ($ this ->minLength ), $ path );
316324 }
317325 }
318326 if ($ this ->maxLength !== null ) {
319327 if (mb_strlen ($ data , 'UTF-8 ' ) > $ this ->maxLength ) {
320- $ this ->fail (new StringException ('String is too long ' , StringException::TOO_LONG ), $ path );
328+ $ this ->fail ((new StringException ('String is too long ' , StringException::TOO_LONG ))
329+ ->withData ($ data )->withConstraint ($ this ->maxLength ), $ path );
321330 }
322331 }
323332 if ($ this ->pattern !== null ) {
324333 if (0 === preg_match (Helper::toPregPattern ($ this ->pattern ), $ data )) {
325- $ this ->fail (new StringException (json_encode ($ data ) . ' does not match to '
326- . $ this ->pattern , StringException::PATTERN_MISMATCH ), $ path );
334+ $ this ->fail ((new StringException (json_encode ($ data ) . ' does not match to '
335+ . $ this ->pattern , StringException::PATTERN_MISMATCH ))
336+ ->withData ($ data )->withConstraint ($ this ->pattern ), $ path );
327337 }
328338 }
329339 if ($ this ->format !== null ) {
330340 $ validationError = Format::validationError ($ this ->format , $ data );
331341 if ($ validationError !== null ) {
332342 if (!($ this ->format === "uri " && substr ($ path , -3 ) === ':id ' )) {
333- $ this ->fail (new StringException ($ validationError ), $ path );
343+ $ this ->fail ((new StringException ($ validationError ))
344+ ->withData ($ data ), $ path );
334345 }
335346 }
336347 }
@@ -345,55 +356,62 @@ private function processNumeric($data, $path)
345356 {
346357 if ($ this ->multipleOf !== null ) {
347358 $ div = $ data / $ this ->multipleOf ;
348- if ($ div != (int )$ div ) {
349- $ this ->fail (new NumericException ($ data . ' is not multiple of ' . $ this ->multipleOf , NumericException::MULTIPLE_OF ), $ path );
359+ if ($ div != (int )$ div && ($ div = $ data * (1 / $ this ->multipleOf )) && ($ div != (int )$ div )) {
360+ $ this ->fail ((new NumericException ($ data . ' is not multiple of ' . $ this ->multipleOf , NumericException::MULTIPLE_OF ))
361+ ->withData ($ data )->withConstraint ($ this ->multipleOf ), $ path );
350362 }
351363 }
352364
353365 if ($ this ->exclusiveMaximum !== null && !is_bool ($ this ->exclusiveMaximum )) {
354366 if ($ data >= $ this ->exclusiveMaximum ) {
355- $ this ->fail (new NumericException (
367+ $ this ->fail (( new NumericException (
356368 'Value less or equal than ' . $ this ->exclusiveMaximum . ' expected, ' . $ data . ' received ' ,
357- NumericException::MAXIMUM ), $ path );
369+ NumericException::MAXIMUM ))
370+ ->withData ($ data )->withConstraint ($ this ->exclusiveMaximum ), $ path );
358371 }
359372 }
360373
361374 if ($ this ->exclusiveMinimum !== null && !is_bool ($ this ->exclusiveMinimum )) {
362375 if ($ data <= $ this ->exclusiveMinimum ) {
363- $ this ->fail (new NumericException (
376+ $ this ->fail (( new NumericException (
364377 'Value more or equal than ' . $ this ->exclusiveMinimum . ' expected, ' . $ data . ' received ' ,
365- NumericException::MINIMUM ), $ path );
378+ NumericException::MINIMUM ))
379+ ->withData ($ data )->withConstraint ($ this ->exclusiveMinimum ), $ path );
366380 }
367381 }
368382
369383 if ($ this ->maximum !== null ) {
370384 if ($ this ->exclusiveMaximum === true ) {
371385 if ($ data >= $ this ->maximum ) {
372- $ this ->fail (new NumericException (
386+ $ this ->fail (( new NumericException (
373387 'Value less or equal than ' . $ this ->maximum . ' expected, ' . $ data . ' received ' ,
374- NumericException::MAXIMUM ), $ path );
388+ NumericException::MAXIMUM ))
389+ ->withData ($ data )->withConstraint ($ this ->maximum ), $ path );
375390 }
376391 } else {
377392 if ($ data > $ this ->maximum ) {
378- $ this ->fail (new NumericException (
393+ $ this ->fail (( new NumericException (
379394 'Value less than ' . $ this ->maximum . ' expected, ' . $ data . ' received ' ,
380- NumericException::MAXIMUM ), $ path );
395+ NumericException::MAXIMUM ))
396+ ->withData ($ data )->withConstraint ($ this ->maximum ), $ path );
381397 }
382398 }
383399 }
384400
385401 if ($ this ->minimum !== null ) {
386402 if ($ this ->exclusiveMinimum === true ) {
387403 if ($ data <= $ this ->minimum ) {
388- $ this ->fail (new NumericException (
404+ $ this ->fail (( new NumericException (
389405 'Value more or equal than ' . $ this ->minimum . ' expected, ' . $ data . ' received ' ,
390- NumericException::MINIMUM ), $ path );
406+ NumericException::MINIMUM ))
407+ ->withData ($ data )->withConstraint ($ this ->minimum ), $ path );
391408 }
392409 } else {
393410 if ($ data < $ this ->minimum ) {
394- $ this ->fail (new NumericException (
411+ $ this ->fail (( new NumericException (
395412 'Value more than ' . $ this ->minimum . ' expected, ' . $ data . ' received ' ,
396- NumericException::MINIMUM ), $ path );
413+ NumericException::MINIMUM ))
414+ ->withData ($ data )->withConstraint ($ this ->minimum ), $ path );
397415 }
398416 }
399417 }
@@ -445,13 +463,15 @@ private function processOneOf($data, Context $options, $path)
445463 $ exception = new LogicException ('No valid results for oneOf { ' . "\n" . substr ($ failures , 0 , -1 ) . "\n} " );
446464 $ exception ->error = 'No valid results for oneOf ' ;
447465 $ exception ->subErrors = $ subErrors ;
466+ $ exception ->data = $ data ;
448467 $ this ->fail ($ exception , $ path );
449468 } elseif ($ successes > 1 ) {
450469 $ exception = new LogicException ('More than 1 valid result for oneOf: '
451470 . $ successes . '/ ' . count ($ this ->oneOf ) . ' valid results for oneOf { '
452471 . "\n" . substr ($ failures , 0 , -1 ) . "\n} " );
453472 $ exception ->error = 'More than 1 valid result for oneOf ' ;
454473 $ exception ->subErrors = $ subErrors ;
474+ $ exception ->data = $ data ;
455475 $ this ->fail ($ exception , $ path );
456476 }
457477 }
@@ -492,6 +512,7 @@ private function processAnyOf($data, Context $options, $path)
492512 . "\n} " );
493513 $ exception ->error = 'No valid results for anyOf ' ;
494514 $ exception ->subErrors = $ subErrors ;
515+ $ exception ->data = $ data ;
495516 $ this ->fail ($ exception , $ path );
496517 }
497518 return $ result ;
@@ -554,7 +575,12 @@ private function processObjectRequired($array, Context $options, $path)
554575 {
555576 foreach ($ this ->required as $ item ) {
556577 if (!array_key_exists ($ item , $ array )) {
557- $ this ->fail (new ObjectException ('Required property missing: ' . $ item . ', data: ' . json_encode ($ array , JSON_UNESCAPED_SLASHES ), ObjectException::REQUIRED ), $ path );
578+ $ this ->fail (
579+ (new ObjectException (
580+ 'Required property missing: ' . $ item . ', data: ' . json_encode ($ array , JSON_UNESCAPED_SLASHES ),
581+ ObjectException::REQUIRED ))
582+ ->withData ((object )$ array )->withConstraint ($ item ),
583+ $ path );
558584 }
559585 }
560586 }
@@ -780,10 +806,12 @@ private function processObject($data, Context $options, $path, $result = null)
780806
781807 if (!$ options ->skipValidation ) {
782808 if ($ this ->minProperties !== null && count ($ array ) < $ this ->minProperties ) {
783- $ this ->fail (new ObjectException ("Not enough properties " , ObjectException::TOO_FEW ), $ path );
809+ $ this ->fail ((new ObjectException ("Not enough properties " , ObjectException::TOO_FEW ))
810+ ->withData ($ data )->withConstraint ($ this ->minProperties ), $ path );
784811 }
785812 if ($ this ->maxProperties !== null && count ($ array ) > $ this ->maxProperties ) {
786- $ this ->fail (new ObjectException ("Too many properties " , ObjectException::TOO_MANY ), $ path );
813+ $ this ->fail ((new ObjectException ("Too many properties " , ObjectException::TOO_MANY ))
814+ ->withData ($ data )->withConstraint ($ this ->maxProperties ), $ path );
787815 }
788816 if ($ this ->propertyNames !== null ) {
789817 $ propertyNames = self ::unboolSchema ($ this ->propertyNames );
@@ -845,8 +873,9 @@ private function processObject($data, Context $options, $path, $result = null)
845873 } else {
846874 foreach ($ dependencies as $ item ) {
847875 if (!array_key_exists ($ item , $ array )) {
848- $ this ->fail (new ObjectException ('Dependency property missing: ' . $ item ,
849- ObjectException::DEPENDENCY_MISSING ), $ path );
876+ $ this ->fail ((new ObjectException ('Dependency property missing: ' . $ item ,
877+ ObjectException::DEPENDENCY_MISSING ))
878+ ->withData ($ data )->withConstraint ($ item ), $ path );
850879 }
851880 }
852881 }
@@ -892,7 +921,8 @@ private function processObject($data, Context $options, $path, $result = null)
892921 }
893922 if (!$ found && $ this ->additionalProperties !== null ) {
894923 if (!$ options ->skipValidation && $ this ->additionalProperties === false ) {
895- $ this ->fail (new ObjectException ('Additional properties not allowed: ' . $ key ), $ path );
924+ $ this ->fail ((new ObjectException ('Additional properties not allowed: ' . $ key ))
925+ ->withData ($ data ), $ path );
896926 }
897927
898928 if ($ this ->additionalProperties instanceof SchemaContract) {
@@ -968,11 +998,11 @@ private function processArray($data, Context $options, $path, $result)
968998 $ count = count ($ data );
969999 if (!$ options ->skipValidation ) {
9701000 if ($ this ->minItems !== null && $ count < $ this ->minItems ) {
971- $ this ->fail (new ArrayException ("Not enough items in array " ), $ path );
1001+ $ this ->fail (( new ArrayException ("Not enough items in array " ))-> withData ( $ data ), $ path );
9721002 }
9731003
9741004 if ($ this ->maxItems !== null && $ count > $ this ->maxItems ) {
975- $ this ->fail (new ArrayException ("Too many items in array " ), $ path );
1005+ $ this ->fail (( new ArrayException ("Too many items in array " ))-> withData ( $ data ), $ path );
9761006 }
9771007 }
9781008
@@ -1007,26 +1037,26 @@ private function processArray($data, Context $options, $path, $result)
10071037 $ result [$ key ] = $ additionalItems ->process ($ value , $ options , $ path . '-> ' . $ pathItems
10081038 . '[ ' . $ index . ']: ' . $ index );
10091039 } elseif (!$ options ->skipValidation && $ additionalItems === false ) {
1010- $ this ->fail (new ArrayException ('Unexpected array item ' ), $ path );
1040+ $ this ->fail (( new ArrayException ('Unexpected array item ' ))-> withData ( $ data ), $ path );
10111041 }
10121042 }
10131043 ++$ index ;
10141044 }
10151045
10161046 if (!$ options ->skipValidation && $ this ->uniqueItems ) {
10171047 if (!UniqueItems::isValid ($ data )) {
1018- $ this ->fail (new ArrayException ('Array is not unique ' ), $ path );
1048+ $ this ->fail (( new ArrayException ('Array is not unique ' ))-> withData ( $ data ), $ path );
10191049 }
10201050 }
10211051
10221052 if (!$ options ->skipValidation && $ this ->contains !== null ) {
10231053 /** @var Schema|bool $contains */
10241054 $ contains = $ this ->contains ;
10251055 if ($ contains === false ) {
1026- $ this ->fail (new ArrayException ('Contains is false ' ), $ path );
1056+ $ this ->fail (( new ArrayException ('Contains is false ' ))-> withData ( $ data ), $ path );
10271057 }
10281058 if ($ count === 0 ) {
1029- $ this ->fail (new ArrayException ('Empty array fails contains constraint ' ), $ path );
1059+ $ this ->fail (( new ArrayException ('Empty array fails contains constraint ' ) ), $ path );
10301060 }
10311061 if ($ contains === true ) {
10321062 $ contains = self ::unboolSchema ($ contains );
@@ -1041,7 +1071,8 @@ private function processArray($data, Context $options, $path, $result)
10411071 }
10421072 }
10431073 if (!$ containsOk ) {
1044- $ this ->fail (new ArrayException ('Array fails contains constraint ' ), $ path );
1074+ $ this ->fail ((new ArrayException ('Array fails contains constraint ' ))
1075+ ->withData ($ data ), $ path );
10451076 }
10461077 }
10471078 return $ result ;
0 commit comments