From 4737b1106fd23ca12f6b0b7ee74bc944d5876102 Mon Sep 17 00:00:00 2001 From: Elisha Witte Date: Wed, 9 Oct 2024 19:34:01 +0200 Subject: [PATCH 1/5] Start replacing spatie dependency --- .gitignore | 1 + phpunit.xml.dist | 40 +- src/Apple/Components/AuxiliaryField.php | 23 +- src/Apple/Components/Barcode.php | 68 +- src/Apple/Components/Beacon.php | 59 +- src/Apple/Components/CurrencyAmount.php | 27 +- src/Apple/Components/Field.php | 179 ++-- src/Apple/Components/Localization.php | 55 +- src/Apple/Components/Location.php | 55 +- src/Apple/Components/Nfc.php | 52 +- src/Apple/Components/PersonName.php | 82 +- src/Apple/Components/Seat.php | 71 +- src/Apple/Components/SecondaryField.php | 21 +- src/Apple/Components/SemanticLocation.php | 33 +- src/Apple/Components/Semantics.php | 890 ++++++++---------- src/Apple/Components/WifiNetwork.php | 33 +- src/Apple/PassFactory.php | 19 +- src/Apple/Passes/BoardingPass.php | 51 +- src/Apple/Passes/Coupon.php | 15 +- src/Apple/Passes/EventTicket.php | 28 +- src/Apple/Passes/GenericPass.php | 15 +- src/Apple/Passes/Pass.php | 473 +++++----- src/Apple/Passes/StoreCard.php | 15 +- src/Apple/Traits/HasFields.php | 42 - src/Apple/Traits/HasGroupingIdentifier.php | 14 - src/Common/ArrayHelper.php | 64 ++ src/Common/Casters/Caster.php | 8 + src/Common/Casters/DateCaster.php | 40 + src/Common/Casters/ISO8601DateCaster.php | 11 +- src/Common/Casters/LegacyValueCaster.php | 34 +- src/Common/Casters/W3CDateCaster.php | 11 +- src/Common/Component.php | 22 +- src/Common/Validation/RgbColor.php | 46 - src/Google/Components/Common/AppLinkData.php | 42 +- src/Google/Components/Common/AppLinkInfo.php | 52 +- src/Google/Components/Common/AppTarget.php | 8 +- src/Google/Components/Common/Barcode.php | 110 +-- .../Components/Common/CallbackOptions.php | 39 +- .../ClassTemplate/BarcodeSectionDetail.php | 16 +- .../CardBarcodeSectionDetails.php | 40 +- .../Common/ClassTemplate/CardRowItem.php | 55 +- .../ClassTemplate/CardRowTemplateInfo.php | 36 +- .../ClassTemplate/CardTemplateOverride.php | 30 +- .../ClassTemplate/ClassTemplateInfo.php | 47 +- .../Common/ClassTemplate/DetailsItemInfo.php | 16 +- .../ClassTemplate/DetailsTemplateOverride.php | 28 +- .../Common/ClassTemplate/FieldReference.php | 55 +- .../Common/ClassTemplate/FieldSelector.php | 32 +- .../Common/ClassTemplate/FirstRowOption.php | 31 +- .../ClassTemplate/ListTemplateOverride.php | 40 +- .../Common/ClassTemplate/TemplateItem.php | 52 +- src/Google/Components/Common/DateTime.php | 22 +- src/Google/Components/Common/GroupingInfo.php | 31 +- src/Google/Components/Common/Image.php | 18 +- .../Components/Common/ImageModuleData.php | 29 +- src/Google/Components/Common/ImageUri.php | 10 +- src/Google/Components/Common/LatLongPoint.php | 35 +- .../Components/Common/LinksModuleData.php | 22 +- .../Components/Common/LocalizedString.php | 45 +- src/Google/Components/Common/Message.php | 88 +- src/Google/Components/Common/Money.php | 30 +- src/Google/Components/Common/Pagination.php | 27 +- src/Google/Components/Common/Review.php | 8 +- .../Components/Common/RotatingBarcode.php | 129 ++- .../Components/Common/SecurityAnimation.php | 22 +- .../Components/Common/TextModuleData.php | 68 +- src/Google/Components/Common/TimeInterval.php | 28 +- src/Google/Components/Common/TotpDetails.php | 56 +- .../Components/Common/TotpParameters.php | 30 +- .../Components/Common/TranslatedString.php | 34 +- src/Google/Components/Common/Uri.php | 59 +- .../Components/EventTicket/EventDateTime.php | 82 +- .../EventTicket/EventReservationInfo.php | 20 +- .../Components/EventTicket/EventSeat.php | 47 +- .../Components/EventTicket/EventVenue.php | 30 +- src/Google/Components/Flight/AirportInfo.php | 57 +- .../Flight/BoardingAndSeatingInfo.php | 107 +-- .../Flight/BoardingAndSeatingPolicy.php | 63 +- .../Components/Flight/FlightCarrier.php | 86 +- src/Google/Components/Flight/FlightHeader.php | 56 +- .../Components/Flight/FrequentFlyerInfo.php | 29 +- .../Components/Flight/ReservationInfo.php | 38 +- .../Generic/AbstractNotificationValue.php | 15 +- .../Components/Generic/Notifications.php | 8 +- .../Loyalty/DiscoverableProgram.php | 58 +- .../DiscoverableProgramMerchantSigninInfo.php | 16 +- .../DiscoverableProgramMerchantSignupInfo.php | 61 +- .../Components/Loyalty/LoyaltyPoints.php | 44 +- .../Loyalty/LoyaltyPointsBalance.php | 47 +- .../Components/Transit/PurchaseDetails.php | 60 +- src/Google/Components/Transit/TicketCost.php | 36 +- src/Google/Components/Transit/TicketLeg.php | 179 ++-- .../Components/Transit/TicketRestrictions.php | 49 +- src/Google/Components/Transit/TicketSeat.php | 74 +- src/Google/Enumerators/BarcodeType.php | 9 +- .../Responses/EventTicketClassesResponse.php | 18 +- .../Responses/EventTicketObjectsResponse.php | 18 +- .../Responses/FlightClassesResponse.php | 18 +- .../Responses/FlightObjectsResponse.php | 18 +- .../Responses/GenericClassesResponse.php | 18 +- .../Responses/GenericObjectsResponse.php | 18 +- .../Responses/GiftCardClassesResponse.php | 18 +- .../Responses/GiftCardObjectsResponse.php | 18 +- src/Google/Responses/HasPagination.php | 10 - .../Responses/LoyaltyClassesResponse.php | 18 +- .../Responses/LoyaltyObjectsResponse.php | 18 +- src/Google/Responses/OfferClassesResponse.php | 18 +- src/Google/Responses/OfferObjectsResponse.php | 18 +- src/Google/Responses/PaginatedResponse.php | 15 + .../Responses/TransitClassesResponse.php | 18 +- .../Responses/TransitObjectsResponse.php | 18 +- tests/Apple/Components/AuxiliaryFieldTest.php | 6 +- tests/Apple/Components/BarcodeTest.php | 6 +- tests/Apple/Components/BeaconTest.php | 6 +- tests/Apple/Components/CurrencyAmountTest.php | 6 +- tests/Apple/Components/FieldTest.php | 6 +- tests/Apple/Components/LocationTest.php | 6 +- tests/Apple/Components/NfcTest.php | 6 +- tests/Apple/Components/PersonNameTest.php | 6 +- tests/Apple/Components/SeatTest.php | 6 +- tests/Apple/Components/SecondaryFieldTest.php | 6 +- .../Apple/Components/SemanticLocationTest.php | 6 +- tests/Apple/Components/SemanticsTest.php | 6 +- tests/Apple/Components/SerializationTest.php | 9 +- tests/Apple/Components/WifiNetworkTest.php | 6 +- tests/Apple/Fixtures/Components.php | 64 +- tests/Apple/PassFactoryTest.php | 112 ++- tests/Apple/Passes/BoardingPassTest.php | 6 +- tests/Apple/Passes/CouponTest.php | 7 +- tests/Apple/Passes/EventTicketTest.php | 6 +- tests/Apple/Passes/GenericTest.php | 7 +- tests/Apple/Passes/ImageTest.php | 3 + tests/Apple/Passes/LocalizationTest.php | 2 + tests/Apple/Passes/PassTest.php | 27 +- tests/Apple/Passes/StoreCardTest.php | 7 +- 135 files changed, 3082 insertions(+), 2911 deletions(-) delete mode 100644 src/Apple/Traits/HasFields.php delete mode 100644 src/Apple/Traits/HasGroupingIdentifier.php create mode 100644 src/Common/ArrayHelper.php create mode 100644 src/Common/Casters/Caster.php create mode 100644 src/Common/Casters/DateCaster.php delete mode 100644 src/Common/Validation/RgbColor.php delete mode 100644 src/Google/Responses/HasPagination.php create mode 100644 src/Google/Responses/PaginatedResponse.php diff --git a/.gitignore b/.gitignore index 419f269..857c025 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ node_modules service-credentials.json .env /tests/certs +.phpunit.cache/ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b6748ee..afa20a0 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,31 +1,13 @@ - - - - tests - - - - - ./src - - + + + + tests + + + + + ./src + + diff --git a/src/Apple/Components/AuxiliaryField.php b/src/Apple/Components/AuxiliaryField.php index cbaac04..119e8eb 100644 --- a/src/Apple/Components/AuxiliaryField.php +++ b/src/Apple/Components/AuxiliaryField.php @@ -2,17 +2,20 @@ namespace Chiiya\Passes\Apple\Components; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\Choice; -#[Strict] class AuxiliaryField extends SecondaryField { - /** - * Optional. - * A number you use to add a row to the auxiliary field in an event ticket pass type. - * Set the value to 1 to add an auxiliary row. Each row displays up to four fields. - */ - #[ValueIn([0, 1])] - public ?int $row; + public function __construct( + /** + * Optional. + * A number you use to add a row to the auxiliary field in an event ticket pass type. + * Set the value to 1 to add an auxiliary row. Each row displays up to four fields. + */ + #[Choice([0, 1])] + public ?int $row = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Apple/Components/Barcode.php b/src/Apple/Components/Barcode.php index 093b5b1..2dc7ec6 100644 --- a/src/Apple/Components/Barcode.php +++ b/src/Apple/Components/Barcode.php @@ -4,41 +4,41 @@ use Chiiya\Passes\Apple\Enumerators\BarcodeFormat; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class Barcode extends Component { - /** - * Optional. - * For example, a human-readable version of the barcode data in case - * the barcode doesn't scan. - */ - public ?string $altText; - - /** - * Required. - * Barcode format. The barcode format PKBarcodeFormatCode128 isn’t supported for watchOS. - * - * @see BarcodeFormat - */ - #[Required] - #[ValueIn([BarcodeFormat::QR, BarcodeFormat::AZTEC, BarcodeFormat::GS1_128, BarcodeFormat::PDF417])] - public ?string $format; - - /** - * Required. - * Message or payload to be displayed as a barcode. - */ - #[Required] - public ?string $message; - - /** - * Required. - * Text encoding that is used to convert the message from the string representation to a data - * representation to render the barcode. - */ - public ?string $messageEncoding = 'iso-8859-1'; + public function __construct( + /** + * Required. + * Barcode format. The barcode format PKBarcodeFormatCode128 isn’t supported for watchOS. + * + * @see BarcodeFormat + */ + #[NotBlank] + #[Choice([BarcodeFormat::QR, BarcodeFormat::AZTEC, BarcodeFormat::GS1_128, BarcodeFormat::PDF417])] + public string $format, + /** + * Required. + * Message or payload to be displayed as a barcode. + */ + #[NotBlank] + public string $message, + /** + * Required. + * Text encoding that is used to convert the message from the string representation to a data + * representation to render the barcode. + */ + #[NotBlank] + public string $messageEncoding = 'iso-8859-1', + /** + * Optional. + * For example, a human-readable version of the barcode data in case + * the barcode doesn't scan. + */ + public ?string $altText = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Beacon.php b/src/Apple/Components/Beacon.php index 15d9e0e..096d640 100644 --- a/src/Apple/Components/Beacon.php +++ b/src/Apple/Components/Beacon.php @@ -3,40 +3,39 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\NumberBetween; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Range; /** * @since iOS v7.0 */ -#[Strict] class Beacon extends Component { - /** - * Optional. - * Major identifier of a Bluetooth Low Energy location beacon. - */ - #[NumberBetween(0, 65535)] - public ?int $major; - - /** - * Optional. - * Minor identifier of a Bluetooth Low Energy location beacon. - */ - #[NumberBetween(0, 65535)] - public ?int $minor; - - /** - * Required. - * Unique identifier of a Bluetooth Low Energy location beacon. - */ - #[Required] - public ?string $proximityUUID; - - /** - * Optional. - * Text displayed on the lock screen when the pass is currently relevant. - */ - public ?string $relevantText; + public function __construct( + /** + * Required. + * Unique identifier of a Bluetooth Low Energy location beacon. + */ + #[NotBlank] + public string $proximityUUID, + /** + * Optional. + * Major identifier of a Bluetooth Low Energy location beacon. + */ + #[Range(min: 0, max: 65535)] + public ?int $major = null, + /** + * Optional. + * Minor identifier of a Bluetooth Low Energy location beacon. + */ + #[Range(min: 0, max: 65535)] + public ?int $minor = null, + /** + * Optional. + * Text displayed on the lock screen when the pass is currently relevant. + */ + public ?string $relevantText = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/CurrencyAmount.php b/src/Apple/Components/CurrencyAmount.php index 31f10da..15e375b 100644 --- a/src/Apple/Components/CurrencyAmount.php +++ b/src/Apple/Components/CurrencyAmount.php @@ -3,20 +3,21 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Spatie\DataTransferObject\Attributes\Strict; -#[Strict] class CurrencyAmount extends Component { - /** - * Optional. - * The amount of money. - */ - public ?string $amount; - - /** - * Optional. - * The currency code for amount. - */ - public ?string $currencyCode; + public function __construct( + /** + * Optional. + * The amount of money. + */ + public ?string $amount = null, + /** + * Optional. + * The currency code for amount. + */ + public ?string $currencyCode = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Field.php b/src/Apple/Components/Field.php index 5cd5991..2059343 100644 --- a/src/Apple/Components/Field.php +++ b/src/Apple/Components/Field.php @@ -6,97 +6,96 @@ use Chiiya\Passes\Apple\Enumerators\DateStyle; use Chiiya\Passes\Apple\Enumerators\NumberStyle; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Contains; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Regex; -#[Strict] class Field extends Component { - /** - * Optional. - * Attributed value of the field. - * The value may contain HTML markup for links. Only the tag and its href attribute are supported. - * This key's value overrides the text specified by the value key. - */ - public ?string $attributedValue; - - /** - * Optional. - * Format string for the alert text that is displayed when the pass is updated. - * The format string must contain the escape %@, which is replaced with the field’s new value. - * For example, “Gate changed to %@.”. - */ - #[Contains('%@')] - public ?string $changeMessage; - - /** - * Optional. - * Data detectors that are applied to the field’s value. All detectors are applied by default. - * Provide an empty array to use no data detectors. - */ - #[ValueIn([DataDetector::PHONE_NUMBER, DataDetector::LINK, DataDetector::ADDRESS, DataDetector::CALENDAR_EVENT])] - public ?array $dataDetectorTypes; - - /** - * Required. - * The key must be unique within the scope of the entire pass. - */ - #[Required] - public ?string $key; - - /** - * Optional. - * Label text for the field. - */ - public ?string $label; - - /** - * Required. - * Value of the field. - */ - #[Required] - public null|float|int|string $value; - - /** - * Optional. - * Style of date to display. MUST be used in conjunction with $timeStyle. - */ - #[ValueIn([DateStyle::NONE, DateStyle::SHORT, DateStyle::MEDIUM, DateStyle::LONG, DateStyle::FULL])] - public ?string $dateStyle; - - /** - * Optional. - * Always display the time and date in the given time zone, not in the user’s current time zone. - * Defaults to false. - */ - public ?bool $ignoresTimeZone; - - /** - * Optional. - * If true, the label's value is displayed as a relative date; otherwise, it is displayed as an absolute date. - * Defaults to false. - */ - public ?bool $isRelative; - - /** - * Optional. - * Style of time to display. MUST be used in conjunction with $dateStyle. - */ - #[ValueIn([DateStyle::NONE, DateStyle::SHORT, DateStyle::MEDIUM, DateStyle::LONG, DateStyle::FULL])] - public ?string $timeStyle; - - /** - * Optional. - * ISO 4217 currency code for the field’s value. - */ - public ?string $currencyCode; - - /** - * Optional. - * Style of number to display. Only allowed for numeric field values. - */ - #[ValueIn([NumberStyle::DECIMAL, NumberStyle::PERCENT, NumberStyle::SCIENTIFIC, NumberStyle::SPELL_OUT])] - public ?string $numberStyle; + public function __construct( + /** + * Required. + * The key must be unique within the scope of the entire pass. + */ + #[NotBlank] + public string $key, + /** + * Required. + * Value of the field. + */ + #[NotBlank] + public float|int|string $value, + /** + * Optional. + * Label text for the field. + */ + public ?string $label = null, + /** + * Optional. + * Attributed value of the field. + * The value may contain HTML markup for links. Only the tag and its href attribute are supported. + * This key's value overrides the text specified by the value key. + */ + public ?string $attributedValue = null, + /** + * Optional. + * Format string for the alert text that is displayed when the pass is updated. + * The format string must contain the escape %@, which is replaced with the field’s new value. + * For example, “Gate changed to %@.”. + */ + #[Regex('/%@/')] + public ?string $changeMessage = null, + /** + * Optional. + * Data detectors that are applied to the field’s value. All detectors are applied by default. + * Provide an empty array to use no data detectors. + */ + #[All([ + new Choice([ + DataDetector::PHONE_NUMBER, + DataDetector::LINK, + DataDetector::ADDRESS, + DataDetector::CALENDAR_EVENT, + ]), + ])] + public ?array $dataDetectorTypes = null, + /** + * Optional. + * Style of date to display. MUST be used in conjunction with $timeStyle. + */ + #[Choice([DateStyle::NONE, DateStyle::SHORT, DateStyle::MEDIUM, DateStyle::LONG, DateStyle::FULL])] + public ?string $dateStyle = null, + /** + * Optional. + * Always display the time and date in the given time zone, not in the user’s current time zone. + * Defaults to false. + */ + public ?bool $ignoresTimeZone = null, + /** + * Optional. + * If true, the label's value is displayed as a relative date; otherwise, it is displayed as an absolute date. + * Defaults to false. + */ + public ?bool $isRelative = null, + /** + * Optional. + * Style of time to display. MUST be used in conjunction with $dateStyle. + */ + #[Choice([DateStyle::NONE, DateStyle::SHORT, DateStyle::MEDIUM, DateStyle::LONG, DateStyle::FULL])] + public ?string $timeStyle = null, + /** + * Optional. + * ISO 4217 currency code for the field’s value. + */ + public ?string $currencyCode = null, + /** + * Optional. + * Style of number to display. Only allowed for numeric field values. + */ + #[Choice([NumberStyle::DECIMAL, NumberStyle::PERCENT, NumberStyle::SCIENTIFIC, NumberStyle::SPELL_OUT])] + public ?string $numberStyle = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Localization.php b/src/Apple/Components/Localization.php index 55714a6..34ef625 100644 --- a/src/Apple/Components/Localization.php +++ b/src/Apple/Components/Localization.php @@ -2,35 +2,38 @@ namespace Chiiya\Passes\Apple\Components; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Attributes\Strict; -use Spatie\DataTransferObject\Casters\ArrayCaster; -use Spatie\DataTransferObject\DataTransferObject; +use Chiiya\Passes\Common\Component; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Type; -#[Strict] -class Localization extends DataTransferObject +class Localization extends Component { - /** Localization language key (`en`, `es`, ...). */ - #[Required] - public ?string $language; - - /** - * Array of string translations. - * - * @var string[] - */ - public array $strings = []; - - /** - * Array of localized images. - * - * @var Image[] - */ - #[CastWith(ArrayCaster::class, Image::class)] - public array $images = []; + public function __construct( + /** + * Required. + * Localization language key (`en`, `es`, ...). + */ + #[NotBlank] + public string $language, + /** + * Array of string translations. + * + * @var string[] + */ + public array $strings = [], + /** + * Array of localized images. + * + * @var Image[] + */ + #[All([new Type(Image::class)])] + public array $images = [], + ) { + parent::__construct(); + } - public function addString(string $key, string $value): self + public function addString(string $key, string $value): static { $this->strings[$key] = $value; diff --git a/src/Apple/Components/Location.php b/src/Apple/Components/Location.php index c52b847..db42fcb 100644 --- a/src/Apple/Components/Location.php +++ b/src/Apple/Components/Location.php @@ -3,35 +3,34 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class Location extends Component { - /** - * Optional. - * Altitude, in meters, of the location. - */ - public ?float $altitude; - - /** - * Required. - * Latitude, in degrees, of the location. - */ - #[Required] - public ?float $latitude; - - /** - * Required. - * Longitude, in degrees, of the location. - */ - #[Required] - public ?float $longitude; - - /** - * Optional. - * ext displayed on the lock screen when the pass is currently relevant. - */ - public ?string $relevantText; + public function __construct( + /** + * Required. + * Latitude, in degrees, of the location. + */ + #[NotBlank] + public float $latitude, + /** + * Required. + * Longitude, in degrees, of the location. + */ + #[NotBlank] + public float $longitude, + /** + * Optional. + * Altitude, in meters, of the location. + */ + public ?float $altitude = null, + /** + * Optional. + * ext displayed on the lock screen when the pass is currently relevant. + */ + public ?string $relevantText = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Nfc.php b/src/Apple/Components/Nfc.php index 88122cd..ad9d205 100644 --- a/src/Apple/Components/Nfc.php +++ b/src/Apple/Components/Nfc.php @@ -3,33 +3,33 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class Nfc extends Component { - /** - * Required. - * The payload to be transmitted to the Apple Pay terminal. Must be 64 bytes or less. Messages longer - * than 64 bytes are truncated by the system. - */ - #[Required] - public ?string $message; - - /** - * Optional. - * The public encryption key used by the Value Added Services protocol. Use a Base64 encoded X.509 - * SubjectPublicKeyInfo structure containing a ECDH public key for group P256. - */ - public ?string $encryptionPublicKey; - - /** - * Optional. - * A Boolean value that indicates whether the NFC pass requires authentication. The default value is false. - * A value of true requires the user to authenticate for each use of the NFC pass. - * - * @since iOS v13.1 - */ - public ?bool $requiresAuthentication; + public function __construct( + /** + * Required. + * The payload to be transmitted to the Apple Pay terminal. Must be 64 bytes or less. Messages longer + * than 64 bytes are truncated by the system. + */ + #[NotBlank] + public string $message, + /** + * Optional. + * The public encryption key used by the Value Added Services protocol. Use a Base64 encoded X.509 + * SubjectPublicKeyInfo structure containing a ECDH public key for group P256. + */ + public ?string $encryptionPublicKey = null, + /** + * Optional. + * A Boolean value that indicates whether the NFC pass requires authentication. The default value is false. + * A value of true requires the user to authenticate for each use of the NFC pass. + * + * @since iOS v13.1 + */ + public ?bool $requiresAuthentication = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/PersonName.php b/src/Apple/Components/PersonName.php index 5cd4d6f..7c8d331 100644 --- a/src/Apple/Components/PersonName.php +++ b/src/Apple/Components/PersonName.php @@ -3,50 +3,46 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Spatie\DataTransferObject\Attributes\Strict; -#[Strict] class PersonName extends Component { - /** - * Optional. - * The person’s family name or last name. - */ - public ?string $familyName; - - /** - * Optional. - * The person’s given name; also called the forename or first name in some countries. - */ - public ?string $givenName; - - /** - * Optional. - * The person’s middle name. - */ - public ?string $middleName; - - /** - * Optional. - * The prefix for the person’s name, such as “Dr”. - */ - public ?string $namePrefix; - - /** - * Optional. - * The suffix for the person’s name, such as “Junior”. - */ - public ?string $nameSuffix; - - /** - * Optional. - * The person’s nickname. - */ - public ?string $nickname; - - /** - * Optional. - * The phonetic representation of the person’s name. - */ - public ?string $phoneticRepresentation; + public function __construct( + /** + * Optional. + * The person’s family name or last name. + */ + public ?string $familyName = null, + /** + * Optional. + * The person’s given name; also called the forename or first name in some countries. + */ + public ?string $givenName = null, + /** + * Optional. + * The person’s middle name. + */ + public ?string $middleName = null, + /** + * Optional. + * The prefix for the person’s name, such as “Dr”. + */ + public ?string $namePrefix = null, + /** + * Optional. + * The suffix for the person’s name, such as “Junior”. + */ + public ?string $nameSuffix = null, + /** + * Optional. + * The person’s nickname. + */ + public ?string $nickname = null, + /** + * Optional. + * The phonetic representation of the person’s name. + */ + public ?string $phoneticRepresentation = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Seat.php b/src/Apple/Components/Seat.php index 24a6f3f..35328a2 100644 --- a/src/Apple/Components/Seat.php +++ b/src/Apple/Components/Seat.php @@ -3,44 +3,41 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Spatie\DataTransferObject\Attributes\Strict; -#[Strict] class Seat extends Component { - /** - * Optional. - * A description of the seat, such as “A flat bed seat”. - */ - public ?string $seatDescription; - - /** - * Optional. - * The identifier code for the seat. - */ - public ?string $seatIdentifier; - - /** - * Optional. - * The number of the seat. - */ - public ?string $seatNumber; - - /** - * Optional. - * The row that contains the seat. - */ - public ?string $seatRow; - - /** - * Optional. - * The section that contains the seat. - */ - public ?string $seatSection; - - /** - * Optional. - * The type of seat, such as “Reserved seating”. - */ - public ?string $seatType; + public function __construct( + /** + * Optional. + * A description of the seat, such as “A flat bed seat”. + */ + public ?string $seatDescription = null, + /** + * Optional. + * The identifier code for the seat. + */ + public ?string $seatIdentifier = null, + /** + * Optional. + * The number of the seat. + */ + public ?string $seatNumber = null, + /** + * Optional. + * The row that contains the seat. + */ + public ?string $seatRow = null, + /** + * Optional. + * The section that contains the seat. + */ + public ?string $seatSection = null, + /** + * Optional. + * The type of seat, such as “Reserved seating”. + */ + public ?string $seatType = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/SecondaryField.php b/src/Apple/Components/SecondaryField.php index 53f3139..e728b1e 100644 --- a/src/Apple/Components/SecondaryField.php +++ b/src/Apple/Components/SecondaryField.php @@ -3,16 +3,19 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Apple\Enumerators\TextAlignment; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\Choice; -#[Strict] class SecondaryField extends Field { - /** - * Optional. - * Alignment for the field’s contents. Defaults to NATURAL. - */ - #[ValueIn([TextAlignment::LEFT, TextAlignment::CENTER, TextAlignment::RIGHT, TextAlignment::NATURAL])] - public ?string $textAlignment; + public function __construct( + /** + * Optional. + * Alignment for the field’s contents. Defaults to NATURAL. + */ + #[Choice([TextAlignment::LEFT, TextAlignment::CENTER, TextAlignment::RIGHT, TextAlignment::NATURAL])] + public ?string $textAlignment = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Apple/Components/SemanticLocation.php b/src/Apple/Components/SemanticLocation.php index 1b8fd1e..dae2e27 100644 --- a/src/Apple/Components/SemanticLocation.php +++ b/src/Apple/Components/SemanticLocation.php @@ -3,23 +3,24 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class SemanticLocation extends Component { - /** - * Required. - * Latitude, in degrees, of the location. - */ - #[Required] - public ?float $latitude; - - /** - * Required. - * Longitude, in degrees, of the location. - */ - #[Required] - public ?float $longitude; + public function __construct( + /** + * Required. + * Latitude, in degrees, of the location. + */ + #[NotBlank] + public float $latitude, + /** + * Required. + * Longitude, in degrees, of the location. + */ + #[NotBlank] + public float $longitude, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/Semantics.php b/src/Apple/Components/Semantics.php index 30ff9bc..ddc79b9 100644 --- a/src/Apple/Components/Semantics.php +++ b/src/Apple/Components/Semantics.php @@ -2,486 +2,424 @@ namespace Chiiya\Passes\Apple\Components; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Apple\Enumerators\EventType; use Chiiya\Passes\Common\Casters\ISO8601DateCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Attributes\Strict; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use DateTimeInterface; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\Type; -#[Strict] class Semantics extends Component { - /** - * Optional. - * The IATA airline code, such as “EX” for flightCode “EX123”. Use this key only for airline boarding passes. - */ - public ?string $airlineCode; - - /** - * Optional. - * An array of the Apple Music persistent ID for each artist performing at the event, in decreasing order of significance. - * Use this key for any type of event ticket. - * - * @var null|string[] - */ - public ?array $artistIDs; - - /** - * Optional. - * The unique abbreviation of the away team’s name. Use this key only for a sports event ticket. - */ - public ?string $awayTeamAbbreviation; - - /** - * Optional. - * The home location of the away team. Use this key only for a sports event ticket. - */ - public ?string $awayTeamLocation; - - /** - * Optional. - * The name of the away team. Use this key only for a sports event ticket. - */ - public ?string $awayTeamName; - - /** - * Optional. - * The current balance redeemable with the pass. Use this key only for a store card pass. - */ - public ?CurrencyAmount $balance; - - /** - * Optional. - * A group number for boarding. Use this key for any type of boarding pass. - */ - public ?string $boardingGroup; - - /** - * Optional. - * A sequence number for boarding. Use this key for any type of boarding pass. - */ - public ?string $boardingSequenceNumber; - - /** - * Optional. - * The number of the passenger car. A train car is also called a carriage, - * wagon, coach, or bogie in some countries. Use this key only for a train or other - * rail boarding pass. - */ - public ?string $carNumber; - - /** - * Optional. - * A booking or reservation confirmation number. Use this key for any type of boarding pass. - */ - public ?string $confirmationNumber; - - /** - * Optional. - * The updated date and time of arrival, if different from the originally scheduled date - * and time. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $currentArrivalDate; - - /** - * Optional. - * The updated date and time of boarding, if different from the originally scheduled date - * and time. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $currentBoardingDate; - - /** - * Optional. - * The updated departure date and time, if different from the originally - * scheduled date and time. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $currentDepartureDate; - - /** - * Optional. - * The IATA airport code for the departure airport, such as “MPM” or “LHR”. Use - * this key only for airline boarding passes. - */ - public ?string $departureAirportCode; - - /** - * Optional. - * The full name of the departure airport, such as “Maputo International Airport”. Use - * this key only for airline boarding passes. - */ - public ?string $departureAirportName; - - /** - * Optional. - * The gate number or letters of the departure gate, such as “1A”. Do not include the word “Gate.”. - */ - public ?string $departureGate; - - /** - * Optional. - * An object that represents the geographic coordinates of the transit departure location, - * suitable for display on a map. If possible, use precise locations, which are more useful - * to travelers; for example, the specific location of an airport gate. Use this key for any - * type of boarding pass. - */ - public ?SemanticLocation $departureLocation; - - /** - * Optional. - * A brief description of the departure location. For example, for a flight departing from - * an airport whose code is “LHR,” an appropriate description might be “London, Heathrow“. Use - * this key for any type of boarding pass. - */ - public ?string $departureLocationDescription; - - /** - * Optional. - * The name of the departure platform, such as “A”. Don’t include the word “Platform.” Use - * this key only for a train or other rail boarding pass. - */ - public ?string $departurePlatform; - - /** - * Optional. - * The name of the departure station, such as “1st Street Station”. Use this key only for - * a train or other rail boarding pass. - */ - public ?string $departureStationName; - - /** - * Optional. - * The name or letter of the departure terminal, such as “A”. Don’t include the word - * “Terminal.” Use this key only for airline boarding passes. - */ - public ?string $departureTerminal; - - /** - * Optional. - * The IATA airport code for the destination airport, such as “MPM” or “LHR”. Use this - * key only for airline boarding passes. - */ - public ?string $destinationAirportCode; - - /** - * Optional. - * The full name of the destination airport, such as “London Heathrow”. Use this key - * only for airline boarding passes. - */ - public ?string $destinationAirportName; - - /** - * Optional. - * The gate number or letter of the destination gate, such as “1A”. Don’t include the - * word “Gate.” Use this key only for airline boarding passes. - */ - public ?string $destinationGate; - - /** - * Optional. - * An object that represents the geographic coordinates of the transit departure location, - * suitable for display on a map. Use this key for any type of boarding pass. - */ - public ?SemanticLocation $destinationLocation; - - /** - * Optional. - * A brief description of the destination location. For example, for a flight arriving at an - * airport whose code is “MPM,” “Maputo“ might be an appropriate description. Use this - * key for any type of boarding pass. - */ - public ?string $destinationLocationDescription; - - /** - * Optional. - * The name of the destination platform, such as “A”. Don’t include the word “Platform.” - * Use this key only for a train or other rail boarding pass. - */ - public ?string $destinationPlatform; - - /** - * Optional. - * The name of the destination station, such as “1st Street Station”. Use this key only - * for a train or other rail boarding pass. - */ - public ?string $destinationStationName; - - /** - * Optional. - * The terminal name or letter of the destination terminal, such as “A”. Don’t include - * the word “Terminal.” Use this key only for airline boarding passes. - */ - public ?string $destinationTerminal; - - /** - * Optional. - * The duration of the event or transit journey, in seconds. Use this key for any - * type of boarding pass and any type of event ticket. - */ - public ?int $duration; - - /** - * Optional. - * The date and time the event ends. Use this key for any type of event ticket. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $eventEndDate; - - /** - * Optional. - * The full name of the event, such as the title of a movie. Use this key for any - * type of event ticket. - */ - public ?string $eventName; - - /** - * Optional. - * The date and time the event starts. Use this key for any type of event ticket. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $eventStartDate; - - /** - * Optional. - * The type of event. Use this key for any type of event ticket. - */ - #[ValueIn([ - EventType::GENERIC, - EventType::LIVE_PERFORMANCE, - EventType::MOVIE, - EventType::SPORTS, - EventType::CONFERENCE, - EventType::CONVENTION, - EventType::WORKSHOP, - EventType::SOCIAL_GATHERING, - ])] - public ?string $eventType; - - /** - * Optional. - * The IATA flight code, such as “EX123”. Use this key only for airline boarding passes. - */ - public ?string $flightCode; - - /** - * Optional. - * The numeric portion of the IATA flight code, such as 123 for flightCode “EX123”. - * Use this key only for airline boarding passes. - */ - public ?int $flightNumber; - - /** - * Optional. - * The genre of the performance, such as “Classical”. Use this key for any type of event ticket. - */ - public ?string $genre; - - /** - * Optional. - * The unique abbreviation of the home team’s name. Use this key only for a sports event ticket. - */ - public ?string $homeTeamAbbreviation; - - /** - * Optional. - * The home location of the home team. Use this key only for a sports event ticket. - */ - public ?string $homeTeamLocation; - - /** - * Optional. - * The name of the home team. Use this key only for a sports event ticket. - */ - public ?string $homeTeamName; - - /** - * Optional. - * The abbreviated league name for a sports event. Use this key only for a sports event ticket. - */ - public ?string $leagueAbbreviation; - - /** - * Optional. - * The unabbreviated league name for a sports event. Use this key only for a sports event ticket. - */ - public ?string $leagueName; - - /** - * Optional. - * The name of a frequent flyer or loyalty program. Use this key for any type of boarding pass. - */ - public ?string $membershipProgramName; - - /** - * Optional. - * The ticketed passenger’s frequent flyer or loyalty number. Use this key for any type of boarding pass. - */ - public ?string $membershipProgramNumber; - - /** - * Optional. - * The originally scheduled date and time of arrival. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $originalArrivalDate; - - /** - * Optional. - * The originally scheduled date and time of boarding. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $originalBoardingDate; - - /** - * Optional. - * The originally scheduled date and time of departure. Use this key for any type of boarding pass. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $originalDepartureDate; - - /** - * Optional. - * An object that represents the name of the passenger. Use this key for any type of boarding pass. - */ - public ?PersonName $passengerName; - - /** - * Optional. - * An array of the full names of the performers and opening acts at the event, in decreasing - * order of significance. Use this key for any type of event ticket. - * - * @var null|string[] - */ - public ?array $performerNames; - - /** - * Optional. - * The priority status the ticketed passenger holds, such as “Gold” or “Silver”. Use this - * key for any type of boarding pass. - */ - public ?string $priorityStatus; - - /** - * Optional. - * An array of objects that represent the details for each seat at an event or on a transit - * journey. Use this key for any type of boarding pass or event ticket. - * - * @var null|Seat[] - */ - #[CastWith(ArrayCaster::class, Seat::class)] - public ?array $seats; - - /** - * Optional. - * The type of security screening for the ticketed passenger, such as “Priority”. Use this - * key for any type of boarding pass. - */ - public ?string $securityScreening; - - /** - * Optional. - * A Boolean value that determines whether the user’s device remains silent during an event - * or transit journey. The system may override the key and determine the length of the period - * of silence. Use this key for any type of boarding pass or event ticket. - */ - public ?bool $silenceRequested; - - /** - * Optional. - * The commonly used name of the sport. Use this key only for a sports event ticket. - */ - public ?string $sportName; - - /** - * Optional. - * The total price for the pass. Use this key for any pass type. - */ - public ?CurrencyAmount $totalPrice; - - /** - * Optional. - * The name of the transit company. Use this key for any type of boarding pass. - */ - public ?string $transitProvider; - - /** - * Optional. - * A brief description of the current boarding status for the vessel, such as - * “On Time” or “Delayed”. For delayed status, provide currentBoardingDate, - * currentDepartureDate, and currentArrivalDate where available. Use this key for - * any type of boarding pass. - */ - public ?string $transitStatus; - - /** - * Optional. - * A brief description that explains the reason for the current transitStatus, - * such as “Thunderstorms”. Use this key for any type of boarding pass. - */ - public ?string $transitStatusReason; - - /** - * Optional. - * The name of the vehicle to board, such as the name of a boat. Use this key for any type of boarding pass. - */ - public ?string $vehicleName; - - /** - * Optional. - * The identifier of the vehicle to board, such as the aircraft registration number or train number. - * Use this key for any type of boarding pass. - */ - public ?string $vehicleNumber; - - /** - * Optional. - * A brief description of the type of vehicle to board, such as the model and manufacturer of a - * plane or the class of a boat. Use this key for any type of boarding pass. - */ - public ?string $vehicleType; - - /** - * Optional. - * The full name of the entrance, such as “Gate A”, to use to gain access to the ticketed event. - * Use this key for any type of event ticket. - */ - public ?string $venueEntrance; - - /** - * Optional. - * An object that represents the geographic coordinates of the venue. Use this key for any type of event ticket. - */ - public ?SemanticLocation $venueLocation; - - /** - * Optional. - * The full name of the venue. Use this key for any type of event ticket. - */ - public ?string $venueName; - - /** - * Optional. - * The phone number for enquiries about the venue’s ticketed event. Use this key for any type of event ticket. - */ - public ?string $venuePhoneNumber; - - /** - * Optional. - * The full name of the room where the ticketed event is to take place. Use this key for any type of event ticket. - */ - public ?string $venueRoom; - - /** - * Optional. - * An array of objects that represent the WiFi networks associated with the event; for example, the network - * name and password associated with a developer conference. Use this key for any type of pass. - * - * @var null|WifiNetwork[] - */ - #[CastWith(ArrayCaster::class, WifiNetwork::class)] - public ?array $wifiAccess; + public function __construct( + /** + * Optional. + * The IATA airline code, such as “EX” for flightCode “EX123”. Use this key only for airline boarding passes. + */ + public ?string $airlineCode = null, + /** + * Optional. + * An array of the Apple Music persistent ID for each artist performing at the event, in decreasing order of significance. + * Use this key for any type of event ticket. + * + * @var null|string[] + */ + public ?array $artistIDs = null, + /** + * Optional. + * The unique abbreviation of the away team’s name. Use this key only for a sports event ticket. + */ + public ?string $awayTeamAbbreviation = null, + /** + * Optional. + * The home location of the away team. Use this key only for a sports event ticket. + */ + public ?string $awayTeamLocation = null, + /** + * Optional. + * The name of the away team. Use this key only for a sports event ticket. + */ + public ?string $awayTeamName = null, + /** + * Optional. + * The current balance redeemable with the pass. Use this key only for a store card pass. + */ + public ?CurrencyAmount $balance = null, + /** + * Optional. + * A group number for boarding. Use this key for any type of boarding pass. + */ + public ?string $boardingGroup = null, + /** + * Optional. + * A sequence number for boarding. Use this key for any type of boarding pass. + */ + public ?string $boardingSequenceNumber = null, + /** + * Optional. + * The number of the passenger car. A train car is also called a carriage, + * wagon, coach, or bogie in some countries. Use this key only for a train or other + * rail boarding pass. + */ + public ?string $carNumber = null, + /** + * Optional. + * A booking or reservation confirmation number. Use this key for any type of boarding pass. + */ + public ?string $confirmationNumber = null, + /** + * Optional. + * The IATA airport code for the departure airport, such as “MPM” or “LHR”. Use + * this key only for airline boarding passes. + */ + public ?string $departureAirportCode = null, + /** + * Optional. + * The full name of the departure airport, such as “Maputo International Airport”. Use + * this key only for airline boarding passes. + */ + public ?string $departureAirportName = null, + /** + * Optional. + * The gate number or letters of the departure gate, such as “1A”. Do not include the word “Gate.”. + */ + public ?string $departureGate = null, + /** + * Optional. + * An object that represents the geographic coordinates of the transit departure location, + * suitable for display on a map. If possible, use precise locations, which are more useful + * to travelers; for example, the specific location of an airport gate. Use this key for any + * type of boarding pass. + */ + public ?SemanticLocation $departureLocation = null, + /** + * Optional. + * A brief description of the departure location. For example, for a flight departing from + * an airport whose code is “LHR,” an appropriate description might be “London, Heathrow“. Use + * this key for any type of boarding pass. + */ + public ?string $departureLocationDescription = null, + /** + * Optional. + * The name of the departure platform, such as “A”. Don’t include the word “Platform.” Use + * this key only for a train or other rail boarding pass. + */ + public ?string $departurePlatform = null, + /** + * Optional. + * The name of the departure station, such as “1st Street Station”. Use this key only for + * a train or other rail boarding pass. + */ + public ?string $departureStationName = null, + /** + * Optional. + * The name or letter of the departure terminal, such as “A”. Don’t include the word + * “Terminal.” Use this key only for airline boarding passes. + */ + public ?string $departureTerminal = null, + /** + * Optional. + * The IATA airport code for the destination airport, such as “MPM” or “LHR”. Use this + * key only for airline boarding passes. + */ + public ?string $destinationAirportCode = null, + /** + * Optional. + * The full name of the destination airport, such as “London Heathrow”. Use this key + * only for airline boarding passes. + */ + public ?string $destinationAirportName = null, + /** + * Optional. + * The gate number or letter of the destination gate, such as “1A”. Don’t include the + * word “Gate.” Use this key only for airline boarding passes. + */ + public ?string $destinationGate = null, + /** + * Optional. + * An object that represents the geographic coordinates of the transit departure location, + * suitable for display on a map. Use this key for any type of boarding pass. + */ + public ?SemanticLocation $destinationLocation = null, + /** + * Optional. + * A brief description of the destination location. For example, for a flight arriving at an + * airport whose code is “MPM,” “Maputo“ might be an appropriate description. Use this + * key for any type of boarding pass. + */ + public ?string $destinationLocationDescription = null, + /** + * Optional. + * The name of the destination platform, such as “A”. Don’t include the word “Platform.” + * Use this key only for a train or other rail boarding pass. + */ + public ?string $destinationPlatform = null, + /** + * Optional. + * The name of the destination station, such as “1st Street Station”. Use this key only + * for a train or other rail boarding pass. + */ + public ?string $destinationStationName = null, + /** + * Optional. + * The terminal name or letter of the destination terminal, such as “A”. Don’t include + * the word “Terminal.” Use this key only for airline boarding passes. + */ + public ?string $destinationTerminal = null, + /** + * Optional. + * The duration of the event or transit journey, in seconds. Use this key for any + * type of boarding pass and any type of event ticket. + */ + public ?int $duration = null, + /** + * Optional. + * The full name of the event, such as the title of a movie. Use this key for any + * type of event ticket. + */ + public ?string $eventName = null, + /** + * Optional. + * The type of event. Use this key for any type of event ticket. + */ + #[Choice([ + EventType::GENERIC, + EventType::LIVE_PERFORMANCE, + EventType::MOVIE, + EventType::SPORTS, + EventType::CONFERENCE, + EventType::CONVENTION, + EventType::WORKSHOP, + EventType::SOCIAL_GATHERING, + ])] + public ?string $eventType = null, + /** + * Optional. + * The IATA flight code, such as “EX123”. Use this key only for airline boarding passes. + */ + public ?string $flightCode = null, + /** + * Optional. + * The numeric portion of the IATA flight code, such as 123 for flightCode “EX123”. + * Use this key only for airline boarding passes. + */ + public ?int $flightNumber = null, + /** + * Optional. + * The genre of the performance, such as “Classical”. Use this key for any type of event ticket. + */ + public ?string $genre = null, + /** + * Optional. + * The unique abbreviation of the home team’s name. Use this key only for a sports event ticket. + */ + public ?string $homeTeamAbbreviation = null, + /** + * Optional. + * The home location of the home team. Use this key only for a sports event ticket. + */ + public ?string $homeTeamLocation = null, + /** + * Optional. + * The name of the home team. Use this key only for a sports event ticket. + */ + public ?string $homeTeamName = null, + /** + * Optional. + * The abbreviated league name for a sports event. Use this key only for a sports event ticket. + */ + public ?string $leagueAbbreviation = null, + /** + * Optional. + * The unabbreviated league name for a sports event. Use this key only for a sports event ticket. + */ + public ?string $leagueName = null, + /** + * Optional. + * The name of a frequent flyer or loyalty program. Use this key for any type of boarding pass. + */ + public ?string $membershipProgramName = null, + /** + * Optional. + * The ticketed passenger’s frequent flyer or loyalty number. Use this key for any type of boarding pass. + */ + public ?string $membershipProgramNumber = null, + /** + * Optional. + * An object that represents the name of the passenger. Use this key for any type of boarding pass. + */ + public ?PersonName $passengerName = null, + /** + * Optional. + * An array of the full names of the performers and opening acts at the event, in decreasing + * order of significance. Use this key for any type of event ticket. + * + * @var null|string[] + */ + public ?array $performerNames = null, + /** + * Optional. + * The priority status the ticketed passenger holds, such as “Gold” or “Silver”. Use this + * key for any type of boarding pass. + */ + public ?string $priorityStatus = null, + /** + * Optional. + * An array of objects that represent the details for each seat at an event or on a transit + * journey. Use this key for any type of boarding pass or event ticket. + * + * @var null|Seat[] + */ + #[All([new Type(Seat::class)])] + public ?array $seats = null, + /** + * Optional. + * The type of security screening for the ticketed passenger, such as “Priority”. Use this + * key for any type of boarding pass. + */ + public ?string $securityScreening = null, + /** + * Optional. + * A Boolean value that determines whether the user’s device remains silent during an event + * or transit journey. The system may override the key and determine the length of the period + * of silence. Use this key for any type of boarding pass or event ticket. + */ + public ?bool $silenceRequested = null, + /** + * Optional. + * The commonly used name of the sport. Use this key only for a sports event ticket. + */ + public ?string $sportName = null, + /** + * Optional. + * The total price for the pass. Use this key for any pass type. + */ + public ?CurrencyAmount $totalPrice = null, + /** + * Optional. + * The name of the transit company. Use this key for any type of boarding pass. + */ + public ?string $transitProvider = null, + /** + * Optional. + * A brief description of the current boarding status for the vessel, such as + * “On Time” or “Delayed”. For delayed status, provide currentBoardingDate, + * currentDepartureDate, and currentArrivalDate where available. Use this key for + * any type of boarding pass. + */ + public ?string $transitStatus = null, + /** + * Optional. + * A brief description that explains the reason for the current transitStatus, + * such as “Thunderstorms”. Use this key for any type of boarding pass. + */ + public ?string $transitStatusReason = null, + /** + * Optional. + * The name of the vehicle to board, such as the name of a boat. Use this key for any type of boarding pass. + */ + public ?string $vehicleName = null, + /** + * Optional. + * The identifier of the vehicle to board, such as the aircraft registration number or train number. + * Use this key for any type of boarding pass. + */ + public ?string $vehicleNumber = null, + /** + * Optional. + * A brief description of the type of vehicle to board, such as the model and manufacturer of a + * plane or the class of a boat. Use this key for any type of boarding pass. + */ + public ?string $vehicleType = null, + /** + * Optional. + * The full name of the entrance, such as “Gate A”, to use to gain access to the ticketed event. + * Use this key for any type of event ticket. + */ + public ?string $venueEntrance = null, + /** + * Optional. + * An object that represents the geographic coordinates of the venue. Use this key for any type of event ticket. + */ + public ?SemanticLocation $venueLocation = null, + /** + * Optional. + * The full name of the venue. Use this key for any type of event ticket. + */ + public ?string $venueName = null, + /** + * Optional. + * The phone number for enquiries about the venue’s ticketed event. Use this key for any type of event ticket. + */ + public ?string $venuePhoneNumber = null, + /** + * Optional. + * The full name of the room where the ticketed event is to take place. Use this key for any type of event ticket. + */ + public ?string $venueRoom = null, + /** + * Optional. + * An array of objects that represent the WiFi networks associated with the event; for example, the network + * name and password associated with a developer conference. Use this key for any type of pass. + * + * @var null|WifiNetwork[] + */ + #[All([new Type(WifiNetwork::class)])] + public ?array $wifiAccess = null, + /** + * Optional. + * The updated date and time of arrival, if different from the originally scheduled date + * and time. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $currentArrivalDate = null, + /** + * Optional. + * The updated date and time of boarding, if different from the originally scheduled date + * and time. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $currentBoardingDate = null, + /** + * Optional. + * The updated departure date and time, if different from the originally + * scheduled date and time. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $currentDepartureDate = null, + /** + * Optional. + * The date and time the event ends. Use this key for any type of event ticket. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $eventEndDate = null, + /** + * Optional. + * The date and time the event starts. Use this key for any type of event ticket. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $eventStartDate = null, + /** + * Optional. + * The originally scheduled date and time of arrival. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $originalArrivalDate = null, + /** + * Optional. + * The originally scheduled date and time of boarding. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $originalBoardingDate = null, + /** + * Optional. + * The originally scheduled date and time of departure. Use this key for any type of boarding pass. + */ + #[Cast(ISO8601DateCaster::class)] + public null|DateTimeInterface|string $originalDepartureDate = null, + ) { + parent::__construct(); + } } diff --git a/src/Apple/Components/WifiNetwork.php b/src/Apple/Components/WifiNetwork.php index 7f26625..faa79ac 100644 --- a/src/Apple/Components/WifiNetwork.php +++ b/src/Apple/Components/WifiNetwork.php @@ -3,23 +3,24 @@ namespace Chiiya\Passes\Apple\Components; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\Strict; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class WifiNetwork extends Component { - /** - * Required. - * The password for the WiFi network. - */ - #[Required] - public ?string $password; - - /** - * Required. - * The name for the WiFi network. - */ - #[Required] - public ?string $ssid; + public function __construct( + /** + * Required. + * The password for the WiFi network. + */ + #[NotBlank] + public string $password, + /** + * Required. + * The name for the WiFi network. + */ + #[NotBlank] + public string $ssid, + ) { + parent::__construct(); + } } diff --git a/src/Apple/PassFactory.php b/src/Apple/PassFactory.php index 68169bc..30dbbfd 100644 --- a/src/Apple/PassFactory.php +++ b/src/Apple/PassFactory.php @@ -16,6 +16,7 @@ use RecursiveIteratorIterator; use RuntimeException; use SplFileInfo; +use Symfony\Component\Validator\Validation; use Throwable; use ZipArchive; @@ -196,10 +197,20 @@ public function delete(string $path): void */ protected function validate(Pass $pass): void { - $errors = $this->validateImages($pass); + $validator = Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator(); + $messages = []; + $errors = $validator->validate($pass); if (count($errors) > 0) { - throw new ValidationException('Invalid pass', $errors); + foreach ($errors as $error) { + $messages[] = $error->getPropertyPath().': '.$error->getMessage(); + } + } + + $messages = array_merge($messages, $this->validateImages($pass)); + + if (count($messages) > 0) { + throw new ValidationException('Invalid pass', $messages); } } @@ -342,10 +353,10 @@ protected function createLocalizations(Pass $pass, string $dir): void foreach ($localization->strings as $key => $value) { $strings .= '"'.addslashes($key).'" = "'.addslashes($value).'";'.PHP_EOL; } - file_put_contents($localizationDir.self::STRINGS_FILENAME, $strings); + file_put_contents($localizationDir.'/'.self::STRINGS_FILENAME, $strings); foreach ($localization->images as $image) { - $filename = $localizationDir.($image->getName() ?? $image->getFilename()); + $filename = $localizationDir.'/'.($image->getName() ?? $image->getFilename()); copy($image->getPathname(), $filename); } } diff --git a/src/Apple/Passes/BoardingPass.php b/src/Apple/Passes/BoardingPass.php index 0f4578f..ee8ee0c 100644 --- a/src/Apple/Passes/BoardingPass.php +++ b/src/Apple/Passes/BoardingPass.php @@ -3,36 +3,41 @@ namespace Chiiya\Passes\Apple\Passes; use Chiiya\Passes\Apple\Enumerators\TransitType; -use Chiiya\Passes\Apple\Traits\HasFields; -use Chiiya\Passes\Apple\Traits\HasGroupingIdentifier; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; -use Spatie\DataTransferObject\Arr; -use Spatie\DataTransferObject\Attributes\Strict; +use Chiiya\Passes\Common\ArrayHelper; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; -#[Strict] class BoardingPass extends Pass { - use HasFields; - use HasGroupingIdentifier; - - /** - * Required. - * Type of transit. - * - * @see TransitType - */ - #[Required] - #[ValueIn([TransitType::AIR, TransitType::BOAT, TransitType::BUS, TransitType::TRAIN, TransitType::GENERIC])] - public ?string $transitType; + public function __construct( + /** + * Required. + * Type of transit. + * + * @see TransitType + */ + #[NotBlank] + #[Choice([TransitType::AIR, TransitType::BOAT, TransitType::BUS, TransitType::TRAIN, TransitType::GENERIC])] + public string $transitType, + /** + * Optional. + * Identifier used to group related passes. If a grouping identifier is specified, passes with the same style, + * pass type identifier, and grouping identifier are displayed as a group. Otherwise, passes are grouped + * automatically. + */ + public ?string $groupingIdentifier = null, + ...$args, + ) { + parent::__construct(...$args); + } - public function toArray(): array + public function encode(): array { - $array = parent::toArray(); + $array = parent::encode(); $keys = array_merge($this->fields(), ['transitType']); - $fields = Arr::only($array, $keys); + $fields = ArrayHelper::only($array, $keys); - return array_merge(Arr::except($array, $keys), [ + return array_merge(ArrayHelper::except($array, $keys), [ 'boardingPass' => $fields, ]); } diff --git a/src/Apple/Passes/Coupon.php b/src/Apple/Passes/Coupon.php index a9f0b4f..ed602b8 100644 --- a/src/Apple/Passes/Coupon.php +++ b/src/Apple/Passes/Coupon.php @@ -2,21 +2,16 @@ namespace Chiiya\Passes\Apple\Passes; -use Chiiya\Passes\Apple\Traits\HasFields; -use Spatie\DataTransferObject\Arr; -use Spatie\DataTransferObject\Attributes\Strict; +use Chiiya\Passes\Common\ArrayHelper; -#[Strict] class Coupon extends Pass { - use HasFields; - - public function toArray(): array + public function encode(): array { - $array = parent::toArray(); - $fields = Arr::only($array, $this->fields()); + $array = parent::encode(); + $fields = ArrayHelper::only($array, $this->fields()); - return array_merge(Arr::except($array, $this->fields()), [ + return array_merge(ArrayHelper::except($array, $this->fields()), [ 'coupon' => $fields, ]); } diff --git a/src/Apple/Passes/EventTicket.php b/src/Apple/Passes/EventTicket.php index 62fe3b3..40a74d6 100644 --- a/src/Apple/Passes/EventTicket.php +++ b/src/Apple/Passes/EventTicket.php @@ -2,23 +2,29 @@ namespace Chiiya\Passes\Apple\Passes; -use Chiiya\Passes\Apple\Traits\HasFields; -use Chiiya\Passes\Apple\Traits\HasGroupingIdentifier; -use Spatie\DataTransferObject\Arr; -use Spatie\DataTransferObject\Attributes\Strict; +use Chiiya\Passes\Common\ArrayHelper; -#[Strict] class EventTicket extends Pass { - use HasFields; - use HasGroupingIdentifier; + public function __construct( + /** + * Optional. + * Identifier used to group related passes. If a grouping identifier is specified, passes with the same style, + * pass type identifier, and grouping identifier are displayed as a group. Otherwise, passes are grouped + * automatically. + */ + public ?string $groupingIdentifier = null, + ...$args, + ) { + parent::__construct(...$args); + } - public function toArray(): array + public function encode(): array { - $array = parent::toArray(); - $fields = Arr::only($array, $this->fields()); + $array = parent::encode(); + $fields = ArrayHelper::only($array, $this->fields()); - return array_merge(Arr::except($array, $this->fields()), [ + return array_merge(ArrayHelper::except($array, $this->fields()), [ 'eventTicket' => $fields, ]); } diff --git a/src/Apple/Passes/GenericPass.php b/src/Apple/Passes/GenericPass.php index 13d2796..eea1e01 100644 --- a/src/Apple/Passes/GenericPass.php +++ b/src/Apple/Passes/GenericPass.php @@ -2,21 +2,16 @@ namespace Chiiya\Passes\Apple\Passes; -use Chiiya\Passes\Apple\Traits\HasFields; -use Spatie\DataTransferObject\Arr; -use Spatie\DataTransferObject\Attributes\Strict; +use Chiiya\Passes\Common\ArrayHelper; -#[Strict] class GenericPass extends Pass { - use HasFields; - - public function toArray(): array + public function encode(): array { - $array = parent::toArray(); - $fields = Arr::only($array, $this->fields()); + $array = parent::encode(); + $fields = ArrayHelper::only($array, $this->fields()); - return array_merge(Arr::except($array, $this->fields()), [ + return array_merge(ArrayHelper::except($array, $this->fields()), [ 'generic' => $fields, ]); } diff --git a/src/Apple/Passes/Pass.php b/src/Apple/Passes/Pass.php index ca68b2d..44c85e2 100644 --- a/src/Apple/Passes/Pass.php +++ b/src/Apple/Passes/Pass.php @@ -2,254 +2,262 @@ namespace Chiiya\Passes\Apple\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; +use Chiiya\Passes\Apple\Components\AuxiliaryField; use Chiiya\Passes\Apple\Components\Barcode; use Chiiya\Passes\Apple\Components\Beacon; +use Chiiya\Passes\Apple\Components\Field; use Chiiya\Passes\Apple\Components\Image; use Chiiya\Passes\Apple\Components\Localization; use Chiiya\Passes\Apple\Components\Location; use Chiiya\Passes\Apple\Components\Nfc; +use Chiiya\Passes\Apple\Components\SecondaryField; use Chiiya\Passes\Apple\Components\Semantics; use Chiiya\Passes\Common\Casters\W3CDateCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Contains; -use Chiiya\Passes\Common\Validation\MaxItems; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\RgbColor; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use DateTimeInterface; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\CssColor; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Type; +use Symfony\Component\Validator\Constraints\Url; abstract class Pass extends Component { - /** - * Required. - * Brief description of the pass, used by the iOS accessibility technologies. - */ - #[Required] - public ?string $description; - - /** - * Required. - * Version of the file format. - */ - #[Required] - public int $formatVersion = 1; - - /** - * Required. - * Display name of the organization that originated and signed the pass. - */ - #[Required] - public ?string $organizationName; - - /** - * Required. - * Pass type identifier, as issued by Apple. The value must correspond with your signing certificate. - */ - #[Required] - public ?string $passTypeIdentifier; - - /** - * Required. - * Serial number that uniquely identifies the pass. No two passes with the same pass type identifier - * may have the same serial number. - */ - #[Required] - public ?string $serialNumber; - - /** - * Required. - * Team identifier of the organization that originated and signed the pass, as issued by Apple. - */ - #[Required] - public ?string $teamIdentifier; - - /** - * Optional. - * A Boolean value introduced in iOS 11 that controls whether to show the Share button on the - * back of a pass. A value of true removes the button. The default value is false. This flag - * has no effect in earlier versions of iOS, nor does it prevent sharing the pass in some other way. - */ - public ?bool $sharingProhibited; - - /** - * Optional. - * A URL to be passed to the associated app when launching it. - */ - public ?string $appLaunchUrl; - - /** - * Optional. - * A list of iTunes Store item identifiers for the associated apps. - * - * @var null|int[] - */ - public ?array $associatedStoreIdentifiers; - - /** - * Optional. - * Custom information for companion apps. This data is not displayed to the user. - * May contain any JSON data. - */ - public ?array $userInfo; - - /** - * Optional. - * Date and time when the pass expires. - */ - #[CastWith(W3CDateCaster::class)] - public ?string $expirationDate; - - /** - * Optional. - * A Boolean value that indicates that the pass is void, such as a redeemed, - * one-time-use coupon. The default value is false. - */ - public ?bool $voided; - - /** - * Optional. - * Beacons marking locations where the pass is relevant. - * - * @since iOS v7.0 - * - * @var Beacon[] - */ - #[CastWith(ArrayCaster::class, Beacon::class)] - #[MaxItems(10)] - public array $beacons = []; - - /** - * Optional. - * Locations where the pass is relevant. - * - * @var Location[] - */ - #[CastWith(ArrayCaster::class, Location::class)] - #[MaxItems(10)] - public array $locations = []; - - /** - * Optional. - * Maximum distance in meters from a relevant latitude and longitude that the pass is relevant. - * - * @since iOS v7.0 - */ - public ?int $maxDistance; - - /** - * Optional. - * Date and time when the pass becomes relevant. - */ - #[CastWith(W3CDateCaster::class)] - public ?string $relevantDate; - - /** - * Optional - * An object that contains machine-readable metadata the system uses to offer a pass and suggest - * related actions. For example, setting Don’t Disturb mode for the duration of a movie. - */ - public ?Semantics $semantics; - - /** - * Optional. - * Information specific to the pass’s barcode. - * - * @deprecated - */ - public ?Barcode $barcode; - - /** - * Optional. - * Information specific to the pass’s barcode. The system uses the first valid barcode dictionary in the array. - * Additional dictionaries can be added as fallbacks. - * - * @since iOS v7.0 - * - * @var Barcode[] - */ - #[CastWith(ArrayCaster::class, Barcode::class)] - public array $barcodes = []; - - /** - * Optional. - * Background color of the pass, specified as an CSS-style RGB triple. - */ - #[RgbColor] - public ?string $backgroundColor; - - /** - * Optional. - * Foreground color of the pass, specified as a CSS-style RGB triple. - */ - #[RgbColor] - public ?string $foregroundColor; - - /** - * Optional. - * Color of the label text, specified as a CSS-style RGB triple. - */ - #[RgbColor] - public ?string $labelColor; - - /** - * Optional. - * Text displayed next to the logo on the pass. - */ - public ?string $logoText; - - /** - * Optional. - * The authentication token to use with the web service. The token must be 16 characters or longer. - */ - public ?string $authenticationToken; - - /** - * Optional. - * The URL for a web service that you use to update or personalize the pass. The URL can include an optional port number. - * - * @see https://developer.apple.com/library/archive/documentation/PassKit/Reference/PassKit_WebService/WebService.html#//apple_ref/doc/uid/TP40011988 - */ - #[Contains('https://')] - public ?string $webServiceURL; - - /** - * Optional. - * Information used for Value Added Service Protocol transactions. - * - * @since iOS v9.0 - */ - public ?Nfc $nfc; - - /** - * Optional. - * A Boolean value that controls whether to display the strip image without a - * shine effect. The default value is true. - */ - public ?bool $suppressStripShine; - - /** - * Array of images to add to the pass archive. - * - * @var Image[] - */ - protected array $images = []; - - /** - * Array of localizations to add to the pass archive. - * - * @var Localization[] - */ - protected array $localizations = []; + public function __construct( + /** + * Required. + * Brief description of the pass, used by the iOS accessibility technologies. + */ + #[NotBlank] + public string $description, + /** + * Required. + * Display name of the organization that originated and signed the pass. + */ + #[NotBlank] + public string $organizationName, + /** + * Required. + * Pass type identifier, as issued by Apple. The value must correspond with your signing certificate. + */ + #[NotBlank] + public string $passTypeIdentifier, + /** + * Required. + * Serial number that uniquely identifies the pass. No two passes with the same pass type identifier + * may have the same serial number. + */ + #[NotBlank] + public string $serialNumber, + /** + * Required. + * Team identifier of the organization that originated and signed the pass, as issued by Apple. + */ + #[NotBlank] + public string $teamIdentifier, + /** + * Required. + * Version of the file format. + */ + #[NotBlank] + public int $formatVersion = 1, + /** + * Optional. + * A Boolean value introduced in iOS 11 that controls whether to show the Share button on the + * back of a pass. A value of true removes the button. The default value is false. This flag + * has no effect in earlier versions of iOS, nor does it prevent sharing the pass in some other way. + */ + public ?bool $sharingProhibited = null, + /** + * Optional. + * A URL to be passed to the associated app when launching it. + */ + public ?string $appLaunchUrl = null, + /** + * Optional. + * A list of iTunes Store item identifiers for the associated apps. + * + * @var null|int[] + */ + public ?array $associatedStoreIdentifiers = null, + /** + * Optional. + * Custom information for companion apps. This data is not displayed to the user. + * May contain any JSON data. + */ + public ?array $userInfo = null, + /** + * Optional. + * A Boolean value that indicates that the pass is void, such as a redeemed, + * one-time-use coupon. The default value is false. + */ + public ?bool $voided = null, + /** + * Optional. + * Beacons marking locations where the pass is relevant. + * + * @since iOS v7.0 + * + * @var Beacon[] + */ + #[All([new Type(Beacon::class)])] + #[Count(max: 10)] + public array $beacons = [], + /** + * Optional. + * Locations where the pass is relevant. + * + * @var Location[] + */ + #[All([new Type(Location::class)])] + #[Count(max: 10)] + public array $locations = [], + /** + * Optional. + * Maximum distance in meters from a relevant latitude and longitude that the pass is relevant. + * + * @since iOS v7.0 + */ + public ?int $maxDistance = null, + /** + * Optional + * An object that contains machine-readable metadata the system uses to offer a pass and suggest + * related actions. For example, setting Don’t Disturb mode for the duration of a movie. + */ + public ?Semantics $semantics = null, + /** + * Optional. + * Information specific to the pass’s barcode. + * + * @deprecated + */ + public ?Barcode $barcode = null, + /** + * Optional. + * Information specific to the pass’s barcode. The system uses the first valid barcode dictionary in the array. + * Additional dictionaries can be added as fallbacks. + * + * @since iOS v7.0 + * + * @var Barcode[] + */ + #[All([new Type(Barcode::class)])] + public array $barcodes = [], + /** + * Optional. + * Background color of the pass, specified as an CSS-style RGB triple. + */ + #[CssColor(formats: CssColor::RGB)] + public ?string $backgroundColor = null, + /** + * Optional. + * Foreground color of the pass, specified as a CSS-style RGB triple. + */ + #[CssColor(formats: CssColor::RGB)] + public ?string $foregroundColor = null, + /** + * Optional. + * Color of the label text, specified as a CSS-style RGB triple. + */ + #[CssColor(formats: CssColor::RGB)] + public ?string $labelColor = null, + /** + * Optional. + * Text displayed next to the logo on the pass. + */ + public ?string $logoText = null, + /** + * Optional. + * The authentication token to use with the web service. The token must be 16 characters or longer. + */ + public ?string $authenticationToken = null, + /** + * Optional. + * The URL for a web service that you use to update or personalize the pass. The URL can include an optional port number. + * + * @see https://developer.apple.com/library/archive/documentation/PassKit/Reference/PassKit_WebService/WebService.html#//apple_ref/doc/uid/TP40011988 + */ + #[Url] + public ?string $webServiceURL = null, + /** + * Optional. + * Information used for Value Added Service Protocol transactions. + * + * @since iOS v9.0 + */ + public ?Nfc $nfc = null, + /** + * Optional. + * A Boolean value that controls whether to display the strip image without a + * shine effect. The default value is true. + */ + public ?bool $suppressStripShine = null, + /** + * Array of images to add to the pass archive. + * + * @var Image[] + */ + #[All([new Type(Image::class)])] + protected array $images = [], + /** + * Array of localizations to add to the pass archive. + * + * @var Localization[] + */ + #[All([new Type(Localization::class)])] + protected array $localizations = [], + /** + * Optional. + * Date and time when the pass expires. + */ + #[Cast(W3CDateCaster::class)] + public null|DateTimeInterface|string $expirationDate = null, + /** + * Optional. + * Date and time when the pass becomes relevant. + */ + #[Cast(W3CDateCaster::class)] + public null|DateTimeInterface|string $relevantDate = null, + /** @var SecondaryField[] */ + #[All([new Type(SecondaryField::class)])] + #[Count(max: 3)] + #[Cast(ArrayCaster::class, itemType: SecondaryField::class)] + public array $headerFields = [], + /** @var Field[] */ + #[All([new Type(Field::class)])] + #[Count(max: 2)] + #[Cast(ArrayCaster::class, itemType: Field::class)] + public array $primaryFields = [], + /** @var SecondaryField[] */ + #[All([new Type(SecondaryField::class)])] + #[Count(max: 4)] + #[Cast(ArrayCaster::class, itemType: SecondaryField::class)] + public array $secondaryFields = [], + /** @var AuxiliaryField[] */ + #[All([new Type(AuxiliaryField::class)])] + #[Count(max: 5)] + #[Cast(ArrayCaster::class, itemType: AuxiliaryField::class)] + public array $auxiliaryFields = [], + /** @var Field[] */ + #[All([new Type(Field::class)])] + #[Cast(ArrayCaster::class, itemType: Field::class)] + public array $backFields = [], + ) { + parent::__construct(); + } /** * @return Image[] */ - final public function getImages(): array + public function getImages(): array { return $this->images; } - final public function addImage(Image $image): self + public function addImage(Image $image): self { $this->images[] = $image; @@ -259,15 +267,20 @@ final public function addImage(Image $image): self /** * @return Localization[] */ - final public function getLocalizations(): array + public function getLocalizations(): array { return $this->localizations; } - final public function addLocalization(Localization $localization): self + public function addLocalization(Localization $localization): self { $this->localizations[] = $localization; return $this; } + + protected function fields(): array + { + return ['headerFields', 'primaryFields', 'secondaryFields', 'auxiliaryFields', 'backFields']; + } } diff --git a/src/Apple/Passes/StoreCard.php b/src/Apple/Passes/StoreCard.php index 27a59d4..2426a2d 100644 --- a/src/Apple/Passes/StoreCard.php +++ b/src/Apple/Passes/StoreCard.php @@ -2,21 +2,16 @@ namespace Chiiya\Passes\Apple\Passes; -use Chiiya\Passes\Apple\Traits\HasFields; -use Spatie\DataTransferObject\Arr; -use Spatie\DataTransferObject\Attributes\Strict; +use Chiiya\Passes\Common\ArrayHelper; -#[Strict] class StoreCard extends Pass { - use HasFields; - - public function toArray(): array + public function encode(): array { - $array = parent::toArray(); - $fields = Arr::only($array, $this->fields()); + $array = parent::encode(); + $fields = ArrayHelper::only($array, $this->fields()); - return array_merge(Arr::except($array, $this->fields()), [ + return array_merge(ArrayHelper::except($array, $this->fields()), [ 'storeCard' => $fields, ]); } diff --git a/src/Apple/Traits/HasFields.php b/src/Apple/Traits/HasFields.php deleted file mode 100644 index 89fb619..0000000 --- a/src/Apple/Traits/HasFields.php +++ /dev/null @@ -1,42 +0,0 @@ - 1) { + $part = array_shift($parts); + + if (isset($array[$part]) && Arr::accessible($array[$part])) { + $array = &$array[$part]; + } else { + continue 2; + } + } + + unset($array[array_shift($parts)]); + } + } +} diff --git a/src/Common/Casters/Caster.php b/src/Common/Casters/Caster.php new file mode 100644 index 0000000..7d4a4ff --- /dev/null +++ b/src/Common/Casters/Caster.php @@ -0,0 +1,8 @@ +format(), $value); + + if ($date === false) { + return null; + } + + return $date; + } + + public function serialize(mixed $value): ?string + { + if ($value === null) { + return null; + } + + if ($value instanceof DateTimeInterface) { + return $value->format($this->format()); + } + + return (string) $value; + } + + abstract protected function format(): string; +} diff --git a/src/Common/Casters/ISO8601DateCaster.php b/src/Common/Casters/ISO8601DateCaster.php index d4e2d77..ffc2691 100644 --- a/src/Common/Casters/ISO8601DateCaster.php +++ b/src/Common/Casters/ISO8601DateCaster.php @@ -3,16 +3,11 @@ namespace Chiiya\Passes\Common\Casters; use DateTimeInterface; -use Spatie\DataTransferObject\Caster; -class ISO8601DateCaster implements Caster +class ISO8601DateCaster extends DateCaster { - public function cast(mixed $value): string + protected function format(): string { - if ($value instanceof DateTimeInterface) { - return $value->format(DateTimeInterface::ATOM); - } - - return (string) $value; + return DateTimeInterface::ATOM; } } diff --git a/src/Common/Casters/LegacyValueCaster.php b/src/Common/Casters/LegacyValueCaster.php index 6f85028..1afb96a 100644 --- a/src/Common/Casters/LegacyValueCaster.php +++ b/src/Common/Casters/LegacyValueCaster.php @@ -2,28 +2,36 @@ namespace Chiiya\Passes\Common\Casters; +use Antwerpes\DataTransferObject\CastsProperty; use Chiiya\Passes\Common\LegacyValueEnumerator; -use LogicException; -use Spatie\DataTransferObject\Caster; -class LegacyValueCaster implements Caster +class LegacyValueCaster implements CastsProperty { public function __construct( - private array $types, - private string $enum, + private readonly string $enum, ) {} - public function cast(mixed $value): string + public function unserialize(mixed $value): ?string { - foreach ($this->types as $type) { - if ($type === 'string') { - /** @var LegacyValueEnumerator $enum */ - $enum = new $this->enum; + if ($value === null) { + return null; + } + + /** @var LegacyValueEnumerator $enum */ + $enum = new $this->enum; + + return $enum->mapLegacyValues($value); + } - return $enum->mapLegacyValues($value); - } + public function serialize(mixed $value): ?string + { + if ($value === null) { + return null; } - throw new LogicException('Caster [LegacyValueCaster] may only be used to cast strings.'); + /** @var LegacyValueEnumerator $enum */ + $enum = new $this->enum; + + return $enum->mapLegacyValues($value); } } diff --git a/src/Common/Casters/W3CDateCaster.php b/src/Common/Casters/W3CDateCaster.php index dae4522..14eedfb 100644 --- a/src/Common/Casters/W3CDateCaster.php +++ b/src/Common/Casters/W3CDateCaster.php @@ -3,16 +3,11 @@ namespace Chiiya\Passes\Common\Casters; use DateTimeInterface; -use Spatie\DataTransferObject\Caster; -class W3CDateCaster implements Caster +class W3CDateCaster extends DateCaster { - public function cast(mixed $value): string + protected function format(): string { - if ($value instanceof DateTimeInterface) { - return $value->format(DateTimeInterface::W3C); - } - - return (string) $value; + return DateTimeInterface::W3C; } } diff --git a/src/Common/Component.php b/src/Common/Component.php index 23d0ca0..4ece05c 100644 --- a/src/Common/Component.php +++ b/src/Common/Component.php @@ -2,17 +2,35 @@ namespace Chiiya\Passes\Common; +use Antwerpes\DataTransferObject\DataTransferObject; +use Chiiya\Passes\Exceptions\ValidationException; use JsonSerializable; -use Spatie\DataTransferObject\DataTransferObject; +use Symfony\Component\Validator\Validation; abstract class Component extends DataTransferObject implements JsonSerializable { + public function __construct() + { + $validator = Validation::createValidatorBuilder()->enableAttributeMapping()->getValidator(); + $errors = $validator->validate($this); + + if (count($errors) > 0) { + $messages = []; + + foreach ($errors as $error) { + $messages[] = static::class.'.'.$error->getPropertyPath().': '.$error->getMessage(); + } + + throw new ValidationException('Invalid arguments', $messages); + } + } + /** * Convert the object into something JSON serializable. */ final public function jsonSerialize(): array { - return $this->removeEmptyValues($this->toArray()); + return $this->removeEmptyValues($this->encode()); } /** diff --git a/src/Common/Validation/RgbColor.php b/src/Common/Validation/RgbColor.php deleted file mode 100644 index 77b95f3..0000000 --- a/src/Common/Validation/RgbColor.php +++ /dev/null @@ -1,46 +0,0 @@ -isValidRgbColor($value)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid('The value is not a valid rgb color definition.'); - } - - private function isValidRgbColor(mixed $value): bool - { - if ($value === null) { - return true; - } - - $value = str_replace(' ', '', $value); - - if (! str_starts_with($value, 'rgb(')) { - return false; - } - $items = explode(',', mb_substr($value, 4, -1)); - - if (count($items) !== 3) { - return false; - } - - foreach ($items as $item) { - if ((int) $item < 0 || (int) $item > 255) { - return false; - } - } - - return true; - } -} diff --git a/src/Google/Components/Common/AppLinkData.php b/src/Google/Components/Common/AppLinkData.php index f749a1f..36c7c42 100644 --- a/src/Google/Components/Common/AppLinkData.php +++ b/src/Google/Components/Common/AppLinkData.php @@ -6,24 +6,26 @@ class AppLinkData extends Component { - /** - * Optional. - * Optional information about the partner app link. If included, the app link link module will be rendered on - * the valuable details on the android client. - */ - public ?AppLinkInfo $androidAppLinkInfo; - - /** - * Optional. - * Optional information about the partner app link. If included, the app link link module will be rendered on - * the valuable details on the ios client. - */ - public ?AppLinkInfo $iosAppLinkInfo; - - /** - * Optional. - * Optional information about the partner app link. If included, the app link link module will be rendered on - * the valuable details on the web client. - */ - public ?AppLinkInfo $webAppLinkInfo; + public function __construct( + /** + * Optional. + * Optional information about the partner app link. If included, the app link link module will be rendered on + * the valuable details on the android client. + */ + public ?AppLinkInfo $androidAppLinkInfo = null, + /** + * Optional. + * Optional information about the partner app link. If included, the app link link module will be rendered on + * the valuable details on the ios client. + */ + public ?AppLinkInfo $iosAppLinkInfo = null, + /** + * Optional. + * Optional information about the partner app link. If included, the app link link module will be rendered on + * the valuable details on the web client. + */ + public ?AppLinkInfo $webAppLinkInfo = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/AppLinkInfo.php b/src/Google/Components/Common/AppLinkInfo.php index 02f7a3b..765daf2 100644 --- a/src/Google/Components/Common/AppLinkInfo.php +++ b/src/Google/Components/Common/AppLinkInfo.php @@ -3,34 +3,32 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; class AppLinkInfo extends Component { - /** - * Optional. - * Optional image to be displayed in the App Link Module. - */ - public ?Image $appLogoImage; - - /** - * Required. - * String to be displayed in the title of the App Link Module. - */ - #[Required] - public ?LocalizedString $title; - - /** - * Required. - * String to be displayed in the description of the App Link Module. - */ - #[Required] - public ?LocalizedString $description; - - /** - * Optional. - * Url to follow when opening the App Link Module on clients. It will be used by partners to open their - * webpage or deeplink into their app. - */ - public ?AppTarget $appTarget; + public function __construct( + /** + * Required. + * String to be displayed in the title of the App Link Module. + */ + public LocalizedString $title, + /** + * Required. + * String to be displayed in the description of the App Link Module. + */ + public LocalizedString $description, + /** + * Optional. + * Optional image to be displayed in the App Link Module. + */ + public ?Image $appLogoImage = null, + /** + * Optional. + * Url to follow when opening the App Link Module on clients. It will be used by partners to open their + * webpage or deeplink into their app. + */ + public ?AppTarget $appTarget = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/AppTarget.php b/src/Google/Components/Common/AppTarget.php index 6b821bd..0f992a3 100644 --- a/src/Google/Components/Common/AppTarget.php +++ b/src/Google/Components/Common/AppTarget.php @@ -6,6 +6,10 @@ class AppTarget extends Component { - /** Optional. */ - public ?Uri $targetUri; + public function __construct( + /** Optional. */ + public ?Uri $targetUri = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/Barcode.php b/src/Google/Components/Common/Barcode.php index ca7a40f..134e197 100644 --- a/src/Google/Components/Common/Barcode.php +++ b/src/Google/Components/Common/Barcode.php @@ -2,66 +2,66 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\BarcodeRenderEncoding; use Chiiya\Passes\Google\Enumerators\BarcodeType; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class Barcode extends Component { - /** - * Required. - * The type of barcode. - */ - #[Required] - #[ValueIn([ - BarcodeType::BARCODE_TYPE_UNSPECIFIED, - BarcodeType::AZTEC, - BarcodeType::CODE_39, - BarcodeType::CODE_128, - BarcodeType::CODABAR, - BarcodeType::DATA_MATRIX, - BarcodeType::EAN_8, - BarcodeType::EAN_13, - BarcodeType::ITF_14, - BarcodeType::PDF_417, - BarcodeType::QR_CODE, - BarcodeType::UPC_A, - BarcodeType::TEXT_ONLY, - ])] - #[CastWith(LegacyValueCaster::class, BarcodeType::class)] - public ?string $type; - - /** - * Optional. - * The render encoding for the barcode. When specified, barcode is rendered in the given encoding. - * Otherwise best known encoding is chosen by Google. - */ - #[ValueIn([BarcodeRenderEncoding::UTF_8, BarcodeRenderEncoding::RENDER_ENCODING_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, BarcodeRenderEncoding::class)] - public ?string $renderEncoding; - - /** - * Required. - * The value encoded in the barcode. - */ - #[Required] - public ?string $value; - - /** - * Optional. - * An optional text that will override the default text that shows under the barcode. This field is intended - * for a human readable equivalent of the barcode value, used when the barcode cannot be scanned. - */ - public ?string $alternateText; - - /** - * Optional. - * Optional text that will be shown when the barcode is hidden behind a click action. This happens in cases - * where a pass has Smart Tap enabled. If not specified, a default is chosen by Google. - */ - public ?LocalizedString $showCodeText; + public function __construct( + /** + * Required. + * The type of barcode. + */ + #[NotBlank] + #[Choice([ + BarcodeType::BARCODE_TYPE_UNSPECIFIED, + BarcodeType::AZTEC, + BarcodeType::CODE_39, + BarcodeType::CODE_128, + BarcodeType::CODABAR, + BarcodeType::DATA_MATRIX, + BarcodeType::EAN_8, + BarcodeType::EAN_13, + BarcodeType::ITF_14, + BarcodeType::PDF_417, + BarcodeType::QR_CODE, + BarcodeType::UPC_A, + BarcodeType::TEXT_ONLY, + ])] + #[Cast(LegacyValueCaster::class, BarcodeType::class)] + public string $type, + /** + * Required. + * The value encoded in the barcode. + */ + #[NotBlank] + public string $value, + /** + * Optional. + * An optional text that will override the default text that shows under the barcode. This field is intended + * for a human-readable equivalent of the barcode value, used when the barcode cannot be scanned. + */ + public ?string $alternateText = null, + /** + * Optional. + * Optional text that will be shown when the barcode is hidden behind a click action. This happens in cases + * where a pass has Smart Tap enabled. If not specified, a default is chosen by Google. + */ + public ?LocalizedString $showCodeText = null, + /** + * Optional. + * The render encoding for the barcode. When specified, barcode is rendered in the given encoding. + * Otherwise, best known encoding is chosen by Google. + */ + #[Choice([BarcodeRenderEncoding::UTF_8, BarcodeRenderEncoding::RENDER_ENCODING_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, BarcodeRenderEncoding::class)] + public ?string $renderEncoding = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/CallbackOptions.php b/src/Google/Components/Common/CallbackOptions.php index 101f441..7ff1416 100644 --- a/src/Google/Components/Common/CallbackOptions.php +++ b/src/Google/Components/Common/CallbackOptions.php @@ -3,25 +3,28 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Contains; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Url; class CallbackOptions extends Component { - /** - * Required. - * The HTTPS url configured by the merchant. The URL should be hosted on HTTPS and robots.txt should allow - * the URL path to be accessible by UserAgent:Google-Valuables. - */ - #[Required] - #[Contains('https://')] - public ?string $url; - - /** - * Optional. - * URL for the merchant endpoint that would be called to request updates. The URL should be hosted on HTTPS - * and robots.txt should allow the URL path to be accessible by UserAgent:Google-Valuables. - */ - #[Contains('https://')] - public ?string $updateRequestUrl; + public function __construct( + /** + * Required. + * The HTTPS url configured by the merchant. The URL should be hosted on HTTPS and robots.txt should allow + * the URL path to be accessible by UserAgent:Google-Valuables. + */ + #[NotBlank] + #[Url] + public string $url, + /** + * Optional. + * URL for the merchant endpoint that would be called to request updates. The URL should be hosted on HTTPS + * and robots.txt should allow the URL path to be accessible by UserAgent:Google-Valuables. + */ + #[Url] + public ?string $updateRequestUrl = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/BarcodeSectionDetail.php b/src/Google/Components/Common/ClassTemplate/BarcodeSectionDetail.php index 177f95f..06a3bb9 100644 --- a/src/Google/Components/Common/ClassTemplate/BarcodeSectionDetail.php +++ b/src/Google/Components/Common/ClassTemplate/BarcodeSectionDetail.php @@ -3,14 +3,16 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; class BarcodeSectionDetail extends Component { - /** - * Required. - * A reference to an existing text-based or image field to display. - */ - #[Required] - public ?FieldSelector $fieldSelector; + public function __construct( + /** + * Required. + * A reference to an existing text-based or image field to display. + */ + public FieldSelector $fieldSelector, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/CardBarcodeSectionDetails.php b/src/Google/Components/Common/ClassTemplate/CardBarcodeSectionDetails.php index 365757a..b8c6b26 100644 --- a/src/Google/Components/Common/ClassTemplate/CardBarcodeSectionDetails.php +++ b/src/Google/Components/Common/ClassTemplate/CardBarcodeSectionDetails.php @@ -6,23 +6,25 @@ class CardBarcodeSectionDetails extends Component { - /** - * Optional. - * Optional information to display above the barcode. If secondTopDetail is defined, this will be displayed - * to the start side of this detail section. - */ - public ?BarcodeSectionDetail $firstTopDetail; - - /** - * Optional. - * Optional information to display below the barcode. - */ - public ?BarcodeSectionDetail $firstBottomDetail; - - /** - * Optional. - * Optional second piece of information to display above the barcode. If firstTopDetail is defined, this will be - * displayed to the end side of this detail section. - */ - public ?BarcodeSectionDetail $secondTopDetail; + public function __construct( + /** + * Optional. + * Optional information to display above the barcode. If secondTopDetail is defined, this will be displayed + * to the start side of this detail section. + */ + public ?BarcodeSectionDetail $firstTopDetail = null, + /** + * Optional. + * Optional information to display below the barcode. + */ + public ?BarcodeSectionDetail $firstBottomDetail = null, + /** + * Optional. + * Optional second piece of information to display above the barcode. If firstTopDetail is defined, this will be + * displayed to the end side of this detail section. + */ + public ?BarcodeSectionDetail $secondTopDetail = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/CardRowItem.php b/src/Google/Components/Common/ClassTemplate/CardRowItem.php index dad93b4..ff69148 100644 --- a/src/Google/Components/Common/ClassTemplate/CardRowItem.php +++ b/src/Google/Components/Common/ClassTemplate/CardRowItem.php @@ -6,31 +6,32 @@ class CardRowItem extends Component { - /** - * Optional. - * The item to be displayed in the row. This item will be automatically centered. - * Used for 1-ITEM-ROW. - */ - public ?TemplateItem $item; - - /** - * Optional. - * The item to be displayed at the start of the row. This item will be aligned to the left. - * Used for 2-ITEM-ROW and 3-ITEM-ROW. - */ - public ?TemplateItem $startItem; - - /** - * Optional. - * The item to be displayed at the end of the row. This item will be aligned to the right. - * Used for 3-ITEM-ROW. - */ - public ?TemplateItem $middleItem; - - /** - * Optional. - * The item to be displayed at the end of the row. This item will be aligned to the right. - * Used for 2-ITEM-ROW and 3-ITEM-ROW. - */ - public ?TemplateItem $endItem; + public function __construct( + /** + * Optional. + * The item to be displayed in the row. This item will be automatically centered. + * Used for 1-ITEM-ROW. + */ + public ?TemplateItem $item = null, + /** + * Optional. + * The item to be displayed at the start of the row. This item will be aligned to the left. + * Used for 2-ITEM-ROW and 3-ITEM-ROW. + */ + public ?TemplateItem $startItem = null, + /** + * Optional. + * The item to be displayed at the end of the row. This item will be aligned to the right. + * Used for 3-ITEM-ROW. + */ + public ?TemplateItem $middleItem = null, + /** + * Optional. + * The item to be displayed at the end of the row. This item will be aligned to the right. + * Used for 2-ITEM-ROW and 3-ITEM-ROW. + */ + public ?TemplateItem $endItem = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/CardRowTemplateInfo.php b/src/Google/Components/Common/ClassTemplate/CardRowTemplateInfo.php index 3712ff1..8c0d708 100644 --- a/src/Google/Components/Common/ClassTemplate/CardRowTemplateInfo.php +++ b/src/Google/Components/Common/ClassTemplate/CardRowTemplateInfo.php @@ -6,21 +6,23 @@ class CardRowTemplateInfo extends Component { - /** - * Optional. - * Template for a row containing one item. Exactly one of "oneItem", "twoItems", "threeItems" must be set. - */ - public ?CardRowItem $oneItem; - - /** - * Optional. - * Template for a row containing two items. Exactly one of "oneItem", "twoItems", "threeItems" must be set. - */ - public ?CardRowItem $twoItems; - - /** - * Optional. - * Template for a row containing three items. Exactly one of "oneItem", "twoItems", "threeItems" must be set. - */ - public ?CardRowItem $threeItems; + public function __construct( + /** + * Optional. + * Template for a row containing one item. Exactly one of "oneItem", "twoItems", "threeItems" must be set. + */ + public ?CardRowItem $oneItem = null, + /** + * Optional. + * Template for a row containing two items. Exactly one of "oneItem", "twoItems", "threeItems" must be set. + */ + public ?CardRowItem $twoItems = null, + /** + * Optional. + * Template for a row containing three items. Exactly one of "oneItem", "twoItems", "threeItems" must be set. + */ + public ?CardRowItem $threeItems = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/CardTemplateOverride.php b/src/Google/Components/Common/ClassTemplate/CardTemplateOverride.php index 478628d..661e82a 100644 --- a/src/Google/Components/Common/ClassTemplate/CardTemplateOverride.php +++ b/src/Google/Components/Common/ClassTemplate/CardTemplateOverride.php @@ -2,21 +2,25 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxItems; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\NotBlank; class CardTemplateOverride extends Component { - /** - * Required. - * - * @var FieldReference[] - */ - #[CastWith(ArrayCaster::class, CardRowTemplateInfo::class)] - #[Required] - #[MaxItems(2)] - public array $cardRowTemplateInfos = []; + public function __construct( + /** + * Required. + * + * @var FieldReference[] + */ + #[Cast(ArrayCaster::class, CardRowTemplateInfo::class)] + #[NotBlank] + #[Count(max: 2)] + public array $cardRowTemplateInfos = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/ClassTemplateInfo.php b/src/Google/Components/Common/ClassTemplate/ClassTemplateInfo.php index dfb39ee..13e28aa 100644 --- a/src/Google/Components/Common/ClassTemplate/ClassTemplateInfo.php +++ b/src/Google/Components/Common/ClassTemplate/ClassTemplateInfo.php @@ -6,27 +6,28 @@ class ClassTemplateInfo extends Component { - /** - * Optional. - * Specifies extra information to be displayed above and below the barcode. - */ - public ?CardBarcodeSectionDetails $cardBarcodeSectionDetails; - - /** - * Optional. - * Override for the card view. - */ - public ?CardTemplateOverride $cardTemplateOverride; - - /** - * Optional. - * Override for the details view (beneath the card view). - */ - public ?DetailsTemplateOverride $detailsTemplateOverride; - - /** - * Optional. - * Override for the passes list view. - */ - public ?ListTemplateOverride $listTemplateOverride; + public function __construct( + /** + * Optional. + * Specifies extra information to be displayed above and below the barcode. + */ + public ?CardBarcodeSectionDetails $cardBarcodeSectionDetails = null, + /** + * Optional. + * Override for the card view. + */ + public ?CardTemplateOverride $cardTemplateOverride = null, + /** + * Optional. + * Override for the details view (beneath the card view). + */ + public ?DetailsTemplateOverride $detailsTemplateOverride = null, + /** + * Optional. + * Override for the passes list view. + */ + public ?ListTemplateOverride $listTemplateOverride = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/DetailsItemInfo.php b/src/Google/Components/Common/ClassTemplate/DetailsItemInfo.php index fcea4ef..81c6b57 100644 --- a/src/Google/Components/Common/ClassTemplate/DetailsItemInfo.php +++ b/src/Google/Components/Common/ClassTemplate/DetailsItemInfo.php @@ -3,14 +3,16 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; class DetailsItemInfo extends Component { - /** - * Required. - * The item to be displayed in the details list. - */ - #[Required] - public ?TemplateItem $item; + public function __construct( + /** + * Required. + * The item to be displayed in the details list. + */ + public TemplateItem $item, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/DetailsTemplateOverride.php b/src/Google/Components/Common/ClassTemplate/DetailsTemplateOverride.php index 80c5adb..d1cfa92 100644 --- a/src/Google/Components/Common/ClassTemplate/DetailsTemplateOverride.php +++ b/src/Google/Components/Common/ClassTemplate/DetailsTemplateOverride.php @@ -2,20 +2,24 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\NotBlank; class DetailsTemplateOverride extends Component { - /** - * Required. - * Information for the "nth" item displayed in the details list. - * - * @var FieldReference[] - */ - #[CastWith(ArrayCaster::class, DetailsItemInfo::class)] - #[Required] - public array $detailsItemInfos = []; + public function __construct( + /** + * Required. + * Information for the "nth" item displayed in the details list. + * + * @var FieldReference[] + */ + #[Cast(ArrayCaster::class, DetailsItemInfo::class)] + #[NotBlank] + public array $detailsItemInfos = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/FieldReference.php b/src/Google/Components/Common/ClassTemplate/FieldReference.php index ec47b07..3ed4e26 100644 --- a/src/Google/Components/Common/ClassTemplate/FieldReference.php +++ b/src/Google/Components/Common/ClassTemplate/FieldReference.php @@ -2,36 +2,39 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\DateFormat; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class FieldReference extends Component { - /** - * Required. - * Path to the field being referenced, prefixed with "object" or "class" and separated with dots. - * For example, it may be the string "object.purchaseDetails.purchasePrice". - */ - #[Required] - public ?string $fieldPath; - - /** - * Optional. - * Only valid if the fieldPath references a date field. Chooses how the date field will be - * formatted and displayed in the UI. - */ - #[ValueIn([ - DateFormat::DATE_FORMAT_UNSPECIFIED, - DateFormat::DATE_ONLY, - DateFormat::TIME_ONLY, - DateFormat::DATE_YEAR, - DateFormat::DATE_TIME, - DateFormat::DATE_TIME_YEAR, - ])] - #[CastWith(LegacyValueCaster::class, DateFormat::class)] - public ?string $dateFormat; + public function __construct( + /** + * Required. + * Path to the field being referenced, prefixed with "object" or "class" and separated with dots. + * For example, it may be the string "object.purchaseDetails.purchasePrice". + */ + #[NotBlank] + public string $fieldPath, + /** + * Optional. + * Only valid if the fieldPath references a date field. Chooses how the date field will be + * formatted and displayed in the UI. + */ + #[Choice([ + DateFormat::DATE_FORMAT_UNSPECIFIED, + DateFormat::DATE_ONLY, + DateFormat::TIME_ONLY, + DateFormat::DATE_YEAR, + DateFormat::DATE_TIME, + DateFormat::DATE_TIME_YEAR, + ])] + #[Cast(LegacyValueCaster::class, DateFormat::class)] + public ?string $dateFormat = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/FieldSelector.php b/src/Google/Components/Common/ClassTemplate/FieldSelector.php index 9396fb0..2ce5902 100644 --- a/src/Google/Components/Common/ClassTemplate/FieldSelector.php +++ b/src/Google/Components/Common/ClassTemplate/FieldSelector.php @@ -2,22 +2,26 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MinItems; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\NotBlank; class FieldSelector extends Component { - /** - * Required. - * If more than one reference is supplied, then the first one that references a non-empty field will be displayed. - * - * @var FieldReference[] - */ - #[CastWith(ArrayCaster::class, FieldReference::class)] - #[Required] - #[MinItems(1)] - public array $fields = []; + public function __construct( + /** + * Required. + * If more than one reference is supplied, then the first one that references a non-empty field will be displayed. + * + * @var FieldReference[] + */ + #[Cast(ArrayCaster::class, FieldReference::class)] + #[NotBlank] + #[Count(min: 1)] + public array $fields = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/FirstRowOption.php b/src/Google/Components/Common/ClassTemplate/FirstRowOption.php index 3e667d6..fc47bed 100644 --- a/src/Google/Components/Common/ClassTemplate/FirstRowOption.php +++ b/src/Google/Components/Common/ClassTemplate/FirstRowOption.php @@ -2,24 +2,27 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\TransitOption; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class FirstRowOption extends Component { - /** Optional. */ - #[ValueIn([ - TransitOption::ORIGIN_AND_DESTINATION_CODES, - TransitOption::ORIGIN_AND_DESTINATION_NAMES, - TransitOption::ORIGIN_NAME, - TransitOption::TRANSIT_OPTION_UNSPECIFIED, - ])] - #[CastWith(LegacyValueCaster::class, TransitOption::class)] - public ?string $transitOption; - - /** Optional. */ - public ?FieldSelector $fieldOption; + public function __construct( + /** Optional. */ + #[Choice([ + TransitOption::ORIGIN_AND_DESTINATION_CODES, + TransitOption::ORIGIN_AND_DESTINATION_NAMES, + TransitOption::ORIGIN_NAME, + TransitOption::TRANSIT_OPTION_UNSPECIFIED, + ])] + #[Cast(LegacyValueCaster::class, TransitOption::class)] + public ?string $transitOption = null, + /** Optional. */ + public ?FieldSelector $fieldOption = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/ListTemplateOverride.php b/src/Google/Components/Common/ClassTemplate/ListTemplateOverride.php index 26367aa..11d7f2a 100644 --- a/src/Google/Components/Common/ClassTemplate/ListTemplateOverride.php +++ b/src/Google/Components/Common/ClassTemplate/ListTemplateOverride.php @@ -6,23 +6,25 @@ class ListTemplateOverride extends Component { - /** - * Optional. - * Specifies from a predefined set of options what the will be displayed in the first row. - */ - public ?FirstRowOption $firstRowOption; - - /** - * Optional. - * A reference to the field to be displayed in the second row. - */ - public ?FieldSelector $secondRowOption; - - /** - * Optional. - * A reference to the field to be displayed in the third row. - * - * @deprecated - */ - public ?FieldSelector $thirdRowOption; + public function __construct( + /** + * Optional. + * Specifies from a predefined set of options what the will be displayed in the first row. + */ + public ?FirstRowOption $firstRowOption = null, + /** + * Optional. + * A reference to the field to be displayed in the second row. + */ + public ?FieldSelector $secondRowOption = null, + /** + * Optional. + * A reference to the field to be displayed in the third row. + * + * @deprecated + */ + public ?FieldSelector $thirdRowOption = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ClassTemplate/TemplateItem.php b/src/Google/Components/Common/ClassTemplate/TemplateItem.php index 0b5e93a..0399486 100644 --- a/src/Google/Components/Common/ClassTemplate/TemplateItem.php +++ b/src/Google/Components/Common/ClassTemplate/TemplateItem.php @@ -2,35 +2,37 @@ namespace Chiiya\Passes\Google\Components\Common\ClassTemplate; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\PredefinedItem; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class TemplateItem extends Component { - /** - * Optional. - * A reference to a field to display. - */ - public ?FieldSelector $firstValue; - - /** - * Optional. - * A reference to a field to display. This may only be populated if the firstValue field is populated. - */ - public ?FieldSelector $secondValue; - - /** - * Optional. - * A predefined item to display. Only one of firstValue or predefinedItem may be set. - */ - #[ValueIn([ - PredefinedItem::FLIGHT_NUMBER_AND_OPERATING_FLIGHT_NUMBER, - PredefinedItem::FREQUENT_FLYER_PROGRAM_NAME_AND_NUMBER, - PredefinedItem::PREDEFINED_ITEM_UNSPECIFIED, - ])] - #[CastWith(LegacyValueCaster::class, PredefinedItem::class)] - public ?string $predefinedItem; + public function __construct( + /** + * Optional. + * A reference to a field to display. + */ + public ?FieldSelector $firstValue = null, + /** + * Optional. + * A reference to a field to display. This may only be populated if the firstValue field is populated. + */ + public ?FieldSelector $secondValue = null, + /** + * Optional. + * A predefined item to display. Only one of firstValue or predefinedItem may be set. + */ + #[Choice([ + PredefinedItem::FLIGHT_NUMBER_AND_OPERATING_FLIGHT_NUMBER, + PredefinedItem::FREQUENT_FLYER_PROGRAM_NAME_AND_NUMBER, + PredefinedItem::PREDEFINED_ITEM_UNSPECIFIED, + ])] + #[Cast(LegacyValueCaster::class, PredefinedItem::class)] + public ?string $predefinedItem = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/DateTime.php b/src/Google/Components/Common/DateTime.php index 145ac7f..5ed69d3 100644 --- a/src/Google/Components/Common/DateTime.php +++ b/src/Google/Components/Common/DateTime.php @@ -2,18 +2,22 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\ISO8601DateCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\NotBlank; class DateTime extends Component { - /** - * Required. - * An ISO 8601 extended format date/time with optional offset. - */ - #[Required] - #[CastWith(ISO8601DateCaster::class)] - public ?string $date; + public function __construct( + /** + * Required. + * An ISO 8601 extended format date/time with optional offset. + */ + #[NotBlank] + #[Cast(ISO8601DateCaster::class)] + public string $date, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/GroupingInfo.php b/src/Google/Components/Common/GroupingInfo.php index 6cfd406..bacf2c4 100644 --- a/src/Google/Components/Common/GroupingInfo.php +++ b/src/Google/Components/Common/GroupingInfo.php @@ -6,18 +6,21 @@ class GroupingInfo extends Component { - /** - * Optional. - * Optional index for sorting the passes when they are grouped with other passes. Passes with lower sort index - * are shown before passes with higher sort index. If unspecified, the value is assumed to be INT_MAX. For two - * passes with same sort index, the sorting behavior is undefined. - */ - public ?int $sortIndex; - - /** - * Optional - * Optional grouping ID for grouping the passes with the same ID visually together. Grouping with different - * types of passes is allowed. - */ - public ?string $groupingId; + public function __construct( + /** + * Optional. + * Optional index for sorting the passes when they are grouped with other passes. Passes with lower sort index + * are shown before passes with higher sort index. If unspecified, the value is assumed to be INT_MAX. For two + * passes with same sort index, the sorting behavior is undefined. + */ + public ?int $sortIndex = null, + /** + * Optional. + * Optional grouping ID for grouping the passes with the same ID visually together. Grouping with different + * types of passes is allowed. + */ + public ?string $groupingId = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/Image.php b/src/Google/Components/Common/Image.php index 3b8337e..d71aa8e 100644 --- a/src/Google/Components/Common/Image.php +++ b/src/Google/Components/Common/Image.php @@ -3,16 +3,20 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class Image extends Component { - /** - * Required. - * The location of the image. URIs must have a scheme. - */ - #[Required] - public ?ImageUri $sourceUri; + public function __construct( + /** + * Required. + * The location of the image. URIs must have a scheme. + */ + #[NotBlank] + public ImageUri $sourceUri, + ) { + parent::__construct(); + } /** * Helper method for creating new localized string: diff --git a/src/Google/Components/Common/ImageModuleData.php b/src/Google/Components/Common/ImageModuleData.php index a880749..ec14fe6 100644 --- a/src/Google/Components/Common/ImageModuleData.php +++ b/src/Google/Components/Common/ImageModuleData.php @@ -3,20 +3,23 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class ImageModuleData extends Component { - /** - * Required. - * A 100% width image. - */ - #[Required] - public ?Image $mainImage; - - /** - * Optional. - * The ID associated with an image module. This field is here to enable ease of management of image modules. - */ - public ?string $id; + public function __construct( + /** + * Required. + * A 100% width image. + */ + #[NotBlank] + public Image $mainImage, + /** + * Optional. + * The ID associated with an image module. This field is here to enable ease of management of image modules. + */ + public ?string $id = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/ImageUri.php b/src/Google/Components/Common/ImageUri.php index 477f2c8..3f25416 100644 --- a/src/Google/Components/Common/ImageUri.php +++ b/src/Google/Components/Common/ImageUri.php @@ -3,10 +3,14 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class ImageUri extends Component { - #[Required] - public ?string $uri; + public function __construct( + #[NotBlank] + public string $uri, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/LatLongPoint.php b/src/Google/Components/Common/LatLongPoint.php index 514135f..b5a3a84 100644 --- a/src/Google/Components/Common/LatLongPoint.php +++ b/src/Google/Components/Common/LatLongPoint.php @@ -3,23 +3,26 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class LatLongPoint extends Component { - /** - * Required. - * The latitude specified as any value in the range of -90.0 through +90.0, both inclusive. Values outside - * these bounds will be rejected. - */ - #[Required] - public ?float $latitude; - - /** - * Required. - * The longitude specified in the range -180.0 through +180.0, both inclusive. Values outside these bounds - * will be rejected. - */ - #[Required] - public ?float $longitude; + public function __construct( + /** + * Required. + * The latitude specified as any value in the range of -90.0 through +90.0, both inclusive. Values outside + * these bounds will be rejected. + */ + #[NotBlank] + public float $latitude, + /** + * Required. + * The longitude specified in the range -180.0 through +180.0, both inclusive. Values outside these bounds + * will be rejected. + */ + #[NotBlank] + public float $longitude, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/LinksModuleData.php b/src/Google/Components/Common/LinksModuleData.php index 4ccdee9..bb0ee46 100644 --- a/src/Google/Components/Common/LinksModuleData.php +++ b/src/Google/Components/Common/LinksModuleData.php @@ -2,17 +2,21 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; class LinksModuleData extends Component { - /** - * The list of URIs. - * - * @var Uri[] - */ - #[CastWith(ArrayCaster::class, Uri::class)] - public array $uris = []; + public function __construct( + /** + * The list of URIs. + * + * @var Uri[] + */ + #[Cast(ArrayCaster::class, Uri::class)] + public array $uris = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/LocalizedString.php b/src/Google/Components/Common/LocalizedString.php index 5af9cae..a21a78a 100644 --- a/src/Google/Components/Common/LocalizedString.php +++ b/src/Google/Components/Common/LocalizedString.php @@ -2,28 +2,32 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Type; class LocalizedString extends Component { - /** - * Optional. - * Contains the translations for the string. - * - * @var TranslatedString[] - */ - #[CastWith(ArrayCaster::class, TranslatedString::class)] - public array $translatedValues = []; - - /** - * Required. - * Contains the string to be displayed if no appropriate translation is available. - */ - #[Required] - public ?TranslatedString $defaultValue; + public function __construct( + /** + * Required. + * Contains the string to be displayed if no appropriate translation is available. + */ + public TranslatedString $defaultValue, + /** + * Optional. + * Contains the translations for the string. + * + * @var TranslatedString[] + */ + #[All([new Type(TranslatedString::class)])] + #[Cast(ArrayCaster::class, TranslatedString::class)] + public array $translatedValues = [], + ) { + parent::__construct(); + } /** * Helper method for creating new localized string: @@ -33,4 +37,9 @@ public static function make(string $language, string $value): static { return new static(defaultValue: new TranslatedString(language: $language, value: $value)); } + + public static function create(array $values): static + { + return new self(...$values); + } } diff --git a/src/Google/Components/Common/Message.php b/src/Google/Components/Common/Message.php index 04366a4..23d63d8 100644 --- a/src/Google/Components/Common/Message.php +++ b/src/Google/Components/Common/Message.php @@ -2,55 +2,53 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\MessageType; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class Message extends Component { - /** - * Optional. - * The message header. - */ - public ?string $header; - - /** - * Optional. - * The message body. - */ - public ?string $body; - - /** - * Optional. - * The period of time that the message will be displayed to users. - */ - public ?TimeInterval $displayInterval; - - /** - * Optional. - * The ID associated with a message. This field is here to enable ease of management of messages. - */ - public ?string $id; - - /** - * Optional. - * The type of the message. Currently, this can only be set for offers. - */ - #[ValueIn([MessageType::EXPIRATION_NOTIFICATION, MessageType::MESSAGE_TYPE_UNSPECIFIED, MessageType::TEXT])] - #[CastWith(LegacyValueCaster::class, MessageType::class)] - public ?string $messageType; - - /** - * Optional. - * Translated strings for the message header. - */ - public ?LocalizedString $localizedHeader; - - /** - * Optional. - * Translated strings for the message body. - */ - public ?LocalizedString $localizedBody; + public function __construct( + /** + * Optional. + * The message header. + */ + public ?string $header = null, + /** + * Optional. + * The message body. + */ + public ?string $body = null, + /** + * Optional. + * The period of time that the message will be displayed to users. + */ + public ?TimeInterval $displayInterval = null, + /** + * Optional. + * The ID associated with a message. This field is here to enable ease of management of messages. + */ + public ?string $id = null, + /** + * Optional. + * The type of the message. Currently, this can only be set for offers. + */ + #[Choice([MessageType::EXPIRATION_NOTIFICATION, MessageType::MESSAGE_TYPE_UNSPECIFIED, MessageType::TEXT])] + #[Cast(LegacyValueCaster::class, MessageType::class)] + public ?string $messageType = null, + /** + * Optional. + * Translated strings for the message header. + */ + public ?LocalizedString $localizedHeader = null, + /** + * Optional. + * Translated strings for the message body. + */ + public ?LocalizedString $localizedBody = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/Money.php b/src/Google/Components/Common/Money.php index 4ddef42..d69da99 100644 --- a/src/Google/Components/Common/Money.php +++ b/src/Google/Components/Common/Money.php @@ -4,20 +4,24 @@ use Chiiya\Passes\Common\Component; use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class Money extends Component { - /** - * Required. - * The unit of money amount in micros. For example, $1 USD would be represented as 1000000 micros. - */ - #[Required] - public ?string $micros; - - /** - * Required. - * The currency code, such as "USD" or "EUR.". - */ - #[Required] - public ?string $currencyCode; + public function __construct( + /** + * Required. + * The unit of money amount in micros. For example, $1 USD would be represented as 1000000 micros. + */ + #[NotBlank] + public string $micros, + /** + * Required. + * The currency code, such as "USD" or "EUR.". + */ + #[NotBlank] + public string $currencyCode, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/Pagination.php b/src/Google/Components/Common/Pagination.php index b7775f8..de50262 100644 --- a/src/Google/Components/Common/Pagination.php +++ b/src/Google/Components/Common/Pagination.php @@ -3,20 +3,21 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; class Pagination extends Component { - /** - * Required. - * Number of results returned in this page. - */ - #[Required] - public ?int $resultsPerPage; - - /** - * Optional. - * Page token to send to fetch the next page. - */ - public ?string $nextPageToken; + public function __construct( + /** + * Required. + * Number of results returned in this page. + */ + public int $resultsPerPage, + /** + * Optional. + * Page token to send to fetch the next page. + */ + public ?string $nextPageToken = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/Review.php b/src/Google/Components/Common/Review.php index 254e5e4..7521813 100644 --- a/src/Google/Components/Common/Review.php +++ b/src/Google/Components/Common/Review.php @@ -6,6 +6,10 @@ class Review extends Component { - /** The review comments. */ - public ?string $comments; + public function __construct( + /** The review comments. */ + public ?string $comments = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/RotatingBarcode.php b/src/Google/Components/Common/RotatingBarcode.php index c3c618d..606896d 100644 --- a/src/Google/Components/Common/RotatingBarcode.php +++ b/src/Google/Components/Common/RotatingBarcode.php @@ -2,77 +2,74 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\BarcodeRenderEncoding; use Chiiya\Passes\Google\Enumerators\BarcodeType; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class RotatingBarcode extends Component { - /** - * Required - * The type of barcode. - */ - #[Required] - #[ValueIn([ - BarcodeType::BARCODE_TYPE_UNSPECIFIED, - BarcodeType::AZTEC, - BarcodeType::CODE_39, - BarcodeType::CODE_128, - BarcodeType::CODABAR, - BarcodeType::DATA_MATRIX, - BarcodeType::EAN_8, - BarcodeType::EAN_13, - BarcodeType::ITF_14, - BarcodeType::PDF_417, - BarcodeType::QR_CODE, - BarcodeType::UPC_A, - BarcodeType::TEXT_ONLY, - ])] - #[CastWith(LegacyValueCaster::class, BarcodeType::class)] - public ?string $type; - - /** - * Optional - * The render encoding for the barcode. When specified, barcode is rendered in the given encoding. - * Otherwise best known encoding is chosen by Google. - */ - #[ValueIn([BarcodeRenderEncoding::UTF_8, BarcodeRenderEncoding::RENDER_ENCODING_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, BarcodeRenderEncoding::class)] - public ?string $renderEncoding; - - /** - * Required. - * String encoded barcode value. - * This string supports the following substitutions: - * {totp_value_n}: Replaced with the TOTP value (see TotpDetails.parameters). - * {totp_timestamp_millis}: Replaced with the timestamp (millis since epoch) at which the barcode was generated. - * {totp_timestamp_seconds}: Replaced with the timestamp (seconds since epoch) at which the barcode was generated. - */ - #[Required] - public ?string $valuePattern; - - /** - * Required - * Details used to evaluate the {totp_value_n} substitutions. - */ - #[Required] - public ?TotpDetails $totpDetails; - - /** - * Optional. - * An optional text that will override the default text that shows under the barcode. This field is intended - * for a human readable equivalent of the barcode value, used when the barcode cannot be scanned. - */ - public ?string $alternateText; - - /** - * Optional. - * Optional text that will be shown when the barcode is hidden behind a click action. This happens in cases - * where a pass has Smart Tap enabled. If not specified, a default is chosen by Google. - */ - public ?LocalizedString $showCodeText; + public function __construct( + /** + * Required + * The type of barcode. + */ + #[NotBlank] + #[Choice([ + BarcodeType::BARCODE_TYPE_UNSPECIFIED, + BarcodeType::AZTEC, + BarcodeType::CODE_39, + BarcodeType::CODE_128, + BarcodeType::CODABAR, + BarcodeType::DATA_MATRIX, + BarcodeType::EAN_8, + BarcodeType::EAN_13, + BarcodeType::ITF_14, + BarcodeType::PDF_417, + BarcodeType::QR_CODE, + BarcodeType::UPC_A, + BarcodeType::TEXT_ONLY, + ])] + #[Cast(LegacyValueCaster::class, BarcodeType::class)] + public string $type, + /** + * Required. + * String encoded barcode value. + * This string supports the following substitutions: + * {totp_value_n}: Replaced with the TOTP value (see `totpDetails.parameters`). + * {totp_timestamp_millis}: Replaced with the timestamp (millis since epoch) at which the barcode was generated. + * {totp_timestamp_seconds}: Replaced with the timestamp (seconds since epoch) at which the barcode was generated. + */ + public string $valuePattern, + /** + * Required + * Details used to evaluate the {totp_value_n} substitutions. + */ + public TotpDetails $totpDetails, + /** + * Optional + * The render encoding for the barcode. When specified, barcode is rendered in the given encoding. + * Otherwise, best known encoding is chosen by Google. + */ + #[Choice([BarcodeRenderEncoding::UTF_8, BarcodeRenderEncoding::RENDER_ENCODING_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, BarcodeRenderEncoding::class)] + public ?string $renderEncoding = null, + /** + * Optional. + * An optional text that will override the default text that shows under the barcode. This field is intended + * for a human-readable equivalent of the barcode value, used when the barcode cannot be scanned. + */ + public ?string $alternateText = null, + /** + * Optional. + * Optional text that will be shown when the barcode is hidden behind a click action. This happens in cases + * where a pass has Smart Tap enabled. If not specified, a default is chosen by Google. + */ + public ?LocalizedString $showCodeText = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/SecurityAnimation.php b/src/Google/Components/Common/SecurityAnimation.php index dcd8878..36a4b89 100644 --- a/src/Google/Components/Common/SecurityAnimation.php +++ b/src/Google/Components/Common/SecurityAnimation.php @@ -3,17 +3,21 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\AnimationType; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class SecurityAnimation extends Component { - /** - * Required. - * Type of animation. - */ - #[Required] - #[ValueIn([AnimationType::ANIMATION_UNSPECIFIED, AnimationType::FOIL_SHIMMER])] - public ?string $animationType; + public function __construct( + /** + * Required. + * Type of animation. + */ + #[NotBlank] + #[Choice([AnimationType::ANIMATION_UNSPECIFIED, AnimationType::FOIL_SHIMMER])] + public string $animationType, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/TextModuleData.php b/src/Google/Components/Common/TextModuleData.php index 6b9a7b2..f37903a 100644 --- a/src/Google/Components/Common/TextModuleData.php +++ b/src/Google/Components/Common/TextModuleData.php @@ -3,41 +3,41 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxLength; +use Symfony\Component\Validator\Constraints\Length; class TextModuleData extends Component { - /** - * Optional. - * The header of the Text Module. Recommended maximum length is 35 characters to ensure full string is - * displayed on smaller screens. - */ - #[MaxLength(35)] - public ?string $header; - - /** - * Optional. - * The body of the Text Module, which is defined as an uninterrupted string. Recommended maximum length is - * 500 characters to ensure full string is displayed on smaller screens. - */ - #[MaxLength(500)] - public ?string $body; - - /** - * Optional. - * Translated strings for the header. - */ - public ?LocalizedString $localizedHeader; - - /** - * Optional. - * Translated strings for the body. - */ - public ?LocalizedString $localizedBody; - - /** - * Optional. - * The ID associated with a text module. This field is here to enable ease of management of text modules. - */ - public ?string $id; + public function __construct( + /** + * Optional. + * The header of the Text Module. Recommended maximum length is 35 characters to ensure full string is + * displayed on smaller screens. + */ + #[Length(max: 35)] + public ?string $header = null, + /** + * Optional. + * The body of the Text Module, which is defined as an uninterrupted string. Recommended maximum length is + * 500 characters to ensure full string is displayed on smaller screens. + */ + #[Length(max: 500)] + public ?string $body = null, + /** + * Optional. + * Translated strings for the header. + */ + public ?LocalizedString $localizedHeader = null, + /** + * Optional. + * Translated strings for the body. + */ + public ?LocalizedString $localizedBody = null, + /** + * Optional. + * The ID associated with a text module. This field is here to enable ease of management of text modules. + */ + public ?string $id = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/TimeInterval.php b/src/Google/Components/Common/TimeInterval.php index b88ac87..7704f83 100644 --- a/src/Google/Components/Common/TimeInterval.php +++ b/src/Google/Components/Common/TimeInterval.php @@ -3,21 +3,21 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; class TimeInterval extends Component { - /** - * Required. - * Start time of the interval. - */ - #[Required] - public ?DateTime $start; - - /** - * Required. - * End time of the interval. - */ - #[Required] - public ?DateTime $end; + public function __construct( + /** + * Required. + * Start time of the interval. + */ + public ?DateTime $start, + /** + * Required. + * End time of the interval. + */ + public ?DateTime $end, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/TotpDetails.php b/src/Google/Components/Common/TotpDetails.php index 110f269..cba4f82 100644 --- a/src/Google/Components/Common/TotpDetails.php +++ b/src/Google/Components/Common/TotpDetails.php @@ -2,36 +2,38 @@ namespace Chiiya\Passes\Google\Components\Common; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\TotpAlgorithm; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class TotpDetails extends Component { - /** - * Required. - * The time interval used for the TOTP value generation, in milliseconds. - */ - #[Required] - public ?string $periodMillis; - - /** - * Required. - * The TOTP algorithm used to generate the OTP. - */ - #[Required] - #[ValueIn([TotpAlgorithm::TOTP_ALGORITHM_UNSPECIFIED, TotpAlgorithm::TOTP_SHA1])] - public ?string $algorithm; - - /** - * Required. - * The TOTP parameters for each of the {totp_value_*} substitutions. - * The TotpParameters at index n is used for the {totp_value_n} substitution. - */ - #[Required] - #[CastWith(ArrayCaster::class, TotpParameters::class)] - public ?array $parameters; + public function __construct( + /** + * Required. + * The time interval used for the TOTP value generation, in milliseconds. + */ + #[NotBlank] + public string $periodMillis, + /** + * Required. + * The TOTP algorithm used to generate the OTP. + */ + #[NotBlank] + #[Choice([TotpAlgorithm::TOTP_ALGORITHM_UNSPECIFIED, TotpAlgorithm::TOTP_SHA1])] + public string $algorithm, + /** + * Required. + * The TOTP parameters for each of the {totp_value_*} substitutions. + * The TotpParameters at index n is used for the {totp_value_n} substitution. + */ + #[NotBlank] + #[Cast(ArrayCaster::class, TotpParameters::class)] + public array $parameters = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Common/TotpParameters.php b/src/Google/Components/Common/TotpParameters.php index 4ba4b1c..7b7c5fd 100644 --- a/src/Google/Components/Common/TotpParameters.php +++ b/src/Google/Components/Common/TotpParameters.php @@ -3,23 +3,25 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class TotpParameters extends Component { - /** - * Required. - * The secret key used for the TOTP value generation, encoded as a Base16 string. - */ - #[Required] - public ?string $key; - - /** - * Required. - * The length of the TOTP value in decimal digits. - */ - #[Required] - public ?int $valueLength; + public function __construct( + /** + * Required. + * The secret key used for the TOTP value generation, encoded as a Base16 string. + */ + #[NotBlank] + public string $key, + /** + * Required. + * The length of the TOTP value in decimal digits. + */ + public int $valueLength, + ) { + parent::__construct(); + } /** * Helper method for creating new localized string, eg: diff --git a/src/Google/Components/Common/TranslatedString.php b/src/Google/Components/Common/TranslatedString.php index f8c9f32..5addea2 100644 --- a/src/Google/Components/Common/TranslatedString.php +++ b/src/Google/Components/Common/TranslatedString.php @@ -3,21 +3,29 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class TranslatedString extends Component { - /** - * Required. - * Represents the BCP 47 language tag. Example values are "en-US", "en-GB", "de", or "de-AT". - */ - #[Required] - public ?string $language; + public function __construct( + /** + * Required. + * Represents the BCP 47 language tag. Example values are "en-US", "en-GB", "de", or "de-AT". + */ + #[NotBlank] + public string $language, + /** + * Required. + * The UTF-8 encoded translated string. + */ + #[NotBlank] + public string $value, + ) { + parent::__construct(); + } - /** - * Required. - * The UTF-8 encoded translated string. - */ - #[Required] - public ?string $value; + public static function create(array $values): static + { + return new self(...$values); + } } diff --git a/src/Google/Components/Common/Uri.php b/src/Google/Components/Common/Uri.php index c1b8961..fd88ef5 100644 --- a/src/Google/Components/Common/Uri.php +++ b/src/Google/Components/Common/Uri.php @@ -3,38 +3,39 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; class Uri extends Component { - /** - * Required. - * The location of a web page, image, or other resource. URIs must have a scheme. - */ - #[Required] - public ?string $uri; - - /** - * Required in some cases. - * The URI's title appearing in the app as text. Recommended maximum is 20 characters to ensure full string - * is displayed on smaller screens. - */ - #[MaxLength(20)] - public ?string $description; - - /** - * Optional. - * Translated strings for the description. Recommended maximum is 20 characters to ensure full string is - * displayed on smaller screens. - */ - public ?LocalizedString $localizedDescription; - - /** - * Optional. - * The ID associated with a uri. This field is here to enable ease of management of uris. - */ - public ?string $id; + public function __construct( + /** + * Required. + * The location of a web page, image, or other resource. URIs must have a scheme. + */ + #[NotBlank] + public string $uri, + /** + * Required in some cases. + * The URI's title appearing in the app as text. Recommended maximum is 20 characters to ensure full string + * is displayed on smaller screens. + */ + #[Length(max: 20)] + public ?string $description = null, + /** + * Optional. + * Translated strings for the description. Recommended maximum is 20 characters to ensure full string is + * displayed on smaller screens. + */ + public ?LocalizedString $localizedDescription = null, + /** + * Optional. + * The ID associated with a uri. This field is here to enable ease of management of uris. + */ + public ?string $id = null, + ) { + parent::__construct(); + } /** * Helper method for creating new uri: diff --git a/src/Google/Components/EventTicket/EventDateTime.php b/src/Google/Components/EventTicket/EventDateTime.php index 0f049e5..be7e0b3 100644 --- a/src/Google/Components/EventTicket/EventDateTime.php +++ b/src/Google/Components/EventTicket/EventDateTime.php @@ -2,51 +2,55 @@ namespace Chiiya\Passes\Google\Components\EventTicket; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\ISO8601DateCaster; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Enumerators\DoorsOpenLabel; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class EventDateTime extends Component { - /** - * Optional. - * The date/time when the doors open at the venue. - * ISO 8601 + optional offset. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $doorsOpen; - - /** - * Optional. - * The date/time when the event starts. - * ISO 8601 + optional offset. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $start; - - /** - * Optional. - * The date/time when the event ends. - * ISO 8601 + optional offset. - */ - #[CastWith(ISO8601DateCaster::class)] - public ?string $end; - - /** - * Optional. - * The label to use for the doors open value (doorsOpen) on the card detail view. - */ - #[ValueIn([DoorsOpenLabel::DOORS_OPEN, DoorsOpenLabel::GATES_OPEN, DoorsOpenLabel::DOORS_OPEN_LABEL_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, DoorsOpenLabel::class)] - public ?string $doorsOpenLabel; - - /** - * Optional. - * A custom label to use for the doors open value (doorsOpen) on the card detail view. - */ - public ?LocalizedString $customDoorsOpenLabel; + public function __construct( + /** + * Optional. + * The date/time when the doors open at the venue. + * ISO 8601 + optional offset. + */ + #[Cast(ISO8601DateCaster::class)] + public ?string $doorsOpen = null, + /** + * Optional. + * The date/time when the event starts. + * ISO 8601 + optional offset. + */ + #[Cast(ISO8601DateCaster::class)] + public ?string $start = null, + /** + * Optional. + * The date/time when the event ends. + * ISO 8601 + optional offset. + */ + #[Cast(ISO8601DateCaster::class)] + public ?string $end = null, + /** + * Optional. + * The label to use for the doors open value (doorsOpen) on the card detail view. + */ + #[Choice([ + DoorsOpenLabel::DOORS_OPEN, + DoorsOpenLabel::GATES_OPEN, + DoorsOpenLabel::DOORS_OPEN_LABEL_UNSPECIFIED, + ])] + #[Cast(LegacyValueCaster::class, DoorsOpenLabel::class)] + public ?string $doorsOpenLabel = null, + /** + * Optional. + * A custom label to use for the doors open value (doorsOpen) on the card detail view. + */ + public ?LocalizedString $customDoorsOpenLabel = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/EventTicket/EventReservationInfo.php b/src/Google/Components/EventTicket/EventReservationInfo.php index 8bd8915..b0293ac 100644 --- a/src/Google/Components/EventTicket/EventReservationInfo.php +++ b/src/Google/Components/EventTicket/EventReservationInfo.php @@ -3,15 +3,19 @@ namespace Chiiya\Passes\Google\Components\EventTicket; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class EventReservationInfo extends Component { - /** - * Required. - * The confirmation code of the event reservation. This may also take the form of an "order number", - * "confirmation number", "reservation number", or other equivalent. - */ - #[Required] - public ?string $confirmationCode; + public function __construct( + /** + * Required. + * The confirmation code of the event reservation. This may also take the form of an "order number", + * "confirmation number", "reservation number", or other equivalent. + */ + #[NotBlank] + public string $confirmationCode, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/EventTicket/EventSeat.php b/src/Google/Components/EventTicket/EventSeat.php index 59e1070..ac1e7b6 100644 --- a/src/Google/Components/EventTicket/EventSeat.php +++ b/src/Google/Components/EventTicket/EventSeat.php @@ -7,27 +7,28 @@ class EventSeat extends Component { - /** - * Optional. - * The seat number, such as "1", "2", "3", or any other seat identifier. - */ - public ?LocalizedString $seat; - - /** - * Optional. - * The row of the seat, such as "1", E", "BB", or "A5". - */ - public ?LocalizedString $row; - - /** - * Optional. - * The section of the seat, such as "121". - */ - public ?LocalizedString $section; - - /** - * Optional. - * The gate the ticket holder should enter to get to their seat, such as "A" or "West". - */ - public ?LocalizedString $gate; + public function __construct( + /** + * Optional. + * The seat number, such as "1", "2", "3", or any other seat identifier. + */ + public ?LocalizedString $seat = null, + /** + * Optional. + * The row of the seat, such as "1", E", "BB", or "A5". + */ + public ?LocalizedString $row = null, + /** + * Optional. + * The section of the seat, such as "121". + */ + public ?LocalizedString $section = null, + /** + * Optional. + * The gate the ticket holder should enter to get to their seat, such as "A" or "West". + */ + public ?LocalizedString $gate = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/EventTicket/EventVenue.php b/src/Google/Components/EventTicket/EventVenue.php index 3d9b4a9..c4c26d7 100644 --- a/src/Google/Components/EventTicket/EventVenue.php +++ b/src/Google/Components/EventTicket/EventVenue.php @@ -3,23 +3,23 @@ namespace Chiiya\Passes\Google\Components\EventTicket; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\LocalizedString; class EventVenue extends Component { - /** - * Required. - * The name of the venue, such as "AT&T Park". - */ - #[Required] - public ?LocalizedString $name; - - /** - * Required. - * The address of the venue, such as "24 Willie Mays Plaza\nSan Francisco, CA 94107". Address lines - * are separated by line feed (\n) characters. - */ - #[Required] - public ?LocalizedString $address; + public function __construct( + /** + * Required. + * The name of the venue, such as "AT&T Park". + */ + public LocalizedString $name, + /** + * Required. + * The address of the venue, such as "24 Willie Mays Plaza\nSan Francisco, CA 94107". Address lines + * are separated by line feed (\n) characters. + */ + public LocalizedString $address, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/AirportInfo.php b/src/Google/Components/Flight/AirportInfo.php index f304219..314c28e 100644 --- a/src/Google/Components/Flight/AirportInfo.php +++ b/src/Google/Components/Flight/AirportInfo.php @@ -3,36 +3,37 @@ namespace Chiiya\Passes\Google\Components\Flight; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\LocalizedString; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; class AirportInfo extends Component { - /** - * Required. - * Three character IATA airport code. This is a required field for origin and destination. - */ - #[Required] - #[MaxLength(3)] - public ?string $airportIataCode; - - /** - * Optional. - * Terminal name. Eg: "INTL" or "I". - */ - public ?string $terminal; - - /** - * Optional. - * A name of the gate. Eg: "B59" or "59". - */ - public ?string $gate; - - /** - * Optional. - * Optional field that overrides the airport city name defined by IATA. By default, Google takes the - * airportIataCode provided and maps it to the official airport city name defined by IATA. - */ - public ?LocalizedString $airportNameOverride; + public function __construct( + /** + * Required. + * Three character IATA airport code. This is a required field for origin and destination. + */ + #[NotBlank] + #[Length(max: 3)] + public string $airportIataCode, + /** + * Optional. + * Terminal name. Eg: "INTL" or "I". + */ + public ?string $terminal = null, + /** + * Optional. + * A name of the gate. Eg: "B59" or "59". + */ + public ?string $gate = null, + /** + * Optional. + * Optional field that overrides the airport city name defined by IATA. By default, Google takes the + * airportIataCode provided and maps it to the official airport city name defined by IATA. + */ + public ?LocalizedString $airportNameOverride = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/BoardingAndSeatingInfo.php b/src/Google/Components/Flight/BoardingAndSeatingInfo.php index f75c753..e221b8e 100644 --- a/src/Google/Components/Flight/BoardingAndSeatingInfo.php +++ b/src/Google/Components/Flight/BoardingAndSeatingInfo.php @@ -2,67 +2,64 @@ namespace Chiiya\Passes\Google\Components\Flight; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Enumerators\Flight\BoardingDoor; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class BoardingAndSeatingInfo extends Component { - /** - * Optional. - * The value of boarding group (or zone) this passenger shall board with. - */ - public ?string $boardingGroup; - - /** - * Optional. - * The value of passenger seat. If there is no specific identifier, use seatAssignment instead. - */ - public ?string $seatNumber; - - /** - * Optional. - * The value of the seat class, eg: "Economy" or "Economy Plus". - */ - public ?string $seatClass; - - /** - * Optional. - * A small image shown above the boarding barcode. Airlines can use it to communicate any special - * boarding privileges. - */ - public ?Image $boardingPrivilegeImage; - - /** - * Optional. - * The value of boarding position, e.g. "76". - */ - public ?string $boardingPosition; - - /** - * Optional. - * The sequence number on the boarding pass. This usually matches the sequence in which the passengers - * checked in. Airline might use the number for manual boarding and bag tags. - */ - public ?string $sequenceNumber; - - /** - * Optional. - * Set this field only if this flight boards through more than one door or bridge and you want to explicitly - * print the door location on the boarding pass. Most airlines route their passengers to the right door or bridge - * by refering to doors/bridges by the seatClass. In those cases boardingDoor should not be set. - */ - #[ValueIn([BoardingDoor::BACK, BoardingDoor::FRONT, BoardingDoor::BOARDING_DOOR_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, BoardingDoor::class)] - public ?string $boardingDoor; - - /** - * Optional. - * The passenger's seat assignment. To be used when there is no specific identifier to use in seatNumber. - */ - public ?LocalizedString $seatAssignment; + public function __construct( + /** + * Optional. + * The value of boarding group (or zone) this passenger shall board with. + */ + public ?string $boardingGroup = null, + /** + * Optional. + * The value of passenger seat. If there is no specific identifier, use seatAssignment instead. + */ + public ?string $seatNumber = null, + /** + * Optional. + * The value of the seat class, eg: "Economy" or "Economy Plus". + */ + public ?string $seatClass = null, + /** + * Optional. + * A small image shown above the boarding barcode. Airlines can use it to communicate any special + * boarding privileges. + */ + public ?Image $boardingPrivilegeImage = null, + /** + * Optional. + * The value of boarding position, e.g. "76". + */ + public ?string $boardingPosition = null, + /** + * Optional. + * The sequence number on the boarding pass. This usually matches the sequence in which the passengers + * checked in. Airline might use the number for manual boarding and bag tags. + */ + public ?string $sequenceNumber = null, + /** + * Optional. + * Set this field only if this flight boards through more than one door or bridge and you want to explicitly + * print the door location on the boarding pass. Most airlines route their passengers to the right door or bridge + * by refering to doors/bridges by the seatClass. In those cases boardingDoor should not be set. + */ + #[Choice([BoardingDoor::BACK, BoardingDoor::FRONT, BoardingDoor::BOARDING_DOOR_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, BoardingDoor::class)] + public ?string $boardingDoor = null, + /** + * Optional. + * The passenger's seat assignment. To be used when there is no specific identifier to use in seatNumber. + */ + public ?LocalizedString $seatAssignment = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/BoardingAndSeatingPolicy.php b/src/Google/Components/Flight/BoardingAndSeatingPolicy.php index 952b4fc..e454ac1 100644 --- a/src/Google/Components/Flight/BoardingAndSeatingPolicy.php +++ b/src/Google/Components/Flight/BoardingAndSeatingPolicy.php @@ -2,41 +2,44 @@ namespace Chiiya\Passes\Google\Components\Flight; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\Flight\BoardingPolicy; use Chiiya\Passes\Google\Enumerators\Flight\SeatClassPolicy; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class BoardingAndSeatingPolicy extends Component { - /** - * Optional. - * Indicates the policy the airline uses for boarding. If unset, Google will default to ZONE_BASED. - * - * @see BoardingPolicy - */ - #[ValueIn([ - BoardingPolicy::BOARDING_POLICY_UNSPECIFIED, - BoardingPolicy::ZONE_BASED, - BoardingPolicy::GROUP_BASED, - BoardingPolicy::BOARDING_POLICY_OTHER, - ])] - #[CastWith(LegacyValueCaster::class, BoardingPolicy::class)] - public ?string $boardingPolicy; - - /** - * Optional. - * Seating policy which dictates how we display the seat class. If unset, Google will default to CABIN_BASED. - */ - #[ValueIn([ - SeatClassPolicy::SEAT_CLASS_POLICY_UNSPECIFIED, - SeatClassPolicy::CABIN_BASED, - SeatClassPolicy::CLASS_BASED, - SeatClassPolicy::TIER_BASED, - SeatClassPolicy::SEAT_CLASS_POLICY_OTHER, - ])] - #[CastWith(LegacyValueCaster::class, SeatClassPolicy::class)] - public ?string $seatClassPolicy; + public function __construct( + /** + * Optional. + * Indicates the policy the airline uses for boarding. If unset, Google will default to ZONE_BASED. + * + * @see BoardingPolicy + */ + #[Choice([ + BoardingPolicy::BOARDING_POLICY_UNSPECIFIED, + BoardingPolicy::ZONE_BASED, + BoardingPolicy::GROUP_BASED, + BoardingPolicy::BOARDING_POLICY_OTHER, + ])] + #[Cast(LegacyValueCaster::class, BoardingPolicy::class)] + public ?string $boardingPolicy = null, + /** + * Optional. + * Seating policy which dictates how we display the seat class. If unset, Google will default to CABIN_BASED. + */ + #[Choice([ + SeatClassPolicy::SEAT_CLASS_POLICY_UNSPECIFIED, + SeatClassPolicy::CABIN_BASED, + SeatClassPolicy::CLASS_BASED, + SeatClassPolicy::TIER_BASED, + SeatClassPolicy::SEAT_CLASS_POLICY_OTHER, + ])] + #[Cast(LegacyValueCaster::class, SeatClassPolicy::class)] + public ?string $seatClassPolicy = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/FlightCarrier.php b/src/Google/Components/Flight/FlightCarrier.php index b1aea85..4905e77 100644 --- a/src/Google/Components/Flight/FlightCarrier.php +++ b/src/Google/Components/Flight/FlightCarrier.php @@ -3,51 +3,53 @@ namespace Chiiya\Passes\Google\Components\Flight; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxLength; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; class FlightCarrier extends Component { - /** - * Required. - * Two character IATA airline code of the marketing carrier (as opposed to operating carrier). - * Exactly one of this or carrierIcaoCode needs to be provided for carrier and operatingCarrier. - */ - #[MaxLength(2)] - public ?string $carrierIataCode; - - /** - * Required. - * Three character ICAO airline code of the marketing carrier (as opposed to operating carrier). Exactly - * one of this or carrierIataCode needs to be provided for carrier and operatingCarrier. - */ - #[MaxLength(3)] - public ?string $carrierIcaoCode; - - /** - * Optional. - * A localized name of the airline specified by carrierIataCode. If unset, issuerName or - * localizedIssuerName from FlightClass will be used for display purposes. - */ - public ?LocalizedString $airlineName; - - /** - * Optional. - * A logo for the airline described by carrierIataCode and localizedAirlineName. This logo will be - * rendered at the top of the detailed card view. - */ - public ?Image $airlineLogo; - - /** - * Optional. - * The wide logo image of the ticket. This image is displayed in the top title bar instead of the logo and card title. - */ - public ?Image $wideAirlineLogo; - - /** - * Optional. - * A logo for the airline alliance, displayed above the QR code that the passenger scans to board. - */ - public ?Image $airlineAllianceLogo; + public function __construct( + /** + * Required. + * Two character IATA airline code of the marketing carrier (as opposed to operating carrier). + * Exactly one of this or carrierIcaoCode needs to be provided for carrier and operatingCarrier. + */ + #[NotBlank] + #[Length(max: 2)] + public string $carrierIataCode, + /** + * Required. + * Three character ICAO airline code of the marketing carrier (as opposed to operating carrier). Exactly + * one of this or carrierIataCode needs to be provided for carrier and operatingCarrier. + */ + #[NotBlank] + #[Length(max: 3)] + public string $carrierIcaoCode, + /** + * Optional. + * A localized name of the airline specified by carrierIataCode. If unset, issuerName or + * localizedIssuerName from FlightClass will be used for display purposes. + */ + public ?LocalizedString $airlineName = null, + /** + * Optional. + * A logo for the airline described by carrierIataCode and localizedAirlineName. This logo will be + * rendered at the top of the detailed card view. + */ + public ?Image $airlineLogo = null, + /** + * Optional. + * The wide logo image of the ticket. This image is displayed in the top title bar instead of the logo and card title. + */ + public ?Image $wideAirlineLogo = null, + /** + * Optional. + * A logo for the airline alliance, displayed above the QR code that the passenger scans to board. + */ + public ?Image $airlineAllianceLogo = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/FlightHeader.php b/src/Google/Components/Flight/FlightHeader.php index f08cda4..e5ff71e 100644 --- a/src/Google/Components/Flight/FlightHeader.php +++ b/src/Google/Components/Flight/FlightHeader.php @@ -3,35 +3,35 @@ namespace Chiiya\Passes\Google\Components\Flight; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; +use Symfony\Component\Validator\Constraints\NotBlank; class FlightHeader extends Component { - /** - * Required. - * Information about airline carrier. This is a required property of flightHeader. - */ - #[Required] - public ?FlightCarrier $carrier; - - /** - * Required. - * The flight number without IATA carrier code. This field should contain only digits. - * This is a required property of flightHeader. - */ - #[Required] - public ?string $flightNumber; - - /** - * Optional. - * Information about operating airline carrier. - */ - public ?FlightCarrier $operatingCarrier; - - /** - * Optional. - * The flight number used by the operating carrier without IATA carrier code. - * This field should contain only digits. - */ - public ?string $operatingFlightNumber; + public function __construct( + /** + * Required. + * Information about airline carrier. This is a required property of flightHeader. + */ + public FlightCarrier $carrier, + /** + * Required. + * The flight number without IATA carrier code. This field should contain only digits. + * This is a required property of flightHeader. + */ + #[NotBlank] + public string $flightNumber, + /** + * Optional. + * Information about operating airline carrier. + */ + public ?FlightCarrier $operatingCarrier = null, + /** + * Optional. + * The flight number used by the operating carrier without IATA carrier code. + * This field should contain only digits. + */ + public ?string $operatingFlightNumber = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/FrequentFlyerInfo.php b/src/Google/Components/Flight/FrequentFlyerInfo.php index ed05001..2acf903 100644 --- a/src/Google/Components/Flight/FrequentFlyerInfo.php +++ b/src/Google/Components/Flight/FrequentFlyerInfo.php @@ -3,21 +3,24 @@ namespace Chiiya\Passes\Google\Components\Flight; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\LocalizedString; +use Symfony\Component\Validator\Constraints\NotBlank; class FrequentFlyerInfo extends Component { - /** - * Optional. - * Frequent flyer program name. eg: "Lufthansa Miles & More". - */ - public ?LocalizedString $frequentFlyerProgramName; - - /** - * Required. - * Frequent flyer number. - */ - #[Required] - public ?string $frequentFlyerNumber; + public function __construct( + /** + * Required. + * Frequent flyer number. + */ + #[NotBlank] + public string $frequentFlyerNumber, + /** + * Optional. + * Frequent flyer program name. eg: "Lufthansa Miles & More". + */ + public ?LocalizedString $frequentFlyerProgramName = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Flight/ReservationInfo.php b/src/Google/Components/Flight/ReservationInfo.php index b0ed70e..b9cbcf5 100644 --- a/src/Google/Components/Flight/ReservationInfo.php +++ b/src/Google/Components/Flight/ReservationInfo.php @@ -6,22 +6,24 @@ class ReservationInfo extends Component { - /** - * Optional. - * Confirmation code needed to check into this flight. This is the number that the passenger would enter - * into a kiosk at the airport to look up the flight and print a boarding pass. - */ - public ?string $confirmationCode; - - /** - * Optional. - * E-ticket number. - */ - public ?string $eticketNumber; - - /** - * Optional. - * Frequent flyer membership information. - */ - public ?FrequentFlyerInfo $frequentFlyerInfo; + public function __construct( + /** + * Optional. + * Confirmation code needed to check into this flight. This is the number that the passenger would enter + * into a kiosk at the airport to look up the flight and print a boarding pass. + */ + public ?string $confirmationCode = null, + /** + * Optional. + * E-ticket number. + */ + public ?string $eticketNumber = null, + /** + * Optional. + * Frequent flyer membership information. + */ + public ?FrequentFlyerInfo $frequentFlyerInfo = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Generic/AbstractNotificationValue.php b/src/Google/Components/Generic/AbstractNotificationValue.php index c13ea94..4adbe2d 100644 --- a/src/Google/Components/Generic/AbstractNotificationValue.php +++ b/src/Google/Components/Generic/AbstractNotificationValue.php @@ -7,10 +7,13 @@ abstract class AbstractNotificationValue extends Component { - /** - * Required. - * Indicates that the issuer would like GooglePay to send notifications. - */ - #[Required] - public ?bool $enableNotification; + public function __construct( + /** + * Required. + * Indicates that the issuer would like GooglePay to send notifications. + */ + public bool $enableNotification, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Generic/Notifications.php b/src/Google/Components/Generic/Notifications.php index 97166f0..c441210 100644 --- a/src/Google/Components/Generic/Notifications.php +++ b/src/Google/Components/Generic/Notifications.php @@ -12,6 +12,10 @@ */ class Notifications extends Component { - public ?ExpiryNotification $expiryNotification; - public ?UpcomingNotification $upcomingNotification; + public function __construct( + public ?ExpiryNotification $expiryNotification = null, + public ?UpcomingNotification $upcomingNotification = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Loyalty/DiscoverableProgram.php b/src/Google/Components/Loyalty/DiscoverableProgram.php index 928e69c..0dddd44 100644 --- a/src/Google/Components/Loyalty/DiscoverableProgram.php +++ b/src/Google/Components/Loyalty/DiscoverableProgram.php @@ -2,38 +2,40 @@ namespace Chiiya\Passes\Google\Components\Loyalty; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Enumerators\Loyalty\VisibilityState; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class DiscoverableProgram extends Component { - /** - * Optional. - * Information about the ability to signup and add a valuable for this program through a merchant site. - * Used when MERCHANT_HOSTED_SIGNUP is enabled. - */ - public ?DiscoverableProgramMerchantSignupInfo $merchantSignupInfo; - - /** - * Optional. - * Information about the ability to signin and add a valuable for this program through a merchant site. - * Used when MERCHANT_HOSTED_SIGNIN is enabled. - */ - public ?DiscoverableProgramMerchantSigninInfo $merchantSigninInfo; - - /** - * Optional. - * Visibility state of the discoverable program. - */ - #[ValueIn([ - VisibilityState::STATE_UNSPECIFIED, - VisibilityState::TRUSTED_TESTERS, - VisibilityState::LIVE, - VisibilityState::DISABLED, - ])] - #[CastWith(LegacyValueCaster::class, VisibilityState::class)] - public ?string $state; + public function __construct( + /** + * Optional. + * Information about the ability to signup and add a valuable for this program through a merchant site. + * Used when MERCHANT_HOSTED_SIGNUP is enabled. + */ + public ?DiscoverableProgramMerchantSignupInfo $merchantSignupInfo = null, + /** + * Optional. + * Information about the ability to signin and add a valuable for this program through a merchant site. + * Used when MERCHANT_HOSTED_SIGNIN is enabled. + */ + public ?DiscoverableProgramMerchantSigninInfo $merchantSigninInfo = null, + /** + * Optional. + * Visibility state of the discoverable program. + */ + #[Choice([ + VisibilityState::STATE_UNSPECIFIED, + VisibilityState::TRUSTED_TESTERS, + VisibilityState::LIVE, + VisibilityState::DISABLED, + ])] + #[Cast(LegacyValueCaster::class, VisibilityState::class)] + public ?string $state = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Loyalty/DiscoverableProgramMerchantSigninInfo.php b/src/Google/Components/Loyalty/DiscoverableProgramMerchantSigninInfo.php index 98a7260..1489b3e 100644 --- a/src/Google/Components/Loyalty/DiscoverableProgramMerchantSigninInfo.php +++ b/src/Google/Components/Loyalty/DiscoverableProgramMerchantSigninInfo.php @@ -3,15 +3,17 @@ namespace Chiiya\Passes\Google\Components\Loyalty; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\Uri; class DiscoverableProgramMerchantSigninInfo extends Component { - /** - * Required. - * The URL to direct the user to for the merchant's signin site. - */ - #[Required] - public ?Uri $signinWebsite; + public function __construct( + /** + * Required. + * The URL to direct the user to for the merchant's signin site. + */ + public Uri $signinWebsite, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Loyalty/DiscoverableProgramMerchantSignupInfo.php b/src/Google/Components/Loyalty/DiscoverableProgramMerchantSignupInfo.php index 0f732e9..cdad115 100644 --- a/src/Google/Components/Loyalty/DiscoverableProgramMerchantSignupInfo.php +++ b/src/Google/Components/Loyalty/DiscoverableProgramMerchantSignupInfo.php @@ -3,38 +3,41 @@ namespace Chiiya\Passes\Google\Components\Loyalty; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Uri; use Chiiya\Passes\Google\Enumerators\Loyalty\SharedDataType; +use Symfony\Component\Validator\Constraints\Choice; class DiscoverableProgramMerchantSignupInfo extends Component { - /** - * Optional. - * The URL to direct the user to for the merchant's signup site. - */ - public ?Uri $signupWebsite; - - /** - * Optional. - * User data that is sent in a POST request to the signup website URL. This information is encoded and - * then shared so that the merchant's website can prefill fields used to enroll the user for the - * discoverable program. - */ - #[ValueIn([ - SharedDataType::SHARED_DATA_TYPE_UNSPECIFIED, - SharedDataType::FIRST_NAME, - SharedDataType::LAST_NAME, - SharedDataType::STREET_ADDRESS, - SharedDataType::ADDRESS_LINE_1, - SharedDataType::ADDRESS_LINE_2, - SharedDataType::ADDRESS_LINE_3, - SharedDataType::CITY, - SharedDataType::STATE, - SharedDataType::ZIPCODE, - SharedDataType::COUNTRY, - SharedDataType::EMAIL, - SharedDataType::PHONE, - ])] - public array $signupSharedDatas = []; + public function __construct( + /** + * Optional. + * The URL to direct the user to for the merchant's signup site. + */ + public ?Uri $signupWebsite = null, + /** + * Optional. + * User data that is sent in a POST request to the signup website URL. This information is encoded and + * then shared so that the merchant's website can prefill fields used to enroll the user for the + * discoverable program. + */ + #[Choice([ + SharedDataType::SHARED_DATA_TYPE_UNSPECIFIED, + SharedDataType::FIRST_NAME, + SharedDataType::LAST_NAME, + SharedDataType::STREET_ADDRESS, + SharedDataType::ADDRESS_LINE_1, + SharedDataType::ADDRESS_LINE_2, + SharedDataType::ADDRESS_LINE_3, + SharedDataType::CITY, + SharedDataType::STATE, + SharedDataType::ZIPCODE, + SharedDataType::COUNTRY, + SharedDataType::EMAIL, + SharedDataType::PHONE, + ])] + public array $signupSharedDatas = [], + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Loyalty/LoyaltyPoints.php b/src/Google/Components/Loyalty/LoyaltyPoints.php index 39774d2..f064885 100644 --- a/src/Google/Components/Loyalty/LoyaltyPoints.php +++ b/src/Google/Components/Loyalty/LoyaltyPoints.php @@ -3,30 +3,30 @@ namespace Chiiya\Passes\Google\Components\Loyalty; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\LocalizedString; +use Symfony\Component\Validator\Constraints\Length; class LoyaltyPoints extends Component { - /** - * Optional. - * The loyalty points label, such as "Points". Recommended maximum length is 9 characters. - */ - #[MaxLength(9)] - public ?string $label; - - /** - * Required. - * The account holder's loyalty point balance. This is a required field of loyaltyPoints and - * secondaryLoyaltyPoints. - */ - #[Required] - public ?LoyaltyPointsBalance $balance; - - /** - * Optional. - * Translated strings for the label. Recommended maximum length is 9 characters. - */ - public ?LocalizedString $localizedLabel; + public function __construct( + /** + * Required. + * The account holder's loyalty point balance. This is a required field of loyaltyPoints and + * secondaryLoyaltyPoints. + */ + public LoyaltyPointsBalance $balance, + /** + * Optional. + * The loyalty points label, such as "Points". Recommended maximum length is 9 characters. + */ + #[Length(max: 9)] + public ?string $label = null, + /** + * Optional. + * Translated strings for the label. Recommended maximum length is 9 characters. + */ + public ?LocalizedString $localizedLabel = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Loyalty/LoyaltyPointsBalance.php b/src/Google/Components/Loyalty/LoyaltyPointsBalance.php index b8f8930..7c10acd 100644 --- a/src/Google/Components/Loyalty/LoyaltyPointsBalance.php +++ b/src/Google/Components/Loyalty/LoyaltyPointsBalance.php @@ -7,27 +7,28 @@ class LoyaltyPointsBalance extends Component { - /** - * Optional. - * The string form of a balance. Only one of these subtypes (string, int, double, money) should be populated. - */ - public ?string $string; - - /** - * Optional. - * The integer form of a balance. Only one of these subtypes (string, int, double, money) should be populated. - */ - public ?int $int; - - /** - * Optional. - * The double form of a balance. Only one of these subtypes (string, int, double, money) should be populated. - */ - public ?float $double; - - /** - * Optional. - * The money form of a balance. Only one of these subtypes (string, int, double, money) should be populated. - */ - public ?Money $money; + public function __construct( + /** + * Optional. + * The string form of a balance. Only one of these subtypes (string, int, double, money) should be populated. + */ + public ?string $string = null, + /** + * Optional. + * The integer form of a balance. Only one of these subtypes (string, int, double, money) should be populated. + */ + public ?int $int = null, + /** + * Optional. + * The double form of a balance. Only one of these subtypes (string, int, double, money) should be populated. + */ + public ?float $double = null, + /** + * Optional. + * The money form of a balance. Only one of these subtypes (string, int, double, money) should be populated. + */ + public ?Money $money = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Transit/PurchaseDetails.php b/src/Google/Components/Transit/PurchaseDetails.php index 0fbcbaa..95805b4 100644 --- a/src/Google/Components/Transit/PurchaseDetails.php +++ b/src/Google/Components/Transit/PurchaseDetails.php @@ -6,34 +6,34 @@ class PurchaseDetails extends Component { - /** - * Optional. - * Receipt number/identifier for tracking the ticket purchase via the body that sold the ticket. - */ - public ?string $purchaseReceiptNumber; - - /** - * Optional. - * The purchase date/time of the ticket. - */ - public ?string $purchaseDateTime; - - /** - * Optional. - * ID of the account used to purchase the ticket. - */ - public ?string $accountId; - - /** - * Optional. - * The confirmation code for the purchase. This may be the same for multiple different tickets and is - * used to group tickets together. - */ - public ?string $confirmationCode; - - /** - * Optional. - * The cost of the ticket. - */ - public ?TicketCost $ticketCost; + public function __construct( + /** + * Optional. + * Receipt number/identifier for tracking the ticket purchase via the body that sold the ticket. + */ + public ?string $purchaseReceiptNumber = null, + /** + * Optional. + * The purchase date/time of the ticket. + */ + public ?string $purchaseDateTime = null, + /** + * Optional. + * ID of the account used to purchase the ticket. + */ + public ?string $accountId = null, + /** + * Optional. + * The confirmation code for the purchase. This may be the same for multiple different tickets and is + * used to group tickets together. + */ + public ?string $confirmationCode = null, + /** + * Optional. + * The cost of the ticket. + */ + public ?TicketCost $ticketCost = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Transit/TicketCost.php b/src/Google/Components/Transit/TicketCost.php index c5a9d1e..ade0f83 100644 --- a/src/Google/Components/Transit/TicketCost.php +++ b/src/Google/Components/Transit/TicketCost.php @@ -8,21 +8,23 @@ class TicketCost extends Component { - /** - * Optional. - * The face value of the ticket. - */ - public ?Money $faceValue; - - /** - * Optional. - * The actual purchase price of the ticket, after tax and/or discounts. - */ - public ?Money $purchasePrice; - - /** - * Optional. - * A message describing any kind of discount that was applied. - */ - public ?LocalizedString $discountMessage; + public function __construct( + /** + * Optional. + * The face value of the ticket. + */ + public ?Money $faceValue = null, + /** + * Optional. + * The actual purchase price of the ticket, after tax and/or discounts. + */ + public ?Money $purchasePrice = null, + /** + * Optional. + * A message describing any kind of discount that was applied. + */ + public ?LocalizedString $discountMessage = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Transit/TicketLeg.php b/src/Google/Components/Transit/TicketLeg.php index cb61008..5f542d3 100644 --- a/src/Google/Components/Transit/TicketLeg.php +++ b/src/Google/Components/Transit/TicketLeg.php @@ -2,103 +2,94 @@ namespace Chiiya\Passes\Google\Components\Transit; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MinItems; use Chiiya\Passes\Google\Components\Common\LocalizedString; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Count; class TicketLeg extends Component { - /** - * Optional. - * The origin station code. This is required if destinationStationCode is present or if - * originName is not present. - */ - public ?string $originStationCode; - - /** - * Optional. - * The name of the origin station. This is required if destinationName is present or if - * originStationCode is not present. - */ - public ?LocalizedString $originName; - - /** - * Optional. - * The destination station code. - */ - public ?string $destinationStationCode; - - /** - * Optional. - * The destination name. - */ - public ?LocalizedString $destinationName; - - /** - * Optional. - * The date/time of departure. This is required if there is no validity time interval set on the transit object. - */ - public ?string $departureDateTime; - - /** - * Optional. - * The date/time of arrival. - */ - public ?string $arrivalDateTime; - - /** - * Optional. - * Short description/name of the fare for this leg of travel. Eg "Anytime Single Use". - */ - public ?LocalizedString $fareName; - - /** - * Optional. - * The train or ship name/number that the passenger needs to board. - */ - public ?string $carriage; - - /** - * Optional. - * The platform or gate where the passenger can board the carriage. - */ - public ?string $platform; - - /** - * Optional. - * The zone of boarding within the platform. - */ - public ?string $zone; - - /** - * Optional. - * The reserved seat for the passenger(s). If more than one seat is to be specified then use the - * ticketSeats field instead. Both ticketSeat and ticketSeats may not be set. - */ - public ?TicketSeat $ticketSeat; - - /** - * Optional. - * The reserved seat for the passenger(s). If only one seat is to be specified then use the ticketSeat - * field instead. Both ticketSeat and ticketSeats may not be set. - * - * @var TicketSeat[] - */ - #[CastWith(ArrayCaster::class, TicketSeat::class)] - #[MinItems(2)] - public array $ticketSeats = []; - - /** - * Optional. - * The name of the transit operator that is operating this leg of a trip. - */ - public ?LocalizedString $transitOperatorName; - - /** - * Optional. - * Terminus station or destination of the train/bus/etc. - */ - public ?LocalizedString $transitTerminusName; + public function __construct( + /** + * Optional. + * The origin station code. This is required if destinationStationCode is present or if + * originName is not present. + */ + public ?string $originStationCode = null, + /** + * Optional. + * The name of the origin station. This is required if destinationName is present or if + * originStationCode is not present. + */ + public ?LocalizedString $originName = null, + /** + * Optional. + * The destination station code. + */ + public ?string $destinationStationCode = null, + /** + * Optional. + * The destination name. + */ + public ?LocalizedString $destinationName = null, + /** + * Optional. + * The date/time of departure. This is required if there is no validity time interval set on the transit object. + */ + public ?string $departureDateTime = null, + /** + * Optional. + * The date/time of arrival. + */ + public ?string $arrivalDateTime = null, + /** + * Optional. + * Short description/name of the fare for this leg of travel. Eg "Anytime Single Use". + */ + public ?LocalizedString $fareName = null, + /** + * Optional. + * The train or ship name/number that the passenger needs to board. + */ + public ?string $carriage = null, + /** + * Optional. + * The platform or gate where the passenger can board the carriage. + */ + public ?string $platform = null, + /** + * Optional. + * The zone of boarding within the platform. + */ + public ?string $zone = null, + /** + * Optional. + * The reserved seat for the passenger(s). If more than one seat is to be specified then use the + * ticketSeats field instead. Both ticketSeat and ticketSeats may not be set. + */ + public ?TicketSeat $ticketSeat = null, + /** + * Optional. + * The reserved seat for the passenger(s). If only one seat is to be specified then use the ticketSeat + * field instead. Both ticketSeat and ticketSeats may not be set. + * + * @var TicketSeat[] + */ + #[Cast(ArrayCaster::class, TicketSeat::class)] + #[Count(min: 2)] + public ?array $ticketSeats = null, + /** + * Optional. + * The name of the transit operator that is operating this leg of a trip. + */ + public ?LocalizedString $transitOperatorName = null, + /** + * Optional. + * Terminus station or destination of the train/bus/etc. + */ + public ?LocalizedString $transitTerminusName = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Transit/TicketRestrictions.php b/src/Google/Components/Transit/TicketRestrictions.php index bf517e1..863f0ee 100644 --- a/src/Google/Components/Transit/TicketRestrictions.php +++ b/src/Google/Components/Transit/TicketRestrictions.php @@ -7,28 +7,29 @@ class TicketRestrictions extends Component { - /** - * Optional. - * Restrictions about routes that may be taken. For example, this may be the string - * "Reserved CrossCountry trains only". - */ - public ?LocalizedString $routeRestrictions; - - /** - * Optional. - * More details about the above routeRestrictions. - */ - public ?LocalizedString $routeRestrictionsDetails; - - /** - * Optional. - * Restrictions about times this ticket may be used. - */ - public ?LocalizedString $timeRestrictions; - - /** - * Optional. - * Extra restrictions that don't fall under the "route" or "time" categories. - */ - public LocalizedString $otherRestrictions; + public function __construct( + /** + * Optional. + * Restrictions about routes that may be taken. For example, this may be the string + * "Reserved CrossCountry trains only". + */ + public ?LocalizedString $routeRestrictions = null, + /** + * Optional. + * More details about the above routeRestrictions. + */ + public ?LocalizedString $routeRestrictionsDetails = null, + /** + * Optional. + * Restrictions about times this ticket may be used. + */ + public ?LocalizedString $timeRestrictions = null, + /** + * Optional. + * Extra restrictions that don't fall under the "route" or "time" categories. + */ + public ?LocalizedString $otherRestrictions = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Components/Transit/TicketSeat.php b/src/Google/Components/Transit/TicketSeat.php index 8ab7854..71ce08b 100644 --- a/src/Google/Components/Transit/TicketSeat.php +++ b/src/Google/Components/Transit/TicketSeat.php @@ -2,48 +2,48 @@ namespace Chiiya\Passes\Google\Components\Transit; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Enumerators\Transit\FareClass; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class TicketSeat extends Component { - /** - * Optional. - * The fare class of the ticketed seat. - * - * @see FareClass - */ - #[ValueIn([FareClass::FARE_CLASS_UNSPECIFIED, FareClass::ECONOMY, FareClass::FIRST, FareClass::BUSINESS])] - #[CastWith(LegacyValueCaster::class, FareClass::class)] - public ?string $fareClass; - - /** - * Optional. - * A custom fare class to be used if no fareClass applies. Both fareClass and customFareClass may not be set. - */ - public ?LocalizedString $customFareClass; - - /** - * Optional. - * The identifier of the train car or coach in which the ticketed seat is located. Eg. "10". - */ - public ?string $coach; - - /** - * Optional. - * The identifier of where the ticketed seat is located. Eg. "42". If there is no specific - * identifier, use seatAssigment instead. - */ - public ?string $seat; - - /** - * Optional. - * The passenger's seat assignment. Eg. "no specific seat". To be used when there is no - * specific identifier to use in seat. - */ - public ?LocalizedString $seatAssignment; + public function __construct( + /** + * Optional. + * The fare class of the ticketed seat. + * + * @see FareClass + */ + #[Choice([FareClass::FARE_CLASS_UNSPECIFIED, FareClass::ECONOMY, FareClass::FIRST, FareClass::BUSINESS])] + #[Cast(LegacyValueCaster::class, FareClass::class)] + public ?string $fareClass = null, + /** + * Optional. + * A custom fare class to be used if no fareClass applies. Both fareClass and customFareClass may not be set. + */ + public ?LocalizedString $customFareClass = null, + /** + * Optional. + * The identifier of the train car or coach in which the ticketed seat is located. Eg. "10". + */ + public ?string $coach = null, + /** + * Optional. + * The identifier of where the ticketed seat is located. Eg. "42". If there is no specific + * identifier, use seatAssigment instead. + */ + public ?string $seat = null, + /** + * Optional. + * The passenger's seat assignment. E.g. "no specific seat". To be used when there is no + * specific identifier to use in seat. + */ + public ?LocalizedString $seatAssignment = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Enumerators/BarcodeType.php b/src/Google/Enumerators/BarcodeType.php index 8a8e1be..a4fbbb8 100644 --- a/src/Google/Enumerators/BarcodeType.php +++ b/src/Google/Enumerators/BarcodeType.php @@ -73,13 +73,10 @@ public function mapLegacyValues(string $value): string 'codabar' => self::CODABAR, 'dataMatrix' => self::DATA_MATRIX, 'ean8' => self::EAN_8, - 'ean13' => self::EAN_13, - 'EAN13' => self::EAN_13, + 'ean13', 'EAN13' => self::EAN_13, 'itf14' => self::ITF_14, - 'pdf417' => self::PDF_417, - 'PDF417' => self::PDF_417, - 'qrCode' => self::QR_CODE, - 'qrcode' => self::QR_CODE, + 'pdf417', 'PDF417' => self::PDF_417, + 'qrCode', 'qrcode' => self::QR_CODE, 'upcA' => self::UPC_A, 'textOnly' => self::TEXT_ONLY, default => $value, diff --git a/src/Google/Responses/EventTicketClassesResponse.php b/src/Google/Responses/EventTicketClassesResponse.php index e7aa392..5ef7526 100644 --- a/src/Google/Responses/EventTicketClassesResponse.php +++ b/src/Google/Responses/EventTicketClassesResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\EventTicketClass; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class EventTicketClassesResponse extends Component +class EventTicketClassesResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, EventTicketClass::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, EventTicketClass::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/EventTicketObjectsResponse.php b/src/Google/Responses/EventTicketObjectsResponse.php index 7c64bb8..5c0aceb 100644 --- a/src/Google/Responses/EventTicketObjectsResponse.php +++ b/src/Google/Responses/EventTicketObjectsResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\EventTicketObject; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class EventTicketObjectsResponse extends Component +class EventTicketObjectsResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, EventTicketObject::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, EventTicketObject::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/FlightClassesResponse.php b/src/Google/Responses/FlightClassesResponse.php index fc4883a..17fe104 100644 --- a/src/Google/Responses/FlightClassesResponse.php +++ b/src/Google/Responses/FlightClassesResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\FlightClass; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class FlightClassesResponse extends Component +class FlightClassesResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, FlightClass::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, FlightClass::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/FlightObjectsResponse.php b/src/Google/Responses/FlightObjectsResponse.php index 3048aaf..cc32d08 100644 --- a/src/Google/Responses/FlightObjectsResponse.php +++ b/src/Google/Responses/FlightObjectsResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\FlightObject; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class FlightObjectsResponse extends Component +class FlightObjectsResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, FlightObject::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, FlightObject::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/GenericClassesResponse.php b/src/Google/Responses/GenericClassesResponse.php index e633f9a..1b8006b 100644 --- a/src/Google/Responses/GenericClassesResponse.php +++ b/src/Google/Responses/GenericClassesResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\GenericClass; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class GenericClassesResponse extends Component +class GenericClassesResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, GenericClass::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, GenericClass::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/GenericObjectsResponse.php b/src/Google/Responses/GenericObjectsResponse.php index 4756f23..410e458 100644 --- a/src/Google/Responses/GenericObjectsResponse.php +++ b/src/Google/Responses/GenericObjectsResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\GenericObject; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class GenericObjectsResponse extends Component +class GenericObjectsResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, GenericObject::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, GenericObject::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/GiftCardClassesResponse.php b/src/Google/Responses/GiftCardClassesResponse.php index 252ed46..78b484b 100644 --- a/src/Google/Responses/GiftCardClassesResponse.php +++ b/src/Google/Responses/GiftCardClassesResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\GiftCardClass; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class GiftCardClassesResponse extends Component +class GiftCardClassesResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, GiftCardClass::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, GiftCardClass::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/GiftCardObjectsResponse.php b/src/Google/Responses/GiftCardObjectsResponse.php index 77bb50e..c0dd985 100644 --- a/src/Google/Responses/GiftCardObjectsResponse.php +++ b/src/Google/Responses/GiftCardObjectsResponse.php @@ -2,15 +2,17 @@ namespace Chiiya\Passes\Google\Responses; -use Chiiya\Passes\Common\Component; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Passes\GiftCardObject; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; -class GiftCardObjectsResponse extends Component +class GiftCardObjectsResponse extends PaginatedResponse { - use HasPagination; - - #[CastWith(ArrayCaster::class, GiftCardObject::class)] - public array $resources = []; + public function __construct( + #[Cast(ArrayCaster::class, GiftCardObject::class)] + public array $resources = [], + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Responses/HasPagination.php b/src/Google/Responses/HasPagination.php deleted file mode 100644 index cf19664..0000000 --- a/src/Google/Responses/HasPagination.php +++ /dev/null @@ -1,10 +0,0 @@ - TextAlignment::LEFT, 'row' => 1, ]); - $component = new AuxiliaryField($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new AuxiliaryField(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/BarcodeTest.php b/tests/Apple/Components/BarcodeTest.php index 021566b..548507d 100644 --- a/tests/Apple/Components/BarcodeTest.php +++ b/tests/Apple/Components/BarcodeTest.php @@ -5,9 +5,11 @@ use Chiiya\Passes\Apple\Components\Barcode; use Chiiya\Passes\Apple\Enumerators\BarcodeFormat; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class BarcodeTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = [ @@ -16,7 +18,7 @@ public function test_attributes(): void 'messageEncoding' => 'iso-8859-2', 'altText' => 'Barcode: ABCD 123 EFGH 456 IJKL 789 MNOP', ]; - $component = new Barcode($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Barcode(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/BeaconTest.php b/tests/Apple/Components/BeaconTest.php index 2ea7419..ef1bb72 100644 --- a/tests/Apple/Components/BeaconTest.php +++ b/tests/Apple/Components/BeaconTest.php @@ -4,9 +4,11 @@ use Chiiya\Passes\Apple\Components\Beacon; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class BeaconTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = [ @@ -15,7 +17,7 @@ public function test_attributes(): void 'minor' => 234, 'relevantText' => "You're near my store", ]; - $component = new Beacon($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Beacon(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/CurrencyAmountTest.php b/tests/Apple/Components/CurrencyAmountTest.php index 5bdbe61..e5c8fb1 100644 --- a/tests/Apple/Components/CurrencyAmountTest.php +++ b/tests/Apple/Components/CurrencyAmountTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\CurrencyAmount; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class CurrencyAmountTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::currencyAmount(); - $component = new CurrencyAmount($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new CurrencyAmount(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/FieldTest.php b/tests/Apple/Components/FieldTest.php index 2e4cafd..fc9597d 100644 --- a/tests/Apple/Components/FieldTest.php +++ b/tests/Apple/Components/FieldTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\Field; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class FieldTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::fieldAttributes(); - $component = new Field($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Field(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/LocationTest.php b/tests/Apple/Components/LocationTest.php index 8d88743..6a59e65 100644 --- a/tests/Apple/Components/LocationTest.php +++ b/tests/Apple/Components/LocationTest.php @@ -4,9 +4,11 @@ use Chiiya\Passes\Apple\Components\Location; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class LocationTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = [ @@ -15,7 +17,7 @@ public function test_attributes(): void 'longitude' => -122.029, 'relevantText' => 'Store nearby on 3rd and Main.', ]; - $component = new Location($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Location(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/NfcTest.php b/tests/Apple/Components/NfcTest.php index 10d84b1..e454d11 100644 --- a/tests/Apple/Components/NfcTest.php +++ b/tests/Apple/Components/NfcTest.php @@ -4,9 +4,11 @@ use Chiiya\Passes\Apple\Components\Nfc; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class NfcTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = [ @@ -14,7 +16,7 @@ public function test_attributes(): void 'encryptionPublicKey' => 'ABC123', 'requiresAuthentication' => false, ]; - $component = new Nfc($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Nfc(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/PersonNameTest.php b/tests/Apple/Components/PersonNameTest.php index f50231e..e764fe2 100644 --- a/tests/Apple/Components/PersonNameTest.php +++ b/tests/Apple/Components/PersonNameTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\PersonName; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class PersonNameTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::personName(); - $component = new PersonName($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new PersonName(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/SeatTest.php b/tests/Apple/Components/SeatTest.php index 7ea1c6a..a3f6646 100644 --- a/tests/Apple/Components/SeatTest.php +++ b/tests/Apple/Components/SeatTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\Seat; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class SeatTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::seat(); - $component = new Seat($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new Seat(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/SecondaryFieldTest.php b/tests/Apple/Components/SecondaryFieldTest.php index a31d002..255dc34 100644 --- a/tests/Apple/Components/SecondaryFieldTest.php +++ b/tests/Apple/Components/SecondaryFieldTest.php @@ -6,15 +6,17 @@ use Chiiya\Passes\Apple\Enumerators\TextAlignment; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class SecondaryFieldTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = array_merge(Components::fieldAttributes(), [ 'textAlignment' => TextAlignment::LEFT, ]); - $component = new SecondaryField($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new SecondaryField(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/SemanticLocationTest.php b/tests/Apple/Components/SemanticLocationTest.php index c244769..076be72 100644 --- a/tests/Apple/Components/SemanticLocationTest.php +++ b/tests/Apple/Components/SemanticLocationTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\SemanticLocation; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class SemanticLocationTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::semanticLocation(); - $component = new SemanticLocation($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new SemanticLocation(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Components/SemanticsTest.php b/tests/Apple/Components/SemanticsTest.php index 7198079..b7f95c3 100644 --- a/tests/Apple/Components/SemanticsTest.php +++ b/tests/Apple/Components/SemanticsTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\Semantics; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class SemanticsTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::semantics(); - $component = new Semantics($attributes); + $component = new Semantics(...$attributes); $expected = array_merge($attributes, [ 'currentArrivalDate' => '2022-01-01T08:00:00+00:00', 'balance' => Components::currencyAmount(), @@ -23,6 +25,6 @@ public function test_attributes(): void 'venueLocation' => Components::semanticLocation(), 'wifiAccess' => [Components::wifiNetwork()], ]); - $this->assertSameArray($expected, $component->toArray()); + $this->assertSameArray($expected, $component->encode()); } } diff --git a/tests/Apple/Components/SerializationTest.php b/tests/Apple/Components/SerializationTest.php index 84cfebd..74bd802 100644 --- a/tests/Apple/Components/SerializationTest.php +++ b/tests/Apple/Components/SerializationTest.php @@ -4,21 +4,20 @@ use Chiiya\Passes\Apple\Components\Location; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class SerializationTest extends TestCase { + #[Group('apple')] public function test_that_empty_values_are_removed(): void { - $location = new Location([ - 'latitude' => 37.331, - 'longitude' => -122.029, - ]); + $location = new Location(latitude: 37.331, longitude: -122.029); $this->assertSameArray([ 'latitude' => 37.331, 'longitude' => -122.029, 'altitude' => null, 'relevantText' => null, - ], $location->toArray()); + ], $location->encode()); $this->assertSame([ 'latitude' => 37.331, 'longitude' => -122.029, diff --git a/tests/Apple/Components/WifiNetworkTest.php b/tests/Apple/Components/WifiNetworkTest.php index 92b78b2..52785ef 100644 --- a/tests/Apple/Components/WifiNetworkTest.php +++ b/tests/Apple/Components/WifiNetworkTest.php @@ -5,13 +5,15 @@ use Chiiya\Passes\Apple\Components\WifiNetwork; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class WifiNetworkTest extends TestCase { + #[Group('apple')] public function test_attributes(): void { $attributes = Components::wifiNetwork(); - $component = new WifiNetwork($attributes); - $this->assertSameArray($attributes, $component->toArray()); + $component = new WifiNetwork(...$attributes); + $this->assertSameArray($attributes, $component->encode()); } } diff --git a/tests/Apple/Fixtures/Components.php b/tests/Apple/Fixtures/Components.php index a476dab..9db3b4c 100644 --- a/tests/Apple/Fixtures/Components.php +++ b/tests/Apple/Fixtures/Components.php @@ -27,41 +27,37 @@ class Components { public static function location(): Location { - return new Location([ - 'altitude' => 10.0, - 'latitude' => 37.331, - 'longitude' => -122.029, - 'relevantText' => 'Store nearby on 3rd and Main.', - ]); + return new Location( + latitude: 37.331, + longitude: -122.029, + altitude: 10.0, + relevantText: 'Store nearby on 3rd and Main.', + ); } public static function beacon(): Beacon { - return new Beacon([ - 'proximityUUID' => 'F8F589E9-C07E-58B0-AEAB-A36BE4D48FAC', - 'major' => 23423, - 'minor' => 234, - 'relevantText' => "You're near my store", - ]); + return new Beacon( + proximityUUID: 'F8F589E9-C07E-58B0-AEAB-A36BE4D48FAC', + major: 23423, + minor: 234, + relevantText: "You're near my store", + ); } - public static function barcode(array $attributes = []): Barcode + public static function barcode(): Barcode { - return new Barcode(array_merge([ - 'format' => BarcodeFormat::PDF417, - 'message' => 'ABCD 123 EFGH 456 IJKL 789 MNOP', - 'messageEncoding' => 'iso-8859-2', - 'altText' => 'Barcode: ABCD 123 EFGH 456 IJKL 789 MNOP', - ], $attributes)); + return new Barcode( + format: BarcodeFormat::PDF417, + message: 'ABCD 123 EFGH 456 IJKL 789 MNOP', + messageEncoding: 'iso-8859-2', + altText: 'Barcode: ABCD 123 EFGH 456 IJKL 789 MNOP', + ); } public static function nfc(): Nfc { - return new Nfc([ - 'message' => 'Example message', - 'encryptionPublicKey' => 'ABC123', - 'requiresAuthentication' => true, - ]); + return new Nfc(message: 'Example message', encryptionPublicKey: 'ABC123', requiresAuthentication: true); } public static function passAttributes(): array @@ -95,7 +91,7 @@ public static function fullPassAttributes(): array 'locations' => [$location], 'maxDistance' => 10, 'relevantDate' => '2020-12-01', - 'semantics' => new Semantics(self::semantics()), + 'semantics' => new Semantics(...self::semantics()), 'barcodes' => [$barcode], 'backgroundColor' => 'rgb(255, 255, 255)', 'foregroundColor' => 'rgb(155, 155, 155)', @@ -145,7 +141,7 @@ public static function fields(): array ], 'primaryFields' => [new Field(key: 'primary', value: '::value::')], 'secondaryFields' => [ - new SecondaryField(key: 'secondary1', value: '::value::', textAlignment: TextAlignment::RIGHT), + new SecondaryField(textAlignment: TextAlignment::RIGHT, key: 'secondary1', value: '::value::'), new SecondaryField(key: 'secondary2', value: '::value::'), ], 'auxiliaryFields' => [new AuxiliaryField(key: 'aux', value: '::value::')], @@ -287,7 +283,7 @@ public static function semantics(): array 'awayTeamAbbreviation' => '::awayTeamAbbreviation::', 'awayTeamLocation' => '::awayTeamLocation::', 'awayTeamName' => '::awayTeamName::', - 'balance' => new CurrencyAmount(self::currencyAmount()), + 'balance' => new CurrencyAmount(...self::currencyAmount()), 'boardingGroup' => '::boardingGroup::', 'boardingSequenceNumber' => '::boardingSequenceNumber::', 'carNumber' => '::carNumber::', @@ -298,7 +294,7 @@ public static function semantics(): array 'departureAirportCode' => '::departureAirportCode::', 'departureAirportName' => '::departureAirportName::', 'departureGate' => '::departureGate::', - 'departureLocation' => new SemanticLocation(self::semanticLocation()), + 'departureLocation' => new SemanticLocation(...self::semanticLocation()), 'departureLocationDescription' => '::departureLocationDescription::', 'departurePlatform' => '::departurePlatform::', 'departureStationName' => '::departureStationName::', @@ -306,7 +302,7 @@ public static function semantics(): array 'destinationAirportCode' => '::destinationAirportCode::', 'destinationAirportName' => '::destinationAirportName::', 'destinationGate' => '::destinationGate::', - 'destinationLocation' => new SemanticLocation(self::semanticLocation()), + 'destinationLocation' => new SemanticLocation(...self::semanticLocation()), 'destinationLocationDescription' => '::destinationLocationDescription::', 'destinationPlatform' => '::destinationPlatform::', 'destinationStationName' => '::destinationStationName::', @@ -329,14 +325,14 @@ public static function semantics(): array 'originalArrivalDate' => '::originalArrivalDate::', 'originalBoardingDate' => '::originalBoardingDate::', 'originalDepartureDate' => '::originalDepartureDate::', - 'passengerName' => new PersonName(self::personName()), + 'passengerName' => new PersonName(...self::personName()), 'performerNames' => ['::performerNames::'], 'priorityStatus' => '::priorityStatus::', - 'seats' => [new Seat(self::seat())], + 'seats' => [new Seat(...self::seat())], 'securityScreening' => '::securityScreening::', 'silenceRequested' => false, 'sportName' => '::sportName::', - 'totalPrice' => new CurrencyAmount(self::currencyAmount()), + 'totalPrice' => new CurrencyAmount(...self::currencyAmount()), 'transitProvider' => '::transitProvider::', 'transitStatus' => '::transitStatus::', 'transitStatusReason' => '::transitStatusReason::', @@ -344,11 +340,11 @@ public static function semantics(): array 'vehicleNumber' => '::vehicleNumber::', 'vehicleType' => '::vehicleType::', 'venueEntrance' => '::venueEntrance::', - 'venueLocation' => new SemanticLocation(self::semanticLocation()), + 'venueLocation' => new SemanticLocation(...self::semanticLocation()), 'venueName' => '::venueName::', 'venuePhoneNumber' => '::venuePhoneNumber::', 'venueRoom' => '::venueRoom::', - 'wifiAccess' => [new WifiNetwork(self::wifiNetwork())], + 'wifiAccess' => [new WifiNetwork(...self::wifiNetwork())], ]; } } diff --git a/tests/Apple/PassFactoryTest.php b/tests/Apple/PassFactoryTest.php index 84451f0..99d706b 100644 --- a/tests/Apple/PassFactoryTest.php +++ b/tests/Apple/PassFactoryTest.php @@ -11,37 +11,36 @@ use Chiiya\Passes\Apple\PassFactory; use Chiiya\Passes\Exceptions\ValidationException; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class PassFactoryTest extends TestCase { protected PassFactory $factory; + #[Group('apple')] public function test_create_pass(): void { - $pass = new Coupon([ - 'description' => 'Example description', - 'organizationName' => 'ACME', - 'passTypeIdentifier' => 'pass.com.acme.test', - 'serialNumber' => '1890038600058', - 'teamIdentifier' => '12345ABCD', - 'primaryFields' => [new Field(key: 'primary', value: '::value::', label: 'Coupon')], - ]); + $pass = new Coupon( + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '1890038600058', + teamIdentifier: '12345ABCD', + primaryFields: [new Field(key: 'primary', value: '::value::', label: 'Coupon')], + ); $pass ->addImage(new Image(realpath(__DIR__.'/Fixtures/icon.png'))) ->addImage(new Image(realpath(__DIR__.'/Fixtures/icon@2x.png'), ImageType::ICON, 2)) - ->addLocalization(new Localization([ - 'language' => 'en', - 'strings' => [ - 'EXAMPLE' => 'Free Breakfast', - ], + ->addLocalization(new Localization(language: 'en', strings: [ + 'EXAMPLE' => 'Free Breakfast', ])) - ->addLocalization(new Localization([ - 'language' => 'de', - 'strings' => [ + ->addLocalization(new Localization( + language: 'de', + strings: [ 'EXAMPLE' => 'Free Breakfast', ], - 'images' => [new Image(realpath(__DIR__.'/Fixtures/icon.png'), 'icon')], - ])); + images: [new Image(realpath(__DIR__.'/Fixtures/icon.png'), 'icon')], + )); $this->factory->setCertificate(getenv('PASSES_APPLE_CERT')); $this->factory->setPassword(getenv('PASSES_APPLE_PASSWORD')); $this->factory->setWwdr(getenv('PASSES_APPLE_WWDR')); @@ -51,16 +50,17 @@ public function test_create_pass(): void $this->assertFileExists(__DIR__.'/1890038600058.pkpass'); } + #[Group('apple')] public function test_that_it_can_skip_signature(): void { - $pass = new EventTicket([ - 'description' => 'Example description', - 'organizationName' => 'ACME', - 'passTypeIdentifier' => 'pass.com.acme.test', - 'serialNumber' => '2890038600058', - 'teamIdentifier' => '12345ABCD', - 'primaryFields' => [new Field(key: 'primary', value: '::value::', label: 'Coupon')], - ]); + $pass = new EventTicket( + primaryFields: [new Field(key: 'primary', value: '::value::', label: 'Coupon')], + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '2890038600058', + teamIdentifier: '12345ABCD', + ); $pass->addImage(new Image(realpath(__DIR__.'/Fixtures/icon.png'), 'icon')); $this->factory->setSkipSignature(true); $this->factory->setOutput(__DIR__); @@ -68,15 +68,16 @@ public function test_that_it_can_skip_signature(): void $this->assertFileExists(__DIR__.'/2890038600058.pkpass'); } + #[Group('apple')] public function test_that_image_format_is_validated(): void { - $pass = new Coupon([ - 'description' => 'Example description', - 'organizationName' => 'ACME', - 'passTypeIdentifier' => 'pass.com.acme.test', - 'serialNumber' => '1890038600058', - 'teamIdentifier' => '12345ABCD', - ]); + $pass = new Coupon( + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '1890038600058', + teamIdentifier: '12345ABCD', + ); $pass->addImage(new Image(realpath(__DIR__.'/Fixtures/format.jpg'), 'icon')); $this->factory->setSkipSignature(true); $this->factory->setOutput(__DIR__); @@ -85,15 +86,16 @@ public function test_that_image_format_is_validated(): void $this->factory->create($pass); } + #[Group('apple')] public function test_that_image_type_is_validated(): void { - $pass = new Coupon([ - 'description' => 'Example description', - 'organizationName' => 'ACME', - 'passTypeIdentifier' => 'pass.com.acme.test', - 'serialNumber' => '1890038600058', - 'teamIdentifier' => '12345ABCD', - ]); + $pass = new Coupon( + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '1890038600058', + teamIdentifier: '12345ABCD', + ); $pass->addImage(new Image(realpath(__DIR__.'/Fixtures/icon.png'), ImageType::BACKGROUND)); $this->factory->setSkipSignature(true); $this->factory->setOutput(__DIR__); @@ -116,15 +118,16 @@ public function test_that_image_type_is_validated(): void } } + #[Group('apple')] public function test_that_it_validates_illegal_image_combination(): void { - $pass = new EventTicket([ - 'description' => 'Example description', - 'organizationName' => 'ACME', - 'passTypeIdentifier' => 'pass.com.acme.test', - 'serialNumber' => '1890038600058', - 'teamIdentifier' => '12345ABCD', - ]); + $pass = new EventTicket( + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '1890038600058', + teamIdentifier: '12345ABCD', + ); $pass ->addImage(new Image(realpath(__DIR__.'/Fixtures/icon.png'), ImageType::ICON)) ->addImage(new Image(realpath(__DIR__.'/Fixtures/icon.png'), ImageType::STRIP)) @@ -138,6 +141,21 @@ public function test_that_it_validates_illegal_image_combination(): void $this->factory->create($pass); } + #[Group('apple')] + public function test_validation(): void + { + $this->expectException(ValidationException::class); + $this->expectExceptionMessageMatches('/Field.dateStyle: The value you selected is not a valid choice./'); + new Coupon( + description: 'Example description', + organizationName: 'ACME', + passTypeIdentifier: 'pass.com.acme.test', + serialNumber: '1890038600058', + teamIdentifier: '12345ABCD', + primaryFields: [new Field(key: 'primary', value: '::value::', label: 'Coupon', dateStyle: '::invalid::')], + ); + } + protected function setUp(): void { parent::setUp(); diff --git a/tests/Apple/Passes/BoardingPassTest.php b/tests/Apple/Passes/BoardingPassTest.php index 33d941b..e12f823 100644 --- a/tests/Apple/Passes/BoardingPassTest.php +++ b/tests/Apple/Passes/BoardingPassTest.php @@ -6,22 +6,24 @@ use Chiiya\Passes\Apple\Passes\BoardingPass; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class BoardingPassTest extends TestCase { + #[Group('apple')] public function test_is_serialized_correctly(): void { $attributes = array_merge(Components::passAttributes(), Components::fields(), [ 'groupingIdentifier' => 'ID-123', 'transitType' => TransitType::AIR, ]); - $pass = new BoardingPass($attributes); + $pass = new BoardingPass(...$attributes); $expected = array_merge(Components::passAttributes(), Components::nullablePassAttributes(), [ 'boardingPass' => array_merge(Components::fieldValues(), [ 'transitType' => TransitType::AIR, ]), 'groupingIdentifier' => 'ID-123', ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } diff --git a/tests/Apple/Passes/CouponTest.php b/tests/Apple/Passes/CouponTest.php index a7127f3..a4fe914 100644 --- a/tests/Apple/Passes/CouponTest.php +++ b/tests/Apple/Passes/CouponTest.php @@ -5,15 +5,18 @@ use Chiiya\Passes\Apple\Passes\Coupon; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class CouponTest extends TestCase { + #[Group('apple')] public function test_is_serialized_correctly(): void { - $pass = new Coupon(array_merge(Components::passAttributes(), Components::fields())); + $attributes = array_merge(Components::passAttributes(), Components::fields()); + $pass = new Coupon(...$attributes); $expected = array_merge(Components::passAttributes(), Components::nullablePassAttributes(), [ 'coupon' => Components::fieldValues(), ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } diff --git a/tests/Apple/Passes/EventTicketTest.php b/tests/Apple/Passes/EventTicketTest.php index 228a5ae..4bb7c21 100644 --- a/tests/Apple/Passes/EventTicketTest.php +++ b/tests/Apple/Passes/EventTicketTest.php @@ -5,19 +5,21 @@ use Chiiya\Passes\Apple\Passes\EventTicket; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class EventTicketTest extends TestCase { + #[Group('apple')] public function test_is_serialized_correctly(): void { $attributes = array_merge(Components::passAttributes(), Components::fields(), [ 'groupingIdentifier' => 'ID-123', ]); - $pass = new EventTicket($attributes); + $pass = new EventTicket(...$attributes); $expected = array_merge(Components::passAttributes(), Components::nullablePassAttributes(), [ 'eventTicket' => Components::fieldValues(), 'groupingIdentifier' => 'ID-123', ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } diff --git a/tests/Apple/Passes/GenericTest.php b/tests/Apple/Passes/GenericTest.php index cec7edf..e7fd90a 100644 --- a/tests/Apple/Passes/GenericTest.php +++ b/tests/Apple/Passes/GenericTest.php @@ -5,15 +5,18 @@ use Chiiya\Passes\Apple\Passes\GenericPass; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class GenericTest extends TestCase { + #[Group('apple')] public function test_is_serialized_correctly(): void { - $pass = new GenericPass(array_merge(Components::passAttributes(), Components::fields())); + $attributes = array_merge(Components::passAttributes(), Components::fields()); + $pass = new GenericPass(...$attributes); $expected = array_merge(Components::passAttributes(), Components::nullablePassAttributes(), [ 'generic' => Components::fieldValues(), ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } diff --git a/tests/Apple/Passes/ImageTest.php b/tests/Apple/Passes/ImageTest.php index 48445b7..6718c09 100644 --- a/tests/Apple/Passes/ImageTest.php +++ b/tests/Apple/Passes/ImageTest.php @@ -3,10 +3,12 @@ namespace Chiiya\Passes\Tests\Apple\Passes; use Chiiya\Passes\Apple\Components\Image; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; class ImageTest extends TestCase { + #[Group('apple')] public function test_that_it_can_be_instantiated(): void { $image = new Image(realpath(__DIR__.'/../Fixtures/icon.png'), 'icon', 2); @@ -16,6 +18,7 @@ public function test_that_it_can_be_instantiated(): void $this->assertNull($image->getName()); } + #[Group('apple')] public function test_setters(): void { $image = new Image(realpath(__DIR__.'/../Fixtures/icon.png')); diff --git a/tests/Apple/Passes/LocalizationTest.php b/tests/Apple/Passes/LocalizationTest.php index ae0ec74..70b1128 100644 --- a/tests/Apple/Passes/LocalizationTest.php +++ b/tests/Apple/Passes/LocalizationTest.php @@ -3,10 +3,12 @@ namespace Chiiya\Passes\Tests\Apple\Passes; use Chiiya\Passes\Apple\Components\Localization; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; class LocalizationTest extends TestCase { + #[Group('apple')] public function test_strings_can_be_added(): void { $localization = new Localization(language: 'de'); diff --git a/tests/Apple/Passes/PassTest.php b/tests/Apple/Passes/PassTest.php index 5554712..518eec1 100644 --- a/tests/Apple/Passes/PassTest.php +++ b/tests/Apple/Passes/PassTest.php @@ -8,12 +8,14 @@ use Chiiya\Passes\Apple\Passes\Coupon; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class PassTest extends TestCase { + #[Group('apple')] public function test_images_can_be_added(): void { - $pass = new Coupon(Components::passAttributes()); + $pass = new Coupon(...Components::passAttributes()); $pass->addImage(new Image(realpath(__DIR__.'/../Fixtures/icon.png'), 'icon')); $pass->addImage(new Image(realpath(__DIR__.'/../Fixtures/icon@2x.png'))); $images = $pass->getImages(); @@ -21,21 +23,12 @@ public function test_images_can_be_added(): void $this->assertSame('icon', $images[0]->getName()); } + #[Group('apple')] public function test_localizations_can_be_added(): void { - $pass = new Coupon(Components::passAttributes()); - $pass->addLocalization(new Localization([ - 'language' => 'en', - 'strings' => [ - 'example' => 'EXAMPLE', - ], - ])); - $pass->addLocalization(new Localization([ - 'language' => 'de', - 'strings' => [ - 'example' => 'BEISPIEL', - ], - ])); + $pass = new Coupon(...Components::passAttributes()); + $pass->addLocalization(new Localization(language: 'en', strings: ['example' => 'EXAMPLE'])); + $pass->addLocalization(new Localization(language: 'de', strings: ['example' => 'BEISPIEL'])); $localizations = $pass->getLocalizations(); $this->assertCount(2, $localizations); $this->assertSame('en', $localizations[0]->language); @@ -44,9 +37,11 @@ public function test_localizations_can_be_added(): void ], $localizations[0]->strings); } + #[Group('apple')] public function test_pass_is_serialized_correctly(): void { - $pass = new Coupon(array_merge(Components::fullPassAttributes(), Components::fields())); + $attributes = array_merge(Components::fullPassAttributes(), Components::fields()); + $pass = new Coupon(...$attributes); $expected = array_merge(Components::fullPassAttributes(), [ 'expirationDate' => '2025-12-31T23:59:59+00:00', 'beacons' => [[ @@ -86,6 +81,6 @@ public function test_pass_is_serialized_correctly(): void 'wifiAccess' => [Components::wifiNetwork()], ]), ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } diff --git a/tests/Apple/Passes/StoreCardTest.php b/tests/Apple/Passes/StoreCardTest.php index f3bd186..f56069e 100644 --- a/tests/Apple/Passes/StoreCardTest.php +++ b/tests/Apple/Passes/StoreCardTest.php @@ -5,15 +5,18 @@ use Chiiya\Passes\Apple\Passes\StoreCard; use Chiiya\Passes\Tests\Apple\Fixtures\Components; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class StoreCardTest extends TestCase { + #[Group('apple')] public function test_is_serialized_correctly(): void { - $pass = new StoreCard(array_merge(Components::passAttributes(), Components::fields())); + $attributes = array_merge(Components::passAttributes(), Components::fields()); + $pass = new StoreCard(...$attributes); $expected = array_merge(Components::passAttributes(), Components::nullablePassAttributes(), [ 'storeCard' => Components::fieldValues(), ]); - $this->assertSameArray($expected, $pass->toArray()); + $this->assertSameArray($expected, $pass->encode()); } } From 20da88c4fa3d8cd134628f42004235d3c1b8baf6 Mon Sep 17 00:00:00 2001 From: Elisha Witte Date: Thu, 10 Oct 2024 13:47:55 +0200 Subject: [PATCH 2/5] Migrate to antwerpes/data-transfer-object --- src/Common/Casters/LegacyValueCaster.php | 10 + src/Google/Components/Common/DateTime.php | 3 +- src/Google/Passes/AbstractClass.php | 186 +++++------ src/Google/Passes/AbstractObject.php | 207 ++++++------ src/Google/Passes/BaseClass.php | 182 +++++----- src/Google/Passes/BaseObject.php | 78 ++--- src/Google/Passes/EventTicketClass.php | 231 ++++++------- src/Google/Passes/EventTicketObject.php | 117 ++++--- src/Google/Passes/FlightClass.php | 162 +++++---- src/Google/Passes/FlightObject.php | 83 +++-- src/Google/Passes/GenericObject.php | 130 ++++---- src/Google/Passes/GiftCardClass.php | 133 ++++---- src/Google/Passes/GiftCardObject.php | 74 ++--- src/Google/Passes/LoyaltyClass.php | 228 ++++++------- src/Google/Passes/LoyaltyObject.php | 80 ++--- src/Google/Passes/OfferClass.php | 204 ++++++------ src/Google/Passes/OfferObject.php | 15 +- src/Google/Passes/TransitClass.php | 329 +++++++++---------- src/Google/Passes/TransitObject.php | 251 +++++++------- src/Google/Repositories/BaseRepository.php | 6 +- src/Google/Repositories/ClassRepository.php | 2 +- src/Google/Repositories/ObjectRepository.php | 2 +- tests/Google/Fixtures/Passes.php | 16 +- tests/Google/GenericClassTest.php | 13 +- tests/Google/GenericObjectTest.php | 13 +- tests/Google/OfferClassTest.php | 13 +- tests/Google/OfferObjectTest.php | 13 +- 27 files changed, 1360 insertions(+), 1421 deletions(-) diff --git a/src/Common/Casters/LegacyValueCaster.php b/src/Common/Casters/LegacyValueCaster.php index 1afb96a..b2510f5 100644 --- a/src/Common/Casters/LegacyValueCaster.php +++ b/src/Common/Casters/LegacyValueCaster.php @@ -4,15 +4,21 @@ use Antwerpes\DataTransferObject\CastsProperty; use Chiiya\Passes\Common\LegacyValueEnumerator; +use LogicException; class LegacyValueCaster implements CastsProperty { public function __construct( + private readonly array $types, private readonly string $enum, ) {} public function unserialize(mixed $value): ?string { + if (! in_array('string', $this->types, true)) { + throw new LogicException('Caster [LegacyValueCaster] may only be used to cast strings.'); + } + if ($value === null) { return null; } @@ -25,6 +31,10 @@ public function unserialize(mixed $value): ?string public function serialize(mixed $value): ?string { + if (! in_array('string', $this->types, true)) { + throw new LogicException('Caster [LegacyValueCaster] may only be used to cast strings.'); + } + if ($value === null) { return null; } diff --git a/src/Google/Components/Common/DateTime.php b/src/Google/Components/Common/DateTime.php index 5ed69d3..8dd149d 100644 --- a/src/Google/Components/Common/DateTime.php +++ b/src/Google/Components/Common/DateTime.php @@ -5,6 +5,7 @@ use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\ISO8601DateCaster; use Chiiya\Passes\Common\Component; +use DateTimeInterface; use Symfony\Component\Validator\Constraints\NotBlank; class DateTime extends Component @@ -16,7 +17,7 @@ public function __construct( */ #[NotBlank] #[Cast(ISO8601DateCaster::class)] - public string $date, + public DateTimeInterface|string $date, ) { parent::__construct(); } diff --git a/src/Google/Passes/AbstractClass.php b/src/Google/Passes/AbstractClass.php index ef27a1e..7df6728 100644 --- a/src/Google/Passes/AbstractClass.php +++ b/src/Google/Passes/AbstractClass.php @@ -2,11 +2,10 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxItems; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\CallbackOptions; use Chiiya\Passes\Google\Components\Common\ClassTemplate\ClassTemplateInfo; use Chiiya\Passes\Google\Components\Common\ImageModuleData; @@ -15,100 +14,95 @@ use Chiiya\Passes\Google\Components\Common\TextModuleData; use Chiiya\Passes\Google\Enumerators\MultipleDevicesAndHoldersAllowedStatus; use Chiiya\Passes\Google\Enumerators\ViewUnlockRequirement; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\NotBlank; abstract class AbstractClass extends Component { - /** - * Optional. - * Template information about how the class should be displayed. If unset, Google will fallback to a default - * set of fields to display. - */ - public ?ClassTemplateInfo $classTemplateInfo; - - /** - * Required. - * The unique identifier for a class. This ID must be unique across all classes from an issuer. This value - * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. - */ - #[Required] - public ?string $id; - - /** - * Optional. - * Image module data. The maximum number of these fields displayed is 1 from object level and 1 for - * class object level. - * - * @var ImageModuleData[] - */ - #[CastWith(ArrayCaster::class, ImageModuleData::class)] - #[MaxItems(1)] - public array $imageModulesData = []; - - /** - * Optional. - * Text module data. If text module data is also defined on the class, both will be displayed. The - * maximum number of these fields displayed is 10 from the object and 10 from the class. - * - * @var TextModuleData[] - */ - #[CastWith(ArrayCaster::class, TextModuleData::class)] - #[MaxItems(10)] - public array $textModulesData = []; - - /** - * Optional. - * Links module data. If links module data is also defined on the object, both will be displayed. - */ - public ?LinksModuleData $linksModuleData; - - /** - * Optional. - * Available only to Smart Tap enabled partners. Contact support for additional guidance. - */ - public ?bool $enableSmartTap; - - /** - * Optional. - * Available only to Smart Tap enabled partners. Contact support for additional guidance. - */ - public array $redemptionIssuers = []; - - /** - * Optional - * If this is set a security animation will be rendered on pass details. - */ - public ?SecurityAnimation $securityAnimation; - - /** - * Optional. - * Identifies whether multiple users and devices will save the same object referencing this class. - */ - #[ValueIn([ - MultipleDevicesAndHoldersAllowedStatus::STATUS_UNSPECIFIED, - MultipleDevicesAndHoldersAllowedStatus::MULTIPLE_HOLDERS, - MultipleDevicesAndHoldersAllowedStatus::ONE_USER_ALL_DEVICES, - MultipleDevicesAndHoldersAllowedStatus::ONE_USER_ONE_DEVICE, - ])] - #[CastWith(LegacyValueCaster::class, MultipleDevicesAndHoldersAllowedStatus::class)] - public ?string $multipleDevicesAndHoldersAllowedStatus; - - /** - * Optional. - * Callback options to be used to call the issuer back for every save/delete of an object for this class by - * the end-user. All objects of this class are eligible for the callback. - */ - public ?CallbackOptions $callbackOptions; - - /** - * Optional - * Defines what unlock mechanism, if any, is required to view the card. - */ - #[ValueIn([ - ViewUnlockRequirement::VIEW_UNLOCK_REQUIREMENT_UNSPECIFIED, - ViewUnlockRequirement::UNLOCK_NOT_REQUIRED, - ViewUnlockRequirement::UNLOCK_REQUIRED_TO_VIEW, - ])] - protected ?string $viewUnlockRequirement; + public function __construct( + /** + * Required. + * The unique identifier for a class. This ID must be unique across all classes from an issuer. This value + * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. + */ + #[NotBlank] + public string $id, + /** + * Optional. + * Template information about how the class should be displayed. If unset, Google will fall back to a default + * set of fields to display. + */ + public ?ClassTemplateInfo $classTemplateInfo = null, + /** + * Optional. + * Image module data. The maximum number of these fields displayed is 1 from object level and 1 for + * class object level. + * + * @var ImageModuleData[] + */ + #[Cast(ArrayCaster::class, ImageModuleData::class)] + #[Count(max: 1)] + public array $imageModulesData = [], + /** + * Optional. + * Text module data. If text module data is also defined on the class, both will be displayed. The + * maximum number of these fields displayed is 10 from the object and 10 from the class. + * + * @var TextModuleData[] + */ + #[Cast(ArrayCaster::class, TextModuleData::class)] + #[Count(max: 10)] + public array $textModulesData = [], + /** + * Optional. + * Links module data. If links module data is also defined on the object, both will be displayed. + */ + public ?LinksModuleData $linksModuleData = null, + /** + * Optional. + * Available only to Smart Tap enabled partners. Contact support for additional guidance. + */ + public ?bool $enableSmartTap = null, + /** + * Optional. + * Available only to Smart Tap enabled partners. Contact support for additional guidance. + */ + public array $redemptionIssuers = [], + /** + * Optional + * If this is set a security animation will be rendered on pass details. + */ + public ?SecurityAnimation $securityAnimation = null, + /** + * Optional. + * Identifies whether multiple users and devices will save the same object referencing this class. + */ + #[Choice([ + MultipleDevicesAndHoldersAllowedStatus::STATUS_UNSPECIFIED, + MultipleDevicesAndHoldersAllowedStatus::MULTIPLE_HOLDERS, + MultipleDevicesAndHoldersAllowedStatus::ONE_USER_ALL_DEVICES, + MultipleDevicesAndHoldersAllowedStatus::ONE_USER_ONE_DEVICE, + ])] + #[Cast(LegacyValueCaster::class, MultipleDevicesAndHoldersAllowedStatus::class)] + public ?string $multipleDevicesAndHoldersAllowedStatus = null, + /** + * Optional. + * Callback options to be used to call the issuer back for every save/delete of an object for this class by + * the end-user. All objects of this class are eligible for the callback. + */ + public ?CallbackOptions $callbackOptions = null, + /** + * Optional + * Defines what unlock mechanism, if any, is required to view the card. + */ + #[Choice([ + ViewUnlockRequirement::VIEW_UNLOCK_REQUIREMENT_UNSPECIFIED, + ViewUnlockRequirement::UNLOCK_NOT_REQUIRED, + ViewUnlockRequirement::UNLOCK_REQUIRED_TO_VIEW, + ])] + protected ?string $viewUnlockRequirement = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Passes/AbstractObject.php b/src/Google/Passes/AbstractObject.php index add3f96..ae31d6a 100644 --- a/src/Google/Passes/AbstractObject.php +++ b/src/Google/Passes/AbstractObject.php @@ -2,11 +2,10 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MaxItems; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\AppLinkData; use Chiiya\Passes\Google\Components\Common\Barcode; use Chiiya\Passes\Google\Components\Common\GroupingInfo; @@ -17,112 +16,104 @@ use Chiiya\Passes\Google\Components\Common\TextModuleData; use Chiiya\Passes\Google\Components\Common\TimeInterval; use Chiiya\Passes\Google\Enumerators\State; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\NotBlank; class AbstractObject extends Component { - /** - * Required. - * The unique identifier for an object. This ID must be unique across all objects from an issuer. This value - * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. - */ - #[Required] - public ?string $id; - - /** - * Required. - * The class associated with this object. The class must be of the same type as this object, must already exist, - * and must be approved. Class IDs should follow the format issuer ID.identifier where the former is issued by - * Google and latter is chosen by you. - */ - #[Required] - public ?string $classId; - - /** - * Required. - * The state of the object. This field is used to determine how an object is displayed in the app. - */ - #[ValueIn([State::STATE_UNSPECIFIED, State::ACTIVE, State::COMPLETED, State::EXPIRED, State::INACTIVE])] - #[CastWith(LegacyValueCaster::class, State::class)] - #[Required] - public ?string $state; - - /** - * Optional. - * The barcode type and value. - */ - public ?Barcode $barcode; - - /** - * Optional. - * The time period this object will be active and object can be used. An object's state will be changed to - * expired when this time period has passed. - */ - public ?TimeInterval $validTimeInterval; - - /** - * Optional. - * Available only to Smart Tap enabled partners. Contact support for additional guidance. - */ - public ?string $smartTapRedemptionValue; - - /** - * Optional. - * Grouping info for event tickets. - */ - public ?GroupingInfo $groupingInfo; - - /** - * Optional. - * Image module data. The maximum number of these fields displayed is 1 from object level and 1 for - * class object level. - * - * @var ImageModuleData[] - */ - #[CastWith(ArrayCaster::class, ImageModuleData::class)] - #[MaxItems(1)] - public array $imageModulesData = []; - - /** - * Optional. - * Text module data. If text module data is also defined on the class, both will be displayed. The maximum - * number of these fields displayed is 10 from the object and 10 from the class. - * - * @var TextModuleData[] - */ - #[CastWith(ArrayCaster::class, TextModuleData::class)] - #[MaxItems(10)] - public array $textModulesData = []; - - /** - * Optional. - * Links module data. If links module data is also defined on the class, both will be displayed. - */ - public ?LinksModuleData $linksModuleData; - - /** - * Optional. - * Optional information about the partner app link. - */ - public ?AppLinkData $appLinkData; - - /** - * Optional. - * Optional banner image displayed on the front of the card. If none is present, hero image of the class, - * if present, will be displayed. If hero image of the class is also not present, nothing will be displayed. - */ - public ?Image $heroImage; - - /** - * Optional - * The rotating barcode settings/details. - */ - public ?RotatingBarcode $rotatingBarcode; - - /** - * Optional. - * Indicates if the object has users. This field is set by the platform. - */ - public ?bool $hasUsers; + public function __construct( + /** + * Required. + * The unique identifier for an object. This ID must be unique across all objects from an issuer. This value + * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. + */ + #[NotBlank] + public string $id, + /** + * Required. + * The class associated with this object. The class must be of the same type as this object, must already exist, + * and must be approved. Class IDs should follow the format issuer ID.identifier where the former is issued by + * Google and latter is chosen by you. + */ + #[NotBlank] + public string $classId, + /** + * Required. + * The state of the object. This field is used to determine how an object is displayed in the app. + */ + #[Choice([State::STATE_UNSPECIFIED, State::ACTIVE, State::COMPLETED, State::EXPIRED, State::INACTIVE])] + #[Cast(LegacyValueCaster::class, State::class)] + #[NotBlank] + public string $state, + /** + * Optional. + * The barcode type and value. + */ + public ?Barcode $barcode = null, + /** + * Optional. + * The time period this object will be active and object can be used. An object's state will be changed to + * expired when this time period has passed. + */ + public ?TimeInterval $validTimeInterval = null, + /** + * Optional. + * Available only to Smart Tap enabled partners. Contact support for additional guidance. + */ + public ?string $smartTapRedemptionValue = null, + /** + * Optional. + * Grouping info for event tickets. + */ + public ?GroupingInfo $groupingInfo = null, + /** + * Optional. + * Image module data. The maximum number of these fields displayed is 1 from object level and 1 for + * class object level. + * + * @var ImageModuleData[] + */ + #[Cast(ArrayCaster::class, ImageModuleData::class)] + #[Count(max: 1)] + public array $imageModulesData = [], + /** + * Optional. + * Text module data. If text module data is also defined on the class, both will be displayed. The maximum + * number of these fields displayed is 10 from the object and 10 from the class. + * + * @var TextModuleData[] + */ + #[Cast(ArrayCaster::class, TextModuleData::class)] + #[Count(max: 10)] + public array $textModulesData = [], + /** + * Optional. + * Links module data. If links module data is also defined on the class, both will be displayed. + */ + public ?LinksModuleData $linksModuleData = null, + /** + * Optional. + * Optional information about the partner app link. + */ + public ?AppLinkData $appLinkData = null, + /** + * Optional. + * Optional banner image displayed on the front of the card. If none is present, hero image of the class, + * if present, will be displayed. If hero image of the class is also not present, nothing will be displayed. + */ + public ?Image $heroImage = null, + /** + * Optional + * The rotating barcode settings/details. + */ + public ?RotatingBarcode $rotatingBarcode = null, + /** + * Optional. + * Indicates if the object has users. This field is set by the platform. + */ + public ?bool $hasUsers = null, + ) { + parent::__construct(); + } } diff --git a/src/Google/Passes/BaseClass.php b/src/Google/Passes/BaseClass.php index 77ee750..18b3159 100644 --- a/src/Google/Passes/BaseClass.php +++ b/src/Google/Passes/BaseClass.php @@ -2,12 +2,9 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\HexColor; -use Chiiya\Passes\Common\Validation\MaxItems; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LatLongPoint; use Chiiya\Passes\Google\Components\Common\LocalizedString; @@ -15,95 +12,94 @@ use Chiiya\Passes\Google\Components\Common\Review; use Chiiya\Passes\Google\Components\Common\Uri; use Chiiya\Passes\Google\Enumerators\ReviewStatus; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\CssColor; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; abstract class BaseClass extends AbstractClass { - /** - * Required. - * The issuer name. Recommended maximum length is 20 characters to ensure full string is displayed on - * smaller screens. - */ - #[Required] - #[MaxLength(20)] - public ?string $issuerName; - - /** - * Optional. - * An array of messages displayed in the app. All users of this object will receive its associated messages. - * The maximum number of these fields is 10. - * - * @var Message[] - */ - #[CastWith(ArrayCaster::class, Message::class)] - #[MaxItems(10)] - public array $messages = []; - - /** - * Optional. - * The URI of your application's home page. - */ - public ?Uri $homepageUri; - - /** - * Optional. - * List of locations. - * - * @var LatLongPoint[] - */ - #[CastWith(ArrayCaster::class, LatLongPoint::class)] - #[MaxItems(20)] - public array $locations = []; - - /** - * Required. - * The status of the class. - */ - #[Required] - #[ValueIn([ - ReviewStatus::REVIEW_STATUS_UNSPECIFIED, - ReviewStatus::UNDER_REVIEW, - ReviewStatus::APPROVED, - ReviewStatus::REJECTED, - ReviewStatus::DRAFT, - ])] - #[CastWith(LegacyValueCaster::class, ReviewStatus::class)] - public ?string $reviewStatus; - - /** - * Optional. - * The review comments set by the platform when a class is marked approved or rejected. - */ - public ?Review $review; - - /** - * Optional. - * Country code used to display the card's country (when the user is not in that country), as well - * as to display localized content when content is not available in the user's locale. - */ - public ?string $countryCode; - - /** - * Optional. - * Optional banner image displayed on the front of the card. If none is present, nothing will be displayed. - * The image will display at 100% width. - */ - public ?Image $heroImage; - - /** - * Optional. - * The background color for the card. If not set the dominant color of the hero image is used, and if no hero - * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, - * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. - */ - #[HexColor] - public ?string $hexBackgroundColor; - - /** - * Optional. - * Translated strings for the issuerName. Recommended maximum length is 20 characters to ensure full string - * is displayed on smaller screens. - */ - public ?LocalizedString $localizedIssuerName; + public function __construct( + /** + * Required. + * The issuer name. Recommended maximum length is 20 characters to ensure full string is displayed on + * smaller screens. + */ + #[NotBlank] + #[Length(max: 20)] + public string $issuerName, + /** + * Required. + * The status of the class. + */ + #[NotBlank] + #[Choice([ + ReviewStatus::REVIEW_STATUS_UNSPECIFIED, + ReviewStatus::UNDER_REVIEW, + ReviewStatus::APPROVED, + ReviewStatus::REJECTED, + ReviewStatus::DRAFT, + ])] + #[Cast(LegacyValueCaster::class, ReviewStatus::class)] + public string $reviewStatus, + /** + * Optional. + * An array of messages displayed in the app. All users of this object will receive its associated messages. + * The maximum number of these fields is 10. + * + * @var Message[] + */ + #[Cast(ArrayCaster::class, Message::class)] + #[Count(max: 10)] + public array $messages = [], + /** + * Optional. + * The URI of your application's home page. + */ + public ?Uri $homepageUri = null, + /** + * Optional. + * List of locations. + * + * @var LatLongPoint[] + */ + #[Cast(ArrayCaster::class, LatLongPoint::class)] + #[Count(max: 20)] + public array $locations = [], + /** + * Optional. + * The review comments set by the platform when a class is marked approved or rejected. + */ + public ?Review $review = null, + /** + * Optional. + * Country code used to display the card's country (when the user is not in that country), as well + * as to display localized content when content is not available in the user's locale. + */ + public ?string $countryCode = null, + /** + * Optional. + * Optional banner image displayed on the front of the card. If none is present, nothing will be displayed. + * The image will display at 100% width. + */ + public ?Image $heroImage = null, + /** + * Optional. + * The background color for the card. If not set the dominant color of the hero image is used, and if no hero + * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, + * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. + */ + #[CssColor(formats: [CssColor::HEX_LONG, CssColor::HEX_SHORT])] + public ?string $hexBackgroundColor = null, + /** + * Optional. + * Translated strings for the issuerName. Recommended maximum length is 20 characters to ensure full string + * is displayed on smaller screens. + */ + public ?LocalizedString $localizedIssuerName = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/BaseObject.php b/src/Google/Passes/BaseObject.php index 03f5474..254f751 100644 --- a/src/Google/Passes/BaseObject.php +++ b/src/Google/Passes/BaseObject.php @@ -2,47 +2,49 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\MaxItems; +use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Google\Components\Common\LatLongPoint; use Chiiya\Passes\Google\Components\Common\Message; -use Spatie\DataTransferObject\Attributes\CastWith; -use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Count; abstract class BaseObject extends AbstractObject { - /** - * Optional. - * An array of messages displayed in the app. All users of this object will receive its associated messages. - * The maximum number of these fields is 10. - * - * @var Message[] - */ - #[CastWith(ArrayCaster::class, Message::class)] - #[MaxItems(10)] - public array $messages = []; - - /** - * Optional. - * The list of locations where the object can be used. The platform uses this information to trigger - * geolocated notifications to users. Note that locations in the object override locations in the class which - * override locations in the Google Places ID. - */ - #[CastWith(ArrayCaster::class, LatLongPoint::class)] - #[MaxItems(20)] - public array $locations = []; - - /** - * Whether this object is currently linked to a single device. This field is set by the platform when a user - * saves the object, linking it to their device. Intended for use by select partners. Contact support - * for additional information. - */ - public ?bool $hasLinkedDevice; - - /** - * Optional. - * Indicates if notifications should explicitly be suppressed. If this field is set to true, regardless of - * the messages field, expiration notifications to the user will be suppressed. By default, this field is - * set to false. - */ - public ?bool $disableExpirationNotification; + public function __construct( + /** + * Optional. + * An array of messages displayed in the app. All users of this object will receive its associated messages. + * The maximum number of these fields is 10. + * + * @var Message[] + */ + #[Cast(ArrayCaster::class, Message::class)] + #[Count(max: 10)] + public array $messages = [], + /** + * Optional. + * The list of locations where the object can be used. The platform uses this information to trigger + * geolocated notifications to users. Note that locations in the object override locations in the class which + * override locations in the Google Places ID. + */ + #[Cast(ArrayCaster::class, LatLongPoint::class)] + #[Count(max: 20)] + public array $locations = [], + /** + * Whether this object is currently linked to a single device. This field is set by the platform when a user + * saves the object, linking it to their device. Intended for use by select partners. Contact support + * for additional information. + */ + public ?bool $hasLinkedDevice = null, + /** + * Optional. + * Indicates if notifications should explicitly be suppressed. If this field is set to true, regardless of + * the messages field, expiration notifications to the user will be suppressed. By default, this field is + * set to false. + */ + public ?bool $disableExpirationNotification = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/EventTicketClass.php b/src/Google/Passes/EventTicketClass.php index e022cf5..d4a6fc6 100644 --- a/src/Google/Passes/EventTicketClass.php +++ b/src/Google/Passes/EventTicketClass.php @@ -2,9 +2,8 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\EventTicket\EventDateTime; @@ -14,130 +13,118 @@ use Chiiya\Passes\Google\Enumerators\EventTicket\RowLabel; use Chiiya\Passes\Google\Enumerators\EventTicket\SeatLabel; use Chiiya\Passes\Google\Enumerators\EventTicket\SectionLabel; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; class EventTicketClass extends BaseClass { /** @var string */ final public const IDENTIFIER = 'eventTicketClass'; - /** - * Optional. - * The fine print, terms, or conditions of the pass. - */ - public ?LocalizedString $finePrint; - - /** - * Required. - * The name of the event, such as "LA Dodgers at SF Giants". - */ - #[Required] - public ?LocalizedString $eventName; - - /** - * Optional. - * The ID of the event. This ID should be unique for every event in an account. It is used to group tickets - * together if the user has saved multiple tickets for the same event. It can be at most 64 characters. - */ - public ?string $eventId; - - /** - * Optional. - * The logo image of the ticket. This image is displayed in the card detail view of the app. - */ - public ?Image $logo; - - /** - * Optional. - * The wide logo of the ticket. When provided, this will be used in place of the logo in the top left of the card view. - */ - public ?Image $wideLogo; - - /** - * Optional. - * Event venue details. - */ - public ?EventVenue $venue; - - /** - * Optional. - * The date & time information of the event. - */ - public ?EventDateTime $dateTime; - - /** - * Optional. - * The label to use for the confirmation code value on the card detail view. - */ - #[ValueIn([ - ConfirmationCodeLabel::CONFIRMATION_CODE_LABEL_UNSPECIFIED, - ConfirmationCodeLabel::CONFIRMATION_CODE, - ConfirmationCodeLabel::CONFIRMATION_NUMBER, - ConfirmationCodeLabel::ORDER_NUMBER, - ConfirmationCodeLabel::RESERVATION_NUMBER, - ])] - #[CastWith(LegacyValueCaster::class, ConfirmationCodeLabel::class)] - public ?string $confirmationCodeLabel; - - /** - * Optional. - * A custom label to use for the confirmation code value on the card detail view. - */ - public ?string $customConfirmationCodeLabel; - - /** - * Optional. - * The label to use for the seat value on the card detail view. - */ - #[ValueIn([SeatLabel::SEAT, SeatLabel::SEAT_LABEL_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, SeatLabel::class)] - public ?string $seatLabel; - - /** - * Optional. - * A custom label to use for the seat value on the card detail view. - */ - public ?string $customSeatLabel; - - /** - * Optional. - * The label to use for the row value on the card detail view. - */ - #[ValueIn([RowLabel::ROW, RowLabel::ROW_LABEL_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, RowLabel::class)] - public ?string $rowLabel; - - /** - * Optional. - * A custom label to use for the row value on the card detail view. - */ - public ?string $customRowLabel; - - /** - * Optional. - * The label to use for the section value on the card detail view. - */ - #[ValueIn([SectionLabel::SECTION, SectionLabel::THEATER, SectionLabel::SECTION_LABEL_UNSPECIFIED])] - #[CastWith(LegacyValueCaster::class, SectionLabel::class)] - public ?string $sectionLabel; - - /** - * Optional. - * A custom label to use for the section value on the card detail view. - */ - public ?string $customSectionLabel; - - /** - * Optional. - * The label to use for the gate value on the card detail view. - */ - #[ValueIn([GateLabel::GATE_LABEL_UNSPECIFIED, GateLabel::GATE, GateLabel::DOOR, GateLabel::ENTRANCE])] - #[CastWith(LegacyValueCaster::class, GateLabel::class)] - public ?string $gateLabel; - - /** - * Optional. - * A custom label to use for the gate value on the card detail view. - */ - public ?string $customGateLabel; + public function __construct( + /** + * Required. + * The name of the event, such as "LA Dodgers at SF Giants". + */ + public LocalizedString $eventName, + /** + * Optional. + * The fine print, terms, or conditions of the pass. + */ + public ?LocalizedString $finePrint = null, + /** + * Optional. + * The ID of the event. This ID should be unique for every event in an account. It is used to group tickets + * together if the user has saved multiple tickets for the same event. It can be at most 64 characters. + */ + public ?string $eventId = null, + /** + * Optional. + * The logo image of the ticket. This image is displayed in the card detail view of the app. + */ + public ?Image $logo = null, + /** + * Optional. + * The wide logo of the ticket. When provided, this will be used in place of the logo in the top left of the card view. + */ + public ?Image $wideLogo = null, + /** + * Optional. + * Event venue details. + */ + public ?EventVenue $venue = null, + /** + * Optional. + * The date & time information of the event. + */ + public ?EventDateTime $dateTime = null, + /** + * Optional. + * The label to use for the confirmation code value on the card detail view. + */ + #[Choice([ + ConfirmationCodeLabel::CONFIRMATION_CODE_LABEL_UNSPECIFIED, + ConfirmationCodeLabel::CONFIRMATION_CODE, + ConfirmationCodeLabel::CONFIRMATION_NUMBER, + ConfirmationCodeLabel::ORDER_NUMBER, + ConfirmationCodeLabel::RESERVATION_NUMBER, + ])] + #[Cast(LegacyValueCaster::class, ConfirmationCodeLabel::class)] + public ?string $confirmationCodeLabel = null, + /** + * Optional. + * A custom label to use for the confirmation code value on the card detail view. + */ + public ?string $customConfirmationCodeLabel = null, + /** + * Optional. + * The label to use for the seat value on the card detail view. + */ + #[Choice([SeatLabel::SEAT, SeatLabel::SEAT_LABEL_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, SeatLabel::class)] + public ?string $seatLabel = null, + /** + * Optional. + * A custom label to use for the seat value on the card detail view. + */ + public ?string $customSeatLabel = null, + /** + * Optional. + * The label to use for the row value on the card detail view. + */ + #[Choice([RowLabel::ROW, RowLabel::ROW_LABEL_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, RowLabel::class)] + public ?string $rowLabel = null, + /** + * Optional. + * A custom label to use for the row value on the card detail view. + */ + public ?string $customRowLabel = null, + /** + * Optional. + * The label to use for the section value on the card detail view. + */ + #[Choice([SectionLabel::SECTION, SectionLabel::THEATER, SectionLabel::SECTION_LABEL_UNSPECIFIED])] + #[Cast(LegacyValueCaster::class, SectionLabel::class)] + public ?string $sectionLabel = null, + /** + * Optional. + * A custom label to use for the section value on the card detail view. + */ + public ?string $customSectionLabel = null, + /** + * Optional. + * The label to use for the gate value on the card detail view. + */ + #[Choice([GateLabel::GATE_LABEL_UNSPECIFIED, GateLabel::GATE, GateLabel::DOOR, GateLabel::ENTRANCE])] + #[Cast(LegacyValueCaster::class, GateLabel::class)] + public ?string $gateLabel = null, + /** + * Optional. + * A custom label to use for the gate value on the card detail view. + */ + public ?string $customGateLabel = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/EventTicketObject.php b/src/Google/Passes/EventTicketObject.php index 2930a4e..150aafc 100644 --- a/src/Google/Passes/EventTicketObject.php +++ b/src/Google/Passes/EventTicketObject.php @@ -2,74 +2,71 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\HexColor; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Common\Money; use Chiiya\Passes\Google\Components\EventTicket\EventReservationInfo; use Chiiya\Passes\Google\Components\EventTicket\EventSeat; +use Symfony\Component\Validator\Constraints\CssColor; class EventTicketObject extends BaseObject { /** @var string */ final public const IDENTIFIER = 'eventTicketObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?EventTicketClass $classReference; - - /** - * Optional. - * Seating details for this ticket. - */ - public ?EventSeat $seatInfo; - - /** - * Optional. - * Reservation details for this ticket. This is expected to be shared amongst all tickets that - * were purchased in the same order. - */ - public ?EventReservationInfo $reservationInfo; - - /** - * Optional. - * Name of the ticket holder, if the ticket is assigned to a person. E.g. "John Doe" or "Jane Doe". - */ - public ?string $ticketHolderName; - - /** - * Optional. - * The number of the ticket. This can be a unique identifier across all tickets in an issuer's system, - * all tickets for the event (e.g. XYZ1234512345), or all tickets in the order (1, 2, 3, etc.). - */ - public ?string $ticketNumber; - - /** - * Optional. - * The type of the ticket, such as "Adult" or "Child", or "VIP" or "Standard". - */ - public ?LocalizedString $ticketType; - - /** - * Optional. - * The face value of the ticket, matching what would be printed on a physical version of the ticket. - */ - public ?Money $faceValue; - - /** - * Optional. - * A list of offer objects linked to this event ticket. The offer objects must already exist. Offer object IDs - * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. - */ - public array $linkedOfferIds = []; - - /** - * Optional. - * The background color for the card. If not set the dominant color of the hero image is used, and if no hero - * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, - * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. - */ - #[HexColor] - public ?string $hexBackgroundColor; + public function __construct( + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?EventTicketClass $classReference = null, + /** + * Optional. + * Seating details for this ticket. + */ + public ?EventSeat $seatInfo = null, + /** + * Optional. + * Reservation details for this ticket. This is expected to be shared amongst all tickets that + * were purchased in the same order. + */ + public ?EventReservationInfo $reservationInfo = null, + /** + * Optional. + * Name of the ticket holder, if the ticket is assigned to a person. E.g. "John Doe" or "Jane Doe". + */ + public ?string $ticketHolderName = null, + /** + * Optional. + * The number of the ticket. This can be a unique identifier across all tickets in an issuer's system, + * all tickets for the event (e.g. XYZ1234512345), or all tickets in the order (1, 2, 3, etc.). + */ + public ?string $ticketNumber = null, + /** + * Optional. + * The type of the ticket, such as "Adult" or "Child", or "VIP" or "Standard". + */ + public ?LocalizedString $ticketType = null, + /** + * Optional. + * The face value of the ticket, matching what would be printed on a physical version of the ticket. + */ + public ?Money $faceValue = null, + /** + * Optional. + * A list of offer objects linked to this event ticket. The offer objects must already exist. Offer object IDs + * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. + */ + public array $linkedOfferIds = [], + /** + * Optional. + * The background color for the card. If not set the dominant color of the hero image is used, and if no hero + * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, + * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. + */ + #[CssColor(formats: [CssColor::HEX_LONG, CssColor::HEX_SHORT])] + public ?string $hexBackgroundColor = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/FlightClass.php b/src/Google/Passes/FlightClass.php index 1b29cf7..737f4d4 100644 --- a/src/Google/Passes/FlightClass.php +++ b/src/Google/Passes/FlightClass.php @@ -2,100 +2,92 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Flight\AirportInfo; use Chiiya\Passes\Google\Components\Flight\BoardingAndSeatingPolicy; use Chiiya\Passes\Google\Components\Flight\FlightHeader; use Chiiya\Passes\Google\Enumerators\Flight\FlightStatus; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class FlightClass extends BaseClass { /** @var string */ final public const IDENTIFIER = 'flightClass'; - /** - * Required. - * The scheduled date and time when the aircraft is expected to depart the gate (not the runway). - */ - #[Required] - public ?string $localScheduledDepartureDateTime; - - /** - * Optional. - * The estimated time the aircraft plans to pull from the gate or the actual time the aircraft already - * pulled from the gate. Note: This is not the runway time. - */ - public ?string $localEstimatedOrActualDepartureDateTime; - - /** - * Optional. - * The boarding time as it would be printed on the boarding pass. - */ - public ?string $localBoardingDateTime; - - /** - * Optional. - * The scheduled time the aircraft plans to reach the destination gate (not the runway). - */ - public ?string $localScheduledArrivalDateTime; - - /** - * Optional. - * The estimated time the aircraft plans to reach the destination gate (not the runway) or the actual - * time it reached the gate. - */ - public ?string $localEstimatedOrActualArrivalDateTime; - - /** - * Required. - * Information about the flight carrier and number. - */ - #[Required] - public ?FlightHeader $flightHeader; - - /** - * Required. - * Origin airport. - */ - #[Required] - public ?AirportInfo $origin; - - /** - * Required. - * Destination airport. - */ - #[Required] - public ?AirportInfo $destination; - - /** - * Optional. - * If unset, Google will compute status based on data from other sources, such as FlightStats, etc. - */ - #[ValueIn([ - FlightStatus::FLIGHT_STATUS_UNSPECIFIED, - FlightStatus::SCHEDULED, - FlightStatus::ACTIVE, - FlightStatus::LANDED, - FlightStatus::CANCELLED, - FlightStatus::REDIRECTED, - FlightStatus::DIVERTED, - ])] - #[CastWith(LegacyValueCaster::class, FlightStatus::class)] - public ?string $flightStatus; - - /** - * Optional. - * Policies for boarding and seating. These will inform which labels will be shown to users. - */ - public ?BoardingAndSeatingPolicy $boardingAndSeatingPolicy; - - /** - * Optional. - * The gate closing time as it would be printed on the boarding pass. Do not set this field if you do - * not want to print it in the boarding pass. - */ - public ?string $localGateClosingDateTime; + public function __construct( + /** + * Required. + * The scheduled date and time when the aircraft is expected to depart the gate (not the runway). + */ + #[NotBlank] + public string $localScheduledDepartureDateTime, + /** + * Required. + * Information about the flight carrier and number. + */ + public FlightHeader $flightHeader, + /** + * Required. + * Origin airport. + */ + public AirportInfo $origin, + /** + * Required. + * Destination airport. + */ + public AirportInfo $destination, + /** + * Optional. + * The estimated time the aircraft plans to pull from the gate or the actual time the aircraft already + * pulled from the gate. Note: This is not the runway time. + */ + public ?string $localEstimatedOrActualDepartureDateTime = null, + /** + * Optional. + * The boarding time as it would be printed on the boarding pass. + */ + public ?string $localBoardingDateTime = null, + /** + * Optional. + * The scheduled time the aircraft plans to reach the destination gate (not the runway). + */ + public ?string $localScheduledArrivalDateTime = null, + /** + * Optional. + * The estimated time the aircraft plans to reach the destination gate (not the runway) or the actual + * time it reached the gate. + */ + public ?string $localEstimatedOrActualArrivalDateTime = null, + /** + * Optional. + * If unset, Google will compute status based on data from other sources, such as FlightStats, etc. + */ + #[Choice([ + FlightStatus::FLIGHT_STATUS_UNSPECIFIED, + FlightStatus::SCHEDULED, + FlightStatus::ACTIVE, + FlightStatus::LANDED, + FlightStatus::CANCELLED, + FlightStatus::REDIRECTED, + FlightStatus::DIVERTED, + ])] + #[Cast(LegacyValueCaster::class, FlightStatus::class)] + public ?string $flightStatus = null, + /** + * Optional. + * Policies for boarding and seating. These will inform which labels will be shown to users. + */ + public ?BoardingAndSeatingPolicy $boardingAndSeatingPolicy = null, + /** + * Optional. + * The gate closing time as it would be printed on the boarding pass. Do not set this field if you do + * not want to print it in the boarding pass. + */ + public ?string $localGateClosingDateTime = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/FlightObject.php b/src/Google/Passes/FlightObject.php index cae29e3..0f0a658 100644 --- a/src/Google/Passes/FlightObject.php +++ b/src/Google/Passes/FlightObject.php @@ -2,55 +2,54 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\HexColor; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Flight\BoardingAndSeatingInfo; use Chiiya\Passes\Google\Components\Flight\ReservationInfo; +use Symfony\Component\Validator\Constraints\CssColor; +use Symfony\Component\Validator\Constraints\NotBlank; class FlightObject extends BaseObject { /** @var string */ final public const IDENTIFIER = 'flightObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?FlightClass $classReference; - - /** - * Required. - * Passenger name as it would appear on the boarding pass. - */ - #[Required] - public ?string $passengerName; - - /** - * Optional. - * Passenger specific information about boarding and seating. - */ - public ?BoardingAndSeatingInfo $boardingAndSeatingInfo; - - /** - * Required. - * Information about flight reservation. - */ - #[Required] - public ?ReservationInfo $reservationInfo; - - /** - * Optional. - * An image for the security program that applies to the passenger. - */ - public ?Image $securityProgramLogo; - - /** - * Optional. - * The background color for the card. If not set the dominant color of the hero image is used, and if no hero - * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, - * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. - */ - #[HexColor] - public ?string $hexBackgroundColor; + public function __construct( + /** + * Required. + * Passenger name as it would appear on the boarding pass. + */ + #[NotBlank] + public string $passengerName, + /** + * Required. + * Information about flight reservation. + */ + public ReservationInfo $reservationInfo, + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?FlightClass $classReference = null, + /** + * Optional. + * Passenger specific information about boarding and seating. + */ + public ?BoardingAndSeatingInfo $boardingAndSeatingInfo = null, + /** + * Optional. + * An image for the security program that applies to the passenger. + */ + public ?Image $securityProgramLogo = null, + /** + * Optional. + * The background color for the card. If not set the dominant color of the hero image is used, and if no hero + * image is set, the dominant color of the logo is used. The format is #rrggbb where rrggbb is a hex RGB triplet, + * such as #ffcc00. You can also use the shorthand version of the RGB triplet which is #rgb, such as #fc0. + */ + #[CssColor(formats: [CssColor::HEX_LONG, CssColor::HEX_SHORT])] + public ?string $hexBackgroundColor = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/GenericObject.php b/src/Google/Passes/GenericObject.php index a9137ce..88ad434 100644 --- a/src/Google/Passes/GenericObject.php +++ b/src/Google/Passes/GenericObject.php @@ -2,80 +2,78 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\HexColor; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Generic\Notifications; use Chiiya\Passes\Google\Enumerators\Generic\GenericType; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\CssColor; class GenericObject extends AbstractObject { /** @var string */ final public const IDENTIFIER = 'genericObject'; - /** - * Optional - * The type of the generic card. - */ - #[ValueIn([ - GenericType::GENERIC_TYPE_UNSPECIFIED, - GenericType::GENERIC_SEASON_PASS, - GenericType::GENERIC_UTILITY_BILLS, - GenericType::GENERIC_PARKING_PASS, - GenericType::GENERIC_VOUCHER, - GenericType::GENERIC_GYM_MEMBERSHIP, - GenericType::GENERIC_LIBRARY_MEMBERSHIP, - GenericType::GENERIC_RESERVATIONS, - GenericType::GENERIC_AUTO_INSURANCE, - GenericType::GENERIC_HOME_INSURANCE, - GenericType::GENERIC_ENTRY_TICKET, - GenericType::GENERIC_RECEIPT, - GenericType::GENERIC_OTHER, - ])] - public ?string $genericType; - - /** - * Required - * The title of the pass. This is usually the Business name such as "XXX Gym", "AAA Insurance". - */ - public LocalizedString $cardTitle; - - /** - * Optional - * The subheader of the pass, such as location where this pass can be used. - */ - public ?LocalizedString $subheader; - - /** - * Required - * The header of the pass, such as "50% off coupon" or "Library card" or "Voucher". - */ - public LocalizedString $header; - - /** - * Optional. - * The logo image of the ticket. This image is displayed in the card detail view of the app. - */ - public ?Image $logo; - - /** - * Optional. - * The wide logo of the pass. When provided, this will be used in place of the logo in the top left of the card view. - */ - public ?Image $wideLogo; - - /** - * Optional. - * The background color for the card. If not set, the dominant color of the hero image is used, and if no hero - * image is set, the dominant color of the logo is used and if logo is not set, a color would be chosen by Google. - */ - #[HexColor] - public ?string $hexBackgroundColor; - - /** - * Optional. - * Indicates if the object needs to have notification enabled. - */ - public ?Notifications $notifications; + public function __construct( + /** + * Required + * The title of the pass. This is usually the Business name such as "XXX Gym", "AAA Insurance". + */ + public LocalizedString $cardTitle, + /** + * Required + * The header of the pass, such as "50% off coupon" or "Library card" or "Voucher". + */ + public LocalizedString $header, + /** + * Optional + * The type of the generic card. + */ + #[Choice([ + GenericType::GENERIC_TYPE_UNSPECIFIED, + GenericType::GENERIC_SEASON_PASS, + GenericType::GENERIC_UTILITY_BILLS, + GenericType::GENERIC_PARKING_PASS, + GenericType::GENERIC_VOUCHER, + GenericType::GENERIC_GYM_MEMBERSHIP, + GenericType::GENERIC_LIBRARY_MEMBERSHIP, + GenericType::GENERIC_RESERVATIONS, + GenericType::GENERIC_AUTO_INSURANCE, + GenericType::GENERIC_HOME_INSURANCE, + GenericType::GENERIC_ENTRY_TICKET, + GenericType::GENERIC_RECEIPT, + GenericType::GENERIC_OTHER, + ])] + public ?string $genericType = null, + /** + * Optional + * The subheader of the pass, such as location where this pass can be used. + */ + public ?LocalizedString $subheader = null, + /** + * Optional. + * The logo image of the ticket. This image is displayed in the card detail view of the app. + */ + public ?Image $logo = null, + /** + * Optional. + * The wide logo of the pass. When provided, this will be used in place of the logo in the top left of the card view. + */ + public ?Image $wideLogo = null, + /** + * Optional. + * The background color for the card. If not set, the dominant color of the hero image is used, and if no hero + * image is set, the dominant color of the logo is used and if logo is not set, a color would be chosen by Google. + */ + #[CssColor(formats: [CssColor::HEX_LONG, CssColor::HEX_SHORT])] + public ?string $hexBackgroundColor = null, + /** + * Optional. + * Indicates if the object needs to have notification enabled. + */ + public ?Notifications $notifications = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/GiftCardClass.php b/src/Google/Passes/GiftCardClass.php index c37ff64..e5bc366 100644 --- a/src/Google/Passes/GiftCardClass.php +++ b/src/Google/Passes/GiftCardClass.php @@ -10,73 +10,68 @@ class GiftCardClass extends BaseClass /** @var string */ final public const IDENTIFIER = 'giftCardClass'; - /** - * Optional. - * Merchant name, such as "Adam's Apparel". The app may display an ellipsis after the first 20 - * characters to ensure full string is displayed on smaller screens. - */ - public ?string $merchantName; - - /** - * Optional. - * The logo of the gift card program or company. This logo is displayed in both the details and list - * views of the app. - */ - public ?Image $programLogo; - - /** - * Optional. - * The wide logo of the gift card program or company. When provided, this will be used in place of the program logo in the top left of the card view. - */ - public ?Image $wideProgramLogo; - - /** - * Optional. - * The label to display for the PIN, such as "4-digit PIN". - */ - public ?string $pinLabel; - - /** - * Optional. - * The label to display for event number, such as "Target Event #". - */ - public ?string $eventNumberLabel; - - /** - * Optional. - * Determines whether the merchant supports gift card redemption using barcode. If true, app displays a - * barcode for the gift card on the Gift card details screen. If false, a barcode is not displayed. - */ - public ?bool $allowBarcodeRedemption; - - /** - * Optional. - * Translated strings for the merchantName. The app may display an ellipsis after the first 20 - * characters to ensure full string is displayed on smaller screens. - */ - public ?LocalizedString $localizedMerchantName; - - /** - * Optional. - * Translated strings for the pinLabel. - */ - public ?LocalizedString $localizedPinLabel; - - /** - * Optional. - * Translated strings for the eventNumberLabel. - */ - public ?LocalizedString $localizedEventNumberLabel; - - /** - * Optional. - * The label to display for the card number, such as "Card Number". - */ - public ?string $cardNumberLabel; - - /** - * Optional. - * Translated strings for the cardNumberLabel. - */ - public ?LocalizedString $localizedCardNumberLabel; + public function __construct( + /** + * Optional. + * Merchant name, such as "Adam's Apparel". The app may display an ellipsis after the first 20 + * characters to ensure full string is displayed on smaller screens. + */ + public ?string $merchantName = null, + /** + * Optional. + * The logo of the gift card program or company. This logo is displayed in both the details and list + * views of the app. + */ + public ?Image $programLogo = null, + /** + * Optional. + * The wide logo of the gift card program or company. When provided, this will be used in place of the program logo in the top left of the card view. + */ + public ?Image $wideProgramLogo = null, + /** + * Optional. + * The label to display for the PIN, such as "4-digit PIN". + */ + public ?string $pinLabel = null, + /** + * Optional. + * The label to display for event number, such as "Target Event #". + */ + public ?string $eventNumberLabel = null, + /** + * Optional. + * Determines whether the merchant supports gift card redemption using barcode. If true, app displays a + * barcode for the gift card on the Gift card details screen. If false, a barcode is not displayed. + */ + public ?bool $allowBarcodeRedemption = null, + /** + * Optional. + * Translated strings for the merchantName. The app may display an ellipsis after the first 20 + * characters to ensure full string is displayed on smaller screens. + */ + public ?LocalizedString $localizedMerchantName = null, + /** + * Optional. + * Translated strings for the pinLabel. + */ + public ?LocalizedString $localizedPinLabel = null, + /** + * Optional. + * Translated strings for the eventNumberLabel. + */ + public ?LocalizedString $localizedEventNumberLabel = null, + /** + * Optional. + * The label to display for the card number, such as "Card Number". + */ + public ?string $cardNumberLabel = null, + /** + * Optional. + * Translated strings for the cardNumberLabel. + */ + public ?LocalizedString $localizedCardNumberLabel = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/GiftCardObject.php b/src/Google/Passes/GiftCardObject.php index 3ad6fba..d3e83e6 100644 --- a/src/Google/Passes/GiftCardObject.php +++ b/src/Google/Passes/GiftCardObject.php @@ -2,49 +2,49 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\DateTime; use Chiiya\Passes\Google\Components\Common\Money; +use Symfony\Component\Validator\Constraints\NotBlank; class GiftCardObject extends BaseObject { /** @var string */ final public const IDENTIFIER = 'giftCardObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?GiftCardClass $classReference; - - /** - * Required. - * The card's number. - */ - #[Required] - public ?string $cardNumber; - - /** - * Optional. - * The card's PIN. - */ - public ?string $pin; - - /** - * Optional. - * The card's monetary balance. - */ - public ?Money $balance; - - /** - * Optional. - * The date and time when the balance was last updated. - */ - public ?DateTime $balanceUpdateTime; - - /** - * Optional. - * The card's event number, an optional field used by some gift cards. - */ - public ?string $eventNumber; + public function __construct( + /** + * Required. + * The card's number. + */ + #[NotBlank] + public string $cardNumber, + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?GiftCardClass $classReference = null, + /** + * Optional. + * The card's PIN. + */ + public ?string $pin = null, + /** + * Optional. + * The card's monetary balance. + */ + public ?Money $balance = null, + /** + * Optional. + * The date and time when the balance was last updated. + */ + public ?DateTime $balanceUpdateTime = null, + /** + * Optional. + * The card's event number, an optional field used by some gift cards. + */ + public ?string $eventNumber = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/LoyaltyClass.php b/src/Google/Passes/LoyaltyClass.php index b496406..fb77a31 100644 --- a/src/Google/Passes/LoyaltyClass.php +++ b/src/Google/Passes/LoyaltyClass.php @@ -2,133 +2,121 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Loyalty\DiscoverableProgram; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; class LoyaltyClass extends BaseClass { /** @var string */ final public const IDENTIFIER = 'loyaltyClass'; - /** - * Required. - * The program name, such as "Adam's Apparel". The app may display an ellipsis after the first 20 - * characters to ensure full string is displayed on smaller screens. - */ - #[Required] - public ?string $programName; - - /** - * Required. - * The logo of the loyalty program or company. This logo is displayed in both the details and list - * views of the app. - */ - #[Required] - public ?Image $programLogo; - - /** - * Optional. - * The wide logo of the loyalty program or company. When provided, this will be used in place of the program logo in the top left of the card view. - */ - public ?Image $wideProgramLogo; - - /** - * Optional. - * The account name label, such as "Member Name." Recommended maximum length is 15 characters to - * ensure full string is displayed on smaller screens. - */ - #[MaxLength(15)] - public ?string $accountNameLabel; - - /** - * Optional. - * The account ID label, such as "Member ID." Recommended maximum length is 15 characters to ensure - * full string is displayed on smaller screens. - */ - #[MaxLength(15)] - public ?string $accountIdLabel; - - /** - * Optional. - * The rewards tier label, such as "Rewards Tier." Recommended maximum length is 9 characters to ensure - * full string is displayed on smaller screens. - */ - #[MaxLength(9)] - public ?string $rewardsTierLabel; - - /** - * Optional. - * The rewards tier, such as "Gold" or "Platinum." Recommended maximum length is 7 characters to ensure - * full string is displayed on smaller screens. - */ - #[MaxLength(7)] - public ?string $rewardsTier; - - /** - * Optional. - * Translated strings for the programName. The app may display an ellipsis after the first 20 characters - * to ensure full string is displayed on smaller screens. - */ - public ?LocalizedString $localizedProgramName; - - /** - * Optional. - * Translated strings for the accountNameLabel. Recommended maximum length is 15 characters to ensure - * full string is displayed on smaller screens. - */ - public ?LocalizedString $localizedAccountNameLabel; - - /** - * Optional. - * Translated strings for the accountIdLabel. Recommended maximum length is 15 characters to ensure full - * string is displayed on smaller screens. - */ - public ?LocalizedString $localizedAccountIdLabel; - - /** - * Optional. - * Translated strings for the rewardsTierLabel. Recommended maximum length is 9 characters to ensure full - * string is displayed on smaller screens. - */ - public ?LocalizedString $localizedRewardsTierLabel; - - /** - * Optional. - * Translated strings for the rewardsTier. Recommended maximum length is 7 characters to ensure full string - * is displayed on smaller screens. - */ - public ?LocalizedString $localizedRewardsTier; - - /** - * Optional. - * The secondary rewards tier label, such as "Rewards Tier.". - */ - public ?string $secondaryRewardsTierLabel; - - /** - * Optional. - * Translated strings for the secondaryRewardsTierLabel. - */ - public ?LocalizedString $localizedSecondaryRewardsTierLabel; - - /** - * Optional. - * The secondary rewards tier, such as "Gold" or "Platinum.". - */ - public ?string $secondaryRewardsTier; - - /** - * Optional. - * Translated strings for the secondaryRewardsTier. - */ - public ?LocalizedString $localizedSecondaryRewardsTier; - - /** - * Optional. - * Information about how the class may be discovered and instantiated from within the Google Pay app. - */ - public ?DiscoverableProgram $discoverableProgram; + public function __construct( + /** + * Required. + * The program name, such as "Adam's Apparel". The app may display an ellipsis after the first 20 + * characters to ensure full string is displayed on smaller screens. + */ + #[NotBlank] + public string $programName, + /** + * Required. + * The logo of the loyalty program or company. This logo is displayed in both the details and list + * views of the app. + */ + public Image $programLogo, + /** + * Optional. + * The wide logo of the loyalty program or company. When provided, this will be used in place of the program logo in the top left of the card view. + */ + public ?Image $wideProgramLogo = null, + /** + * Optional. + * The account name label, such as "Member Name." Recommended maximum length is 15 characters to + * ensure full string is displayed on smaller screens. + */ + #[Length(max: 15)] + public ?string $accountNameLabel = null, + /** + * Optional. + * The account ID label, such as "Member ID." Recommended maximum length is 15 characters to ensure + * full string is displayed on smaller screens. + */ + #[Length(max: 15)] + public ?string $accountIdLabel = null, + /** + * Optional. + * The rewards tier label, such as "Rewards Tier." Recommended maximum length is 9 characters to ensure + * full string is displayed on smaller screens. + */ + #[Length(max: 9)] + public ?string $rewardsTierLabel = null, + /** + * Optional. + * The rewards tier, such as "Gold" or "Platinum." Recommended maximum length is 7 characters to ensure + * full string is displayed on smaller screens. + */ + #[Length(max: 7)] + public ?string $rewardsTier = null, + /** + * Optional. + * Translated strings for the programName. The app may display an ellipsis after the first 20 characters + * to ensure full string is displayed on smaller screens. + */ + public ?LocalizedString $localizedProgramName = null, + /** + * Optional. + * Translated strings for the accountNameLabel. Recommended maximum length is 15 characters to ensure + * full string is displayed on smaller screens. + */ + public ?LocalizedString $localizedAccountNameLabel = null, + /** + * Optional. + * Translated strings for the accountIdLabel. Recommended maximum length is 15 characters to ensure full + * string is displayed on smaller screens. + */ + public ?LocalizedString $localizedAccountIdLabel = null, + /** + * Optional. + * Translated strings for the rewardsTierLabel. Recommended maximum length is 9 characters to ensure full + * string is displayed on smaller screens. + */ + public ?LocalizedString $localizedRewardsTierLabel = null, + /** + * Optional. + * Translated strings for the rewardsTier. Recommended maximum length is 7 characters to ensure full string + * is displayed on smaller screens. + */ + public ?LocalizedString $localizedRewardsTier = null, + /** + * Optional. + * The secondary rewards tier label, such as "Rewards Tier.". + */ + public ?string $secondaryRewardsTierLabel = null, + /** + * Optional. + * Translated strings for the secondaryRewardsTierLabel. + */ + public ?LocalizedString $localizedSecondaryRewardsTierLabel = null, + /** + * Optional. + * The secondary rewards tier, such as "Gold" or "Platinum.". + */ + public ?string $secondaryRewardsTier = null, + /** + * Optional. + * Translated strings for the secondaryRewardsTier. + */ + public ?LocalizedString $localizedSecondaryRewardsTier = null, + /** + * Optional. + * Information about how the class may be discovered and instantiated from within the Google Pay app. + */ + public ?DiscoverableProgram $discoverableProgram = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/LoyaltyObject.php b/src/Google/Passes/LoyaltyObject.php index e6e9913..fb23f4e 100644 --- a/src/Google/Passes/LoyaltyObject.php +++ b/src/Google/Passes/LoyaltyObject.php @@ -2,51 +2,51 @@ namespace Chiiya\Passes\Google\Passes; -use Chiiya\Passes\Common\Validation\MaxLength; use Chiiya\Passes\Google\Components\Loyalty\LoyaltyPoints; +use Symfony\Component\Validator\Constraints\Length; class LoyaltyObject extends BaseObject { /** @var string */ final public const IDENTIFIER = 'loyaltyObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?LoyaltyClass $classReference; - - /** - * Optional. - * The loyalty account holder name, such as "John Smith." Recommended maximum length is 20 characters - * to ensure full string is displayed on smaller screens. - */ - #[MaxLength(20)] - public ?string $accountName; - - /** - * Optional. - * The loyalty account identifier. Recommended maximum length is 20 characters. - */ - #[MaxLength(20)] - public ?string $accountId; - - /** - * Optional. - * The loyalty reward points label, balance, and type. - */ - public ?LoyaltyPoints $loyaltyPoints; - - /** - * Optional. - * A list of offer objects linked to this loyalty card. The offer objects must already exist. Offer object IDs - * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. - */ - public array $linkedOfferIds = []; - - /** - * Optional. - * The secondary loyalty reward points label, balance, and type. Shown in addition to the primary loyalty points. - */ - public ?LoyaltyPoints $secondaryLoyaltyPoints; + public function __construct( + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?LoyaltyClass $classReference = null, + /** + * Optional. + * The loyalty account holder name, such as "John Smith." Recommended maximum length is 20 characters + * to ensure full string is displayed on smaller screens. + */ + #[Length(max: 20)] + public ?string $accountName = null, + /** + * Optional. + * The loyalty account identifier. Recommended maximum length is 20 characters. + */ + #[Length(max: 20)] + public ?string $accountId = null, + /** + * Optional. + * The loyalty reward points label, balance, and type. + */ + public ?LoyaltyPoints $loyaltyPoints = null, + /** + * Optional. + * A list of offer objects linked to this loyalty card. The offer objects must already exist. Offer object IDs + * should follow the format issuer ID.identifier where the former is issued by Google and latter is chosen by you. + */ + public array $linkedOfferIds = [], + /** + * Optional. + * The secondary loyalty reward points label, balance, and type. Shown in addition to the primary loyalty points. + */ + public ?LoyaltyPoints $secondaryLoyaltyPoints = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/OfferClass.php b/src/Google/Passes/OfferClass.php index 3e3f73a..3eac3b0 100644 --- a/src/Google/Passes/OfferClass.php +++ b/src/Google/Passes/OfferClass.php @@ -2,121 +2,113 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\MaxLength; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Common\Uri; use Chiiya\Passes\Google\Enumerators\Offer\RedemptionChannel; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; class OfferClass extends BaseClass { /** @var string */ final public const IDENTIFIER = 'offerClass'; - /** - * Required. - * The title of the offer, such as "20% off any t-shirt." Recommended maximum length is 60 characters - * to ensure full string is displayed on smaller screens. - */ - #[Required] - #[MaxLength(60)] - public ?string $title; - - /** - * Required. - * The redemption channels applicable to this offer. - */ - #[ValueIn([ - RedemptionChannel::REDEMPTION_CHANNEL_UNSPECIFIED, - RedemptionChannel::INSTORE, - RedemptionChannel::ONLINE, - RedemptionChannel::BOTH, - RedemptionChannel::TEMPORARY_PRICE_REDUCTION, - ])] - #[CastWith(LegacyValueCaster::class, RedemptionChannel::class)] - #[Required] - public ?string $redemptionChannel; - - /** - * Required. - * The offer provider (either the aggregator name or merchant name). Recommended maximum length is 12 - * characters to ensure full string is displayed on smaller screens. - */ - #[Required] - #[MaxLength(12)] - public ?string $provider; - - /** - * Optional. - * The title image of the offer. This image is displayed in both the details and list views of the app. - */ - public ?Image $titleImage; - - /** - * Optional. - * The wide title image of the offer. When provided, this will be used in place of the title image in the top left of the card view. - */ - public ?Image $wideTitleImage; - - /** - * Optional. - * The details of the offer. - */ - public ?string $details; - - /** - * Optional. - * The fine print or terms of the offer, such as "20% off any t-shirt at Adam's Apparel.". - */ - public ?string $finePrint; - - /** - * Optional. - * The help link for the offer, such as http://myownpersonaldomain.com/help. - */ - public ?Uri $helpUri; - - /** - * Optional. - * Translated strings for the title. Recommended maximum length is 60 characters to ensure full - * string is displayed on smaller screens. - */ - public ?LocalizedString $localizedTitle; - - /** - * Optional. - * Translated strings for the provider. Recommended maximum length is 12 characters to ensure full - * string is displayed on smaller screens. - */ - public ?LocalizedString $localizedProvider; - - /** - * Optional. - * Translated strings for the details. - */ - public ?LocalizedString $localizedDetails; - - /** - * Optional. - * Translated strings for the finePrint. - */ - public ?LocalizedString $localizedFinePrint; - - /** - * Optional. - * A shortened version of the title of the offer, such as "20% off," shown to users as a quick reference - * to the offer contents. Recommended maximum length is 20 characters. - */ - #[MaxLength(20)] - public ?string $shortTitle; - - /** - * Optional. - * Translated strings for the short title. Recommended maximum length is 20 characters. - */ - public ?LocalizedString $localizedShortTitle; + public function __construct( + /** + * Required. + * The title of the offer, such as "20% off any t-shirt." Recommended maximum length is 60 characters + * to ensure full string is displayed on smaller screens. + */ + #[NotBlank] + #[Length(max: 60)] + public string $title, + /** + * Required. + * The redemption channels applicable to this offer. + */ + #[Choice([ + RedemptionChannel::REDEMPTION_CHANNEL_UNSPECIFIED, + RedemptionChannel::INSTORE, + RedemptionChannel::ONLINE, + RedemptionChannel::BOTH, + RedemptionChannel::TEMPORARY_PRICE_REDUCTION, + ])] + #[Cast(LegacyValueCaster::class, RedemptionChannel::class)] + #[NotBlank] + public string $redemptionChannel, + /** + * Required. + * The offer provider (either the aggregator name or merchant name). Recommended maximum length is 12 + * characters to ensure full string is displayed on smaller screens. + */ + #[NotBlank] + #[Length(max: 12)] + public string $provider, + /** + * Optional. + * The title image of the offer. This image is displayed in both the details and list views of the app. + */ + public ?Image $titleImage = null, + /** + * Optional. + * The wide title image of the offer. When provided, this will be used in place of the title image in the top left of the card view. + */ + public ?Image $wideTitleImage = null, + /** + * Optional. + * The details of the offer. + */ + public ?string $details = null, + /** + * Optional. + * The fine print or terms of the offer, such as "20% off any t-shirt at Adam's Apparel.". + */ + public ?string $finePrint = null, + /** + * Optional. + * The help link for the offer, such as http://myownpersonaldomain.com/help. + */ + public ?Uri $helpUri = null, + /** + * Optional. + * Translated strings for the title. Recommended maximum length is 60 characters to ensure full + * string is displayed on smaller screens. + */ + public ?LocalizedString $localizedTitle = null, + /** + * Optional. + * Translated strings for the provider. Recommended maximum length is 12 characters to ensure full + * string is displayed on smaller screens. + */ + public ?LocalizedString $localizedProvider = null, + /** + * Optional. + * Translated strings for the details. + */ + public ?LocalizedString $localizedDetails = null, + /** + * Optional. + * Translated strings for the finePrint. + */ + public ?LocalizedString $localizedFinePrint = null, + /** + * Optional. + * A shortened version of the title of the offer, such as "20% off," shown to users as a quick reference + * to the offer contents. Recommended maximum length is 20 characters. + */ + #[Length(max: 20)] + public ?string $shortTitle = null, + /** + * Optional. + * Translated strings for the short title. Recommended maximum length is 20 characters. + */ + public ?LocalizedString $localizedShortTitle = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/OfferObject.php b/src/Google/Passes/OfferObject.php index 025beec..75507e9 100644 --- a/src/Google/Passes/OfferObject.php +++ b/src/Google/Passes/OfferObject.php @@ -7,9 +7,14 @@ class OfferObject extends BaseObject /** @var string */ final public const IDENTIFIER = 'offerObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?OfferClass $classReference; + public function __construct( + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?OfferClass $classReference = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/TransitClass.php b/src/Google/Passes/TransitClass.php index 22d2f35..7f7df1a 100644 --- a/src/Google/Passes/TransitClass.php +++ b/src/Google/Passes/TransitClass.php @@ -2,189 +2,168 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\Image; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Enumerators\Transit\TransitType; -use Spatie\DataTransferObject\Attributes\CastWith; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\NotBlank; class TransitClass extends BaseClass { /** @var string */ final public const IDENTIFIER = 'transitClass'; - /** - * Optional. - * The name of the transit operator. - */ - public ?LocalizedString $transitOperatorName; - - /** - * Required. - * The logo image of the ticket. This image is displayed in the card detail view of the app. - */ - #[Required] - public ?Image $logo; - - /** - * Optional. - * The wide logo of the ticket. When provided, this will be used in place of the logo in the top left of the card view. - */ - public ?Image $wideLogo; - - /** - * Required. - * The type of transit this class represents, such as "bus". - */ - #[ValueIn([ - TransitType::TRANSIT_TYPE_UNSPECIFIED, - TransitType::BUS, - TransitType::RAIL, - TransitType::TRAM, - TransitType::FERRY, - TransitType::OTHER, - ])] - #[CastWith(LegacyValueCaster::class, TransitType::class)] - #[Required] - public ?string $transitType; - - /** - * Optional. - * Watermark image to display on the user's device. - */ - public ?Image $watermark; - - /** - * Optional. - * If this field is present, transit tickets served to a user's device will always be in this language. - * Represents the BCP 47 language tag. Example values are "en-US", "en-GB", "de", or "de-AT". - */ - public ?string $languageOverride; - - /** - * Optional. - * A custom label to use for the transit terminus name value (transitObject.ticketLeg.transitTerminusName). - */ - public ?LocalizedString $customTransitTerminusNameLabel; - - /** - * Optional. - * A custom label to use for the ticket number value (transitObject.ticketNumber). - */ - public ?LocalizedString $customTicketNumberLabel; - - /** - * Optional. - * A custom label to use for the route restrictions value (transitObject.ticketRestrictions.routeRestrictions). - */ - public ?LocalizedString $customRouteRestrictionsLabel; - - /** - * Optional. - * A custom label to use for the route restrictions details value - * (transitObject.ticketRestrictions.routeRestrictionsDetails). - */ - public ?LocalizedString $customRouteRestrictionsDetailsLabel; - - /** - * Optional. - * A custom label to use for the time restrictions details value - * (transitObject.ticketRestrictions.timeRestrictions). - */ - public ?LocalizedString $customTimeRestrictionsLabel; - - /** - * Optional. - * A custom label to use for the other restrictions value (transitObject.ticketRestrictions.otherRestrictions). - */ - public ?LocalizedString $customOtherRestrictionsLabel; - - /** - * Optional. - * A custom label to use for the purchase receipt number value - * (transitObject.purchaseDetails.purchaseReceiptNumber). - */ - public ?LocalizedString $customPurchaseReceiptNumberLabel; - - /** - * Optional. - * A custom label to use for the confirmation code value (transitObject.purchaseDetails.confirmationCode). - */ - public ?LocalizedString $customConfirmationCodeLabel; - - /** - * Optional. - * A custom label to use for the purchase face value (transitObject.purchaseDetails.ticketCost.faceValue). - */ - public ?LocalizedString $customPurchaseFaceValueLabel; - - /** - * Optional. - * A custom label to use for the purchase price value (transitObject.purchaseDetails.ticketCost.purchasePrice). - */ - public ?LocalizedString $customPurchasePriceLabel; - - /** - * Optional. - * A custom label to use for the transit discount message value - * (transitObject.purchaseDetails.ticketCost.discountMessage). - */ - public ?LocalizedString $customDiscountMessageLabel; - - /** - * Optional. - * A custom label to use for the carriage value (transitObject.ticketLeg.carriage). - */ - public ?LocalizedString $customCarriageLabel; - - /** - * Optional. - * A custom label to use for the seat location value (transitObject.ticketLeg.ticketSeat.seat). - */ - public ?LocalizedString $customSeatLabel; - - /** - * Optional. - * A custom label to use for the coach value (transitObject.ticketLeg.ticketSeat.coach). - */ - public ?LocalizedString $customCoachLabel; - - /** - * Optional. - * A custom label to use for the boarding platform value (transitObject.ticketLeg.platform). - */ - public ?LocalizedString $customPlatformLabel; - - /** - * Optional. - * A custom label to use for the boarding zone value (transitObject.ticketLeg.zone). - */ - public ?LocalizedString $customZoneLabel; - - /** - * Optional. - * A custom label to use for the fare class value (transitObject.ticketLeg.ticketSeat.fareClass). - */ - public ?LocalizedString $customFareClassLabel; - - /** - * Optional. - * A custom label to use for the transit concession category value (transitObject.concessionCategory). - */ - public ?LocalizedString $customConcessionCategoryLabel; - - /** - * Optional. - * A custom label to use for the transit fare name value (transitObject.ticketLeg.fareName). - */ - public ?LocalizedString $customFareNameLabel; - - /** - * Optional. - * Controls the display of the single-leg itinerary for this class. By default, an itinerary will - * only display for multi-leg trips. - */ - public ?bool $enableSingleLegItinerary; + public function __construct( + /** + * Required. + * The type of transit this class represents, such as "bus". + */ + #[Choice([ + TransitType::TRANSIT_TYPE_UNSPECIFIED, + TransitType::BUS, + TransitType::RAIL, + TransitType::TRAM, + TransitType::FERRY, + TransitType::OTHER, + ])] + #[Cast(LegacyValueCaster::class, TransitType::class)] + #[NotBlank] + public string $transitType, + /** + * Required. + * The logo image of the ticket. This image is displayed in the card detail view of the app. + */ + public Image $logo, + /** + * Optional. + * The name of the transit operator. + */ + public ?LocalizedString $transitOperatorName = null, + /** + * Optional. + * The wide logo of the ticket. When provided, this will be used in place of the logo in the top left of the card view. + */ + public ?Image $wideLogo = null, + /** + * Optional. + * Watermark image to display on the user's device. + */ + public ?Image $watermark = null, + /** + * Optional. + * If this field is present, transit tickets served to a user's device will always be in this language. + * Represents the BCP 47 language tag. Example values are "en-US", "en-GB", "de", or "de-AT". + */ + public ?string $languageOverride = null, + /** + * Optional. + * A custom label to use for the transit terminus name value (transitObject.ticketLeg.transitTerminusName). + */ + public ?LocalizedString $customTransitTerminusNameLabel = null, + /** + * Optional. + * A custom label to use for the ticket number value (transitObject.ticketNumber). + */ + public ?LocalizedString $customTicketNumberLabel = null, + /** + * Optional. + * A custom label to use for the route restrictions value (transitObject.ticketRestrictions.routeRestrictions). + */ + public ?LocalizedString $customRouteRestrictionsLabel = null, + /** + * Optional. + * A custom label to use for the route restrictions details value + * (transitObject.ticketRestrictions.routeRestrictionsDetails). + */ + public ?LocalizedString $customRouteRestrictionsDetailsLabel = null, + /** + * Optional. + * A custom label to use for the time restrictions details value + * (transitObject.ticketRestrictions.timeRestrictions). + */ + public ?LocalizedString $customTimeRestrictionsLabel = null, + /** + * Optional. + * A custom label to use for the other restrictions value (transitObject.ticketRestrictions.otherRestrictions). + */ + public ?LocalizedString $customOtherRestrictionsLabel = null, + /** + * Optional. + * A custom label to use for the purchase receipt number value + * (transitObject.purchaseDetails.purchaseReceiptNumber). + */ + public ?LocalizedString $customPurchaseReceiptNumberLabel = null, + /** + * Optional. + * A custom label to use for the confirmation code value (transitObject.purchaseDetails.confirmationCode). + */ + public ?LocalizedString $customConfirmationCodeLabel = null, + /** + * Optional. + * A custom label to use for the purchase face value (transitObject.purchaseDetails.ticketCost.faceValue). + */ + public ?LocalizedString $customPurchaseFaceValueLabel = null, + /** + * Optional. + * A custom label to use for the purchase price value (transitObject.purchaseDetails.ticketCost.purchasePrice). + */ + public ?LocalizedString $customPurchasePriceLabel = null, + /** + * Optional. + * A custom label to use for the transit discount message value + * (transitObject.purchaseDetails.ticketCost.discountMessage). + */ + public ?LocalizedString $customDiscountMessageLabel = null, + /** + * Optional. + * A custom label to use for the carriage value (transitObject.ticketLeg.carriage). + */ + public ?LocalizedString $customCarriageLabel = null, + /** + * Optional. + * A custom label to use for the seat location value (transitObject.ticketLeg.ticketSeat.seat). + */ + public ?LocalizedString $customSeatLabel = null, + /** + * Optional. + * A custom label to use for the coach value (transitObject.ticketLeg.ticketSeat.coach). + */ + public ?LocalizedString $customCoachLabel = null, + /** + * Optional. + * A custom label to use for the boarding platform value (transitObject.ticketLeg.platform). + */ + public ?LocalizedString $customPlatformLabel = null, + /** + * Optional. + * A custom label to use for the boarding zone value (transitObject.ticketLeg.zone). + */ + public ?LocalizedString $customZoneLabel = null, + /** + * Optional. + * A custom label to use for the fare class value (transitObject.ticketLeg.ticketSeat.fareClass). + */ + public ?LocalizedString $customFareClassLabel = null, + /** + * Optional. + * A custom label to use for the transit concession category value (transitObject.concessionCategory). + */ + public ?LocalizedString $customConcessionCategoryLabel = null, + /** + * Optional. + * A custom label to use for the transit fare name value (transitObject.ticketLeg.fareName). + */ + public ?LocalizedString $customFareNameLabel = null, + /** + * Optional. + * Controls the display of the single-leg itinerary for this class. By default, an itinerary will + * only display for multi-leg trips. + */ + public ?bool $enableSingleLegItinerary = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Passes/TransitObject.php b/src/Google/Passes/TransitObject.php index e38ca8b..18a0467 100644 --- a/src/Google/Passes/TransitObject.php +++ b/src/Google/Passes/TransitObject.php @@ -2,10 +2,8 @@ namespace Chiiya\Passes\Google\Passes; +use Antwerpes\DataTransferObject\Attributes\Cast; use Chiiya\Passes\Common\Casters\LegacyValueCaster; -use Chiiya\Passes\Common\Validation\HexColor; -use Chiiya\Passes\Common\Validation\Required; -use Chiiya\Passes\Common\Validation\ValueIn; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Transit\PurchaseDetails; use Chiiya\Passes\Google\Components\Transit\TicketLeg; @@ -14,138 +12,131 @@ use Chiiya\Passes\Google\Enumerators\Transit\PassengerType; use Chiiya\Passes\Google\Enumerators\Transit\TicketStatus; use Chiiya\Passes\Google\Enumerators\Transit\TripType; -use Spatie\DataTransferObject\Attributes\CastWith; use Spatie\DataTransferObject\Casters\ArrayCaster; +use Symfony\Component\Validator\Constraints\Choice; +use Symfony\Component\Validator\Constraints\CssColor; +use Symfony\Component\Validator\Constraints\NotBlank; class TransitObject extends BaseObject { /** @var string */ final public const IDENTIFIER = 'transitObject'; - /** - * Optional. - * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. - */ - public ?TransitClass $classReference; - - /** - * Optional. - * The number of the ticket. This is a unique identifier for the ticket in the transit operator's system. - */ - public ?string $ticketNumber; - - /** - * Optional. - * The number of passengers. - */ - #[ValueIn([ - PassengerType::PASSENGER_TYPE_UNSPECIFIED, - PassengerType::SINGLE_PASSENGER, - PassengerType::MULTIPLE_PASSENGERS, - ])] - #[CastWith(LegacyValueCaster::class, PassengerType::class)] - public ?string $passengerType; - - /** - * Optional. - * The name(s) of the passengers the ticket is assigned to. The above passengerType field is meant to - * give Google context on this field. - */ - public ?string $passengerNames; - - /** - * Optional. - * This id is used to group tickets together if the user has saved multiple tickets for the same trip. - */ - public ?string $tripId; - - /** - * Optional. - * The status of the ticket. For states which affect display, use the state field instead. - */ - #[ValueIn([ - TicketStatus::TICKET_STATUS_UNSPECIFIED, - TicketStatus::USED, - TicketStatus::REFUNDED, - TicketStatus::EXCHANGED, - ])] - #[CastWith(LegacyValueCaster::class, TicketStatus::class)] - public ?string $ticketStatus; - - /** - * Optional. - * A custom status to use for the ticket status value when ticketStatus does not provide the - * right option. Both ticketStatus and customTicketStatus may not be set. - */ - public ?LocalizedString $customTicketStatus; - - /** - * Optional. - * The concession category for the ticket. - */ - #[ValueIn([ - ConcessionCategory::CONCESSION_CATEGORY_UNSPECIFIED, - ConcessionCategory::ADULT, - ConcessionCategory::CHILD, - ConcessionCategory::SENIOR, - ])] - #[CastWith(LegacyValueCaster::class, ConcessionCategory::class)] - public ?string $concessionCategory; - - /** - * Optional. - * A custom concession category to use when concessionCategory does not provide the right option. - * Both concessionCategory and customConcessionCategory may not be set. - */ - public ?LocalizedString $customConcessionCategory; - - /** - * Optional. - * Information about what kind of restrictions there are on using this ticket. For example, - * which days of the week it must be used, or which routes are allowed to be taken. - */ - public ?TicketRestrictions $ticketRestrictions; - - /** - * Optional. - * Purchase details for this ticket. - */ - public ?PurchaseDetails $purchaseDetails; - - /** - * Optional. - * A single ticket leg contains departure and arrival information along with boarding and seating - * information. If more than one leg is to be specified then use the ticketLegs field instead. - * Both ticketLeg and ticketLegs may not be set. - */ - public ?TicketLeg $ticketLeg; - - /** - * Optional. - * Each ticket may contain one or more legs. Each leg contains departure and arrival information along - * with boarding and seating information. If only one leg is to be specified then use the ticketLeg field - * instead. Both ticketLeg and ticketLegs may not be set. - * - * @var TicketLeg[] - */ - #[CastWith(ArrayCaster::class, TicketLeg::class)] - public array $ticketLegs = []; - - /** - * Optional. - * The background color for the card. If not set the dominant color of the hero image is used, and if no - * hero image is set, the dominant color of the logo is used. - */ - #[HexColor] - public ?string $hexBackgroundColor; - - /** - * Required. - * The type of trip this transit object represents. Used to determine which symbol to use between - * the origin and destination. - */ - #[ValueIn([TripType::TRIP_TYPE_UNSPECIFIED, TripType::ROUND_TRIP, TripType::ONE_WAY])] - #[CastWith(LegacyValueCaster::class, TripType::class)] - #[Required] - public ?string $tripType; + public function __construct( + /** + * Required. + * The type of trip this transit object represents. Used to determine which symbol to use between + * the origin and destination. + */ + #[Choice([TripType::TRIP_TYPE_UNSPECIFIED, TripType::ROUND_TRIP, TripType::ONE_WAY])] + #[Cast(LegacyValueCaster::class, TripType::class)] + #[NotBlank] + public string $tripType, + /** + * Optional. + * A copy of the inherited fields of the parent class. These fields are retrieved during a GET. + */ + public ?TransitClass $classReference = null, + /** + * Optional. + * The number of the ticket. This is a unique identifier for the ticket in the transit operator's system. + */ + public ?string $ticketNumber = null, + /** + * Optional. + * The number of passengers. + */ + #[Choice([ + PassengerType::PASSENGER_TYPE_UNSPECIFIED, + PassengerType::SINGLE_PASSENGER, + PassengerType::MULTIPLE_PASSENGERS, + ])] + #[Cast(LegacyValueCaster::class, PassengerType::class)] + public ?string $passengerType = null, + /** + * Optional. + * The name(s) of the passengers the ticket is assigned to. The above passengerType field is meant to + * give Google context on this field. + */ + public ?string $passengerNames = null, + /** + * Optional. + * This id is used to group tickets together if the user has saved multiple tickets for the same trip. + */ + public ?string $tripId = null, + /** + * Optional. + * The status of the ticket. For states which affect display, use the state field instead. + */ + #[Choice([ + TicketStatus::TICKET_STATUS_UNSPECIFIED, + TicketStatus::USED, + TicketStatus::REFUNDED, + TicketStatus::EXCHANGED, + ])] + #[Cast(LegacyValueCaster::class, TicketStatus::class)] + public ?string $ticketStatus = null, + /** + * Optional. + * A custom status to use for the ticket status value when ticketStatus does not provide the + * right option. Both ticketStatus and customTicketStatus may not be set. + */ + public ?LocalizedString $customTicketStatus = null, + /** + * Optional. + * The concession category for the ticket. + */ + #[Choice([ + ConcessionCategory::CONCESSION_CATEGORY_UNSPECIFIED, + ConcessionCategory::ADULT, + ConcessionCategory::CHILD, + ConcessionCategory::SENIOR, + ])] + #[Cast(LegacyValueCaster::class, ConcessionCategory::class)] + public ?string $concessionCategory = null, + /** + * Optional. + * A custom concession category to use when concessionCategory does not provide the right option. + * Both concessionCategory and customConcessionCategory may not be set. + */ + public ?LocalizedString $customConcessionCategory = null, + /** + * Optional. + * Information about what kind of restrictions there are on using this ticket. For example, + * which days of the week it must be used, or which routes are allowed to be taken. + */ + public ?TicketRestrictions $ticketRestrictions = null, + /** + * Optional. + * Purchase details for this ticket. + */ + public ?PurchaseDetails $purchaseDetails = null, + /** + * Optional. + * A single ticket leg contains departure and arrival information along with boarding and seating + * information. If more than one leg is to be specified then use the ticketLegs field instead. + * Both ticketLeg and ticketLegs may not be set. + */ + public ?TicketLeg $ticketLeg = null, + /** + * Optional. + * Each ticket may contain one or more legs. Each leg contains departure and arrival information along + * with boarding and seating information. If only one leg is to be specified then use the ticketLeg field + * instead. Both ticketLeg and ticketLegs may not be set. + * + * @var TicketLeg[] + */ + #[Cast(ArrayCaster::class, TicketLeg::class)] + public array $ticketLegs = [], + /** + * Optional. + * The background color for the card. If not set the dominant color of the hero image is used, and if no + * hero image is set, the dominant color of the logo is used. + */ + #[CssColor(formats: [CssColor::HEX_LONG, CssColor::HEX_SHORT])] + public ?string $hexBackgroundColor = null, + ...$args, + ) { + parent::__construct(...$args); + } } diff --git a/src/Google/Repositories/BaseRepository.php b/src/Google/Repositories/BaseRepository.php index 6175c51..72d7105 100644 --- a/src/Google/Repositories/BaseRepository.php +++ b/src/Google/Repositories/BaseRepository.php @@ -25,7 +25,7 @@ final public function get(string $id): Component $class = $this->getInstanceClass(); $response = $this->client->get($this->buildEntityUrl($id)); - return new $class($response); + return $class::decode($response); } /** @@ -37,7 +37,7 @@ final public function create(Component $instance): Component $class = $this->getInstanceClass(); $response = $this->client->post($this->buildResourceUrl(), $instance); - return new $class($response); + return $class::decode($response); } /** @@ -49,7 +49,7 @@ final public function update(AbstractClass|AbstractObject $instance): Component $class = $this->getInstanceClass(); $response = $this->client->put($this->buildEntityUrl($instance->id), $instance); - return new $class($response); + return $class::decode($response); } /** diff --git a/src/Google/Repositories/ClassRepository.php b/src/Google/Repositories/ClassRepository.php index 372dc41..dc4bfb1 100644 --- a/src/Google/Repositories/ClassRepository.php +++ b/src/Google/Repositories/ClassRepository.php @@ -18,6 +18,6 @@ final public function index(string $issuerId, array $parameters = []): Component $class = $this->getResponseClass(); $response = $this->client->get($url); - return new $class($response); + return $class::decode($response); } } diff --git a/src/Google/Repositories/ObjectRepository.php b/src/Google/Repositories/ObjectRepository.php index 810dfea..80d6665 100644 --- a/src/Google/Repositories/ObjectRepository.php +++ b/src/Google/Repositories/ObjectRepository.php @@ -18,6 +18,6 @@ final public function index(string $classId, array $parameters = []): Component $class = $this->getResponseClass(); $response = $this->client->get($url); - return new $class($response); + return $class::decode($response); } } diff --git a/tests/Google/Fixtures/Passes.php b/tests/Google/Fixtures/Passes.php index bba03a2..b31bd29 100644 --- a/tests/Google/Fixtures/Passes.php +++ b/tests/Google/Fixtures/Passes.php @@ -21,11 +21,13 @@ use Chiiya\Passes\Google\Enumerators\BarcodeRenderEncoding; use Chiiya\Passes\Google\Enumerators\BarcodeType; use Chiiya\Passes\Google\Enumerators\Generic\GenericType; +use Chiiya\Passes\Google\Enumerators\MultipleDevicesAndHoldersAllowedStatus; use Chiiya\Passes\Google\Enumerators\Offer\RedemptionChannel; use Chiiya\Passes\Google\Enumerators\ReviewStatus; use Chiiya\Passes\Google\Enumerators\State; use Chiiya\Passes\Google\Enumerators\TotpAlgorithm; use Chiiya\Passes\Google\Enumerators\ViewUnlockRequirement; +use Chiiya\Passes\Google\Passes\OfferClass; class Passes { @@ -58,7 +60,7 @@ public static function offerObject(): array return [ 'id' => '1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665', 'classId' => '1234567890123456789.coupon-15', - 'classReference' => self::offerClass(), + 'classReference' => new OfferClass(...self::offerClass()), 'state' => State::EXPIRED, 'barcode' => new Barcode(type: BarcodeType::EAN_13, value: '1464194291627'), 'validTimeInterval' => new TimeInterval( @@ -82,7 +84,7 @@ public static function genericClass(): array new Uri(uri: 'https://domain.com/link-2', description: 'Sample link 2'), ], ), - 'multipleDevicesAndHoldersAllowedStatus' => 'oneUserAllDevices', + 'multipleDevicesAndHoldersAllowedStatus' => MultipleDevicesAndHoldersAllowedStatus::ONE_USER_ALL_DEVICES, 'callbackOptions' => new CallbackOptions( url: 'https://domain.com/callback', updateRequestUrl: 'https://domain.com/update-callback', @@ -108,8 +110,8 @@ public static function genericObject(): array 'state' => State::ACTIVE, 'barcode' => new Barcode( type: BarcodeType::QR_CODE, - renderEncoding: BarcodeRenderEncoding::UTF_8, value: '123456789', + renderEncoding: BarcodeRenderEncoding::UTF_8, ), 'validTimeInterval' => new TimeInterval( start: new DateTime(date: '2023-01-01T12:00:00+00:00'), @@ -119,19 +121,19 @@ public static function genericObject(): array upcomingNotification: new UpcomingNotification(enableNotification: true), ), 'textModulesData' => [ - new TextModuleData(id: 'id-1', header: 'header-1', body: 'body-1'), - new TextModuleData(id: 'id-2', header: 'header-2', body: 'body-2'), + new TextModuleData(header: 'header-1', body: 'body-1', id: 'id-1'), + new TextModuleData(header: 'header-2', body: 'body-2', id: 'id-2'), ], 'groupingInfo' => new GroupingInfo(groupingId: 'group-1'), 'rotatingBarcode' => new RotatingBarcode( type: BarcodeType::QR_CODE, - renderEncoding: BarcodeRenderEncoding::UTF_8, valuePattern: '12345', totpDetails: new TotpDetails( - periodMillis: 1000, + periodMillis: '1000', algorithm: TotpAlgorithm::TOTP_SHA1, parameters: [TotpParameters::make('key-1', 123), TotpParameters::make('key-2', 124)], ), + renderEncoding: BarcodeRenderEncoding::UTF_8, alternateText: 'alternate-text', showCodeText: LocalizedString::make('en', 'show-code-text-en'), ), diff --git a/tests/Google/GenericClassTest.php b/tests/Google/GenericClassTest.php index a055cf7..8b691e4 100644 --- a/tests/Google/GenericClassTest.php +++ b/tests/Google/GenericClassTest.php @@ -6,11 +6,13 @@ use Chiiya\Passes\Google\Repositories\GenericClassRepository; use Chiiya\Passes\Tests\Google\Fixtures\Passes; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class GenericClassTest extends TestCase { use MocksApiRequests; + #[Group('google')] public function test_list_instances(): void { $client = $this->createMockClient('generic-classes'); @@ -18,35 +20,38 @@ public function test_list_instances(): void $response = $repository->index('1234567891234567891'); $this->assertSame(1, $response->pagination->resultsPerPage); $this->assertSame('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002', $response->resources[0]->id); - $instance = (new GenericClass(Passes::genericClass()))->jsonSerialize(); + $instance = (new GenericClass(...Passes::genericClass()))->jsonSerialize(); $this->assertSameArray($instance, $response->resources[0]->jsonSerialize()); } + #[Group('google')] public function test_get_instance(): void { $client = $this->createMockClient('generic-class'); $repository = new GenericClassRepository($client); $response = $repository->get('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002'); $this->assertSame('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002', $response->id); - $instance = (new GenericClass(Passes::genericClass()))->jsonSerialize(); + $instance = (new GenericClass(...Passes::genericClass()))->jsonSerialize(); $this->assertSameArray($instance, $response->jsonSerialize()); } + #[Group('google')] public function test_create_instance(): void { $client = $this->createMockClient('generic-class'); $repository = new GenericClassRepository($client); - $instance = new GenericClass(Passes::genericClass()); + $instance = new GenericClass(...Passes::genericClass()); $response = $repository->create($instance); $this->assertSame('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); } + #[Group('google')] public function test_update_instance(): void { $client = $this->createMockClient('generic-class'); $repository = new GenericClassRepository($client); - $instance = new GenericClass(Passes::genericClass()); + $instance = new GenericClass(...Passes::genericClass()); $response = $repository->update($instance); $this->assertSame('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); diff --git a/tests/Google/GenericObjectTest.php b/tests/Google/GenericObjectTest.php index 629071c..ff90a19 100644 --- a/tests/Google/GenericObjectTest.php +++ b/tests/Google/GenericObjectTest.php @@ -6,11 +6,13 @@ use Chiiya\Passes\Google\Repositories\GenericObjectRepository; use Chiiya\Passes\Tests\Google\Fixtures\Passes; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class GenericObjectTest extends TestCase { use MocksApiRequests; + #[Group('google')] public function test_list_instances(): void { $client = $this->createMockClient('generic-objects'); @@ -18,35 +20,38 @@ public function test_list_instances(): void $response = $repository->index('1234567891234567891.718bf4ae-a7a5-11ed-afa1-0242ac120002'); $this->assertSame(1, $response->pagination->resultsPerPage); $this->assertSame('1234567891234567891.fb1e9730-a83b-11ed-afa1-0242ac120002', $response->resources[0]->id); - $instance = (new GenericObject(Passes::genericObject()))->jsonSerialize(); + $instance = (new GenericObject(...Passes::genericObject()))->jsonSerialize(); $this->assertSameArray($instance, $response->resources[0]->jsonSerialize()); } + #[Group('google')] public function test_get_instance(): void { $client = $this->createMockClient('generic-object'); $repository = new GenericObjectRepository($client); $response = $repository->get('1234567891234567891.fb1e9730-a83b-11ed-afa1-0242ac120002'); $this->assertSame('1234567891234567891.fb1e9730-a83b-11ed-afa1-0242ac120002', $response->id); - $instance = (new GenericObject(Passes::genericObject()))->jsonSerialize(); + $instance = (new GenericObject(...Passes::genericObject()))->jsonSerialize(); $this->assertSameArray($instance, $response->jsonSerialize()); } + #[Group('google')] public function test_create_instance(): void { $client = $this->createMockClient('generic-object'); $repository = new GenericObjectRepository($client); - $instance = new GenericObject(Passes::genericObject()); + $instance = new GenericObject(...Passes::genericObject()); $response = $repository->create($instance); $this->assertSame('1234567891234567891.fb1e9730-a83b-11ed-afa1-0242ac120002', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); } + #[Group('google')] public function test_update_instance(): void { $client = $this->createMockClient('generic-object'); $repository = new GenericObjectRepository($client); - $instance = new GenericObject(Passes::genericObject()); + $instance = new GenericObject(...Passes::genericObject()); $response = $repository->update($instance); $this->assertSame('1234567891234567891.fb1e9730-a83b-11ed-afa1-0242ac120002', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); diff --git a/tests/Google/OfferClassTest.php b/tests/Google/OfferClassTest.php index cde8b2b..1042c6d 100644 --- a/tests/Google/OfferClassTest.php +++ b/tests/Google/OfferClassTest.php @@ -6,11 +6,13 @@ use Chiiya\Passes\Google\Repositories\OfferClassRepository; use Chiiya\Passes\Tests\Google\Fixtures\Passes; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class OfferClassTest extends TestCase { use MocksApiRequests; + #[Group('google')] public function test_list_instances(): void { $client = $this->createMockClient('offer-classes'); @@ -18,35 +20,38 @@ public function test_list_instances(): void $response = $repository->index('1234567890123456789'); $this->assertSame(1, $response->pagination->resultsPerPage); $this->assertSame('1234567890123456789.coupon-15', $response->resources[0]->id); - $instance = (new OfferClass(Passes::offerClass()))->jsonSerialize(); + $instance = (new OfferClass(...Passes::offerClass()))->jsonSerialize(); $this->assertSameArray($instance, $response->resources[0]->jsonSerialize()); } + #[Group('google')] public function test_get_instance(): void { $client = $this->createMockClient('offer-class'); $repository = new OfferClassRepository($client); $response = $repository->get('1234567890123456789.coupon-15'); $this->assertSame('1234567890123456789.coupon-15', $response->id); - $instance = (new OfferClass(Passes::offerClass()))->jsonSerialize(); + $instance = (new OfferClass(...Passes::offerClass()))->jsonSerialize(); $this->assertSameArray($instance, $response->jsonSerialize()); } + #[Group('google')] public function test_create_instance(): void { $client = $this->createMockClient('offer-class'); $repository = new OfferClassRepository($client); - $instance = new OfferClass(Passes::offerClass()); + $instance = new OfferClass(...Passes::offerClass()); $response = $repository->create($instance); $this->assertSame('1234567890123456789.coupon-15', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); } + #[Group('google')] public function test_update_instance(): void { $client = $this->createMockClient('offer-class'); $repository = new OfferClassRepository($client); - $instance = new OfferClass(Passes::offerClass()); + $instance = new OfferClass(...Passes::offerClass()); $response = $repository->update($instance); $this->assertSame('1234567890123456789.coupon-15', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); diff --git a/tests/Google/OfferObjectTest.php b/tests/Google/OfferObjectTest.php index 46033ab..185ca21 100644 --- a/tests/Google/OfferObjectTest.php +++ b/tests/Google/OfferObjectTest.php @@ -6,11 +6,13 @@ use Chiiya\Passes\Google\Repositories\OfferObjectRepository; use Chiiya\Passes\Tests\Google\Fixtures\Passes; use Chiiya\Passes\Tests\TestCase; +use PHPUnit\Framework\Attributes\Group; class OfferObjectTest extends TestCase { use MocksApiRequests; + #[Group('google')] public function test_list_instances(): void { $client = $this->createMockClient('offer-objects'); @@ -18,35 +20,38 @@ public function test_list_instances(): void $response = $repository->index('1234567890123456789.coupon-15'); $this->assertSame(1, $response->pagination->resultsPerPage); $this->assertSame('1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665', $response->resources[0]->id); - $instance = (new OfferObject(Passes::offerObject()))->jsonSerialize(); + $instance = (new OfferObject(...Passes::offerObject()))->jsonSerialize(); $this->assertSameArray($instance, $response->resources[0]->jsonSerialize()); } + #[Group('google')] public function test_get_instance(): void { $client = $this->createMockClient('offer-object'); $repository = new OfferObjectRepository($client); $response = $repository->get('1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665'); $this->assertSame('1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665', $response->id); - $instance = (new OfferObject(Passes::offerObject()))->jsonSerialize(); + $instance = (new OfferObject(...Passes::offerObject()))->jsonSerialize(); $this->assertSameArray($instance, $response->jsonSerialize()); } + #[Group('google')] public function test_create_instance(): void { $client = $this->createMockClient('offer-object'); $repository = new OfferObjectRepository($client); - $instance = new OfferObject(Passes::offerObject()); + $instance = new OfferObject(...Passes::offerObject()); $response = $repository->create($instance); $this->assertSame('1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); } + #[Group('google')] public function test_update_instance(): void { $client = $this->createMockClient('offer-object'); $repository = new OfferObjectRepository($client); - $instance = new OfferObject(Passes::offerObject()); + $instance = new OfferObject(...Passes::offerObject()); $response = $repository->update($instance); $this->assertSame('1234567890123456789.002e4fb7-1c92-47cc-873f-46dba4a1b665', $response->id); $this->assertSameArray($instance->jsonSerialize(), $response->jsonSerialize()); From dfc3cd17269a565ae743840878f61a2b8432f3d5 Mon Sep 17 00:00:00 2001 From: Elisha Witte Date: Thu, 10 Oct 2024 13:53:16 +0200 Subject: [PATCH 3/5] Use static method for legacy value mapping --- src/Common/Casters/LegacyValueCaster.php | 17 ++++++----------- src/Common/LegacyValueEnumerator.php | 2 +- .../Enumerators/BarcodeRenderEncoding.php | 2 +- src/Google/Enumerators/BarcodeType.php | 2 +- src/Google/Enumerators/DateFormat.php | 2 +- src/Google/Enumerators/DoorsOpenLabel.php | 2 +- .../EventTicket/ConfirmationCodeLabel.php | 2 +- .../Enumerators/EventTicket/GateLabel.php | 2 +- src/Google/Enumerators/EventTicket/RowLabel.php | 2 +- .../Enumerators/EventTicket/SeatLabel.php | 2 +- .../Enumerators/EventTicket/SectionLabel.php | 2 +- src/Google/Enumerators/Flight/BoardingDoor.php | 2 +- .../Enumerators/Flight/BoardingPolicy.php | 2 +- src/Google/Enumerators/Flight/FlightStatus.php | 2 +- .../Enumerators/Flight/SeatClassPolicy.php | 2 +- .../Enumerators/Loyalty/VisibilityState.php | 2 +- src/Google/Enumerators/MessageType.php | 2 +- .../MultipleDevicesAndHoldersAllowedStatus.php | 2 +- .../Enumerators/Offer/RedemptionChannel.php | 2 +- src/Google/Enumerators/PredefinedItem.php | 2 +- src/Google/Enumerators/ReviewStatus.php | 2 +- src/Google/Enumerators/State.php | 2 +- .../Enumerators/Transit/ConcessionCategory.php | 2 +- src/Google/Enumerators/Transit/FareClass.php | 2 +- .../Enumerators/Transit/PassengerType.php | 2 +- src/Google/Enumerators/Transit/TicketStatus.php | 2 +- src/Google/Enumerators/Transit/TransitType.php | 2 +- src/Google/Enumerators/Transit/TripType.php | 2 +- src/Google/Enumerators/TransitOption.php | 2 +- 29 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/Common/Casters/LegacyValueCaster.php b/src/Common/Casters/LegacyValueCaster.php index b2510f5..f1bcadf 100644 --- a/src/Common/Casters/LegacyValueCaster.php +++ b/src/Common/Casters/LegacyValueCaster.php @@ -6,11 +6,12 @@ use Chiiya\Passes\Common\LegacyValueEnumerator; use LogicException; -class LegacyValueCaster implements CastsProperty +readonly class LegacyValueCaster implements CastsProperty { public function __construct( - private readonly array $types, - private readonly string $enum, + private array $types, + /** @var class-string */ + private string $enum, ) {} public function unserialize(mixed $value): ?string @@ -23,10 +24,7 @@ public function unserialize(mixed $value): ?string return null; } - /** @var LegacyValueEnumerator $enum */ - $enum = new $this->enum; - - return $enum->mapLegacyValues($value); + return $this->enum::mapLegacyValues($value); } public function serialize(mixed $value): ?string @@ -39,9 +37,6 @@ public function serialize(mixed $value): ?string return null; } - /** @var LegacyValueEnumerator $enum */ - $enum = new $this->enum; - - return $enum->mapLegacyValues($value); + return $this->enum::mapLegacyValues($value); } } diff --git a/src/Common/LegacyValueEnumerator.php b/src/Common/LegacyValueEnumerator.php index 0e209db..103f3ea 100644 --- a/src/Common/LegacyValueEnumerator.php +++ b/src/Common/LegacyValueEnumerator.php @@ -4,5 +4,5 @@ interface LegacyValueEnumerator { - public function mapLegacyValues(string $value): string; + public static function mapLegacyValues(string $value): string; } diff --git a/src/Google/Enumerators/BarcodeRenderEncoding.php b/src/Google/Enumerators/BarcodeRenderEncoding.php index 947f4d0..40c1464 100644 --- a/src/Google/Enumerators/BarcodeRenderEncoding.php +++ b/src/Google/Enumerators/BarcodeRenderEncoding.php @@ -17,7 +17,7 @@ public static function values(): array return [self::RENDER_ENCODING_UNSPECIFIED, self::UTF_8]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'UTF_8' => self::UTF_8, diff --git a/src/Google/Enumerators/BarcodeType.php b/src/Google/Enumerators/BarcodeType.php index a4fbbb8..1ec2454 100644 --- a/src/Google/Enumerators/BarcodeType.php +++ b/src/Google/Enumerators/BarcodeType.php @@ -64,7 +64,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'aztec' => self::AZTEC, diff --git a/src/Google/Enumerators/DateFormat.php b/src/Google/Enumerators/DateFormat.php index 65b526b..44b5cf7 100644 --- a/src/Google/Enumerators/DateFormat.php +++ b/src/Google/Enumerators/DateFormat.php @@ -36,7 +36,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'dateTime' => self::DATE_TIME, diff --git a/src/Google/Enumerators/DoorsOpenLabel.php b/src/Google/Enumerators/DoorsOpenLabel.php index 210ae66..3a30a6d 100644 --- a/src/Google/Enumerators/DoorsOpenLabel.php +++ b/src/Google/Enumerators/DoorsOpenLabel.php @@ -20,7 +20,7 @@ public static function values(): array return [self::DOORS_OPEN_LABEL_UNSPECIFIED, self::DOORS_OPEN, self::GATES_OPEN]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'doorsOpen' => self::DOORS_OPEN, diff --git a/src/Google/Enumerators/EventTicket/ConfirmationCodeLabel.php b/src/Google/Enumerators/EventTicket/ConfirmationCodeLabel.php index df27edc..958e45a 100644 --- a/src/Google/Enumerators/EventTicket/ConfirmationCodeLabel.php +++ b/src/Google/Enumerators/EventTicket/ConfirmationCodeLabel.php @@ -32,7 +32,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'confirmationCode' => self::CONFIRMATION_CODE, diff --git a/src/Google/Enumerators/EventTicket/GateLabel.php b/src/Google/Enumerators/EventTicket/GateLabel.php index 70bc897..169fd08 100644 --- a/src/Google/Enumerators/EventTicket/GateLabel.php +++ b/src/Google/Enumerators/EventTicket/GateLabel.php @@ -23,7 +23,7 @@ public static function values(): array return [self::GATE_LABEL_UNSPECIFIED, self::GATE, self::DOOR, self::ENTRANCE]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'gate' => self::GATE, diff --git a/src/Google/Enumerators/EventTicket/RowLabel.php b/src/Google/Enumerators/EventTicket/RowLabel.php index afd9ebf..2610101 100644 --- a/src/Google/Enumerators/EventTicket/RowLabel.php +++ b/src/Google/Enumerators/EventTicket/RowLabel.php @@ -17,7 +17,7 @@ public static function values(): array return [self::ROW_LABEL_UNSPECIFIED, self::ROW]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'row' => self::ROW, diff --git a/src/Google/Enumerators/EventTicket/SeatLabel.php b/src/Google/Enumerators/EventTicket/SeatLabel.php index e8d0bd6..d95e28d 100644 --- a/src/Google/Enumerators/EventTicket/SeatLabel.php +++ b/src/Google/Enumerators/EventTicket/SeatLabel.php @@ -17,7 +17,7 @@ public static function values(): array return [self::SEAT_LABEL_UNSPECIFIED, self::SEAT]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'seat' => self::SEAT, diff --git a/src/Google/Enumerators/EventTicket/SectionLabel.php b/src/Google/Enumerators/EventTicket/SectionLabel.php index 8da62c4..c35939c 100644 --- a/src/Google/Enumerators/EventTicket/SectionLabel.php +++ b/src/Google/Enumerators/EventTicket/SectionLabel.php @@ -20,7 +20,7 @@ public static function values(): array return [self::SECTION_LABEL_UNSPECIFIED, self::SECTION, self::THEATER]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'section' => self::SECTION, diff --git a/src/Google/Enumerators/Flight/BoardingDoor.php b/src/Google/Enumerators/Flight/BoardingDoor.php index e8c7644..f61bc9f 100644 --- a/src/Google/Enumerators/Flight/BoardingDoor.php +++ b/src/Google/Enumerators/Flight/BoardingDoor.php @@ -20,7 +20,7 @@ public static function values(): array return [self::BOARDING_DOOR_UNSPECIFIED, self::FRONT, self::BACK]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'front' => self::FRONT, diff --git a/src/Google/Enumerators/Flight/BoardingPolicy.php b/src/Google/Enumerators/Flight/BoardingPolicy.php index a95455f..a3597c0 100644 --- a/src/Google/Enumerators/Flight/BoardingPolicy.php +++ b/src/Google/Enumerators/Flight/BoardingPolicy.php @@ -28,7 +28,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'zoneBased' => self::ZONE_BASED, diff --git a/src/Google/Enumerators/Flight/FlightStatus.php b/src/Google/Enumerators/Flight/FlightStatus.php index 3a6fc5e..23707bb 100644 --- a/src/Google/Enumerators/Flight/FlightStatus.php +++ b/src/Google/Enumerators/Flight/FlightStatus.php @@ -40,7 +40,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'scheduled' => self::SCHEDULED, diff --git a/src/Google/Enumerators/Flight/SeatClassPolicy.php b/src/Google/Enumerators/Flight/SeatClassPolicy.php index 7c13a27..e47bdec 100644 --- a/src/Google/Enumerators/Flight/SeatClassPolicy.php +++ b/src/Google/Enumerators/Flight/SeatClassPolicy.php @@ -32,7 +32,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'cabinBased' => self::CABIN_BASED, diff --git a/src/Google/Enumerators/Loyalty/VisibilityState.php b/src/Google/Enumerators/Loyalty/VisibilityState.php index c31cde0..ab7a4a4 100644 --- a/src/Google/Enumerators/Loyalty/VisibilityState.php +++ b/src/Google/Enumerators/Loyalty/VisibilityState.php @@ -23,7 +23,7 @@ public static function values(): array return [self::STATE_UNSPECIFIED, self::TRUSTED_TESTERS, self::LIVE, self::DISABLED]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'trustedTesters' => self::TRUSTED_TESTERS, diff --git a/src/Google/Enumerators/MessageType.php b/src/Google/Enumerators/MessageType.php index 3fe05aa..39f3551 100644 --- a/src/Google/Enumerators/MessageType.php +++ b/src/Google/Enumerators/MessageType.php @@ -20,7 +20,7 @@ public static function values(): array return [self::MESSAGE_TYPE_UNSPECIFIED, self::TEXT, self::EXPIRATION_NOTIFICATION]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'text' => self::TEXT, diff --git a/src/Google/Enumerators/MultipleDevicesAndHoldersAllowedStatus.php b/src/Google/Enumerators/MultipleDevicesAndHoldersAllowedStatus.php index d145387..a66a45b 100644 --- a/src/Google/Enumerators/MultipleDevicesAndHoldersAllowedStatus.php +++ b/src/Google/Enumerators/MultipleDevicesAndHoldersAllowedStatus.php @@ -28,7 +28,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'multipleHolders' => self::MULTIPLE_HOLDERS, diff --git a/src/Google/Enumerators/Offer/RedemptionChannel.php b/src/Google/Enumerators/Offer/RedemptionChannel.php index 65115b7..7e64034 100644 --- a/src/Google/Enumerators/Offer/RedemptionChannel.php +++ b/src/Google/Enumerators/Offer/RedemptionChannel.php @@ -32,7 +32,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'instore' => self::INSTORE, diff --git a/src/Google/Enumerators/PredefinedItem.php b/src/Google/Enumerators/PredefinedItem.php index 78f1df2..7c92af3 100644 --- a/src/Google/Enumerators/PredefinedItem.php +++ b/src/Google/Enumerators/PredefinedItem.php @@ -24,7 +24,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'frequentFlyerProgramNameAndNumber' => self::FREQUENT_FLYER_PROGRAM_NAME_AND_NUMBER, diff --git a/src/Google/Enumerators/ReviewStatus.php b/src/Google/Enumerators/ReviewStatus.php index 927f0da..6a5fc76 100644 --- a/src/Google/Enumerators/ReviewStatus.php +++ b/src/Google/Enumerators/ReviewStatus.php @@ -26,7 +26,7 @@ public static function values(): array return [self::REVIEW_STATUS_UNSPECIFIED, self::UNDER_REVIEW, self::APPROVED, self::REJECTED, self::DRAFT]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'underReview' => self::UNDER_REVIEW, diff --git a/src/Google/Enumerators/State.php b/src/Google/Enumerators/State.php index f988222..36ded19 100644 --- a/src/Google/Enumerators/State.php +++ b/src/Google/Enumerators/State.php @@ -26,7 +26,7 @@ public static function values(): array return [self::STATE_UNSPECIFIED, self::ACTIVE, self::COMPLETED, self::EXPIRED, self::INACTIVE]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'active' => self::ACTIVE, diff --git a/src/Google/Enumerators/Transit/ConcessionCategory.php b/src/Google/Enumerators/Transit/ConcessionCategory.php index 63c7d97..b9bdde8 100644 --- a/src/Google/Enumerators/Transit/ConcessionCategory.php +++ b/src/Google/Enumerators/Transit/ConcessionCategory.php @@ -23,7 +23,7 @@ public static function values(): array return [self::CONCESSION_CATEGORY_UNSPECIFIED, self::ADULT, self::CHILD, self::SENIOR]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'adult' => self::ADULT, diff --git a/src/Google/Enumerators/Transit/FareClass.php b/src/Google/Enumerators/Transit/FareClass.php index b109807..a497bd8 100644 --- a/src/Google/Enumerators/Transit/FareClass.php +++ b/src/Google/Enumerators/Transit/FareClass.php @@ -23,7 +23,7 @@ public static function values(): array return [self::FARE_CLASS_UNSPECIFIED, self::ECONOMY, self::FIRST, self::BUSINESS]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'economy' => self::ECONOMY, diff --git a/src/Google/Enumerators/Transit/PassengerType.php b/src/Google/Enumerators/Transit/PassengerType.php index 1e53312..8e4ecf4 100644 --- a/src/Google/Enumerators/Transit/PassengerType.php +++ b/src/Google/Enumerators/Transit/PassengerType.php @@ -20,7 +20,7 @@ public static function values(): array return [self::PASSENGER_TYPE_UNSPECIFIED, self::SINGLE_PASSENGER, self::MULTIPLE_PASSENGERS]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'singlePassenger' => self::SINGLE_PASSENGER, diff --git a/src/Google/Enumerators/Transit/TicketStatus.php b/src/Google/Enumerators/Transit/TicketStatus.php index 82f3f0e..19e927c 100644 --- a/src/Google/Enumerators/Transit/TicketStatus.php +++ b/src/Google/Enumerators/Transit/TicketStatus.php @@ -23,7 +23,7 @@ public static function values(): array return [self::TICKET_STATUS_UNSPECIFIED, self::USED, self::REFUNDED, self::EXCHANGED]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'used' => self::USED, diff --git a/src/Google/Enumerators/Transit/TransitType.php b/src/Google/Enumerators/Transit/TransitType.php index b2ab353..3689f81 100644 --- a/src/Google/Enumerators/Transit/TransitType.php +++ b/src/Google/Enumerators/Transit/TransitType.php @@ -29,7 +29,7 @@ public static function values(): array return [self::TRANSIT_TYPE_UNSPECIFIED, self::BUS, self::RAIL, self::TRAM, self::FERRY, self::OTHER]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'bus' => self::BUS, diff --git a/src/Google/Enumerators/Transit/TripType.php b/src/Google/Enumerators/Transit/TripType.php index 8e25b74..d100223 100644 --- a/src/Google/Enumerators/Transit/TripType.php +++ b/src/Google/Enumerators/Transit/TripType.php @@ -20,7 +20,7 @@ public static function values(): array return [self::TRIP_TYPE_UNSPECIFIED, self::ROUND_TRIP, self::ONE_WAY]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'roundTrip' => self::ROUND_TRIP, diff --git a/src/Google/Enumerators/TransitOption.php b/src/Google/Enumerators/TransitOption.php index 65a3062..36f2840 100644 --- a/src/Google/Enumerators/TransitOption.php +++ b/src/Google/Enumerators/TransitOption.php @@ -28,7 +28,7 @@ public static function values(): array ]; } - public function mapLegacyValues(string $value): string + public static function mapLegacyValues(string $value): string { return match ($value) { 'originAndDestinationNames' => self::ORIGIN_AND_DESTINATION_NAMES, From 8991bbfa9854700037e8ee41474eee561f803dc2 Mon Sep 17 00:00:00 2001 From: Elisha Witte Date: Thu, 10 Oct 2024 15:04:36 +0200 Subject: [PATCH 4/5] Migrate remaining classes --- examples/google_generic.php | 50 +++--- examples/google_offer.php | 16 +- src/Common/Validation/Contains.php | 24 --- src/Common/Validation/HexColor.php | 29 ---- src/Common/Validation/MaxItems.php | 24 --- src/Common/Validation/MaxLength.php | 24 --- src/Common/Validation/MinItems.php | 24 --- src/Common/Validation/NumberBetween.php | 33 ---- src/Common/Validation/Required.php | 28 ---- src/Common/Validation/ValueIn.php | 37 ----- src/Google/Components/Common/Money.php | 1 - .../Generic/AbstractNotificationValue.php | 1 - src/Google/JWT.php | 143 ++++++++++-------- src/Google/Passes/TransitObject.php | 2 +- src/Google/ServiceCredentials.php | 21 +-- 15 files changed, 121 insertions(+), 336 deletions(-) delete mode 100644 src/Common/Validation/Contains.php delete mode 100644 src/Common/Validation/HexColor.php delete mode 100644 src/Common/Validation/MaxItems.php delete mode 100644 src/Common/Validation/MaxLength.php delete mode 100644 src/Common/Validation/MinItems.php delete mode 100644 src/Common/Validation/NumberBetween.php delete mode 100644 src/Common/Validation/Required.php delete mode 100644 src/Common/Validation/ValueIn.php diff --git a/examples/google_generic.php b/examples/google_generic.php index 7a7d55b..e6380c7 100644 --- a/examples/google_generic.php +++ b/examples/google_generic.php @@ -29,13 +29,6 @@ $class = new GenericClass( id: '1234567890123456789.generic-object', - multipleDevicesAndHoldersAllowedStatus: MultipleDevicesAndHoldersAllowedStatus::MULTIPLE_HOLDERS, - linksModuleData: new LinksModuleData( - uris: [ - new Uri(uri: 'https://example.org/app', description: 'App'), - new Uri(uri: 'https://example.org', description: 'Homepage'), - ] - ), imageModulesData: [ new ImageModuleData( mainImage: Image::make('https://example.org/image.png') @@ -46,44 +39,51 @@ header: 'Lorem ipsum', body: 'Dolor sit amet' ) - ] + ], + linksModuleData: new LinksModuleData( + uris: [ + new Uri(uri: 'https://example.org/app', description: 'App'), + new Uri(uri: 'https://example.org', description: 'Homepage'), + ] + ), + multipleDevicesAndHoldersAllowedStatus: MultipleDevicesAndHoldersAllowedStatus::MULTIPLE_HOLDERS ); $repository->create($class); $object = new GenericObject( - classId: '1234567890123456789.generic-object', - id: '1234567890123456789.'.Str::uuid()->toString(), cardTitle: LocalizedString::make('en', '::cardTitle::'), - subheader: LocalizedString::make('en', '::subheader::'), header: LocalizedString::make('en', '::header::'), + subheader: LocalizedString::make('en', '::subheader::'), logo: Image::make('https://example.org/logo.png'), - heroImage: Image::make('https://example.org/hero-image.png'), hexBackgroundColor: '#333', + notifications: new Notifications( + upcomingNotification: new UpcomingNotification( + enableNotification: true + ), + ), + classId: '1234567890123456789.generic-object', + id: '1234567890123456789.'.Str::uuid()->toString(), + heroImage: Image::make('https://example.org/hero-image.png'), state: State::ACTIVE, barcode: new Barcode( type: BarcodeType::QR_CODE, - renderEncoding: BarcodeRenderEncoding::UTF_8, value: '1464194291627', + renderEncoding: BarcodeRenderEncoding::UTF_8, ), validTimeInterval: new TimeInterval( start: new DateTime(date: now()), end: new DateTime(now()->addMonth()) ), - notifications: new Notifications( - upcomingNotification: new UpcomingNotification( - enableNotification: true - ), - ), textModulesData: [ new TextModuleData( - id: 'key-1', header: 'label-1', body: 'value-1', + id: 'key-1', ), new TextModuleData( - id: 'key-2', header: 'label-2', body: 'value-2', + id: 'key-2', ) ], groupingInfo: new GroupingInfo( @@ -91,8 +91,8 @@ classId: '1234567890123456789.generic-object', ) ); -$jwt = (new JWT([ - 'iss' => $credentials->client_email, - 'key' => $credentials->private_key, - 'origins' => ['https://example.org'], -]))->addOfferObject($object)->sign(); +$jwt = (new JWT( + iss: $credentials->client_email, + key: $credentials->private_key, + origins: ['https://example.org'], +))->addGenericObject($object)->sign(); diff --git a/examples/google_offer.php b/examples/google_offer.php index f13cea9..05ce242 100644 --- a/examples/google_offer.php +++ b/examples/google_offer.php @@ -24,15 +24,15 @@ $repository = new OfferClassRepository($client); $class = new OfferClass( - id: '1234567890123456789.coupon-15', - issuerName: 'ACME', - reviewStatus: ReviewStatus::UNDER_REVIEW, title: '15% off purchases', redemptionChannel: RedemptionChannel::INSTORE, provider: 'ACME', titleImage: Image::make('https://example.org/title.png'), helpUri: Uri::make('https://example.org/help'), localizedDetails: LocalizedString::make('en', '::value::'), + id: '1234567890123456789.coupon-15', + issuerName: 'ACME', + reviewStatus: ReviewStatus::UNDER_REVIEW, imageModulesData: [ new ImageModuleData(mainImage: Image::make('https://example.org/wallet.png')), ], @@ -60,8 +60,8 @@ classId: '1234567890123456789.coupon-15', ), ); -$jwt = (new JWT([ - 'iss' => $credentials->client_email, - 'key' => $credentials->private_key, - 'origins' => ['https://example.org'], -]))->addOfferObject($object)->sign(); +$jwt = (new JWT( + iss: $credentials->client_email, + key: $credentials->private_key, + origins: ['https://example.org'], +))->addOfferObject($object)->sign(); diff --git a/src/Common/Validation/Contains.php b/src/Common/Validation/Contains.php deleted file mode 100644 index 17794e6..0000000 --- a/src/Common/Validation/Contains.php +++ /dev/null @@ -1,24 +0,0 @@ -needle)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid("The value must contain {$this->needle}."); - } -} diff --git a/src/Common/Validation/HexColor.php b/src/Common/Validation/HexColor.php deleted file mode 100644 index 9365f1f..0000000 --- a/src/Common/Validation/HexColor.php +++ /dev/null @@ -1,29 +0,0 @@ -isValidHexColor($value)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid('The value is not a valid hex color definition.'); - } - - private function isValidHexColor(mixed $value): bool - { - if ($value === null) { - return true; - } - - return (bool) preg_match('/^#([0-9a-fA-F]{3}){1,2}$/', $value); - } -} diff --git a/src/Common/Validation/MaxItems.php b/src/Common/Validation/MaxItems.php deleted file mode 100644 index 4e70524..0000000 --- a/src/Common/Validation/MaxItems.php +++ /dev/null @@ -1,24 +0,0 @@ -size)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid("The value may not have more than {$this->size} items."); - } -} diff --git a/src/Common/Validation/MaxLength.php b/src/Common/Validation/MaxLength.php deleted file mode 100644 index a827c7b..0000000 --- a/src/Common/Validation/MaxLength.php +++ /dev/null @@ -1,24 +0,0 @@ -size)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid("The value may not be longer than {$this->size} characters."); - } -} diff --git a/src/Common/Validation/MinItems.php b/src/Common/Validation/MinItems.php deleted file mode 100644 index 327c1c1..0000000 --- a/src/Common/Validation/MinItems.php +++ /dev/null @@ -1,24 +0,0 @@ -= $this->size)) { - return ValidationResult::valid(); - } - - return ValidationResult::invalid("The value must have at least {$this->size} items."); - } -} diff --git a/src/Common/Validation/NumberBetween.php b/src/Common/Validation/NumberBetween.php deleted file mode 100644 index 3a3a4dd..0000000 --- a/src/Common/Validation/NumberBetween.php +++ /dev/null @@ -1,33 +0,0 @@ -min) { - return ValidationResult::invalid("Value should be greater than or equal to {$this->min}."); - } - - if ($value > $this->max) { - return ValidationResult::invalid("Value should be less than or equal to {$this->max}."); - } - - return ValidationResult::valid(); - } -} diff --git a/src/Common/Validation/Required.php b/src/Common/Validation/Required.php deleted file mode 100644 index 8b6adb9..0000000 --- a/src/Common/Validation/Required.php +++ /dev/null @@ -1,28 +0,0 @@ -values)) === 0 - ? ValidationResult::valid() - : ValidationResult::invalid($this->errorMessage()); - } - - return in_array($value, $this->values, true) - ? ValidationResult::valid() - : ValidationResult::invalid($this->errorMessage()); - } - - private function errorMessage(): string - { - return 'The value is invalid. Should be one of .'.implode(', ', $this->values); - } -} diff --git a/src/Google/Components/Common/Money.php b/src/Google/Components/Common/Money.php index d69da99..5445cd6 100644 --- a/src/Google/Components/Common/Money.php +++ b/src/Google/Components/Common/Money.php @@ -3,7 +3,6 @@ namespace Chiiya\Passes\Google\Components\Common; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; use Symfony\Component\Validator\Constraints\NotBlank; class Money extends Component diff --git a/src/Google/Components/Generic/AbstractNotificationValue.php b/src/Google/Components/Generic/AbstractNotificationValue.php index 4adbe2d..1494d0e 100644 --- a/src/Google/Components/Generic/AbstractNotificationValue.php +++ b/src/Google/Components/Generic/AbstractNotificationValue.php @@ -3,7 +3,6 @@ namespace Chiiya\Passes\Google\Components\Generic; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\Required; abstract class AbstractNotificationValue extends Component { diff --git a/src/Google/JWT.php b/src/Google/JWT.php index fa656c4..96b8913 100644 --- a/src/Google/JWT.php +++ b/src/Google/JWT.php @@ -2,9 +2,8 @@ namespace Chiiya\Passes\Google; +use Chiiya\Passes\Common\ArrayHelper; use Chiiya\Passes\Common\Component; -use Chiiya\Passes\Common\Validation\MinItems; -use Chiiya\Passes\Common\Validation\Required; use Chiiya\Passes\Google\Passes\EventTicketClass; use Chiiya\Passes\Google\Passes\EventTicketObject; use Chiiya\Passes\Google\Passes\FlightClass; @@ -20,6 +19,8 @@ use Chiiya\Passes\Google\Passes\TransitClass; use Chiiya\Passes\Google\Passes\TransitObject; use Firebase\JWT\JWT as Encoder; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\NotBlank; class JWT extends Component { @@ -29,147 +30,145 @@ class JWT extends Component /** @var string */ final public const TYPE = 'savetoandroidpay'; - /** - * Required. - * Your OAuth 2.0 service account generated email address. - */ - #[Required] - public string $iss; - - /** - * Required. - * Audience. The audience for Google Pay API for Passes Objects will always be google. - */ - public string $aud = self::AUDIENCE; - - /** - * Required. - * Type of JWT. The audience for Google Pay API for Passes Objects will always be savetoandroidpay. - */ - public string $typ = self::TYPE; - - /** - * Required. - * Payload object. Refer to Generating the JWT Guide for an example of creating the payload. - * Only one object or class should be included in the payload arrays. - */ - public array $payload = []; - - /** - * Required. - * Signing key. Should be the service account private key. - */ - #[Required] - public string $key; - - /** - * Required. - * Array of domains to whitelist JWT saving functionality. The Google Pay API for Passes button will - * not render when the origins field is not defined. You could potentially get a "Load denied by X-Frame-Options" - * or "Refused to display" messages in the browser console when the origins field is not defined. - */ - #[Required] - #[MinItems(1)] - public array $origins = []; + public function __construct( + /** + * Required. + * Your OAuth 2.0 service account generated email address. + */ + #[NotBlank] + public string $iss, + /** + * Required. + * Signing key. Should be the service account private key. + */ + #[NotBlank] + public string $key, + /** + * Required. + * Array of domains to whitelist JWT saving functionality. The Google Pay API for Passes button will + * not render when the origins field is not defined. You could potentially get a "Load denied by X-Frame-Options" + * or "Refused to display" messages in the browser console when the origins field is not defined. + */ + #[Count(min: 1)] + public array $origins, + /** + * Required. + * Audience. The audience for Google Pay API for Passes Objects will always be google. + */ + public string $aud = self::AUDIENCE, + /** + * Required. + * Type of JWT. The audience for Google Pay API for Passes Objects will always be savetoandroidpay. + */ + public string $typ = self::TYPE, + /** + * Required. + * Payload object. Refer to Generating the JWT Guide for an example of creating the payload. + * Only one object or class should be included in the payload arrays. + */ + public array $payload = [], + ) { + parent::__construct(); + } public function addOfferClass(OfferClass $class): static { - return $this->addComponent($class, 'offerClasses'); + return $this->addComponent($this->withoutClassReference($class), 'offerClasses'); } public function addOfferObject(OfferObject $object): static { - return $this->addComponent($object, 'offerObjects'); + return $this->addComponent($this->withoutClassReference($object), 'offerObjects'); } public function addSkinnyOfferObject(OfferObject $object): static { - return $this->addComponent($object->only('id'), 'offerObjects'); + return $this->addComponent($this->skinny($object), 'offerObjects'); } public function addLoyaltyClass(LoyaltyClass $class): static { - return $this->addComponent($class, 'loyaltyClasses'); + return $this->addComponent($this->withoutClassReference($class), 'loyaltyClasses'); } public function addLoyaltyObject(LoyaltyObject $object): static { - return $this->addComponent($object, 'loyaltyObjects'); + return $this->addComponent($this->withoutClassReference($object), 'loyaltyObjects'); } public function addSkinnyLoyaltyObject(LoyaltyObject $object): static { - return $this->addComponent($object->only('id'), 'loyaltyObjects'); + return $this->addComponent($this->skinny($object), 'loyaltyObjects'); } public function addGiftCardClass(GiftCardClass $class): static { - return $this->addComponent($class, 'giftCardClasses'); + return $this->addComponent($this->withoutClassReference($class), 'giftCardClasses'); } public function addGiftCardObject(GiftCardObject $object): static { - return $this->addComponent($object, 'giftCardObjects'); + return $this->addComponent($this->withoutClassReference($object), 'giftCardObjects'); } public function addSkinnyGiftCardObject(GiftCardObject $object): static { - return $this->addComponent($object->only('id'), 'giftCardObjects'); + return $this->addComponent($this->skinny($object), 'giftCardObjects'); } public function addEventTicketClass(EventTicketClass $class): static { - return $this->addComponent($class, 'eventTicketClasses'); + return $this->addComponent($this->withoutClassReference($class), 'eventTicketClasses'); } public function addEventTicketObject(EventTicketObject $object): static { - return $this->addComponent($object, 'eventTicketObjects'); + return $this->addComponent($this->withoutClassReference($object), 'eventTicketObjects'); } public function addSkinnyEventTicketObject(EventTicketObject $object): static { - return $this->addComponent($object->only('id'), 'eventTicketObjects'); + return $this->addComponent($this->skinny($object), 'eventTicketObjects'); } public function addFlightClass(FlightClass $class): static { - return $this->addComponent($class, 'flightClasses'); + return $this->addComponent($this->withoutClassReference($class), 'flightClasses'); } public function addFlightObject(FlightObject $object): static { - return $this->addComponent($object, 'flightObjects'); + return $this->addComponent($this->withoutClassReference($object), 'flightObjects'); } public function addSkinnyFlightObject(FlightObject $object): static { - return $this->addComponent($object->only('id'), 'flightObjects'); + return $this->addComponent($this->skinny($object), 'flightObjects'); } public function addTransitClass(TransitClass $class): static { - return $this->addComponent($class, 'transitClasses'); + return $this->addComponent($this->withoutClassReference($class), 'transitClasses'); } public function addTransitObject(TransitObject $object): static { - return $this->addComponent($object, 'transitObjects'); + return $this->addComponent($this->withoutClassReference($object), 'transitObjects'); } public function addSkinnyTransitObject(TransitObject $object): static { - return $this->addComponent($object->only('id'), 'transitObjects'); + return $this->addComponent($this->skinny($object), 'transitObjects'); } public function addGenericClass(GenericClass $class): static { - return $this->addComponent($class, 'genericClasses'); + return $this->addComponent($this->withoutClassReference($class), 'genericClasses'); } public function addGenericObject(GenericObject $object): static { - return $this->addComponent($object, 'genericObjects'); + return $this->addComponent($this->withoutClassReference($object), 'genericObjects'); } /** @@ -177,20 +176,30 @@ public function addGenericObject(GenericObject $object): static */ public function sign(): string { - $payload = $this->removeEmptyValues($this->except('key')->toArray()); + $payload = $this->removeEmptyValues(ArrayHelper::except($this->encode(), ['key'])); $payload['iat'] = time(); return Encoder::encode($payload, $this->key, 'RS256'); } - protected function addComponent(Component $component, string $type): static + protected function addComponent(array $component, string $type): static { if (! array_key_exists($type, $this->payload)) { $this->payload[$type] = []; } - $this->payload[$type][] = $component->except('classReference'); + $this->payload[$type][] = $component; return $this; } + + protected function withoutClassReference(Component $component): array + { + return ArrayHelper::except($component->encode(), ['classReference']); + } + + protected function skinny(Component $component): array + { + return ArrayHelper::only($component->encode(), ['id']); + } } diff --git a/src/Google/Passes/TransitObject.php b/src/Google/Passes/TransitObject.php index 18a0467..72b1993 100644 --- a/src/Google/Passes/TransitObject.php +++ b/src/Google/Passes/TransitObject.php @@ -3,6 +3,7 @@ namespace Chiiya\Passes\Google\Passes; use Antwerpes\DataTransferObject\Attributes\Cast; +use Antwerpes\DataTransferObject\Casts\ArrayCaster; use Chiiya\Passes\Common\Casters\LegacyValueCaster; use Chiiya\Passes\Google\Components\Common\LocalizedString; use Chiiya\Passes\Google\Components\Transit\PurchaseDetails; @@ -12,7 +13,6 @@ use Chiiya\Passes\Google\Enumerators\Transit\PassengerType; use Chiiya\Passes\Google\Enumerators\Transit\TicketStatus; use Chiiya\Passes\Google\Enumerators\Transit\TripType; -use Spatie\DataTransferObject\Casters\ArrayCaster; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\CssColor; use Symfony\Component\Validator\Constraints\NotBlank; diff --git a/src/Google/ServiceCredentials.php b/src/Google/ServiceCredentials.php index fa5120b..0c39d57 100644 --- a/src/Google/ServiceCredentials.php +++ b/src/Google/ServiceCredentials.php @@ -3,13 +3,14 @@ namespace Chiiya\Passes\Google; use InvalidArgumentException; -use Spatie\DataTransferObject\DataTransferObject; -class ServiceCredentials extends DataTransferObject +class ServiceCredentials { - public string $client_id; - public string $client_email; - public string $private_key; + public function __construct( + public string $client_id, + public string $client_email, + public string $private_key, + ) {} public static function parse(string $path): static { @@ -19,10 +20,10 @@ public static function parse(string $path): static $config = json_decode(file_get_contents($path), true); - return new static([ - 'client_id' => $config['client_id'], - 'client_email' => $config['client_email'], - 'private_key' => $config['private_key'], - ]); + return new static( + client_id: $config['client_id'], + client_email: $config['client_email'], + private_key: $config['private_key'], + ); } } From 99cd0c2b2abb92c104b58cf7520b9884a0c480e5 Mon Sep 17 00:00:00 2001 From: Elisha Witte Date: Thu, 10 Oct 2024 15:05:09 +0200 Subject: [PATCH 5/5] Update dependencies --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 3fec32c..86e88a4 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,6 @@ "ext-zip": "*", "antwerpes/data-transfer-object": "^1.0", "google/auth": "^1.18", - "spatie/data-transfer-object": "^3.7", "symfony/validator": "^7.1" }, "require-dev": {