$endpoint, 'namespace' => self::STORE_NAMESPACE, 'data_callback' => array( $this, 'data' ), 'schema_callback' => array( $this, 'schema' ), 'schema_type' => ARRAY_A, ) ); } /** * Response data. */ public function data(): array { $empty = array( 'extras' => array(), 'selections' => array(), 'goals' => array(), 'errors' => array(), 'display' => 'excl', ); $cart = function_exists( 'WC' ) ? WC()->cart : null; if ( ! $cart instanceof \WC_Cart ) { return $empty; } $context = $this->contexts->from_cart( $cart, 'checkout_block' ); $extras = $this->service->get_visible_extras( $context ); $context = $context->with_offered( $extras ); $selections = $this->service->get_selections_for( $extras ); $decimals = wc_get_price_decimals(); $display = $this->tax->display_including_tax( $context ) ? 'incl' : 'excl'; $items = array(); $errors = array(); foreach ( $extras as $extra_id => $extra ) { $type = $this->types->get( $extra->type ); if ( ! $type ) { continue; } $prices = array(); foreach ( $this->service->price_previews( $extra, $context ) as $key => $result ) { $prices[ '' === $key ? 'base' : $key ] = Money::to_minor( $result->display_amount ); } $items[] = array( 'id' => $extra->id, 'type' => $extra->type, 'label' => $extra->label, 'description' => $extra->description, 'required' => $extra->required, 'price' => array( 'amount' => $prices['base'] ?? '0', 'currency_minor_unit' => $decimals, 'display' => $display, ), 'prices' => (object) $prices, 'config' => $type->to_client( $extra, $context ), 'rule_dependencies' => $this->service->rule_dependencies( $extra ), ); $valid = $this->service->validate_extra( $extra, $selections[ $extra_id ] ?? null, $context ); if ( $valid instanceof \WP_Error ) { $errors[ $extra_id ] = $valid->get_error_message(); } } $values = array(); foreach ( $selections as $extra_id => $selection ) { $values[ $extra_id ] = $selection->value; } $goals = array(); foreach ( $this->goals->evaluate_all( $context ) as $goal ) { $goals[] = array( 'id' => (string) $goal['id'], 'threshold' => Money::to_minor( (string) $goal['threshold'] ), 'current' => Money::to_minor( (string) $goal['current'] ), 'remaining' => Money::to_minor( (string) $goal['remaining'] ), 'reached' => (bool) $goal['reached'], 'message' => (string) $goal['message'], ); } $data = array( 'extras' => $items, 'selections' => (object) $values, 'goals' => $goals, 'errors' => (object) $errors, 'display' => $display, ); /** * Filters the data added to the Store API cart response. * * @since 1.0.0 * * @param array $data Data. * @param \Extrova\Core\Context $context Context. */ return (array) apply_filters( 'extrova_cart_extension_data', $data, $context ); } /** * Response schema. */ public function schema(): array { return array( 'extras' => array( 'description' => __( 'Checkout extras visible for this cart.', 'extrova' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'items' => array( 'type' => 'object' ), ), 'selections' => array( 'description' => __( 'Values chosen by the customer, keyed by extra id.', 'extrova' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'goals' => array( 'description' => __( 'Progress goals such as free shipping.', 'extrova' ), 'type' => 'array', 'context' => array( 'view', 'edit' ), 'readonly' => true, 'items' => array( 'type' => 'object' ), ), 'errors' => array( 'description' => __( 'Validation messages keyed by extra id.', 'extrova' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'display' => array( 'description' => __( 'Whether prices include tax (incl) or not (excl).', 'extrova' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ); } }