$runtime_context * @return array */ public static function build_runtime_payload( array $runtime_context = [] ): array { $shop_url = function_exists( 'wc_get_page_permalink' ) ? wc_get_page_permalink( 'shop' ) : home_url( '/' ); if ( ! $shop_url ) { $shop_url = home_url( '/' ); } $checkout_url = function_exists( 'wc_get_checkout_url' ) ? wc_get_checkout_url() : home_url( '/' ); $steps = (string) wooordercart_get_option( 'ips_checkout_select_checkoutsteps', 'checkout_settings_tabs', 'select3' ); $final_order_review = 'on' === wooordercart_get_option( 'enable_checkout_finalordercheck', 'checkout_settings_tabs', 'off' ); $flow = CheckoutPortalFlowResolver::resolve( $steps, $final_order_review ); $review_step_enabled = (bool) $flow['reviewStepEnabled']; $compact_flow_experimental = (bool) $flow['compactFlowExperimental']; $amazon_availability_resolver = new AmazonPayAvailabilityResolver(); $amazon_address_resolver = new AmazonPayAddressResolver( $amazon_availability_resolver ); $address_authority = ( $amazon_availability_resolver->is_login_return() && $amazon_address_resolver->has_wallet_address() ) ? 'amazon' : 'checkout'; $store_api_available = CheckoutStoreApiClient::is_available(); $store_api_nonce = CheckoutStoreApiClient::nonce(); $store_api_endpoints = CheckoutStoreApiClient::endpoints(); $compatibility = CheckoutBlocksCompatibility::build(); $payment_methods = CheckoutPaymentMethodsBuilder::build(); $fields = CheckoutPortalFieldSchemaBuilder::build(); $legal_links = CheckoutPortalLegalLinksBuilder::build(); $labels = CheckoutPortalLabelsBuilder::build(); $terms_policy = CheckoutTermsPolicy::resolve(); $direct_express_policy = CheckoutDirectExpressPolicy::resolve( $terms_policy ); $runtime_meta = self::build_runtime_meta( $runtime_context ); $execution = $runtime_meta['execution']; $bridge = $runtime_meta['bridge']; $slots = CheckoutPortalSlotsBuilder::build( [ 'storeApiAvailable' => $store_api_available, 'storeApiEndpoints' => $store_api_endpoints, 'compatibility' => $compatibility, 'paymentMethods' => $payment_methods, 'checkout' => [ 'compactFlowExperimental' => $compact_flow_experimental, 'reviewStepEnabled' => $review_step_enabled, ], ] ); $allow_summary_item_removal = self::is_checkout_toggle_enabled( 'ips_checkout_summary_item_remove_enabled', true ); $allow_summary_item_quantity_updates = self::is_checkout_toggle_enabled( 'ips_checkout_summary_item_quantity_enabled', true ); $mobile_summary_mode = self::checkout_select( 'ips_checkout_mobile_summary_mode', [ 'expanded', 'collapsible' ], 'collapsible' ); return [ 'mode' => 'ips_react_portal', 'brand' => [ 'name' => get_bloginfo( 'name' ), 'logoHtml' => self::resolve_logo_html(), ], 'customer' => self::build_customer_payload( $checkout_url ), 'urls' => [ 'home' => esc_url_raw( home_url( '/' ) ), 'shop' => esc_url_raw( $shop_url ), 'cart' => esc_url_raw( function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : home_url( '/' ) ), 'checkout' => esc_url_raw( $checkout_url ), 'checkoutClassic' => CheckoutWooFallbackUrlBuilder::build(), ], 'storeApi' => [ 'available' => $store_api_available, 'nonce' => $store_api_nonce, 'endpoints' => $store_api_endpoints, ], 'portalApi' => [ 'nonce' => CheckoutPortalNonce::create(), 'restNonce' => wp_create_nonce( 'wp_rest' ), 'endpoints' => apply_filters( 'ipscmi_order_cart_checkout_endpoints', [ 'selectPickupLocation' => esc_url_raw( rest_url( 'ips-cart/v1/checkout-portal/pickup-location' ) ), ] ), ], 'monitoring' => [ 'enabled' => CheckoutTraceConfig::is_enabled(), 'consoleEnabled' => CheckoutTraceConfig::is_console_enabled(), 'traceEndpoint' => esc_url_raw( rest_url( 'ips-cart/v1/checkout-trace' ) ), 'traceNonce' => wp_create_nonce( CheckoutTraceConfig::frontend_nonce_action() ), ], 'checkout' => [ 'steps' => (string) $flow['steps'], 'finalOrderReview' => $final_order_review, 'reviewStepEnabled' => $review_step_enabled, 'flowMode' => (string) $flow['flowMode'], 'flowProfile' => (string) $flow['profile'], 'flowFallbackApplied' => (bool) $flow['fallbackApplied'], 'flowFallbackReason' => (string) $flow['fallbackReason'], 'compactFlowExperimental' => $compact_flow_experimental, 'addressAuthority' => $address_authority, 'portalCapability' => (string) ( $compatibility['portalCapability'] ?? 'native_woo_fallback' ), 'portalFallbackReason' => (string) ( $compatibility['portalFallbackReason'] ?? '' ), 'displayPricesIncludingTax' => 'incl' === get_option( 'woocommerce_tax_display_cart' ), 'summaryNote' => [ 'text' => sanitize_text_field( wooordercart_get_option( 'ips-checkout-cartsummary-text', 'checkout_settings_tabs', __( 'Sustainability is important to us!', 'ips-order-cart' ) ) ), 'imageUrl' => esc_url_raw( (string) wooordercart_get_option( 'ips-checkout-cartsummary-icon', 'checkout_settings_tabs', '' ) ), ], 'summaryControls' => [ 'allowItemRemoval' => $allow_summary_item_removal, 'allowItemQuantityUpdates' => $allow_summary_item_quantity_updates, 'mobileSummaryMode' => $mobile_summary_mode, ], 'configuredDirectExpressMode' => (string) $direct_express_policy['configuredDirectExpressMode'], 'directExpressMode' => (string) $direct_express_policy['directExpressMode'], 'directExpressLegalNoticeEnabled' => (bool) $direct_express_policy['directExpressLegalNoticeEnabled'], 'directExpressLegalReady' => (bool) $direct_express_policy['directExpressLegalReady'], 'directExpressPolicyReason' => (string) $direct_express_policy['reasonKey'], ], 'style' => CheckoutPortalStyleResolver::build(), 'execution' => $execution, 'bridge' => $bridge, 'contracts' => [ 'supportStatuses' => CheckoutSupportStatus::definitions(), 'fallbackModes' => CheckoutFallbackMode::definitions(), 'slotCategories' => CheckoutSlotCategory::definitions(), ], 'compatibility' => $compatibility, 'paymentMethods' => $payment_methods, 'fields' => $fields, 'slots' => $slots, 'pickup' => LocalPickupResolver::build_checkout_payload(), 'terms' => $terms_policy, 'orderNotes' => self::build_order_notes_payload(), 'legalLinks' => $legal_links, 'labels' => $labels, ]; } /** * @param array $runtime_context * @return array{execution:array,bridge:array} */ public static function build_runtime_meta( array $runtime_context = [] ): array { $execution = is_array( $runtime_context['execution'] ?? null ) ? $runtime_context['execution'] : CheckoutExecutionModeResolver::build_runtime_payload(); $bridge = is_array( $runtime_context['bridge'] ?? null ) ? $runtime_context['bridge'] : CheckoutPortalBridgePayloadBuilder::build(); return [ 'execution' => $execution, 'bridge' => $bridge, ]; } private static function resolve_logo_html(): string { $logo_candidate = get_theme_mod( 'custom_logo' ); if ( is_numeric( $logo_candidate ) && (int) $logo_candidate > 0 ) { $logo_html = wp_get_attachment_image( (int) $logo_candidate, 'full' ); if ( '' !== (string) $logo_html ) { return (string) $logo_html; } } return ''; } /** * @return array */ private static function build_customer_payload( string $checkout_url ): array { $is_logged_in = is_user_logged_in(); $current_user = $is_logged_in ? wp_get_current_user() : null; $display_name = ''; $email = ''; if ( $current_user instanceof \WP_User ) { $first_name = trim( (string) $current_user->first_name ); $last_name = trim( (string) $current_user->last_name ); $display_name = trim( $first_name . ' ' . $last_name ); if ( '' === $display_name ) { $display_name = (string) $current_user->display_name; } $email = (string) $current_user->user_email; } $account_url = function_exists( 'wc_get_page_permalink' ) ? wc_get_page_permalink( 'myaccount' ) : ''; if ( ! $account_url ) { $account_url = wp_login_url( $checkout_url ); } return [ 'identity' => [ 'isLoggedIn' => $is_logged_in, 'displayName' => $display_name, 'email' => $email, 'loginUrl' => esc_url_raw( $account_url ), ], 'login' => [ 'enabled' => ! $is_logged_in, 'endpoint' => esc_url_raw( rest_url( 'ips-cart/v1/checkout-portal/login' ) ), 'sessionEndpoint' => esc_url_raw( rest_url( 'ips-cart/v1/checkout-portal/session' ) ), 'nonce' => CheckoutPortalNonce::create_login(), 'lostPasswordUrl' => esc_url_raw( wp_lostpassword_url( $checkout_url ) ), 'redirectUrl' => esc_url_raw( $checkout_url ), 'allowGuestContinue' => CheckoutCustomerAccountPolicy::is_guest_checkout_enabled(), ], 'account' => CheckoutCustomerAccountPolicy::build_runtime_payload( $checkout_url ), ]; } private static function is_checkout_toggle_enabled( string $key, bool $default ): bool { $value = wooordercart_get_option( $key, 'checkout_settings_tabs', $default ? 'on' : 'off' ); return in_array( $value, [ true, 1, '1', 'on', 'yes' ], true ); } /** * @param array $allowed */ private static function checkout_select( string $key, array $allowed, string $default ): string { $value = wooordercart_get_option( $key, 'checkout_settings_tabs', $default ); $candidate = is_scalar( $value ) ? sanitize_key( (string) $value ) : ''; return in_array( $candidate, $allowed, true ) ? $candidate : $default; } /** * @return array */ private static function build_order_notes_payload(): array { $label = __( 'Order notes', 'ips-order-cart' ); $placeholder = ''; if ( function_exists( 'WC' ) && WC()->checkout() ) { $checkout_fields = WC()->checkout()->get_checkout_fields(); $notes_field = is_array( $checkout_fields['order']['order_comments'] ?? null ) ? $checkout_fields['order']['order_comments'] : []; if ( '' !== (string) ( $notes_field['label'] ?? '' ) ) { $label = (string) $notes_field['label']; } $placeholder = (string) ( $notes_field['placeholder'] ?? '' ); } return [ 'enabled' => true, 'label' => $label, 'placeholder' => $placeholder, ]; } }