Skip validation when decoding API responses#54
Merged
Conversation
Component::__construct() ran Symfony validation on every construction, including while decoding API responses via decode(). Responses may legitimately omit fields that are only required when creating a pass (e.g. a partial classReference when updating a loyalty object), so decoding threw spurious validation errors. Skip validation during decode() (restored afterwards, so nested decoding is handled). Validation still runs for objects constructed directly to be sent. Fixes chiiya/laravel-passes#40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes chiiya/laravel-passes#40.
Updating (or fetching) a pass decodes the API response back into component objects via
BaseRepository.Component::__construct()runs Symfony validation on every construction — including duringdecode()— so a response that legitimately omits fields only required when creating a pass throws spurious validation errors:The reporter correctly traced it to
BaseRepository::update(), which builds aLoyaltyObjectfrom the response whoseclassReferenceis partial.Root cause
Requiredness/validity is a send-time concern, but it was being enforced at parse-time. We don't control what Google returns, so decoding must be lenient.
Fix
Skip validation while decoding.
Component::decode()toggles a guard that makes__construct()bypass validation, and restores the previous value in afinally(so nested decoding — e.g.classReferenceinside an object — is handled correctly). Validation still runs for objects you construct directly to send, so invalid outgoing data is still caught.This resolves the whole class of "validation failed while decoding a response" bugs, not just the loyalty case.
Scope note
A response can also fail to decode if it omits a field whose property is non-nullable (e.g.
LoyaltyClass::$programLogo), which would throw aTypeErrorrather than a validation error. In practice a realclassReferenceincludes the class's genuinely-required fields, so this isn't hit by #40. Making every decodable required field nullable would touch ~60 fields across ~38 files and is intentionally left out of this PR.Tests
Added
tests/Common/ComponentTest.php:ValidationExceptionLoyaltyObjectwith a nested partialclassReference(the Bump actions/checkout from 4 to 5 #40 path) succeedsFull suite passes (57 tests);
just lintclean.