Changeset 3306095
- Timestamp:
- 06/04/2025 01:23:53 AM (10 months ago)
- Location:
- pay-with-flex/trunk
- Files:
-
- 14 added
- 7 deleted
- 18 edited
-
composer.lock (modified) (3 diffs)
-
pay-with-flex.php (modified) (4 diffs)
-
readme.txt (modified) (2 diffs)
-
src/Controller/OrderController.php (modified) (1 diff)
-
src/Controller/WebhookController.php (modified) (5 diffs)
-
src/PaymentGateway.php (modified) (5 diffs)
-
src/Resource/CheckoutSession (added)
-
src/Resource/CheckoutSession.php (deleted)
-
src/Resource/CheckoutSession/CheckoutSession.php (added)
-
src/Resource/CheckoutSession/CustomerDefaults.php (added)
-
src/Resource/CheckoutSession/LineItem.php (added)
-
src/Resource/CheckoutSession/Mode.php (added)
-
src/Resource/CheckoutSession/Refund (added)
-
src/Resource/CheckoutSession/Refund/LineItem.php (added)
-
src/Resource/CheckoutSession/Refund/Refund.php (added)
-
src/Resource/CheckoutSession/ShippingOptions.php (added)
-
src/Resource/CheckoutSession/Status.php (added)
-
src/Resource/CheckoutSession/TaxRate.php (added)
-
src/Resource/CheckoutSessionMode.php (deleted)
-
src/Resource/CheckoutSessionShippingOptions.php (deleted)
-
src/Resource/CheckoutSessionStatus.php (deleted)
-
src/Resource/CheckoutSessionTaxRate.php (deleted)
-
src/Resource/CustomerDefaults.php (deleted)
-
src/Resource/LineItem.php (deleted)
-
src/Resource/Refund.php (added)
-
src/Resource/RefundStatus.php (added)
-
src/Resource/Resource.php (modified) (1 diff)
-
src/Resource/ShippingRate.php (modified) (1 diff)
-
src/Resource/Webhook.php (modified) (4 diffs)
-
src/Resource/WebhookEvent.php (added)
-
vendor/composer/autoload_classmap.php (modified) (2 diffs)
-
vendor/composer/autoload_static.php (modified) (2 diffs)
-
vendor/composer/installed.json (modified) (3 diffs)
-
vendor/composer/installed.php (modified) (3 diffs)
-
vendor/composer/jetpack_autoload_classmap.php (modified) (4 diffs)
-
vendor/symfony/options-resolver/CHANGELOG.md (modified) (1 diff)
-
vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php (modified) (1 diff)
-
vendor/symfony/options-resolver/OptionConfigurator.php (modified) (1 diff)
-
vendor/symfony/options-resolver/OptionsResolver.php (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pay-with-flex/trunk/composer.lock
r3301881 r3306095 608 608 { 609 609 "name": "symfony/options-resolver", 610 "version": "v7. 2.0",610 "version": "v7.3.0", 611 611 "source": { 612 612 "type": "git", 613 613 "url": "https://github.com/symfony/options-resolver.git", 614 "reference": " 7da8fbac9dcfef75ffc212235d76b2754ce0cf50"615 }, 616 "dist": { 617 "type": "zip", 618 "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ 7da8fbac9dcfef75ffc212235d76b2754ce0cf50",619 "reference": " 7da8fbac9dcfef75ffc212235d76b2754ce0cf50",614 "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" 615 }, 616 "dist": { 617 "type": "zip", 618 "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", 619 "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", 620 620 "shasum": "" 621 621 }, … … 655 655 ], 656 656 "support": { 657 "source": "https://github.com/symfony/options-resolver/tree/v7. 2.0"657 "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" 658 658 }, 659 659 "funding": [ … … 671 671 } 672 672 ], 673 "time": "202 4-11-20T11:17:29+00:00"673 "time": "2025-04-04T13:12:05+00:00" 674 674 }, 675 675 { -
pay-with-flex/trunk/pay-with-flex.php
r3301881 r3306095 3 3 * Plugin Name: Flex HSA/FSA Payments 4 4 * Description: Accept HSA/FSA payments directly in the checkout flow. 5 * Version: 2.2.05 * Version: 3.0.0 6 6 * Plugin URI: https://wordpress.org/plugins/pay-with-flex/ 7 7 * Author: Flex … … 24 24 use Flex\Exception\FlexException; 25 25 use Flex\PaymentGateway; 26 use Flex\Resource\ LineItem;26 use Flex\Resource\CheckoutSession\LineItem; 27 27 use Flex\Resource\Price; 28 28 use Flex\Resource\Product; … … 63 63 64 64 if ( null === $hub ) { 65 $data = get_plugin_data( __FILE__ ); 65 $data = get_plugin_data( 66 plugin_file: __FILE__, 67 translate: false 68 ); 66 69 67 70 $client = ClientBuilder::create( … … 74 77 // Exclude any events that are not "in app" as defined above. 75 78 'before_send' => function ( Event $event ): ?Event { 79 // Allow users to opt-out of telemetry. 80 if ( defined( 'FLEX_TELEMETRY' ) && false === \FLEX_TELEMETRY ) { 81 return null; 82 } 83 76 84 $trace = $event->getStacktrace(); 77 85 $exceptions = $event->getExceptions(); -
pay-with-flex/trunk/readme.txt
r3301881 r3306095 4 4 Requires at least: 6.8 5 5 Tested up to: 6.8 6 Stable tag: 2.2.06 Stable tag: 3.0.0 7 7 Requires PHP: 8.1 8 8 License: GPLv3 or later … … 56 56 == Changelog == 57 57 58 = 3.0.0 = 59 * Added support fro processing refunds from within WooCommerce. 60 * Added the `FLEX_TELEMETRY` constant which allows users to opt-out of telemetry by setting the constant to `false`. 61 * Fixed `PHP Notice: Function _load_textdomain_just_in_time was called incorrectly.` 62 58 63 = 2.2.0 = 59 64 * Added support for [WooCommerce block-based checkout](https://woocommerce.com/checkout-blocks/). -
pay-with-flex/trunk/src/Controller/OrderController.php
r3296637 r3306095 11 11 12 12 use Automattic\WooCommerce\Enums\OrderStatus; 13 use Flex\Resource\CheckoutSession ;14 use Flex\Resource\CheckoutSession Status;13 use Flex\Resource\CheckoutSession\CheckoutSession; 14 use Flex\Resource\CheckoutSession\Status as CheckoutSessionStatus; 15 15 use Flex\Resource\ResourceAction; 16 16 -
pay-with-flex/trunk/src/Controller/WebhookController.php
r3296637 r3306095 11 11 12 12 use Automattic\WooCommerce\Enums\OrderStatus; 13 use Flex\Resource\CheckoutSession; 13 use Flex\Exception\FlexException; 14 use Flex\Resource\CheckoutSession\CheckoutSession; 15 use Flex\Resource\Refund; 16 use Flex\Resource\WebhookEvent; 14 17 use Flex\Resource\Webhook; 18 use Sentry\Breadcrumb; 15 19 16 20 use function Flex\payment_gateway; 21 use function Flex\sentry; 17 22 18 23 /** … … 20 25 */ 21 26 class WebhookController extends Controller { 22 23 protected const CHECKOUT_SESSION_COMPLETED = 'checkout.session.completed';24 27 25 28 /** … … 120 123 $data = $request->get_json_params(); 121 124 125 sentry()->addBreadcrumb( 126 new Breadcrumb( 127 category: 'event', 128 level: Breadcrumb::LEVEL_INFO, 129 type: Breadcrumb::TYPE_DEFAULT, 130 metadata: $data, 131 ) 132 ); 133 122 134 if ( ! isset( $data['event_type'] ) ) { 123 $this->logger->error( 124 '[Flex] Webhook Event missing event_type', 125 $context, 126 ); 135 $error = new FlexException( 'Webhook event missing event_type' ); 136 $this->logger->error( $error->getMessage(), $context ); 137 sentry()->captureException( $error ); 127 138 return new \WP_REST_Response( 128 139 data: array( … … 133 144 } 134 145 135 if ( self::CHECKOUT_SESSION_COMPLETED !== $data['event_type'] ) { 136 $context['event_type'] = $data['event_type']; 137 138 $this->logger->error( 139 '[Flex] Cannot handle event type', 140 $context, 141 ); 146 $context['event_type'] = $data['event_type']; 147 148 $type = WebhookEvent::tryFrom( $data['event_type'] ); 149 150 if ( null === $type ) { 151 $error = new FlexException( 'Cannot handle event type' ); 152 $this->logger->error( $error->getMessage(), $context ); 153 sentry()->captureException( $error ); 142 154 return new \WP_REST_Response( 143 155 data: array( … … 148 160 } 149 161 150 if ( ! isset( $data['object']['checkout_session'] ) ) { 151 $this->logger->error( 152 '[Flex] Webhook Event missing checkout session', 153 $context, 154 ); 155 return new \WP_REST_Response( 156 data: array( 157 'error' => 'Cannot handle webhook of type ' . esc_html( $data['event_type'] ), 158 ), 159 status: 422 160 ); 161 } 162 163 $received = CheckoutSession::from_flex( $data['object']['checkout_session'] ); 164 165 $context['checkout_session_id'] = $received->id(); 166 167 $order = $received->wc(); 168 169 if ( null === $order ) { 170 $this->logger->error( 171 '[Flex] WooCommerce order does not exist for the given checkout_session_id', 172 $context, 173 ); 174 return new \WP_REST_Response( 175 data: array( 176 'error' => 'WooCommerce order does not exist for the given checkout_session_id', 177 ), 178 status: 422 179 ); 180 } 181 182 $context['order_id'] = $order->get_id(); 183 184 // If the order has not yet been marked as complete, do so. 185 if ( OrderStatus::PENDING === $order->get_status() ) { 186 $order->payment_complete( $received->id() ); 187 } 188 189 $received->apply_to( $order ); 190 $order->save(); 162 if ( WebhookEvent::CHECKOUT_SESSION_COMPLETED === $type ) { 163 if ( ! isset( $data['object']['checkout_session'] ) || ! is_array( $data['object']['checkout_session'] ) ) { 164 $error = new FlexException( 'Event missing checkout session' ); 165 $this->logger->error( $error->getMessage(), $context ); 166 sentry()->captureException( $error ); 167 return new \WP_REST_Response( 168 data: array( 169 'error' => 'Event missing checkout session', 170 ), 171 status: 422 172 ); 173 } 174 175 $received = CheckoutSession::from_flex( $data['object']['checkout_session'] ); 176 177 $context['checkout_session_id'] = $received->id(); 178 179 $order = $received->wc(); 180 181 if ( null === $order ) { 182 $error = new FlexException( 'WooCommerce order does not exist for the given checkout_session_id' ); 183 $this->logger->error( $error->getMessage(), $context ); 184 sentry()->captureException( $error ); 185 return new \WP_REST_Response( 186 data: array( 187 'error' => 'WooCommerce order does not exist for the given checkout_session_id', 188 ), 189 status: 422 190 ); 191 } 192 193 $context['order_id'] = $order->get_id(); 194 195 // If the order has not yet been marked as complete, do so. 196 if ( OrderStatus::PENDING === $order->get_status() ) { 197 $order->payment_complete( $received->id() ); 198 } 199 200 $received->apply_to( $order ); 201 $order->save(); 202 } elseif ( WebhookEvent::REFUND_UPDATED === $type ) { 203 if ( ! isset( $data['object']['refund'] ) || ! is_array( $data['object']['refund'] ) ) { 204 $error = new FlexException( 'Event missing refund' ); 205 $this->logger->error( $error->getMessage(), $context ); 206 sentry()->captureException( $error ); 207 return new \WP_REST_Response( 208 data: array( 209 'error' => 'Event missing refund', 210 ), 211 status: 422 212 ); 213 } 214 215 $refund = Refund::from_flex( $data['object']['refund'] ); 216 217 if ( $refund->status()?->failure() ) { 218 $wc_refund = $refund->wc(); 219 if ( null === $wc_refund ) { 220 $error = new FlexException( 'WooCommerce refund does not exist for the given refund_id' ); 221 $this->logger->error( $error->getMessage(), $context ); 222 sentry()->captureException( $error ); 223 return new \WP_REST_Response( 224 data: array( 225 'error' => 'WooCommerce refund does not exist for the given refund_id', 226 ), 227 status: 422 228 ); 229 } 230 231 $order = wc_get_order( $wc_refund->get_parent_id() ); 232 233 if ( false === $order ) { 234 $error = new FlexException( 'WooCommerce order does not exist for the given refund_id' ); 235 $this->logger->error( $error->getMessage(), $context ); 236 sentry()->captureException( $error ); 237 return new \WP_REST_Response( 238 data: array( 239 'error' => 'WooCommerce order does not exist for the given refund_id', 240 ), 241 status: 422 242 ); 243 } 244 245 $note = sprintf( 246 // translators: %1$d: refund id. 247 // translators: %2$s: amount of the refund. 248 // translators: %3$s: status of the refund. 249 // translators: %4$s: Flex Refund ID. 250 __( 'Refund %1$d in the amount of %2$s resulted in a status of %3$s in Flex (%4$s) and has been deleted.', 'pay-with-flex' ), 251 $wc_refund->get_id(), 252 $wc_refund->get_formatted_refund_amount(), 253 $refund->status()->value, 254 $refund->id(), 255 ); 256 257 if ( $wc_refund->delete() ) { 258 $order->add_order_note( $note ); 259 } 260 } 261 } 191 262 192 263 $this->logger->debug( -
pay-with-flex/trunk/src/PaymentGateway.php
r3299082 r3306095 12 12 use Automattic\WooCommerce\Enums\OrderStatus; 13 13 use Flex\Exception\FlexException; 14 use Flex\Resource\CheckoutSession; 14 use Flex\Resource\CheckoutSession\CheckoutSession; 15 use Flex\Resource\CheckoutSession\Refund\Refund; 16 use Flex\Resource\ResourceAction; 15 17 use Flex\Resource\Webhook; 18 use Sentry\Breadcrumb; 16 19 use Sentry\State\Scope; 17 20 … … 24 27 25 28 /** 29 * {@inheritdoc} 30 * 31 * @var string 32 */ 33 public $id = 'flex'; 34 35 /** 36 * {@inheritdoc} 37 * 38 * @var bool 39 */ 40 public $has_fields = false; 41 42 /** 43 * {@inheritdoc} 44 * 45 * @var array 46 */ 47 public $supports = array( 'products', 'refunds' ); 48 49 /** 26 50 * Logger. 27 51 * … … 36 60 */ 37 61 public function __construct( bool $actions = true ) { 38 $this->id = 'flex'; 62 $this->logger = wc_get_logger(); 63 64 $this->init_settings(); 65 66 if ( did_action( 'init' ) ) { 67 $this->init(); 68 } 69 70 if ( $actions ) { 71 // Translation cannot be used until after `init`. 72 if ( ! did_action( 'init' ) ) { 73 add_action( 'init', array( $this, 'init' ) ); 74 } 75 // @phpstan-ignore return.void 76 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); 77 } 78 } 79 80 /** 81 * Initialize the Payment Gateway. 82 */ 83 public function init() { 39 84 $this->title = __( 'Flex | Pay with HSA/FSA', 'pay-with-flex' ); 40 85 $this->method_title = __( 'Flex', 'pay-with-flex' ); 41 86 $this->method_description = __( 'Accept HSA/FSA payments directly in the checkout flow.', 'pay-with-flex' ); 42 $this->has_fields = false;43 $this->logger = wc_get_logger();44 45 87 $this->init_form_fields(); 46 $this->init_settings();47 48 if ( $actions ) {49 // @phpstan-ignore return.void50 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );51 }52 88 } 53 89 … … 74 110 'order_id' => $order_id, 75 111 ) 112 ); 113 114 sentry()->configureScope( 115 function ( Scope $scope ) use ( $order_id ): void { 116 $scope->addBreadcrumb( 117 new Breadcrumb( 118 level: Breadcrumb::LEVEL_INFO, 119 type: Breadcrumb::TYPE_DEFAULT, 120 category: 'payment', 121 message: 'Payment', 122 metadata: array( 123 'order_id' => $order_id, 124 ), 125 ) 126 ); 127 }, 76 128 ); 77 129 … … 176 228 ); 177 229 } 230 } 231 232 /** 233 * {@inheritdoc} 234 * 235 * @param int $order_id Order ID. 236 * @param float|null $amount Refund amount. 237 * @param string $reason Refund reason. 238 * @return bool|\WP_Error True or false based on success, or a WP_Error object. 239 * @throws FlexException If we can intuit the refund from the amount and reason. 240 * @throws \Exception When a FlexException is caught. 241 */ 242 public function process_refund( $order_id, $amount = null, $reason = '' ) { 243 sentry()->configureScope( 244 function ( Scope $scope ) use ( $order_id, $amount, $reason ): void { 245 $scope->addBreadcrumb( 246 new Breadcrumb( 247 level: Breadcrumb::LEVEL_INFO, 248 type: Breadcrumb::TYPE_DEFAULT, 249 category: 'refund', 250 message: 'Refund', 251 metadata: array( 252 'order_id' => $order_id, 253 'amount' => $amount, 254 'reason' => $reason, 255 ), 256 ) 257 ); 258 }, 259 ); 260 261 try { 262 $order = wc_get_order( $order_id ); 263 264 sentry()->configureScope( 265 function ( Scope $scope ) use ( $order ): void { 266 $scope->setContext( 267 'Order', 268 $order->get_base_data(), 269 ); 270 }, 271 ); 272 273 $checkout_session = CheckoutSession::from_wc( $order ); 274 275 sentry()->configureScope( 276 function ( Scope $scope ) use ( $checkout_session ): void { 277 $scope->setTags( 278 array( 279 'checkout_session' => $checkout_session->id(), 280 'checkout_session.test_mode' => wc_bool_to_string( $checkout_session->test_mode() ), 281 ) 282 ); 283 284 $scope->setContext( 'Checkout Session', $checkout_session->jsonSerialize() ); 285 }, 286 ); 287 288 $refunds = $order->get_refunds(); 289 290 /** 291 * Retrieve the first refund from the list. 292 * 293 * @var \WC_Order_Refund|false 294 */ 295 $refund = reset( $refunds ); 296 297 if ( false === $refund ) { 298 throw new FlexException( 'Unable to retrieve refund' ); 299 } 300 301 sentry()->configureScope( 302 function ( Scope $scope ) use ( $refund ): void { 303 $scope->setContext( 304 'Refund', 305 $refund->get_base_data() 306 ); 307 }, 308 ); 309 310 if ( $refund->get_amount() !== $amount || $refund->get_reason() !== $reason ) { 311 throw new FlexException( 'Refund amount or reason does not match retrieved refund.' ); 312 } 313 314 // Ensure the Webhooks are up to date. 315 $webhook = Webhook::from_wc( $this ); 316 $webhook->exec( $webhook->needs() ); 317 318 Refund::from_wc( $refund )->exec( ResourceAction::CREATE ); 319 320 } catch ( FlexException $previous ) { 321 $this->logger->error( 322 $previous->getMessage(), 323 array_merge( 324 $previous->getContext(), 325 array( 326 'refund_id' => $order_id, 327 ), 328 ), 329 ); 330 331 sentry()->captureException( 332 new \Exception( 333 message: 'Refund processing failure', 334 previous: $previous, 335 ) 336 ); 337 338 if ( true === \WP_DEBUG ) { 339 // Throw the underlying error message which will be displayed the user. 340 if ( true === \WP_DEBUG_DISPLAY ) { 341 throw $previous; 342 } 343 344 // Log the underlying error message. 345 error_log( $previous->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log 346 } 347 348 throw new \Exception( 349 message: "We're sorry, there was a problem while attempting to processes the refund with Flex. Please try again later.", 350 previous: $previous, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped 351 ); 352 } 353 354 return true; 178 355 } 179 356 -
pay-with-flex/trunk/src/Resource/Resource.php
r3299082 r3306095 46 46 */ 47 47 public static function currency_to_unit_amount( int|float|string $value ): int { 48 if ( is_string( $value ) ) { 49 // Remove a negative sign, currency symbols, etc. 50 $currency_symbol = html_entity_decode( get_woocommerce_currency_symbol() ); 51 $value = trim( $value, $currency_symbol . "- \n\r\t\v\0" ); 52 } else { 53 $value = abs( $value ); 54 } 55 48 56 // Split the string based on the decimal separator. 49 $parts = explode( 50 wc_get_price_decimal_separator(), 51 // Convert to a string, remove the currency symbol if there is one, and trim. 52 trim( str_replace( get_woocommerce_currency_symbol(), '', (string) $value ) ) 53 ); 57 $parts = explode( wc_get_price_decimal_separator(), (string) $value ); 54 58 55 59 return intval( -
pay-with-flex/trunk/src/Resource/ShippingRate.php
r3296637 r3306095 1 1 <?php 2 2 /** 3 * Flex Checkout Session Line Item3 * Flex Shipping Rate. 4 4 * 5 5 * @package Flex -
pay-with-flex/trunk/src/Resource/Webhook.php
r3296637 r3306095 24 24 protected const KEY_HASH = 'webhoook_hash'; 25 25 protected const KEY_SIGNING_SECRET = 'webhoook_signing_secret'; 26 protected const EVENTS = array( 'checkout.session.completed' ); 26 27 /** 28 * Events 29 * 30 * @var WebhookEvent[] 31 */ 32 protected $events; 27 33 28 34 /** … … 34 40 35 41 /** 36 * Creates a checkout session line item 37 * 38 * @param string $url The url the webhooks should subscribe too. 39 * @param ?string $id The id of the webhook. 40 * @param ?string $signing_secret The signing secret of the webhook. 41 * @param string[] $events The events the webhook is subscribed too. 42 * @param ?bool $test_mode Whether the webhook was created in test mode. 42 * Creates a webhook. 43 * 44 * @param string $url The url the webhooks should subscribe too. 45 * @param ?string $id The id of the webhook. 46 * @param ?string $signing_secret The signing secret of the webhook. 47 * @param ?WebhookEvent[] $events The events the webhook is subscribed too. 48 * @param ?bool $test_mode Whether the webhook was created in test mode. 49 * @throws \LogicException If $events does not consist of instances of `WebhookEvent`. 43 50 */ 44 51 public function __construct( … … 46 53 protected ?string $id = null, 47 54 protected ?string $signing_secret = null, 48 protected array $events = self::EVENTS,55 ?array $events = null, 49 56 protected ?bool $test_mode = null, 50 ) {} 57 ) { 58 if ( null !== $events && ! array_all( $events, fn ( $e ) => $e instanceof WebhookEvent ) ) { 59 throw new \LogicException( 'Webhook::$events must only contain instances of WebhookEvent' ); 60 } 61 62 if ( null === $events ) { 63 $events = WebhookEvent::cases(); 64 } 65 66 $this->events = $events; 67 } 51 68 52 69 /** … … 114 131 $this->id = $webhook['webhook_id'] ?? $this->id; 115 132 $this->url = $webhook['url'] ?? $this->url; 116 $this->events = $webhook['events'] ?? $this->events;117 133 $this->signing_secret = $webhook['signing_secret'] ?? $this->signing_secret; 118 134 $this->test_mode = $webhook['test_mode'] ?? $this->test_mode; 135 136 if ( ! empty( $webhook['events'] ) && is_array( $webhook['events'] ) ) { 137 $this->events = array_reduce( 138 $webhook['events'], 139 function ( array $acc, string $value ): array { 140 $event = WebhookEvent::tryFrom( $value ); 141 if ( null !== $event ) { 142 $acc[] = $event; 143 } 144 return $acc; 145 }, 146 array(), 147 ); 148 } 119 149 } 120 150 -
pay-with-flex/trunk/vendor/composer/autoload_classmap.php
r3301881 r3306095 21 21 'Flex\\PaymentGateway' => $baseDir . '/src/PaymentGateway.php', 22 22 'Flex\\PaymentMethod' => $baseDir . '/src/PaymentMethod.php', 23 'Flex\\Resource\\CheckoutSession' => $baseDir . '/src/Resource/CheckoutSession.php', 24 'Flex\\Resource\\CheckoutSessionMode' => $baseDir . '/src/Resource/CheckoutSessionMode.php', 25 'Flex\\Resource\\CheckoutSessionShippingOptions' => $baseDir . '/src/Resource/CheckoutSessionShippingOptions.php', 26 'Flex\\Resource\\CheckoutSessionStatus' => $baseDir . '/src/Resource/CheckoutSessionStatus.php', 27 'Flex\\Resource\\CheckoutSessionTaxRate' => $baseDir . '/src/Resource/CheckoutSessionTaxRate.php', 28 'Flex\\Resource\\CustomerDefaults' => $baseDir . '/src/Resource/CustomerDefaults.php', 29 'Flex\\Resource\\LineItem' => $baseDir . '/src/Resource/LineItem.php', 23 'Flex\\Resource\\CheckoutSession\\CheckoutSession' => $baseDir . '/src/Resource/CheckoutSession/CheckoutSession.php', 24 'Flex\\Resource\\CheckoutSession\\CustomerDefaults' => $baseDir . '/src/Resource/CheckoutSession/CustomerDefaults.php', 25 'Flex\\Resource\\CheckoutSession\\LineItem' => $baseDir . '/src/Resource/CheckoutSession/LineItem.php', 26 'Flex\\Resource\\CheckoutSession\\Mode' => $baseDir . '/src/Resource/CheckoutSession/Mode.php', 27 'Flex\\Resource\\CheckoutSession\\Refund\\LineItem' => $baseDir . '/src/Resource/CheckoutSession/Refund/LineItem.php', 28 'Flex\\Resource\\CheckoutSession\\Refund\\Refund' => $baseDir . '/src/Resource/CheckoutSession/Refund/Refund.php', 29 'Flex\\Resource\\CheckoutSession\\ShippingOptions' => $baseDir . '/src/Resource/CheckoutSession/ShippingOptions.php', 30 'Flex\\Resource\\CheckoutSession\\Status' => $baseDir . '/src/Resource/CheckoutSession/Status.php', 31 'Flex\\Resource\\CheckoutSession\\TaxRate' => $baseDir . '/src/Resource/CheckoutSession/TaxRate.php', 30 32 'Flex\\Resource\\Price' => $baseDir . '/src/Resource/Price.php', 31 33 'Flex\\Resource\\Product' => $baseDir . '/src/Resource/Product.php', 34 'Flex\\Resource\\Refund' => $baseDir . '/src/Resource/Refund.php', 35 'Flex\\Resource\\RefundStatus' => $baseDir . '/src/Resource/RefundStatus.php', 32 36 'Flex\\Resource\\Resource' => $baseDir . '/src/Resource/Resource.php', 33 37 'Flex\\Resource\\ResourceAction' => $baseDir . '/src/Resource/ResourceAction.php', … … 35 39 'Flex\\Resource\\ShippingRate' => $baseDir . '/src/Resource/ShippingRate.php', 36 40 'Flex\\Resource\\Webhook' => $baseDir . '/src/Resource/Webhook.php', 41 'Flex\\Resource\\WebhookEvent' => $baseDir . '/src/Resource/WebhookEvent.php', 37 42 'GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php', 38 43 'GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php', -
pay-with-flex/trunk/vendor/composer/autoload_static.php
r3301881 r3306095 99 99 'Flex\\PaymentGateway' => __DIR__ . '/../..' . '/src/PaymentGateway.php', 100 100 'Flex\\PaymentMethod' => __DIR__ . '/../..' . '/src/PaymentMethod.php', 101 'Flex\\Resource\\CheckoutSession' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession.php', 102 'Flex\\Resource\\CheckoutSessionMode' => __DIR__ . '/../..' . '/src/Resource/CheckoutSessionMode.php', 103 'Flex\\Resource\\CheckoutSessionShippingOptions' => __DIR__ . '/../..' . '/src/Resource/CheckoutSessionShippingOptions.php', 104 'Flex\\Resource\\CheckoutSessionStatus' => __DIR__ . '/../..' . '/src/Resource/CheckoutSessionStatus.php', 105 'Flex\\Resource\\CheckoutSessionTaxRate' => __DIR__ . '/../..' . '/src/Resource/CheckoutSessionTaxRate.php', 106 'Flex\\Resource\\CustomerDefaults' => __DIR__ . '/../..' . '/src/Resource/CustomerDefaults.php', 107 'Flex\\Resource\\LineItem' => __DIR__ . '/../..' . '/src/Resource/LineItem.php', 101 'Flex\\Resource\\CheckoutSession\\CheckoutSession' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/CheckoutSession.php', 102 'Flex\\Resource\\CheckoutSession\\CustomerDefaults' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/CustomerDefaults.php', 103 'Flex\\Resource\\CheckoutSession\\LineItem' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/LineItem.php', 104 'Flex\\Resource\\CheckoutSession\\Mode' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/Mode.php', 105 'Flex\\Resource\\CheckoutSession\\Refund\\LineItem' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/Refund/LineItem.php', 106 'Flex\\Resource\\CheckoutSession\\Refund\\Refund' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/Refund/Refund.php', 107 'Flex\\Resource\\CheckoutSession\\ShippingOptions' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/ShippingOptions.php', 108 'Flex\\Resource\\CheckoutSession\\Status' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/Status.php', 109 'Flex\\Resource\\CheckoutSession\\TaxRate' => __DIR__ . '/../..' . '/src/Resource/CheckoutSession/TaxRate.php', 108 110 'Flex\\Resource\\Price' => __DIR__ . '/../..' . '/src/Resource/Price.php', 109 111 'Flex\\Resource\\Product' => __DIR__ . '/../..' . '/src/Resource/Product.php', 112 'Flex\\Resource\\Refund' => __DIR__ . '/../..' . '/src/Resource/Refund.php', 113 'Flex\\Resource\\RefundStatus' => __DIR__ . '/../..' . '/src/Resource/RefundStatus.php', 110 114 'Flex\\Resource\\Resource' => __DIR__ . '/../..' . '/src/Resource/Resource.php', 111 115 'Flex\\Resource\\ResourceAction' => __DIR__ . '/../..' . '/src/Resource/ResourceAction.php', … … 113 117 'Flex\\Resource\\ShippingRate' => __DIR__ . '/../..' . '/src/Resource/ShippingRate.php', 114 118 'Flex\\Resource\\Webhook' => __DIR__ . '/../..' . '/src/Resource/Webhook.php', 119 'Flex\\Resource\\WebhookEvent' => __DIR__ . '/../..' . '/src/Resource/WebhookEvent.php', 115 120 'GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/AppendStream.php', 116 121 'GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/BufferStream.php', -
pay-with-flex/trunk/vendor/composer/installed.json
r3301881 r3306095 629 629 { 630 630 "name": "symfony/options-resolver", 631 "version": "v7. 2.0",632 "version_normalized": "7. 2.0.0",631 "version": "v7.3.0", 632 "version_normalized": "7.3.0.0", 633 633 "source": { 634 634 "type": "git", 635 635 "url": "https://github.com/symfony/options-resolver.git", 636 "reference": " 7da8fbac9dcfef75ffc212235d76b2754ce0cf50"637 }, 638 "dist": { 639 "type": "zip", 640 "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ 7da8fbac9dcfef75ffc212235d76b2754ce0cf50",641 "reference": " 7da8fbac9dcfef75ffc212235d76b2754ce0cf50",636 "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" 637 }, 638 "dist": { 639 "type": "zip", 640 "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", 641 "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", 642 642 "shasum": "" 643 643 }, … … 646 646 "symfony/deprecation-contracts": "^2.5|^3" 647 647 }, 648 "time": "202 4-11-20T11:17:29+00:00",648 "time": "2025-04-04T13:12:05+00:00", 649 649 "type": "library", 650 650 "installation-source": "dist", … … 679 679 ], 680 680 "support": { 681 "source": "https://github.com/symfony/options-resolver/tree/v7. 2.0"681 "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" 682 682 }, 683 683 "funding": [ -
pay-with-flex/trunk/vendor/composer/installed.php
r3301881 r3306095 4 4 'pretty_version' => 'dev-main', 5 5 'version' => 'dev-main', 6 'reference' => ' cc4788f82da3cf84ab509a01c85acd3dd14841e4',6 'reference' => 'b52bc3dd944a3f0dc9e1ffb085a3e4f95efe9343', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 14 14 'pretty_version' => 'dev-main', 15 15 'version' => 'dev-main', 16 'reference' => ' cc4788f82da3cf84ab509a01c85acd3dd14841e4',16 'reference' => 'b52bc3dd944a3f0dc9e1ffb085a3e4f95efe9343', 17 17 'type' => 'library', 18 18 'install_path' => __DIR__ . '/../../', … … 114 114 ), 115 115 'symfony/options-resolver' => array( 116 'pretty_version' => 'v7. 2.0',117 'version' => '7. 2.0.0',118 'reference' => ' 7da8fbac9dcfef75ffc212235d76b2754ce0cf50',116 'pretty_version' => 'v7.3.0', 117 'version' => '7.3.0.0', 118 'reference' => 'afb9a8038025e5dbc657378bfab9198d75f10fca', 119 119 'type' => 'library', 120 120 'install_path' => __DIR__ . '/../symfony/options-resolver', -
pay-with-flex/trunk/vendor/composer/jetpack_autoload_classmap.php
r3301881 r3306095 75 75 'path' => $baseDir . '/src/PaymentMethod.php' 76 76 ), 77 'Flex\\Resource\\CheckoutSession' => array( 78 'version' => 'dev-main', 79 'path' => $baseDir . '/src/Resource/CheckoutSession.php' 80 ), 81 'Flex\\Resource\\CheckoutSessionMode' => array( 82 'version' => 'dev-main', 83 'path' => $baseDir . '/src/Resource/CheckoutSessionMode.php' 84 ), 85 'Flex\\Resource\\CheckoutSessionShippingOptions' => array( 86 'version' => 'dev-main', 87 'path' => $baseDir . '/src/Resource/CheckoutSessionShippingOptions.php' 88 ), 89 'Flex\\Resource\\CheckoutSessionStatus' => array( 90 'version' => 'dev-main', 91 'path' => $baseDir . '/src/Resource/CheckoutSessionStatus.php' 92 ), 93 'Flex\\Resource\\CheckoutSessionTaxRate' => array( 94 'version' => 'dev-main', 95 'path' => $baseDir . '/src/Resource/CheckoutSessionTaxRate.php' 96 ), 97 'Flex\\Resource\\CustomerDefaults' => array( 98 'version' => 'dev-main', 99 'path' => $baseDir . '/src/Resource/CustomerDefaults.php' 100 ), 101 'Flex\\Resource\\LineItem' => array( 102 'version' => 'dev-main', 103 'path' => $baseDir . '/src/Resource/LineItem.php' 77 'Flex\\Resource\\CheckoutSession\\CheckoutSession' => array( 78 'version' => 'dev-main', 79 'path' => $baseDir . '/src/Resource/CheckoutSession/CheckoutSession.php' 80 ), 81 'Flex\\Resource\\CheckoutSession\\CustomerDefaults' => array( 82 'version' => 'dev-main', 83 'path' => $baseDir . '/src/Resource/CheckoutSession/CustomerDefaults.php' 84 ), 85 'Flex\\Resource\\CheckoutSession\\LineItem' => array( 86 'version' => 'dev-main', 87 'path' => $baseDir . '/src/Resource/CheckoutSession/LineItem.php' 88 ), 89 'Flex\\Resource\\CheckoutSession\\Mode' => array( 90 'version' => 'dev-main', 91 'path' => $baseDir . '/src/Resource/CheckoutSession/Mode.php' 92 ), 93 'Flex\\Resource\\CheckoutSession\\Refund\\LineItem' => array( 94 'version' => 'dev-main', 95 'path' => $baseDir . '/src/Resource/CheckoutSession/Refund/LineItem.php' 96 ), 97 'Flex\\Resource\\CheckoutSession\\Refund\\Refund' => array( 98 'version' => 'dev-main', 99 'path' => $baseDir . '/src/Resource/CheckoutSession/Refund/Refund.php' 100 ), 101 'Flex\\Resource\\CheckoutSession\\ShippingOptions' => array( 102 'version' => 'dev-main', 103 'path' => $baseDir . '/src/Resource/CheckoutSession/ShippingOptions.php' 104 ), 105 'Flex\\Resource\\CheckoutSession\\Status' => array( 106 'version' => 'dev-main', 107 'path' => $baseDir . '/src/Resource/CheckoutSession/Status.php' 108 ), 109 'Flex\\Resource\\CheckoutSession\\TaxRate' => array( 110 'version' => 'dev-main', 111 'path' => $baseDir . '/src/Resource/CheckoutSession/TaxRate.php' 104 112 ), 105 113 'Flex\\Resource\\Price' => array( … … 111 119 'path' => $baseDir . '/src/Resource/Product.php' 112 120 ), 121 'Flex\\Resource\\Refund' => array( 122 'version' => 'dev-main', 123 'path' => $baseDir . '/src/Resource/Refund.php' 124 ), 125 'Flex\\Resource\\RefundStatus' => array( 126 'version' => 'dev-main', 127 'path' => $baseDir . '/src/Resource/RefundStatus.php' 128 ), 113 129 'Flex\\Resource\\Resource' => array( 114 130 'version' => 'dev-main', … … 130 146 'version' => 'dev-main', 131 147 'path' => $baseDir . '/src/Resource/Webhook.php' 148 ), 149 'Flex\\Resource\\WebhookEvent' => array( 150 'version' => 'dev-main', 151 'path' => $baseDir . '/src/Resource/WebhookEvent.php' 132 152 ), 133 153 'GuzzleHttp\\Psr7\\AppendStream' => array( … … 808 828 ), 809 829 'Symfony\\Component\\OptionsResolver\\Debug\\OptionsResolverIntrospector' => array( 810 'version' => '7. 2.0.0',830 'version' => '7.3.0.0', 811 831 'path' => $vendorDir . '/symfony/options-resolver/Debug/OptionsResolverIntrospector.php' 812 832 ), 813 833 'Symfony\\Component\\OptionsResolver\\Exception\\AccessException' => array( 814 'version' => '7. 2.0.0',834 'version' => '7.3.0.0', 815 835 'path' => $vendorDir . '/symfony/options-resolver/Exception/AccessException.php' 816 836 ), 817 837 'Symfony\\Component\\OptionsResolver\\Exception\\ExceptionInterface' => array( 818 'version' => '7. 2.0.0',838 'version' => '7.3.0.0', 819 839 'path' => $vendorDir . '/symfony/options-resolver/Exception/ExceptionInterface.php' 820 840 ), 821 841 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidArgumentException' => array( 822 'version' => '7. 2.0.0',842 'version' => '7.3.0.0', 823 843 'path' => $vendorDir . '/symfony/options-resolver/Exception/InvalidArgumentException.php' 824 844 ), 825 845 'Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException' => array( 826 'version' => '7. 2.0.0',846 'version' => '7.3.0.0', 827 847 'path' => $vendorDir . '/symfony/options-resolver/Exception/InvalidOptionsException.php' 828 848 ), 829 849 'Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException' => array( 830 'version' => '7. 2.0.0',850 'version' => '7.3.0.0', 831 851 'path' => $vendorDir . '/symfony/options-resolver/Exception/MissingOptionsException.php' 832 852 ), 833 853 'Symfony\\Component\\OptionsResolver\\Exception\\NoConfigurationException' => array( 834 'version' => '7. 2.0.0',854 'version' => '7.3.0.0', 835 855 'path' => $vendorDir . '/symfony/options-resolver/Exception/NoConfigurationException.php' 836 856 ), 837 857 'Symfony\\Component\\OptionsResolver\\Exception\\NoSuchOptionException' => array( 838 'version' => '7. 2.0.0',858 'version' => '7.3.0.0', 839 859 'path' => $vendorDir . '/symfony/options-resolver/Exception/NoSuchOptionException.php' 840 860 ), 841 861 'Symfony\\Component\\OptionsResolver\\Exception\\OptionDefinitionException' => array( 842 'version' => '7. 2.0.0',862 'version' => '7.3.0.0', 843 863 'path' => $vendorDir . '/symfony/options-resolver/Exception/OptionDefinitionException.php' 844 864 ), 845 865 'Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException' => array( 846 'version' => '7. 2.0.0',866 'version' => '7.3.0.0', 847 867 'path' => $vendorDir . '/symfony/options-resolver/Exception/UndefinedOptionsException.php' 848 868 ), 849 869 'Symfony\\Component\\OptionsResolver\\OptionConfigurator' => array( 850 'version' => '7. 2.0.0',870 'version' => '7.3.0.0', 851 871 'path' => $vendorDir . '/symfony/options-resolver/OptionConfigurator.php' 852 872 ), 853 873 'Symfony\\Component\\OptionsResolver\\Options' => array( 854 'version' => '7. 2.0.0',874 'version' => '7.3.0.0', 855 875 'path' => $vendorDir . '/symfony/options-resolver/Options.php' 856 876 ), 857 877 'Symfony\\Component\\OptionsResolver\\OptionsResolver' => array( 858 'version' => '7. 2.0.0',878 'version' => '7.3.0.0', 859 879 'path' => $vendorDir . '/symfony/options-resolver/OptionsResolver.php' 860 880 ), -
pay-with-flex/trunk/vendor/symfony/options-resolver/CHANGELOG.md
r3299085 r3306095 1 1 CHANGELOG 2 2 ========= 3 4 7.3 5 --- 6 7 * Support union type in `OptionResolver::setAllowedTypes()` method 8 * Add `OptionsResolver::setOptions()` and `OptionConfigurator::options()` methods 9 * Deprecate defining nested options via `setDefault()`, use `setOptions()` instead 3 10 4 11 6.4 5 12 --- 6 13 7 * Improve message with full path on invalid type in nested option14 * Improve message with full path on invalid type in nested option 8 15 9 16 6.3 -
pay-with-flex/trunk/vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php
r3299085 r3306095 102 102 return ($this->get)('deprecated', $option, \sprintf('No deprecation was set for the "%s" option.', $option)); 103 103 } 104 105 /** 106 * @return \Closure[] 107 * 108 * @throws NoConfigurationException when no nested option is configured 109 */ 110 public function getNestedOptions(string $option): array 111 { 112 return ($this->get)('nested', $option, \sprintf('No nested option was set for the "%s" option.', $option)); 113 } 104 114 } -
pay-with-flex/trunk/vendor/symfony/options-resolver/OptionConfigurator.php
r3299085 r3306095 144 144 return $this; 145 145 } 146 147 /** 148 * Defines nested options. 149 * 150 * @param \Closure(OptionsResolver $resolver, Options $parent): void $nested 151 * 152 * @return $this 153 */ 154 public function options(\Closure $nested): static 155 { 156 $this->resolver->setOptions($this->name, $nested); 157 158 return $this; 159 } 146 160 } -
pay-with-flex/trunk/vendor/symfony/options-resolver/OptionsResolver.php
r3299085 r3306095 66 66 67 67 /** 68 * BC layer. Remove in Symfony 8.0. 69 * 70 * @var array<string, true> 71 */ 72 private array $deprecatedNestedOptions = []; 73 74 /** 68 75 * The names of required options. 69 76 */ … … 179 186 * sub-classes. 180 187 * 181 * If you want to define nested options, you can pass a closure with the182 * following signature:183 *184 * $options->setDefault('database', function (OptionsResolver $resolver) {185 * $resolver->setDefined(['dbname', 'host', 'port', 'user', 'pass']);186 * }187 *188 * To get access to the parent options, add a second argument to the closure's189 * signature:190 *191 * function (OptionsResolver $resolver, Options $parent) {192 * // 'default' === $parent['connection']193 * }194 *195 188 * @return $this 196 189 * … … 227 220 $this->defined[$option] = true; 228 221 229 // Make sure the option is processed and is not nested anymore 230 unset($this->resolved[$option], $this->nested[$option]); 222 // Make sure the option is processed 223 unset($this->resolved[$option]); 224 225 // BC layer. Remove in Symfony 8.0. 226 if (isset($this->deprecatedNestedOptions[$option])) { 227 unset($this->nested[$option]); 228 } 231 229 232 230 return $this; 233 231 } 234 232 233 // Remove in Symfony 8.0. 235 234 if (isset($params[0]) && ($type = $params[0]->getType()) instanceof \ReflectionNamedType && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) { 235 trigger_deprecation('symfony/options-resolver', '7.3', 'Defining nested options via "%s()" is deprecated and will be removed in Symfony 8.0, use "setOptions()" method instead.', __METHOD__); 236 $this->deprecatedNestedOptions[$option] = true; 237 236 238 // Store closure for later evaluation 237 239 $this->nested[$option][] = $value; … … 246 248 } 247 249 248 // This option is not lazy nor nested anymore 249 unset($this->lazy[$option], $this->nested[$option]); 250 // This option is not lazy anymore 251 unset($this->lazy[$option]); 252 253 // BC layer. Remove in Symfony 8.0. 254 if (isset($this->deprecatedNestedOptions[$option])) { 255 unset($this->nested[$option]); 256 } 250 257 251 258 // Yet undefined options can be marked as resolved, because we only need … … 402 409 { 403 410 return array_keys($this->defined); 411 } 412 413 /** 414 * Defines nested options. 415 * 416 * @param \Closure(self $resolver, Options $parent): void $nested 417 * 418 * @return $this 419 */ 420 public function setOptions(string $option, \Closure $nested): static 421 { 422 if ($this->locked) { 423 throw new AccessException('Nested options cannot be defined from a lazy option or normalizer.'); 424 } 425 426 // Store closure for later evaluation 427 $this->nested[$option][] = $nested; 428 $this->defaults[$option] = []; 429 $this->defined[$option] = true; 430 431 // Make sure the option is processed 432 unset($this->resolved[$option]); 433 434 return $this; 404 435 } 405 436 … … 948 979 $value = $this->defaults[$option]; 949 980 981 // Resolve the option if the default value is lazily evaluated 982 if (isset($this->lazy[$option])) { 983 // If the closure is already being called, we have a cyclic dependency 984 if (isset($this->calling[$option])) { 985 throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); 986 } 987 988 $this->calling[$option] = true; 989 try { 990 foreach ($this->lazy[$option] as $closure) { 991 $value = $closure($this, $value); 992 } 993 } finally { 994 unset($this->calling[$option]); 995 } 996 } 997 950 998 // Resolve the option if it is a nested definition 951 999 if (isset($this->nested[$option])) { … … 959 1007 } 960 1008 961 // The following section must be protected from cyclic calls.962 1009 $this->calling[$option] = true; 963 1010 try { … … 990 1037 } 991 1038 992 // Resolve the option if the default value is lazily evaluated993 if (isset($this->lazy[$option])) {994 // If the closure is already being called, we have a cyclic995 // dependency996 if (isset($this->calling[$option])) {997 throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));998 }999 1000 // The following section must be protected from cyclic1001 // calls. Set $calling for the current $option to detect a cyclic1002 // dependency1003 // BEGIN1004 $this->calling[$option] = true;1005 try {1006 foreach ($this->lazy[$option] as $closure) {1007 $value = $closure($this, $value);1008 }1009 } finally {1010 unset($this->calling[$option]);1011 }1012 // END1013 }1014 1015 1039 // Validate the type of the resolved option 1016 1040 if (isset($this->allowedTypes[$option])) { … … 1140 1164 } 1141 1165 1142 private function verifyTypes(string $type, mixed $value, array &$invalidTypes, int $level = 0): bool 1143 { 1166 private function verifyTypes(string $type, mixed $value, ?array &$invalidTypes = null, int $level = 0): bool 1167 { 1168 $type = trim($type); 1169 $allowedTypes = $this->splitOutsideParenthesis($type); 1170 if (\count($allowedTypes) > 1) { 1171 foreach ($allowedTypes as $allowedType) { 1172 if ($this->verifyTypes($allowedType, $value)) { 1173 return true; 1174 } 1175 } 1176 1177 if (\is_array($invalidTypes) && (!$invalidTypes || $level > 0)) { 1178 $invalidTypes[get_debug_type($value)] = true; 1179 } 1180 1181 return false; 1182 } 1183 1184 $type = $allowedTypes[0]; 1185 if (str_starts_with($type, '(') && str_ends_with($type, ')')) { 1186 return $this->verifyTypes(substr($type, 1, -1), $value, $invalidTypes, $level); 1187 } 1188 1144 1189 if (\is_array($value) && str_ends_with($type, '[]')) { 1145 1190 $type = substr($type, 0, -2); … … 1159 1204 } 1160 1205 1161 if ( !$invalidTypes || $level > 0) {1206 if (\is_array($invalidTypes) && (!$invalidTypes || $level > 0)) { 1162 1207 $invalidTypes[get_debug_type($value)] = true; 1163 1208 } 1164 1209 1165 1210 return false; 1211 } 1212 1213 /** 1214 * @return list<string> 1215 */ 1216 private function splitOutsideParenthesis(string $type): array 1217 { 1218 $parts = []; 1219 $currentPart = ''; 1220 $parenthesisLevel = 0; 1221 1222 $typeLength = \strlen($type); 1223 for ($i = 0; $i < $typeLength; ++$i) { 1224 $char = $type[$i]; 1225 1226 if ('(' === $char) { 1227 ++$parenthesisLevel; 1228 } elseif (')' === $char) { 1229 --$parenthesisLevel; 1230 } 1231 1232 if ('|' === $char && 0 === $parenthesisLevel) { 1233 $parts[] = $currentPart; 1234 $currentPart = ''; 1235 } else { 1236 $currentPart .= $char; 1237 } 1238 } 1239 1240 if ('' !== $currentPart) { 1241 $parts[] = $currentPart; 1242 } 1243 1244 return $parts; 1166 1245 } 1167 1246
Note: See TracChangeset
for help on using the changeset viewer.