Add Local Pickup event and Cart/Checkout page views events (https://github.com/woocommerce/woocommerce-blocks/pull/11225)
Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>
This commit is contained in:
parent
70e727e1af
commit
8bf13a7f4f
|
@ -0,0 +1,2 @@
|
|||
export const namespace = 'jetpack-woocommerce-analytics';
|
||||
export const actionPrefix = 'experimental__woocommerce_blocks';
|
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Cart, isObject, objectHasProp } from '@woocommerce/types';
|
||||
import { select } from '@wordpress/data';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_KEY as CART_STORE_KEY } from '../../../data/cart/constants';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
_wca: {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
push: ( properties: Record< string, unknown > ) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface StorePageDetails {
|
||||
id: number;
|
||||
title: string;
|
||||
permalink: string;
|
||||
}
|
||||
|
||||
interface StorePages {
|
||||
checkout: StorePageDetails;
|
||||
cart: StorePageDetails;
|
||||
myaccount: StorePageDetails;
|
||||
privacy: StorePageDetails;
|
||||
shop: StorePageDetails;
|
||||
terms: StorePageDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the _wca object is valid and has a push property that is a function.
|
||||
*
|
||||
* @param wca {unknown} Object that might be a Jetpack WooCommerce Analytics object.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
const isValidWCA = (
|
||||
wca: unknown
|
||||
): wca is { push: ( properties: Record< string, unknown > ) => void } => {
|
||||
if ( ! isObject( wca ) || ! objectHasProp( wca, 'push' ) ) {
|
||||
return false;
|
||||
}
|
||||
return typeof wca.push === 'function';
|
||||
};
|
||||
|
||||
const registerActions = (): void => {
|
||||
if ( ! isValidWCA( window._wca ) ) {
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return;
|
||||
}
|
||||
|
||||
// We will register actions here in a later PR.
|
||||
};
|
||||
|
||||
document.addEventListener( 'DOMContentLoaded', () => {
|
||||
registerActions();
|
||||
} );
|
||||
|
||||
export const cleanUrl = ( link: string ) => {
|
||||
const url = link.split( '?' )[ 0 ];
|
||||
if ( url.charAt( url.length - 1 ) !== '/' ) {
|
||||
return url + '/';
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const maybeTrackCheckoutPageView = ( cart: Cart ) => {
|
||||
const storePages = getSetting< StorePages >( 'storePages', {} );
|
||||
if ( ! objectHasProp( storePages, 'checkout' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
cleanUrl( storePages?.checkout?.permalink ) !==
|
||||
cleanUrl( window.location.href )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isValidWCA( window._wca ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const checkoutData = getSetting< Record< string, unknown > >(
|
||||
'wc-blocks-jetpack-woocommerce-analytics_cart_checkout_info',
|
||||
{}
|
||||
);
|
||||
|
||||
window._wca.push( {
|
||||
_en: 'woocommerceanalytics_checkout_view',
|
||||
products_count: cart.items.length,
|
||||
order_value: cart.totals.total_price,
|
||||
products: JSON.stringify(
|
||||
cart.items.map( ( item ) => {
|
||||
return {
|
||||
pp: item.totals.line_total,
|
||||
pq: item.quantity,
|
||||
pi: item.id,
|
||||
pn: item.name,
|
||||
};
|
||||
} )
|
||||
),
|
||||
...checkoutData,
|
||||
} );
|
||||
};
|
||||
|
||||
const maybeTrackCartPageView = ( cart: Cart ) => {
|
||||
const storePages = getSetting< StorePages >( 'storePages', {} );
|
||||
if ( ! objectHasProp( storePages, 'cart' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
cleanUrl( storePages?.cart?.permalink ) !==
|
||||
cleanUrl( window.location.href )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isValidWCA( window._wca ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const checkoutData = getSetting< Record< string, unknown > >(
|
||||
'wc-blocks-jetpack-woocommerce-analytics_cart_checkout_info',
|
||||
{}
|
||||
);
|
||||
|
||||
window._wca.push( {
|
||||
_en: 'woocommerceanalytics_cart_view',
|
||||
products_count: cart.items.length,
|
||||
order_value: cart.totals.total_price,
|
||||
products: JSON.stringify(
|
||||
cart.items.map( ( item ) => {
|
||||
return {
|
||||
pp: item.totals.line_total,
|
||||
pq: item.quantity,
|
||||
pi: item.id,
|
||||
pn: item.name,
|
||||
pt: item.type,
|
||||
};
|
||||
} )
|
||||
),
|
||||
...checkoutData,
|
||||
} );
|
||||
};
|
||||
|
||||
const maybeTrackOrderReceivedPageView = () => {
|
||||
const orderReceivedProps = getSetting(
|
||||
'wc-blocks-jetpack-woocommerce-analytics_order_received_properties',
|
||||
false
|
||||
);
|
||||
|
||||
if ( ! orderReceivedProps || ! isValidWCA( window._wca ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
window._wca.push( {
|
||||
_en: 'woocommerceanalytics_order_confirmation_view',
|
||||
...orderReceivedProps,
|
||||
} );
|
||||
};
|
||||
|
||||
document.addEventListener( 'DOMContentLoaded', () => {
|
||||
const store = select( CART_STORE_KEY );
|
||||
|
||||
// If the store doesn't load, we aren't on a cart/checkout block page, so maybe it's order received page.
|
||||
if ( ! store ) {
|
||||
maybeTrackOrderReceivedPageView();
|
||||
return;
|
||||
}
|
||||
|
||||
const hasCartLoaded = store.hasFinishedResolution( 'getCartTotals' );
|
||||
if ( hasCartLoaded ) {
|
||||
maybeTrackCartPageView( store.getCartData() );
|
||||
maybeTrackCheckoutPageView( store.getCartData() );
|
||||
}
|
||||
} );
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { cleanUrl } from '../index';
|
||||
|
||||
describe( 'WooCommerce Analytics', () => {
|
||||
describe( 'cleanUrl', () => {
|
||||
it( 'returns a clean URL with a trailing slash', () => {
|
||||
expect( cleanUrl( 'https://test.com?test=1' ) ).toEqual(
|
||||
'https://test.com/'
|
||||
);
|
||||
expect( cleanUrl( '' ) ).toEqual( '/' );
|
||||
expect( cleanUrl( 'https://test.com/' ) ).toEqual(
|
||||
'https://test.com/'
|
||||
);
|
||||
expect( cleanUrl( 'https://test.com' ) ).toEqual(
|
||||
'https://test.com/'
|
||||
);
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -39,6 +39,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
key: '1',
|
||||
id: 1,
|
||||
type: 'simple',
|
||||
quantity: 2,
|
||||
catalog_visibility: 'visible',
|
||||
name: __( 'Beanie', 'woo-gutenberg-products-block' ),
|
||||
|
@ -120,6 +121,7 @@ export const previewCart: CartResponse = {
|
|||
{
|
||||
key: '2',
|
||||
id: 2,
|
||||
type: 'simple',
|
||||
quantity: 1,
|
||||
catalog_visibility: 'visible',
|
||||
name: __( 'Cap', 'woo-gutenberg-products-block' ),
|
||||
|
|
|
@ -123,6 +123,7 @@ export type CatalogVisibility = 'catalog' | 'hidden' | 'search' | 'visible';
|
|||
export interface CartItem {
|
||||
key: string;
|
||||
id: number;
|
||||
type: string;
|
||||
quantity: number;
|
||||
catalog_visibility: CatalogVisibility;
|
||||
quantity_limits: {
|
||||
|
|
|
@ -227,6 +227,8 @@ const entries = {
|
|||
'./assets/js/extensions/google-analytics/index.ts',
|
||||
'wc-shipping-method-pickup-location':
|
||||
'./assets/js/extensions/shipping-methods/pickup-location/index.js',
|
||||
'wc-blocks-jetpack-woocommerce-analytics':
|
||||
'./assets/js/extensions/jetpack/woocommerce-analytics/index.ts',
|
||||
},
|
||||
editor: {
|
||||
'wc-blocks-classic-template-revert-button':
|
||||
|
|
|
@ -8,6 +8,7 @@ use Automattic\WooCommerce\Blocks\BlockPatterns;
|
|||
use Automattic\WooCommerce\Blocks\BlockTemplatesController;
|
||||
use Automattic\WooCommerce\Blocks\BlockTypesController;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\CreateAccount;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\JetpackWooCommerceAnalytics;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\Notices;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\DraftOrders;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\FeatureGating;
|
||||
|
@ -131,6 +132,7 @@ class Bootstrap {
|
|||
$this->container->get( CreateAccount::class )->init();
|
||||
$this->container->get( ShippingController::class )->init();
|
||||
$this->container->get( TasksController::class )->init();
|
||||
$this->container->get( JetpackWooCommerceAnalytics::class )->init();
|
||||
|
||||
// Load assets in admin and on the frontend.
|
||||
if ( ! $is_rest ) {
|
||||
|
@ -364,6 +366,15 @@ class Bootstrap {
|
|||
return new GoogleAnalytics( $asset_api );
|
||||
}
|
||||
);
|
||||
$this->container->register(
|
||||
JetpackWooCommerceAnalytics::class,
|
||||
function( Container $container ) {
|
||||
$asset_api = $container->get( AssetApi::class );
|
||||
$asset_data_registry = $container->get( AssetDataRegistry::class );
|
||||
$block_templates_controller = $container->get( BlockTemplatesController::class );
|
||||
return new JetpackWooCommerceAnalytics( $asset_api, $asset_data_registry, $block_templates_controller );
|
||||
}
|
||||
);
|
||||
$this->container->register(
|
||||
Notices::class,
|
||||
function( Container $container ) {
|
||||
|
|
|
@ -0,0 +1,390 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\Domain\Services;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
|
||||
use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
|
||||
use Automattic\WooCommerce\Blocks\BlockTemplatesController;
|
||||
use Automattic\WooCommerce\Blocks\Package;
|
||||
use WC_Tracks;
|
||||
|
||||
/**
|
||||
* Service class to integrate Blocks with the Jetpack WooCommerce Analytics extension,
|
||||
*/
|
||||
class JetpackWooCommerceAnalytics {
|
||||
/**
|
||||
* Instance of the asset API.
|
||||
*
|
||||
* @var AssetApi
|
||||
*/
|
||||
protected $asset_api;
|
||||
|
||||
/**
|
||||
* Instance of the asset data registry.
|
||||
*
|
||||
* @var AssetDataRegistry
|
||||
*/
|
||||
protected $asset_data_registry;
|
||||
|
||||
/**
|
||||
* Instance of the block templates controller.
|
||||
*
|
||||
* @var BlockTemplatesController
|
||||
*/
|
||||
protected $block_templates_controller;
|
||||
|
||||
/**
|
||||
* Whether the required Jetpack WooCommerce Analytics classes are available.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_compatible;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param AssetApi $asset_api Instance of the asset API.
|
||||
* @param AssetDataRegistry $asset_data_registry Instance of the asset data registry.
|
||||
* @param BlockTemplatesController $block_templates_controller Instance of the block templates controller.
|
||||
*/
|
||||
public function __construct( AssetApi $asset_api, AssetDataRegistry $asset_data_registry, BlockTemplatesController $block_templates_controller ) {
|
||||
$this->asset_api = $asset_api;
|
||||
$this->asset_data_registry = $asset_data_registry;
|
||||
$this->block_templates_controller = $block_templates_controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook into WP.
|
||||
*/
|
||||
public function init() {
|
||||
add_action( 'init', array( $this, 'check_compatibility' ) );
|
||||
add_action( 'rest_pre_serve_request', array( $this, 'track_local_pickup' ), 10, 4 );
|
||||
|
||||
$is_rest = wc()->is_rest_api_request();
|
||||
if ( ! $is_rest ) {
|
||||
add_action( 'init', array( $this, 'init_if_compatible' ), 20 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets product categories or varation attributes as a formatted concatenated string
|
||||
*
|
||||
* @param object $product WC_Product.
|
||||
* @return string
|
||||
*/
|
||||
public function get_product_categories_concatenated( $product ) {
|
||||
|
||||
if ( ! $product instanceof WC_Product ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$variation_data = $product->is_type( 'variation' ) ? wc_get_product_variation_attributes( $product->get_id() ) : '';
|
||||
if ( is_array( $variation_data ) && ! empty( $variation_data ) ) {
|
||||
$line = wc_get_formatted_variation( $variation_data, true );
|
||||
} else {
|
||||
$out = array();
|
||||
$categories = get_the_terms( $product->get_id(), 'product_cat' );
|
||||
if ( $categories ) {
|
||||
foreach ( $categories as $category ) {
|
||||
$out[] = $category->name;
|
||||
}
|
||||
}
|
||||
$line = implode( '/', $out );
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather relevant product information. Taken from Jetpack WooCommerce Analytics Module.
|
||||
*
|
||||
* @param \WC_Product $product product.
|
||||
* @return array
|
||||
*/
|
||||
public function get_product_details( $product ) {
|
||||
return array(
|
||||
'id' => $product->get_id(),
|
||||
'name' => $product->get_title(),
|
||||
'category' => $this->get_product_categories_concatenated( $product ),
|
||||
'price' => $product->get_price(),
|
||||
'type' => $product->get_type(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the order received page view event properties to the asset data registry. The front end will consume these
|
||||
* later.
|
||||
*
|
||||
* @param int $order_id The order ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function output_order_received_page_view_properties( $order_id ) {
|
||||
$order = wc_get_order( $order_id );
|
||||
$product_data = wp_json_encode(
|
||||
array_map(
|
||||
function( $item ) {
|
||||
$product = wc_get_product( $item->get_product_id() );
|
||||
$product_details = $this->get_product_details( $product );
|
||||
return array(
|
||||
'pi' => $product_details['id'],
|
||||
'pq' => $item->get_quantity(),
|
||||
'pt' => $product_details['type'],
|
||||
'pn' => $product_details['name'],
|
||||
'pc' => $product_details['category'],
|
||||
'pp' => $product_details['price'],
|
||||
);
|
||||
},
|
||||
$order->get_items()
|
||||
)
|
||||
);
|
||||
|
||||
$properties = $this->get_cart_checkout_info();
|
||||
$properties['products'] = $product_data;
|
||||
$this->asset_data_registry->add( 'wc-blocks-jetpack-woocommerce-analytics_order_received_properties', $properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check compatibility with Jetpack WooCommerce Analytics.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function check_compatibility() {
|
||||
// Require Jetpack WooCommerce Analytics to be available.
|
||||
$this->is_compatible = class_exists( 'Jetpack_WooCommerce_Analytics_Universal', false ) &&
|
||||
class_exists( 'Jetpack_WooCommerce_Analytics', false ) &&
|
||||
\Jetpack_WooCommerce_Analytics::should_track_store();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize if compatible.
|
||||
*/
|
||||
public function init_if_compatible() {
|
||||
if ( ! $this->is_compatible ) {
|
||||
return;
|
||||
}
|
||||
$this->register_assets();
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'register_script_data' ) );
|
||||
add_action( 'woocommerce_thankyou', array( $this, 'output_order_received_page_view_properties' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register scripts.
|
||||
*/
|
||||
public function register_assets() {
|
||||
if ( ! $this->is_compatible ) {
|
||||
return;
|
||||
}
|
||||
$asset_file = include Package::get_path() . 'build/wc-blocks-jetpack-woocommerce-analytics.asset.php';
|
||||
if ( is_array( $asset_file['dependencies'] ) ) {
|
||||
$this->asset_api->register_script( 'wc-blocks-jetpack-woocommerce-analytics', 'build/wc-blocks-jetpack-woocommerce-analytics.js', array_merge( array( 'wc-blocks' ), $asset_file['dependencies'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the Google Tag Manager script if prerequisites are met.
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
// Additional check here before finally enqueueing the scripts. Done late here because checking these earlier fails.
|
||||
if ( ! is_cart() && ! is_checkout() ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_script( 'wc-blocks-jetpack-woocommerce-analytics' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the Google Tag Manager script if prerequisites are met.
|
||||
*/
|
||||
public function register_script_data() {
|
||||
$this->asset_data_registry->add( 'wc-blocks-jetpack-woocommerce-analytics_cart_checkout_info', $this->get_cart_checkout_info() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_user_id() {
|
||||
if ( is_user_logged_in() ) {
|
||||
$blogid = \Jetpack::get_option( 'id' );
|
||||
$userid = get_current_user_id();
|
||||
return $blogid . ':' . $userid;
|
||||
}
|
||||
return 'null';
|
||||
}
|
||||
|
||||
/**
|
||||
* Default event properties which should be included with all events.
|
||||
*
|
||||
* @return array Array of standard event props.
|
||||
*/
|
||||
public function get_common_properties() {
|
||||
if ( ! class_exists( 'Jetpack' ) || ! is_callable( array( 'Jetpack', 'get_option' ) ) ) {
|
||||
return array();
|
||||
}
|
||||
return array(
|
||||
'blog_id' => \Jetpack::get_option( 'id' ),
|
||||
'ui' => $this->get_user_id(),
|
||||
'url' => home_url(),
|
||||
'woo_version' => WC()->version,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about the cart & checkout pages, in particular whether the store is using shortcodes or Gutenberg blocks.
|
||||
* This info is cached in a transient.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_cart_checkout_info() {
|
||||
$transient_name = 'woocommerce_blocks_jetpack_woocommerce_analytics_cart_checkout_info_cache';
|
||||
|
||||
$info = get_transient( $transient_name );
|
||||
|
||||
// Return cached data early to prevent additional processing, the transient lasts for 1 day.
|
||||
if ( false !== $info ) {
|
||||
return $info;
|
||||
}
|
||||
|
||||
$cart_template = null;
|
||||
$checkout_template = null;
|
||||
$cart_template_id = null;
|
||||
$checkout_template_id = null;
|
||||
$templates = $this->block_templates_controller->get_block_templates( array( 'cart', 'checkout' ) );
|
||||
$guest_checkout = ucfirst( get_option( 'woocommerce_enable_guest_checkout', 'No' ) );
|
||||
$create_account = ucfirst( get_option( 'woocommerce_enable_signup_and_login_from_checkout', 'No' ) );
|
||||
|
||||
foreach ( $templates as $template ) {
|
||||
if ( 'cart' === $template->slug ) {
|
||||
$cart_template_id = ( $template->id );
|
||||
continue;
|
||||
}
|
||||
if ( 'checkout' === $template->slug ) {
|
||||
$checkout_template_id = ( $template->id );
|
||||
}
|
||||
}
|
||||
|
||||
// Get the template and its contents from the IDs we found above.
|
||||
if ( function_exists( 'get_block_template' ) ) {
|
||||
$cart_template = get_block_template( $cart_template_id );
|
||||
$checkout_template = get_block_template( $checkout_template_id );
|
||||
}
|
||||
|
||||
if ( function_exists( 'gutenberg_get_block_template' ) ) {
|
||||
$cart_template = get_block_template( $cart_template_id );
|
||||
$checkout_template = get_block_template( $checkout_template_id );
|
||||
}
|
||||
|
||||
// Update the info transient with data we got from the templates, if the site isn't using WC Blocks we
|
||||
// won't be doing this so no concern about overwriting.
|
||||
// Sites that load this code will be loading it on a page using the relevant block, but we still need to check
|
||||
// the other page to see if it's using the block or shortcode.
|
||||
$info = array(
|
||||
'cart_page_contains_cart_block' => str_contains( $cart_template->content, '<!-- wp:woocommerce/cart' ),
|
||||
'cart_page_contains_cart_shortcode' => str_contains( $cart_template->content, '[woocommerce_cart]' ),
|
||||
'checkout_page_contains_checkout_block' => str_contains( $checkout_template->content, '<!-- wp:woocommerce/checkout' ),
|
||||
'checkout_page_contains_checkout_shortcode' => str_contains( $checkout_template->content, '[woocommerce_checkout]' ),
|
||||
'additional_blocks_on_cart_page' => $this->get_additional_blocks(
|
||||
$cart_template->content,
|
||||
array( 'woocommerce/cart' )
|
||||
),
|
||||
'additional_blocks_on_checkout_page' => $this->get_additional_blocks(
|
||||
$checkout_template->content,
|
||||
array( 'woocommerce/checkout' )
|
||||
),
|
||||
'device' => wp_is_mobile() ? 'mobile' : 'desktop',
|
||||
'guest_checkout' => 'Yes' === $guest_checkout ? 'Yes' : 'No',
|
||||
'create_account' => 'Yes' === $create_account ? 'Yes' : 'No',
|
||||
'store_currency' => get_woocommerce_currency(),
|
||||
);
|
||||
set_transient( $transient_name, $info, DAY_IN_SECONDS );
|
||||
return array_merge( $this->get_common_properties(), $info );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional blocks used in a post or template.
|
||||
*
|
||||
* @param string $content The post content.
|
||||
* @param array $exclude The blocks to exclude.
|
||||
*
|
||||
* @return array The additional blocks.
|
||||
*/
|
||||
private function get_additional_blocks( $content, $exclude = array() ) {
|
||||
$parsed_blocks = parse_blocks( $content );
|
||||
return $this->get_nested_blocks( $parsed_blocks, $exclude );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nested blocks from a block array.
|
||||
*
|
||||
* @param array $blocks The blocks array to find nested blocks inside.
|
||||
* @param string[] $exclude Blocks to exclude, won't find nested blocks within any of the supplied blocks.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_nested_blocks( $blocks, $exclude = array() ) {
|
||||
if ( ! is_array( $blocks ) ) {
|
||||
return array();
|
||||
}
|
||||
$additional_blocks = array();
|
||||
foreach ( $blocks as $block ) {
|
||||
if ( ! isset( $block['blockName'] ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( in_array( $block['blockName'], $exclude, true ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( is_array( $block['innerBlocks'] ) ) {
|
||||
$additional_blocks = array_merge( $additional_blocks, self::get_nested_blocks( $block['innerBlocks'], $exclude ) );
|
||||
}
|
||||
$additional_blocks[] = $block['blockName'];
|
||||
}
|
||||
return $additional_blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track local pickup settings changes via Store API
|
||||
*
|
||||
* @param bool $served Whether the request has already been served.
|
||||
* @param \WP_REST_Response $result The response object.
|
||||
* @param \WP_REST_Request $request The request object.
|
||||
* @return bool
|
||||
*/
|
||||
public function track_local_pickup( $served, $result, $request ) {
|
||||
if ( '/wp/v2/settings' !== $request->get_route() ) {
|
||||
return $served;
|
||||
}
|
||||
// Param name here comes from the show_in_rest['name'] value when registering the setting.
|
||||
if ( ! $request->get_param( 'pickup_location_settings' ) && ! $request->get_param( 'pickup_locations' ) ) {
|
||||
return $served;
|
||||
}
|
||||
|
||||
if ( ! $this->is_compatible ) {
|
||||
return $served;
|
||||
}
|
||||
|
||||
$event_name = 'local_pickup_save_changes';
|
||||
|
||||
$settings = $request->get_param( 'pickup_location_settings' );
|
||||
$locations = $request->get_param( 'pickup_locations' );
|
||||
|
||||
$data = array(
|
||||
'local_pickup_enabled' => 'yes' === $settings['enabled'] ? true : false,
|
||||
'title' => __( 'Local Pickup', 'woo-gutenberg-products-block' ) === $settings['title'],
|
||||
'price' => '' === $settings['cost'] ? true : false,
|
||||
'cost' => '' === $settings['cost'] ? 0 : $settings['cost'],
|
||||
'taxes' => $settings['tax_status'],
|
||||
'total_pickup_locations' => count( $locations ),
|
||||
'pickup_locations_enabled' => count(
|
||||
array_filter(
|
||||
$locations,
|
||||
function( $location ) {
|
||||
return $location['enabled']; }
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
WC_Tracks::record_event( $event_name, $data );
|
||||
|
||||
return $served;
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ class CartItemSchema extends ItemSchema {
|
|||
return [
|
||||
'key' => $cart_item['key'],
|
||||
'id' => $product->get_id(),
|
||||
'type' => $product->get_type(),
|
||||
'quantity' => wc_stock_amount( $cart_item['quantity'] ),
|
||||
'quantity_limits' => (object) ( new QuantityLimits() )->get_cart_item_quantity_limits( $cart_item ),
|
||||
'name' => $this->prepare_html_response( $product->get_title() ),
|
||||
|
|
|
@ -19,6 +19,12 @@ abstract class ItemSchema extends ProductSchema {
|
|||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'type' => [
|
||||
'description' => __( 'The item type.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'id' => [
|
||||
'description' => __( 'The item product or variation ID.', 'woo-gutenberg-products-block' ),
|
||||
'type' => 'integer',
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
## Table of Contents <!-- omit in toc -->
|
||||
|
||||
- [List Cart Items](#list-cart-items)
|
||||
- [Single Cart Item](#single-cart-item)
|
||||
- [Add Cart Item](#add-cart-item)
|
||||
- [Edit Single Cart Item](#edit-single-cart-item)
|
||||
- [Delete Single Cart Item](#delete-single-cart-item)
|
||||
- [Delete All Cart Items](#delete-all-cart-items)
|
||||
- [List Cart Items](#list-cart-items)
|
||||
- [Single Cart Item](#single-cart-item)
|
||||
- [Add Cart Item](#add-cart-item)
|
||||
- [Edit Single Cart Item](#edit-single-cart-item)
|
||||
- [Delete Single Cart Item](#delete-single-cart-item)
|
||||
- [Delete All Cart Items](#delete-all-cart-items)
|
||||
|
||||
## List Cart Items
|
||||
|
||||
|
@ -29,6 +29,7 @@ curl "https://example-store.com/wp-json/wc/store/v1/cart/items"
|
|||
"key": "c74d97b01eae257e44aa9d5bade97baf",
|
||||
"id": 16,
|
||||
"quantity": 1,
|
||||
"type": "simple",
|
||||
"quantity_limits": {
|
||||
"minimum": 1,
|
||||
"maximum": 1,
|
||||
|
@ -108,6 +109,7 @@ curl "https://example-store.com/wp-json/wc/store/v1/cart/items"
|
|||
"key": "e03e407f41901484125496b5ec69a76f",
|
||||
"id": 29,
|
||||
"quantity": 1,
|
||||
"type": "variation",
|
||||
"quantity_limits": {
|
||||
"minimum": 1,
|
||||
"maximum": 9999,
|
||||
|
|
|
@ -82,6 +82,7 @@ class CartItems extends ControllerTestCase {
|
|||
0 => array(
|
||||
'key' => $this->keys[0],
|
||||
'id' => $this->products[0]->get_id(),
|
||||
'type' => $this->products[0]->get_type(),
|
||||
'name' => $this->products[0]->get_name(),
|
||||
'sku' => $this->products[0]->get_sku(),
|
||||
'permalink' => $this->products[0]->get_permalink(),
|
||||
|
@ -113,6 +114,7 @@ class CartItems extends ControllerTestCase {
|
|||
array(
|
||||
'key' => $this->keys[0],
|
||||
'id' => $this->products[0]->get_id(),
|
||||
'type' => $this->products[0]->get_type(),
|
||||
'name' => $this->products[0]->get_name(),
|
||||
'sku' => $this->products[0]->get_sku(),
|
||||
'permalink' => $this->products[0]->get_permalink(),
|
||||
|
@ -256,6 +258,7 @@ class CartItems extends ControllerTestCase {
|
|||
|
||||
$this->assertArrayHasKey( 'key', $data );
|
||||
$this->assertArrayHasKey( 'id', $data );
|
||||
$this->assertArrayHasKey( 'type', $data );
|
||||
$this->assertArrayHasKey( 'quantity', $data );
|
||||
$this->assertArrayHasKey( 'name', $data );
|
||||
$this->assertArrayHasKey( 'sku', $data );
|
||||
|
|
Loading…
Reference in New Issue