File "CartCheckoutUtils.php"
Full Path: /home/amervokv/ecomlive.net/wp-content/plugins/woocommerce/src/Blocks/AIContent/CartCheckoutUtils.php
File size: 12.54 KB
MIME-type: text/x-php
Charset: utf-8
<?php // phpcs:ignore Generic.PHP.RequireStrictTypes.MissingDeclaration
namespace Automattic\WooCommerce\Blocks\Utils;
/**
* Class containing utility methods for dealing with the Cart and Checkout blocks.
*/
class CartCheckoutUtils {
/**
* Returns true if:
* - The cart page is being viewed.
* - The page contains a cart block, cart shortcode or classic shortcode block with the cart attribute.
*
* @return bool
*/
public static function is_cart_page() {
global $post;
$page_id = wc_get_page_id( 'cart' );
$is_cart_page = $page_id && is_page( $page_id );
if ( $is_cart_page ) {
return true;
}
// Check page contents for block/shortcode.
return is_a( $post, 'WP_Post' ) && ( wc_post_content_has_shortcode( 'woocommerce_cart' ) || self::has_block_variation( 'woocommerce/classic-shortcode', 'shortcode', 'cart', $post->post_content ) );
}
/**
* Returns true if:
* - The checkout page is being viewed.
* - The page contains a checkout block, checkout shortcode or classic shortcode block with the checkout attribute.
*
* @return bool
*/
public static function is_checkout_page() {
global $post;
$page_id = wc_get_page_id( 'checkout' );
$is_checkout_page = $page_id && is_page( $page_id );
if ( $is_checkout_page ) {
return true;
}
// Check page contents for block/shortcode.
return is_a( $post, 'WP_Post' ) && ( wc_post_content_has_shortcode( 'woocommerce_checkout' ) || self::has_block_variation( 'woocommerce/classic-shortcode', 'shortcode', 'checkout', $post->post_content ) );
}
/**
* Check if the post content contains a block with a specific attribute value.
*
* @param string $block_id The block ID to check for.
* @param string $attribute The attribute to check.
* @param string $value The value to check for.
* @return boolean
*/
public static function has_block_variation( $block_id, $attribute, $value, $post_content ) {
if ( ! $post_content ) {
return false;
}
if ( has_block( $block_id, $post_content ) ) {
$blocks = (array) parse_blocks( $post_content );
foreach ( $blocks as $block ) {
if ( isset( $block['attrs'][ $attribute ] ) && $value === $block['attrs'][ $attribute ] ) {
return true;
}
// Cart is default so it will be empty.
if ( 'woocommerce/classic-shortcode' === $block_id && 'shortcode' === $attribute && 'cart' === $value && ! isset( $block['attrs']['shortcode'] ) ) {
return true;
}
}
}
return false;
}
/**
* Checks if the default cart page is using the Cart block.
*
* @return bool true if the WC cart page is using the Cart block.
*/
public static function is_cart_block_default() {
if ( wc_current_theme_is_fse_theme() ) {
// Ignore the pages and check the templates.
$templates_from_db = BlockTemplateUtils::get_block_templates_from_db( array( 'cart' ), 'wp_template' );
foreach ( $templates_from_db as $template ) {
if ( has_block( 'woocommerce/cart', $template->content ) ) {
return true;
}
}
}
$cart_page_id = wc_get_page_id( 'cart' );
return $cart_page_id && has_block( 'woocommerce/cart', $cart_page_id );
}
/**
* Checks if the default checkout page is using the Checkout block.
*
* @return bool true if the WC checkout page is using the Checkout block.
*/
public static function is_checkout_block_default() {
if ( wc_current_theme_is_fse_theme() ) {
// Ignore the pages and check the templates.
$templates_from_db = BlockTemplateUtils::get_block_templates_from_db( array( 'checkout' ), 'wp_template' );
foreach ( $templates_from_db as $template ) {
if ( has_block( 'woocommerce/checkout', $template->content ) ) {
return true;
}
}
}
$checkout_page_id = wc_get_page_id( 'checkout' );
return $checkout_page_id && has_block( 'woocommerce/checkout', $checkout_page_id );
}
/**
* Migrate checkout block field visibility attributes to settings when using the checkout block.
*
* This migration routine is called if the options (woocommerce_checkout_phone_field, woocommerce_checkout_company_field,
* woocommerce_checkout_address_2_field) are not set. They are not set by default; they were orignally set by the
* customizer interface of the legacy shortcode based checkout.
*
* Once migration is initiated, the settings will be updated and will not trigger this routine again.
*
* Note: The block only stores non-default attributes. Not all attributes will be present.
*
* e.g. `{"showCompanyField":true,"requireCompanyField":true,"showApartmentField":false,"className":"wc-block-checkout"}`
*
* If the attributes are missing, we assume default values are needed.
*/
protected static function migrate_checkout_block_field_visibility_attributes() {
// Before migrating attributes, migrate the "default" options checkout block uses into the settings.
update_option( 'woocommerce_checkout_phone_field', 'optional' );
update_option( 'woocommerce_checkout_company_field', 'hidden' );
update_option( 'woocommerce_checkout_address_2_field', 'optional' );
// Parse the block from the checkout page.
$checkout_blocks = \WC_Blocks_Utils::get_blocks_from_page( 'woocommerce/checkout', 'checkout' );
if ( empty( $checkout_blocks ) || ! isset( $checkout_blocks[0]['attrs'] ) ) {
return;
}
// Combine actual attributes with default values.
$block_attributes = wp_parse_args(
$checkout_blocks[0]['attrs'],
array(
'showPhoneField' => true,
'requirePhoneField' => false,
'showCompanyField' => false,
'requireCompanyField' => false,
'showApartmentField' => true,
'requireApartmentField' => false,
)
);
if ( $block_attributes['showPhoneField'] ) {
update_option( 'woocommerce_checkout_phone_field', $block_attributes['requirePhoneField'] ? 'required' : 'optional' );
} else {
update_option( 'woocommerce_checkout_phone_field', 'hidden' );
}
if ( $block_attributes['showCompanyField'] ) {
update_option( 'woocommerce_checkout_company_field', $block_attributes['requireCompanyField'] ? 'required' : 'optional' );
} else {
update_option( 'woocommerce_checkout_company_field', 'hidden' );
}
if ( $block_attributes['showApartmentField'] ) {
update_option( 'woocommerce_checkout_address_2_field', $block_attributes['requireApartmentField'] ? 'required' : 'optional' );
} else {
update_option( 'woocommerce_checkout_address_2_field', 'hidden' );
}
}
/**
* Get the default visibility for the address_2 field.
*
* @return string
*/
public static function get_company_field_visibility() {
$option_value = get_option( 'woocommerce_checkout_company_field' );
if ( $option_value ) {
return $option_value;
}
if ( self::is_checkout_block_default() ) {
self::migrate_checkout_block_field_visibility_attributes();
return get_option( 'woocommerce_checkout_company_field', 'hidden' );
}
return 'optional';
}
/**
* Get the default visibility for the address_2 field.
*
* @return string
*/
public static function get_address_2_field_visibility() {
$option_value = get_option( 'woocommerce_checkout_address_2_field' );
if ( $option_value ) {
return $option_value;
}
if ( self::is_checkout_block_default() ) {
self::migrate_checkout_block_field_visibility_attributes();
return get_option( 'woocommerce_checkout_address_2_field', 'optional' );
}
return 'optional';
}
/**
* Get the default visibility for the address_2 field.
*
* @return string
*/
public static function get_phone_field_visibility() {
$option_value = get_option( 'woocommerce_checkout_phone_field' );
if ( $option_value ) {
return $option_value;
}
if ( self::is_checkout_block_default() ) {
self::migrate_checkout_block_field_visibility_attributes();
return get_option( 'woocommerce_checkout_phone_field', 'optional' );
}
return 'required';
}
/**
* Checks if the template overriding the page loads the page content or not.
* Templates by default load the page content, but if that block is deleted the content can get out of sync with the one presented in the page editor.
*
* @param string $block The block to check.
*
* @return bool true if the template has out of sync content.
*/
public static function is_overriden_by_custom_template_content( string $block ): bool {
$block = str_replace( 'woocommerce/', '', $block );
if ( wc_current_theme_is_fse_theme() ) {
$templates_from_db = BlockTemplateUtils::get_block_templates_from_db( array( 'page-' . $block ) );
foreach ( $templates_from_db as $template ) {
if ( ! has_block( 'woocommerce/page-content-wrapper', $template->content ) ) {
// Return true if the template does not load the page content via the woocommerce/page-content-wrapper block.
return true;
}
}
}
return false;
}
/**
* Gets country codes, names, states, and locale information.
*
* @return array
*/
public static function get_country_data() {
$billing_countries = WC()->countries->get_allowed_countries();
$shipping_countries = WC()->countries->get_shipping_countries();
$country_locales = wc()->countries->get_country_locale();
$country_states = wc()->countries->get_states();
$all_countries = self::deep_sort_with_accents( array_unique( array_merge( $billing_countries, $shipping_countries ) ) );
$country_data = [];
foreach ( array_keys( $all_countries ) as $country_code ) {
$country_data[ $country_code ] = [
'allowBilling' => isset( $billing_countries[ $country_code ] ),
'allowShipping' => isset( $shipping_countries[ $country_code ] ),
'states' => $country_states[ $country_code ] ?? [],
'locale' => $country_locales[ $country_code ] ?? [],
];
}
return $country_data;
}
/**
* Removes accents from an array of values, sorts by the values, then returns the original array values sorted.
*
* @param array $array Array of values to sort.
* @return array Sorted array.
*/
protected static function deep_sort_with_accents( $array ) {
if ( ! is_array( $array ) || empty( $array ) ) {
return $array;
}
$array_without_accents = array_map(
function ( $value ) {
return is_array( $value )
? self::deep_sort_with_accents( $value )
: remove_accents( wc_strtolower( html_entity_decode( $value ) ) );
},
$array
);
asort( $array_without_accents );
return array_replace( $array_without_accents, $array );
}
/**
* Retrieves formatted shipping zones from WooCommerce.
*
* @return array An array of formatted shipping zones.
*/
public static function get_shipping_zones() {
$shipping_zones = \WC_Shipping_Zones::get_zones();
$formatted_shipping_zones = array_reduce(
$shipping_zones,
function ( $acc, $zone ) {
$acc[] = [
'id' => $zone['id'],
'title' => $zone['zone_name'],
'description' => $zone['formatted_zone_location'],
];
return $acc;
},
[]
);
$formatted_shipping_zones[] = [
'id' => 0,
'title' => __( 'International', 'woocommerce' ),
'description' => __( 'Locations outside all other zones', 'woocommerce' ),
];
return $formatted_shipping_zones;
}
/**
* Recursively search the checkout block to find the express checkout block and
* get the button style attributes
*
* @param array $blocks Blocks to search.
* @param string $cart_or_checkout The block type to check.
*/
public static function find_express_checkout_attributes( $blocks, $cart_or_checkout ) {
$express_block_name = 'woocommerce/' . $cart_or_checkout . '-express-payment-block';
foreach ( $blocks as $block ) {
if ( ! empty( $block['blockName'] ) && $express_block_name === $block['blockName'] && ! empty( $block['attrs'] ) ) {
return $block['attrs'];
}
if ( ! empty( $block['innerBlocks'] ) ) {
$answer = self::find_express_checkout_attributes( $block['innerBlocks'], $cart_or_checkout );
if ( $answer ) {
return $answer;
}
}
}
}
/**
* Given an array of blocks, find the express payment block and update its attributes.
*
* @param array $blocks Blocks to search.
* @param string $cart_or_checkout The block type to check.
* @param array $updated_attrs The new attributes to set.
*/
public static function update_blocks_with_new_attrs( &$blocks, $cart_or_checkout, $updated_attrs ) {
$express_block_name = 'woocommerce/' . $cart_or_checkout . '-express-payment-block';
foreach ( $blocks as $key => &$block ) {
if ( ! empty( $block['blockName'] ) && $express_block_name === $block['blockName'] ) {
$blocks[ $key ]['attrs'] = $updated_attrs;
}
if ( ! empty( $block['innerBlocks'] ) ) {
self::update_blocks_with_new_attrs( $block['innerBlocks'], $cart_or_checkout, $updated_attrs );
}
}
}
}