summaryrefslogtreecommitdiffstats
path: root/includes/class-cepis-woo-assets.php
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-26 16:41:48 -0300
committerMurilo Ijanc <[email protected]>2026-07-26 16:47:14 -0300
commit535dbda6b48171f8115b455e54790de94d97d42a (patch)
tree5c0410011e61a883bdf063ee612875a637fb1d22 /includes/class-cepis-woo-assets.php
downloadwoocommerce-0.1.0.tar.gz
Initial importv0.1.0
Diffstat (limited to 'includes/class-cepis-woo-assets.php')
-rw-r--r--includes/class-cepis-woo-assets.php183
1 files changed, 183 insertions, 0 deletions
diff --git a/includes/class-cepis-woo-assets.php b/includes/class-cepis-woo-assets.php
new file mode 100644
index 0000000..def6fe2
--- /dev/null
+++ b/includes/class-cepis-woo-assets.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * What gets loaded on the checkout page, and with what configuration.
+ *
+ * @package CepisWooCommerce
+ */
+
+declare(strict_types=1);
+
+defined( 'ABSPATH' ) || exit;
+
+/**
+ * Detects which of WooCommerce's two checkouts is on screen and loads the
+ * matching integration.
+ *
+ * They are not variations of one another. The classic checkout is a server
+ * rendered form, so the widget can own the fields directly. The Cart/Checkout
+ * Blocks are React, the fields are controlled inputs, and writing to them from
+ * outside is at best ignored on the next render — so there the plugin never
+ * touches the DOM and drives the `wc/store/cart` data store instead.
+ */
+final class Cepis_Woo_Assets {
+
+ /**
+ * Script handle for the vendored widget.
+ */
+ private const WIDGET = 'cepis-autofill';
+
+ /**
+ * Hook the enqueue.
+ */
+ public static function init(): void {
+ add_action( 'wp_enqueue_scripts', array( self::class, 'enqueue' ) );
+ }
+
+ /**
+ * Load the widget plus whichever integration this checkout needs.
+ */
+ public static function enqueue(): void {
+ $checkout = self::checkout_type();
+
+ if ( '' === $checkout || ! Cepis_Woo_Options::enabled() ) {
+ return;
+ }
+
+ wp_register_script(
+ self::WIDGET,
+ CEPIS_WOO_URL . 'assets/js/cepis-autofill.min.js',
+ array(),
+ CEPIS_WOO_VERSION,
+ true
+ );
+
+ $handle = 'cepis-woocommerce-' . $checkout;
+ $dependencies = 'blocks' === $checkout
+ ? array( self::WIDGET, 'wp-data', 'wc-blocks-data-store' )
+ : array( self::WIDGET, 'jquery' );
+
+ wp_enqueue_script(
+ $handle,
+ CEPIS_WOO_URL . 'assets/js/cepis-woocommerce-' . $checkout . '.js',
+ $dependencies,
+ CEPIS_WOO_VERSION,
+ true
+ );
+
+ wp_add_inline_script(
+ $handle,
+ 'window.cepisWooCommerce = ' . wp_json_encode( self::config( $checkout ), JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
+ 'before'
+ );
+ }
+
+ /**
+ * Which checkout is being rendered.
+ *
+ * @return string `blocks`, `classic`, or an empty string when this is not a
+ * checkout the plugin should touch.
+ */
+ private static function checkout_type(): string {
+ if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
+ return '';
+ }
+
+ if ( function_exists( 'is_order_received_page' ) && is_order_received_page() ) {
+ return '';
+ }
+
+ $post = get_post();
+
+ return ( $post instanceof WP_Post && has_block( 'woocommerce/checkout', $post ) ) ? 'blocks' : 'classic';
+ }
+
+ /**
+ * Everything the browser needs, in one object.
+ *
+ * @param string $checkout Either `blocks` or `classic`.
+ *
+ * @return array<string, mixed>
+ */
+ private static function config( string $checkout ): array {
+ return array(
+ 'baseUrl' => 'proxy' === Cepis_Woo_Options::mode()
+ ? Cepis_Woo_Rest::base_url()
+ : Cepis_Woo_Options::base_url(),
+ 'overwrite' => Cepis_Woo_Options::overwrite(),
+ 'focusNumero' => Cepis_Woo_Options::focus_number(),
+ 'debounceMs' => 250,
+ 'timeoutMs' => 8000,
+ 'messages' => Cepis_Woo_Messages::all(),
+ 'fields' => 'blocks' === $checkout ? self::blocks_fields() : self::classic_fields(),
+ );
+ }
+
+ /**
+ * CSS selectors for the classic checkout, per address section.
+ *
+ * `billing_number` and `billing_neighborhood` are not WooCommerce fields —
+ * they come from the "Brazilian Market on WooCommerce" plugin, which is the
+ * de-facto way a Brazilian store gets a house-number and a neighbourhood
+ * box. A selector that matches nothing is skipped, so listing them costs
+ * nothing on a store that does not have them.
+ *
+ * There is deliberately no fallback onto `address_2` for the neighbourhood:
+ * in WooCommerce that field means "apartment, suite, unit", and putting a
+ * neighbourhood there produces a wrong address on the shipping label.
+ *
+ * @return array<string, array<string, string>>
+ */
+ private static function classic_fields(): array {
+ $fields = array();
+
+ foreach ( array( 'billing', 'shipping' ) as $section ) {
+ $fields[ $section ] = array(
+ 'cep' => '#' . $section . '_postcode',
+ 'logradouro' => '#' . $section . '_address_1',
+ 'bairro' => '#' . $section . '_neighborhood',
+ 'localidade' => '#' . $section . '_city',
+ 'uf' => '#' . $section . '_state',
+ 'numero' => '#' . $section . '_number',
+ );
+ }
+
+ /**
+ * Filters the field selectors used on the classic checkout.
+ *
+ * Keys are the API's own field names; values are CSS selectors. A theme
+ * or one-page-checkout plugin that renames the fields hooks in here.
+ *
+ * @param array<string, array<string, string>> $fields Selectors per address section.
+ */
+ return (array) apply_filters( 'cepis_woocommerce_classic_fields', $fields );
+ }
+
+ /**
+ * Store API address keys for the Cart/Checkout Blocks.
+ *
+ * The block checkout has no house-number and no neighbourhood field, and no
+ * plugin currently adds one: "Brazilian Market on WooCommerce" only extends
+ * the classic form. A store that registers its own with
+ * `woocommerce_register_additional_checkout_field()` can map it here, using
+ * the namespaced key the Store API exposes it under.
+ *
+ * @return array<string, string>
+ */
+ private static function blocks_fields(): array {
+ $fields = array(
+ 'logradouro' => 'address_1',
+ 'localidade' => 'city',
+ 'uf' => 'state',
+ );
+
+ /**
+ * Filters the Store API address keys written on the block checkout.
+ *
+ * Keys are the API's own field names; values are keys of the address
+ * object in the `wc/store/cart` data store.
+ *
+ * @param array<string, string> $fields Address keys per API field.
+ */
+ return (array) apply_filters( 'cepis_woocommerce_blocks_fields', $fields );
+ }
+}