@@ -5,90 +5,90 @@ |
||
| 5 | 5 | * PaymentResult class. |
| 6 | 6 | */ |
| 7 | 7 | class PaymentResult { |
| 8 | - /** |
|
| 9 | - * List of valid payment statuses. |
|
| 10 | - * |
|
| 11 | - * @var array |
|
| 12 | - */ |
|
| 13 | - protected $valid_statuses = [ 'success', 'failure', 'pending', 'error' ]; |
|
| 8 | + /** |
|
| 9 | + * List of valid payment statuses. |
|
| 10 | + * |
|
| 11 | + * @var array |
|
| 12 | + */ |
|
| 13 | + protected $valid_statuses = [ 'success', 'failure', 'pending', 'error' ]; |
|
| 14 | 14 | |
| 15 | - /** |
|
| 16 | - * Current payment status. |
|
| 17 | - * |
|
| 18 | - * @var string |
|
| 19 | - */ |
|
| 20 | - protected $status = ''; |
|
| 15 | + /** |
|
| 16 | + * Current payment status. |
|
| 17 | + * |
|
| 18 | + * @var string |
|
| 19 | + */ |
|
| 20 | + protected $status = ''; |
|
| 21 | 21 | |
| 22 | - /** |
|
| 23 | - * Array of details about the payment. |
|
| 24 | - * |
|
| 25 | - * @var string |
|
| 26 | - */ |
|
| 27 | - protected $payment_details = []; |
|
| 22 | + /** |
|
| 23 | + * Array of details about the payment. |
|
| 24 | + * |
|
| 25 | + * @var string |
|
| 26 | + */ |
|
| 27 | + protected $payment_details = []; |
|
| 28 | 28 | |
| 29 | - /** |
|
| 30 | - * Redirect URL for checkout. |
|
| 31 | - * |
|
| 32 | - * @var string |
|
| 33 | - */ |
|
| 34 | - protected $redirect_url = ''; |
|
| 29 | + /** |
|
| 30 | + * Redirect URL for checkout. |
|
| 31 | + * |
|
| 32 | + * @var string |
|
| 33 | + */ |
|
| 34 | + protected $redirect_url = ''; |
|
| 35 | 35 | |
| 36 | - /** |
|
| 37 | - * Constructor. |
|
| 38 | - * |
|
| 39 | - * @param string $status Sets the payment status for the result. |
|
| 40 | - */ |
|
| 41 | - public function __construct( $status = '' ) { |
|
| 42 | - if ( $status ) { |
|
| 43 | - $this->set_status( $status ); |
|
| 44 | - } |
|
| 45 | - } |
|
| 36 | + /** |
|
| 37 | + * Constructor. |
|
| 38 | + * |
|
| 39 | + * @param string $status Sets the payment status for the result. |
|
| 40 | + */ |
|
| 41 | + public function __construct( $status = '' ) { |
|
| 42 | + if ( $status ) { |
|
| 43 | + $this->set_status( $status ); |
|
| 44 | + } |
|
| 45 | + } |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * Magic getter for protected properties. |
|
| 49 | - * |
|
| 50 | - * @param string $name Property name. |
|
| 51 | - */ |
|
| 52 | - public function __get( $name ) { |
|
| 53 | - if ( in_array( $name, [ 'status', 'payment_details', 'redirect_url' ], true ) ) { |
|
| 54 | - return $this->$name; |
|
| 55 | - } |
|
| 56 | - return null; |
|
| 57 | - } |
|
| 47 | + /** |
|
| 48 | + * Magic getter for protected properties. |
|
| 49 | + * |
|
| 50 | + * @param string $name Property name. |
|
| 51 | + */ |
|
| 52 | + public function __get( $name ) { |
|
| 53 | + if ( in_array( $name, [ 'status', 'payment_details', 'redirect_url' ], true ) ) { |
|
| 54 | + return $this->$name; |
|
| 55 | + } |
|
| 56 | + return null; |
|
| 57 | + } |
|
| 58 | 58 | |
| 59 | - /** |
|
| 60 | - * Set payment status. |
|
| 61 | - * |
|
| 62 | - * @throws \Exception When an invalid status is provided. |
|
| 63 | - * |
|
| 64 | - * @param string $payment_status Status to set. |
|
| 65 | - */ |
|
| 66 | - public function set_status( $payment_status ) { |
|
| 67 | - if ( ! in_array( $payment_status, $this->valid_statuses, true ) ) { |
|
| 68 | - throw new \Exception( sprintf( 'Invalid payment status %s. Use one of %s', $payment_status, implode( ', ', $this->valid_statuses ) ) ); |
|
| 69 | - } |
|
| 70 | - $this->status = $payment_status; |
|
| 71 | - } |
|
| 59 | + /** |
|
| 60 | + * Set payment status. |
|
| 61 | + * |
|
| 62 | + * @throws \Exception When an invalid status is provided. |
|
| 63 | + * |
|
| 64 | + * @param string $payment_status Status to set. |
|
| 65 | + */ |
|
| 66 | + public function set_status( $payment_status ) { |
|
| 67 | + if ( ! in_array( $payment_status, $this->valid_statuses, true ) ) { |
|
| 68 | + throw new \Exception( sprintf( 'Invalid payment status %s. Use one of %s', $payment_status, implode( ', ', $this->valid_statuses ) ) ); |
|
| 69 | + } |
|
| 70 | + $this->status = $payment_status; |
|
| 71 | + } |
|
| 72 | 72 | |
| 73 | - /** |
|
| 74 | - * Set payment details. |
|
| 75 | - * |
|
| 76 | - * @param array $payment_details Array of key value pairs of data. |
|
| 77 | - */ |
|
| 78 | - public function set_payment_details( $payment_details = [] ) { |
|
| 79 | - $this->payment_details = []; |
|
| 73 | + /** |
|
| 74 | + * Set payment details. |
|
| 75 | + * |
|
| 76 | + * @param array $payment_details Array of key value pairs of data. |
|
| 77 | + */ |
|
| 78 | + public function set_payment_details( $payment_details = [] ) { |
|
| 79 | + $this->payment_details = []; |
|
| 80 | 80 | |
| 81 | - foreach ( $payment_details as $key => $value ) { |
|
| 82 | - $this->payment_details[ (string) $key ] = (string) $value; |
|
| 83 | - } |
|
| 84 | - } |
|
| 81 | + foreach ( $payment_details as $key => $value ) { |
|
| 82 | + $this->payment_details[ (string) $key ] = (string) $value; |
|
| 83 | + } |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | - /** |
|
| 87 | - * Set redirect URL. |
|
| 88 | - * |
|
| 89 | - * @param array $redirect_url URL to redirect the customer to after checkout. |
|
| 90 | - */ |
|
| 91 | - public function set_redirect_url( $redirect_url = [] ) { |
|
| 92 | - $this->redirect_url = esc_url_raw( $redirect_url ); |
|
| 93 | - } |
|
| 86 | + /** |
|
| 87 | + * Set redirect URL. |
|
| 88 | + * |
|
| 89 | + * @param array $redirect_url URL to redirect the customer to after checkout. |
|
| 90 | + */ |
|
| 91 | + public function set_redirect_url( $redirect_url = [] ) { |
|
| 92 | + $this->redirect_url = esc_url_raw( $redirect_url ); |
|
| 93 | + } |
|
| 94 | 94 | } |
@@ -10,7 +10,7 @@ discard block |
||
| 10 | 10 | * |
| 11 | 11 | * @var array |
| 12 | 12 | */ |
| 13 | - protected $valid_statuses = [ 'success', 'failure', 'pending', 'error' ]; |
|
| 13 | + protected $valid_statuses = ['success', 'failure', 'pending', 'error']; |
|
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | 16 | * Current payment status. |
@@ -38,9 +38,9 @@ discard block |
||
| 38 | 38 | * |
| 39 | 39 | * @param string $status Sets the payment status for the result. |
| 40 | 40 | */ |
| 41 | - public function __construct( $status = '' ) { |
|
| 42 | - if ( $status ) { |
|
| 43 | - $this->set_status( $status ); |
|
| 41 | + public function __construct($status = '') { |
|
| 42 | + if ($status) { |
|
| 43 | + $this->set_status($status); |
|
| 44 | 44 | } |
| 45 | 45 | } |
| 46 | 46 | |
@@ -49,8 +49,8 @@ discard block |
||
| 49 | 49 | * |
| 50 | 50 | * @param string $name Property name. |
| 51 | 51 | */ |
| 52 | - public function __get( $name ) { |
|
| 53 | - if ( in_array( $name, [ 'status', 'payment_details', 'redirect_url' ], true ) ) { |
|
| 52 | + public function __get($name) { |
|
| 53 | + if (in_array($name, ['status', 'payment_details', 'redirect_url'], true)) { |
|
| 54 | 54 | return $this->$name; |
| 55 | 55 | } |
| 56 | 56 | return null; |
@@ -63,9 +63,9 @@ discard block |
||
| 63 | 63 | * |
| 64 | 64 | * @param string $payment_status Status to set. |
| 65 | 65 | */ |
| 66 | - public function set_status( $payment_status ) { |
|
| 67 | - if ( ! in_array( $payment_status, $this->valid_statuses, true ) ) { |
|
| 68 | - throw new \Exception( sprintf( 'Invalid payment status %s. Use one of %s', $payment_status, implode( ', ', $this->valid_statuses ) ) ); |
|
| 66 | + public function set_status($payment_status) { |
|
| 67 | + if (!in_array($payment_status, $this->valid_statuses, true)) { |
|
| 68 | + throw new \Exception(sprintf('Invalid payment status %s. Use one of %s', $payment_status, implode(', ', $this->valid_statuses))); |
|
| 69 | 69 | } |
| 70 | 70 | $this->status = $payment_status; |
| 71 | 71 | } |
@@ -75,11 +75,11 @@ discard block |
||
| 75 | 75 | * |
| 76 | 76 | * @param array $payment_details Array of key value pairs of data. |
| 77 | 77 | */ |
| 78 | - public function set_payment_details( $payment_details = [] ) { |
|
| 78 | + public function set_payment_details($payment_details = []) { |
|
| 79 | 79 | $this->payment_details = []; |
| 80 | 80 | |
| 81 | - foreach ( $payment_details as $key => $value ) { |
|
| 82 | - $this->payment_details[ (string) $key ] = (string) $value; |
|
| 81 | + foreach ($payment_details as $key => $value) { |
|
| 82 | + $this->payment_details[(string) $key] = (string) $value; |
|
| 83 | 83 | } |
| 84 | 84 | } |
| 85 | 85 | |
@@ -88,7 +88,7 @@ discard block |
||
| 88 | 88 | * |
| 89 | 89 | * @param array $redirect_url URL to redirect the customer to after checkout. |
| 90 | 90 | */ |
| 91 | - public function set_redirect_url( $redirect_url = [] ) { |
|
| 92 | - $this->redirect_url = esc_url_raw( $redirect_url ); |
|
| 91 | + public function set_redirect_url($redirect_url = []) { |
|
| 92 | + $this->redirect_url = esc_url_raw($redirect_url); |
|
| 93 | 93 | } |
| 94 | 94 | } |
@@ -12,138 +12,138 @@ |
||
| 12 | 12 | */ |
| 13 | 13 | class InboxNotifications { |
| 14 | 14 | |
| 15 | - const SURFACE_CART_CHECKOUT_NOTE_NAME = 'surface_cart_checkout'; |
|
| 16 | - const SURFACE_CART_CHECKOUT_PROBABILITY_OPTION = 'wc_blocks_surface_cart_checkout_probability'; |
|
| 17 | - const PERCENT_USERS_TO_TARGET = 50; |
|
| 18 | - const INELIGIBLE_EXTENSIONS = [ |
|
| 19 | - 'automatewoo', |
|
| 20 | - 'mailchimp-for-woocommerce', |
|
| 21 | - 'mailpoet', |
|
| 22 | - 'klarna-payments-for-woocommerce', |
|
| 23 | - 'klarna-checkout-for-woocommerce', |
|
| 24 | - 'woocommerce-gutenberg-products-block', // Disallow the notification if the store is using the feature plugin already. |
|
| 25 | - 'woocommerce-all-products-for-subscriptions', |
|
| 26 | - 'woocommerce-bookings', |
|
| 27 | - 'woocommerce-box-office', |
|
| 28 | - 'woocommerce-cart-add-ons', |
|
| 29 | - 'woocommerce-checkout-add-ons', |
|
| 30 | - 'woocommerce-checkout-field-editor', |
|
| 31 | - 'woocommerce-conditional-shipping-and-payments', |
|
| 32 | - 'woocommerce-dynamic-pricing', |
|
| 33 | - 'woocommerce-eu-vat-number', |
|
| 34 | - 'woocommerce-follow-up-emails', |
|
| 35 | - 'woocommerce-gateway-amazon-payments-advanced', |
|
| 36 | - 'woocommerce-gateway-authorize-net-cim', |
|
| 37 | - 'woocommerce-google-analytics-pro', |
|
| 38 | - 'woocommerce-memberships', |
|
| 39 | - 'woocommerce-paypal-payments', |
|
| 40 | - 'woocommerce-pre-orders', |
|
| 41 | - 'woocommerce-product-bundles', |
|
| 42 | - 'woocommerce-shipping-fedex', |
|
| 43 | - 'woocommerce-smart-coupons', |
|
| 44 | - ]; |
|
| 45 | - const ELIGIBLE_COUNTRIES = [ |
|
| 46 | - 'GB', |
|
| 47 | - 'US', |
|
| 48 | - ]; |
|
| 49 | - |
|
| 50 | - |
|
| 51 | - /** |
|
| 52 | - * Deletes the note. |
|
| 53 | - */ |
|
| 54 | - public static function delete_surface_cart_checkout_blocks_notification() { |
|
| 55 | - Notes::delete_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 56 | - } |
|
| 57 | - |
|
| 58 | - /** |
|
| 59 | - * Creates a notification letting merchants know about the Cart and Checkout Blocks. |
|
| 60 | - */ |
|
| 61 | - public static function create_surface_cart_checkout_blocks_notification() { |
|
| 62 | - // If this is the feature plugin, then we don't need to do this. This should only show when Blocks is bundled |
|
| 63 | - // with WooCommerce Core. |
|
| 64 | - if ( Package::feature()->is_feature_plugin_build() ) { |
|
| 65 | - return; |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes' ) ) { |
|
| 69 | - return; |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - if ( ! class_exists( 'WC_Data_Store' ) ) { |
|
| 73 | - return; |
|
| 74 | - } |
|
| 75 | - |
|
| 76 | - if ( apply_filters( 'woocommerce_admin_disabled', false ) ) { |
|
| 77 | - return; |
|
| 78 | - } |
|
| 79 | - |
|
| 80 | - $data_store = \WC_Data_Store::load( 'admin-note' ); |
|
| 81 | - $note_ids = $data_store->get_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 82 | - // Calculate store's eligibility to be shown the notice, starting with whether they have any plugins we know to |
|
| 83 | - // be incompatible with Blocks. This check is done before checking if the note exists already because we want to |
|
| 84 | - // delete the note if the merchant activates an ineligible plugin. |
|
| 85 | - foreach ( self::INELIGIBLE_EXTENSIONS as $extension ) { |
|
| 86 | - if ( is_plugin_active( $extension . '/' . $extension . '.php' ) ) { |
|
| 87 | - |
|
| 88 | - // Delete the notification here, we shouldn't show it if it's not going to work with the merchant's site. |
|
| 89 | - self::delete_surface_cart_checkout_blocks_notification(); |
|
| 90 | - return; |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - foreach ( (array) $note_ids as $note_id ) { |
|
| 95 | - $note = Notes::get_note( $note_id ); |
|
| 96 | - |
|
| 97 | - // Return now because the note already exists. |
|
| 98 | - if ( $note->get_name() === self::SURFACE_CART_CHECKOUT_NOTE_NAME ) { |
|
| 99 | - return; |
|
| 100 | - } |
|
| 101 | - } |
|
| 102 | - |
|
| 103 | - // Next check the store is located in one of the eligible countries. |
|
| 104 | - $raw_country = get_option( 'woocommerce_default_country' ); |
|
| 105 | - $country = explode( ':', $raw_country )[0]; |
|
| 106 | - if ( ! in_array( $country, self::ELIGIBLE_COUNTRIES, true ) ) { |
|
| 107 | - return; |
|
| 108 | - } |
|
| 109 | - |
|
| 110 | - // Pick a random number between 1 and 100 and add this to the wp_options table. This can then be used to target |
|
| 111 | - // a percentage of users. We do this here so we target a truer percentage of eligible users than if we did it |
|
| 112 | - // before checking plugins/country. |
|
| 113 | - $existing_probability = get_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION ); |
|
| 114 | - if ( false === $existing_probability ) { |
|
| 115 | - $existing_probability = wp_rand( 0, 100 ); |
|
| 116 | - add_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION, $existing_probability ); |
|
| 117 | - } |
|
| 118 | - |
|
| 119 | - // Finally, check if the store's generated % chance is below the % of users we want to surface this to. |
|
| 120 | - if ( $existing_probability > self::PERCENT_USERS_TO_TARGET ) { |
|
| 121 | - return; |
|
| 122 | - } |
|
| 123 | - |
|
| 124 | - // At this point, the store meets all the criteria to be shown the notice! Woo! |
|
| 125 | - $note = new Note(); |
|
| 126 | - $note->set_title( |
|
| 127 | - __( |
|
| 128 | - 'Introducing the Cart and Checkout blocks!', |
|
| 129 | - 'woocommerce' |
|
| 130 | - ) |
|
| 131 | - ); |
|
| 132 | - $note->set_content( |
|
| 133 | - __( |
|
| 134 | - "Increase your store's revenue with the conversion optimized Cart & Checkout WooCommerce blocks available in the WooCommerce Blocks extension.", |
|
| 135 | - 'woocommerce' |
|
| 136 | - ) |
|
| 137 | - ); |
|
| 138 | - $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL ); |
|
| 139 | - $note->set_source( 'woo-gutenberg-products-block' ); |
|
| 140 | - $note->set_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 141 | - $note->add_action( |
|
| 142 | - 'learn_more', |
|
| 143 | - 'Learn More', |
|
| 144 | - 'https://woocommerce.com/checkout-blocks/' |
|
| 145 | - ); |
|
| 146 | - $note->save(); |
|
| 147 | - |
|
| 148 | - } |
|
| 15 | + const SURFACE_CART_CHECKOUT_NOTE_NAME = 'surface_cart_checkout'; |
|
| 16 | + const SURFACE_CART_CHECKOUT_PROBABILITY_OPTION = 'wc_blocks_surface_cart_checkout_probability'; |
|
| 17 | + const PERCENT_USERS_TO_TARGET = 50; |
|
| 18 | + const INELIGIBLE_EXTENSIONS = [ |
|
| 19 | + 'automatewoo', |
|
| 20 | + 'mailchimp-for-woocommerce', |
|
| 21 | + 'mailpoet', |
|
| 22 | + 'klarna-payments-for-woocommerce', |
|
| 23 | + 'klarna-checkout-for-woocommerce', |
|
| 24 | + 'woocommerce-gutenberg-products-block', // Disallow the notification if the store is using the feature plugin already. |
|
| 25 | + 'woocommerce-all-products-for-subscriptions', |
|
| 26 | + 'woocommerce-bookings', |
|
| 27 | + 'woocommerce-box-office', |
|
| 28 | + 'woocommerce-cart-add-ons', |
|
| 29 | + 'woocommerce-checkout-add-ons', |
|
| 30 | + 'woocommerce-checkout-field-editor', |
|
| 31 | + 'woocommerce-conditional-shipping-and-payments', |
|
| 32 | + 'woocommerce-dynamic-pricing', |
|
| 33 | + 'woocommerce-eu-vat-number', |
|
| 34 | + 'woocommerce-follow-up-emails', |
|
| 35 | + 'woocommerce-gateway-amazon-payments-advanced', |
|
| 36 | + 'woocommerce-gateway-authorize-net-cim', |
|
| 37 | + 'woocommerce-google-analytics-pro', |
|
| 38 | + 'woocommerce-memberships', |
|
| 39 | + 'woocommerce-paypal-payments', |
|
| 40 | + 'woocommerce-pre-orders', |
|
| 41 | + 'woocommerce-product-bundles', |
|
| 42 | + 'woocommerce-shipping-fedex', |
|
| 43 | + 'woocommerce-smart-coupons', |
|
| 44 | + ]; |
|
| 45 | + const ELIGIBLE_COUNTRIES = [ |
|
| 46 | + 'GB', |
|
| 47 | + 'US', |
|
| 48 | + ]; |
|
| 49 | + |
|
| 50 | + |
|
| 51 | + /** |
|
| 52 | + * Deletes the note. |
|
| 53 | + */ |
|
| 54 | + public static function delete_surface_cart_checkout_blocks_notification() { |
|
| 55 | + Notes::delete_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 56 | + } |
|
| 57 | + |
|
| 58 | + /** |
|
| 59 | + * Creates a notification letting merchants know about the Cart and Checkout Blocks. |
|
| 60 | + */ |
|
| 61 | + public static function create_surface_cart_checkout_blocks_notification() { |
|
| 62 | + // If this is the feature plugin, then we don't need to do this. This should only show when Blocks is bundled |
|
| 63 | + // with WooCommerce Core. |
|
| 64 | + if ( Package::feature()->is_feature_plugin_build() ) { |
|
| 65 | + return; |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes' ) ) { |
|
| 69 | + return; |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + if ( ! class_exists( 'WC_Data_Store' ) ) { |
|
| 73 | + return; |
|
| 74 | + } |
|
| 75 | + |
|
| 76 | + if ( apply_filters( 'woocommerce_admin_disabled', false ) ) { |
|
| 77 | + return; |
|
| 78 | + } |
|
| 79 | + |
|
| 80 | + $data_store = \WC_Data_Store::load( 'admin-note' ); |
|
| 81 | + $note_ids = $data_store->get_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 82 | + // Calculate store's eligibility to be shown the notice, starting with whether they have any plugins we know to |
|
| 83 | + // be incompatible with Blocks. This check is done before checking if the note exists already because we want to |
|
| 84 | + // delete the note if the merchant activates an ineligible plugin. |
|
| 85 | + foreach ( self::INELIGIBLE_EXTENSIONS as $extension ) { |
|
| 86 | + if ( is_plugin_active( $extension . '/' . $extension . '.php' ) ) { |
|
| 87 | + |
|
| 88 | + // Delete the notification here, we shouldn't show it if it's not going to work with the merchant's site. |
|
| 89 | + self::delete_surface_cart_checkout_blocks_notification(); |
|
| 90 | + return; |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + foreach ( (array) $note_ids as $note_id ) { |
|
| 95 | + $note = Notes::get_note( $note_id ); |
|
| 96 | + |
|
| 97 | + // Return now because the note already exists. |
|
| 98 | + if ( $note->get_name() === self::SURFACE_CART_CHECKOUT_NOTE_NAME ) { |
|
| 99 | + return; |
|
| 100 | + } |
|
| 101 | + } |
|
| 102 | + |
|
| 103 | + // Next check the store is located in one of the eligible countries. |
|
| 104 | + $raw_country = get_option( 'woocommerce_default_country' ); |
|
| 105 | + $country = explode( ':', $raw_country )[0]; |
|
| 106 | + if ( ! in_array( $country, self::ELIGIBLE_COUNTRIES, true ) ) { |
|
| 107 | + return; |
|
| 108 | + } |
|
| 109 | + |
|
| 110 | + // Pick a random number between 1 and 100 and add this to the wp_options table. This can then be used to target |
|
| 111 | + // a percentage of users. We do this here so we target a truer percentage of eligible users than if we did it |
|
| 112 | + // before checking plugins/country. |
|
| 113 | + $existing_probability = get_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION ); |
|
| 114 | + if ( false === $existing_probability ) { |
|
| 115 | + $existing_probability = wp_rand( 0, 100 ); |
|
| 116 | + add_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION, $existing_probability ); |
|
| 117 | + } |
|
| 118 | + |
|
| 119 | + // Finally, check if the store's generated % chance is below the % of users we want to surface this to. |
|
| 120 | + if ( $existing_probability > self::PERCENT_USERS_TO_TARGET ) { |
|
| 121 | + return; |
|
| 122 | + } |
|
| 123 | + |
|
| 124 | + // At this point, the store meets all the criteria to be shown the notice! Woo! |
|
| 125 | + $note = new Note(); |
|
| 126 | + $note->set_title( |
|
| 127 | + __( |
|
| 128 | + 'Introducing the Cart and Checkout blocks!', |
|
| 129 | + 'woocommerce' |
|
| 130 | + ) |
|
| 131 | + ); |
|
| 132 | + $note->set_content( |
|
| 133 | + __( |
|
| 134 | + "Increase your store's revenue with the conversion optimized Cart & Checkout WooCommerce blocks available in the WooCommerce Blocks extension.", |
|
| 135 | + 'woocommerce' |
|
| 136 | + ) |
|
| 137 | + ); |
|
| 138 | + $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL ); |
|
| 139 | + $note->set_source( 'woo-gutenberg-products-block' ); |
|
| 140 | + $note->set_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 141 | + $note->add_action( |
|
| 142 | + 'learn_more', |
|
| 143 | + 'Learn More', |
|
| 144 | + 'https://woocommerce.com/checkout-blocks/' |
|
| 145 | + ); |
|
| 146 | + $note->save(); |
|
| 147 | + |
|
| 148 | + } |
|
| 149 | 149 | } |
@@ -42,7 +42,7 @@ discard block |
||
| 42 | 42 | 'woocommerce-shipping-fedex', |
| 43 | 43 | 'woocommerce-smart-coupons', |
| 44 | 44 | ]; |
| 45 | - const ELIGIBLE_COUNTRIES = [ |
|
| 45 | + const ELIGIBLE_COUNTRIES = [ |
|
| 46 | 46 | 'GB', |
| 47 | 47 | 'US', |
| 48 | 48 | ]; |
@@ -52,7 +52,7 @@ discard block |
||
| 52 | 52 | * Deletes the note. |
| 53 | 53 | */ |
| 54 | 54 | public static function delete_surface_cart_checkout_blocks_notification() { |
| 55 | - Notes::delete_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 55 | + Notes::delete_notes_with_name(self::SURFACE_CART_CHECKOUT_NOTE_NAME); |
|
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | /** |
@@ -61,29 +61,29 @@ discard block |
||
| 61 | 61 | public static function create_surface_cart_checkout_blocks_notification() { |
| 62 | 62 | // If this is the feature plugin, then we don't need to do this. This should only show when Blocks is bundled |
| 63 | 63 | // with WooCommerce Core. |
| 64 | - if ( Package::feature()->is_feature_plugin_build() ) { |
|
| 64 | + if (Package::feature()->is_feature_plugin_build()) { |
|
| 65 | 65 | return; |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | - if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes' ) ) { |
|
| 68 | + if (!class_exists('Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes')) { |
|
| 69 | 69 | return; |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | - if ( ! class_exists( 'WC_Data_Store' ) ) { |
|
| 72 | + if (!class_exists('WC_Data_Store')) { |
|
| 73 | 73 | return; |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | - if ( apply_filters( 'woocommerce_admin_disabled', false ) ) { |
|
| 76 | + if (apply_filters('woocommerce_admin_disabled', false)) { |
|
| 77 | 77 | return; |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | - $data_store = \WC_Data_Store::load( 'admin-note' ); |
|
| 81 | - $note_ids = $data_store->get_notes_with_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 80 | + $data_store = \WC_Data_Store::load('admin-note'); |
|
| 81 | + $note_ids = $data_store->get_notes_with_name(self::SURFACE_CART_CHECKOUT_NOTE_NAME); |
|
| 82 | 82 | // Calculate store's eligibility to be shown the notice, starting with whether they have any plugins we know to |
| 83 | 83 | // be incompatible with Blocks. This check is done before checking if the note exists already because we want to |
| 84 | 84 | // delete the note if the merchant activates an ineligible plugin. |
| 85 | - foreach ( self::INELIGIBLE_EXTENSIONS as $extension ) { |
|
| 86 | - if ( is_plugin_active( $extension . '/' . $extension . '.php' ) ) { |
|
| 85 | + foreach (self::INELIGIBLE_EXTENSIONS as $extension) { |
|
| 86 | + if (is_plugin_active($extension . '/' . $extension . '.php')) { |
|
| 87 | 87 | |
| 88 | 88 | // Delete the notification here, we shouldn't show it if it's not going to work with the merchant's site. |
| 89 | 89 | self::delete_surface_cart_checkout_blocks_notification(); |
@@ -91,33 +91,33 @@ discard block |
||
| 91 | 91 | } |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | - foreach ( (array) $note_ids as $note_id ) { |
|
| 95 | - $note = Notes::get_note( $note_id ); |
|
| 94 | + foreach ((array) $note_ids as $note_id) { |
|
| 95 | + $note = Notes::get_note($note_id); |
|
| 96 | 96 | |
| 97 | 97 | // Return now because the note already exists. |
| 98 | - if ( $note->get_name() === self::SURFACE_CART_CHECKOUT_NOTE_NAME ) { |
|
| 98 | + if ($note->get_name() === self::SURFACE_CART_CHECKOUT_NOTE_NAME) { |
|
| 99 | 99 | return; |
| 100 | 100 | } |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | // Next check the store is located in one of the eligible countries. |
| 104 | - $raw_country = get_option( 'woocommerce_default_country' ); |
|
| 105 | - $country = explode( ':', $raw_country )[0]; |
|
| 106 | - if ( ! in_array( $country, self::ELIGIBLE_COUNTRIES, true ) ) { |
|
| 104 | + $raw_country = get_option('woocommerce_default_country'); |
|
| 105 | + $country = explode(':', $raw_country)[0]; |
|
| 106 | + if (!in_array($country, self::ELIGIBLE_COUNTRIES, true)) { |
|
| 107 | 107 | return; |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | // Pick a random number between 1 and 100 and add this to the wp_options table. This can then be used to target |
| 111 | 111 | // a percentage of users. We do this here so we target a truer percentage of eligible users than if we did it |
| 112 | 112 | // before checking plugins/country. |
| 113 | - $existing_probability = get_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION ); |
|
| 114 | - if ( false === $existing_probability ) { |
|
| 115 | - $existing_probability = wp_rand( 0, 100 ); |
|
| 116 | - add_option( self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION, $existing_probability ); |
|
| 113 | + $existing_probability = get_option(self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION); |
|
| 114 | + if (false === $existing_probability) { |
|
| 115 | + $existing_probability = wp_rand(0, 100); |
|
| 116 | + add_option(self::SURFACE_CART_CHECKOUT_PROBABILITY_OPTION, $existing_probability); |
|
| 117 | 117 | } |
| 118 | 118 | |
| 119 | 119 | // Finally, check if the store's generated % chance is below the % of users we want to surface this to. |
| 120 | - if ( $existing_probability > self::PERCENT_USERS_TO_TARGET ) { |
|
| 120 | + if ($existing_probability > self::PERCENT_USERS_TO_TARGET) { |
|
| 121 | 121 | return; |
| 122 | 122 | } |
| 123 | 123 | |
@@ -135,9 +135,9 @@ discard block |
||
| 135 | 135 | 'woocommerce' |
| 136 | 136 | ) |
| 137 | 137 | ); |
| 138 | - $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL ); |
|
| 139 | - $note->set_source( 'woo-gutenberg-products-block' ); |
|
| 140 | - $note->set_name( self::SURFACE_CART_CHECKOUT_NOTE_NAME ); |
|
| 138 | + $note->set_type(Note::E_WC_ADMIN_NOTE_INFORMATIONAL); |
|
| 139 | + $note->set_source('woo-gutenberg-products-block'); |
|
| 140 | + $note->set_name(self::SURFACE_CART_CHECKOUT_NOTE_NAME); |
|
| 141 | 141 | $note->add_action( |
| 142 | 142 | 'learn_more', |
| 143 | 143 | 'Learn More', |
@@ -12,426 +12,426 @@ |
||
| 12 | 12 | */ |
| 13 | 13 | abstract class AbstractBlock { |
| 14 | 14 | |
| 15 | - /** |
|
| 16 | - * Block namespace. |
|
| 17 | - * |
|
| 18 | - * @var string |
|
| 19 | - */ |
|
| 20 | - protected $namespace = 'woocommerce'; |
|
| 21 | - |
|
| 22 | - /** |
|
| 23 | - * Block name within this namespace. |
|
| 24 | - * |
|
| 25 | - * @var string |
|
| 26 | - */ |
|
| 27 | - protected $block_name = ''; |
|
| 28 | - |
|
| 29 | - /** |
|
| 30 | - * Tracks if assets have been enqueued. |
|
| 31 | - * |
|
| 32 | - * @var boolean |
|
| 33 | - */ |
|
| 34 | - protected $enqueued_assets = false; |
|
| 35 | - |
|
| 36 | - /** |
|
| 37 | - * Instance of the asset API. |
|
| 38 | - * |
|
| 39 | - * @var AssetApi |
|
| 40 | - */ |
|
| 41 | - protected $asset_api; |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * Instance of the asset data registry. |
|
| 45 | - * |
|
| 46 | - * @var AssetDataRegistry |
|
| 47 | - */ |
|
| 48 | - protected $asset_data_registry; |
|
| 49 | - |
|
| 50 | - /** |
|
| 51 | - * Instance of the integration registry. |
|
| 52 | - * |
|
| 53 | - * @var IntegrationRegistry |
|
| 54 | - */ |
|
| 55 | - protected $integration_registry; |
|
| 56 | - |
|
| 57 | - /** |
|
| 58 | - * Constructor. |
|
| 59 | - * |
|
| 60 | - * @param AssetApi $asset_api Instance of the asset API. |
|
| 61 | - * @param AssetDataRegistry $asset_data_registry Instance of the asset data registry. |
|
| 62 | - * @param IntegrationRegistry $integration_registry Instance of the integration registry. |
|
| 63 | - * @param string $block_name Optionally set block name during construct. |
|
| 64 | - */ |
|
| 65 | - public function __construct( AssetApi $asset_api, AssetDataRegistry $asset_data_registry, IntegrationRegistry $integration_registry, $block_name = '' ) { |
|
| 66 | - $this->asset_api = $asset_api; |
|
| 67 | - $this->asset_data_registry = $asset_data_registry; |
|
| 68 | - $this->integration_registry = $integration_registry; |
|
| 69 | - $this->block_name = $block_name ? $block_name : $this->block_name; |
|
| 70 | - $this->initialize(); |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * The default render_callback for all blocks. This will ensure assets are enqueued just in time, then render |
|
| 75 | - * the block (if applicable). |
|
| 76 | - * |
|
| 77 | - * @param array|WP_Block $attributes Block attributes, or an instance of a WP_Block. Defaults to an empty array. |
|
| 78 | - * @param string $content Block content. Default empty string. |
|
| 79 | - * @return string Rendered block type output. |
|
| 80 | - */ |
|
| 81 | - public function render_callback( $attributes = [], $content = '' ) { |
|
| 82 | - $render_callback_attributes = $this->parse_render_callback_attributes( $attributes ); |
|
| 83 | - if ( ! is_admin() && ! WC()->is_rest_api_request() ) { |
|
| 84 | - $this->enqueue_assets( $render_callback_attributes ); |
|
| 85 | - } |
|
| 86 | - return $this->render( $render_callback_attributes, $content ); |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - /** |
|
| 90 | - * Enqueue assets used for rendering the block in editor context. |
|
| 91 | - * |
|
| 92 | - * This is needed if a block is not yet within the post content--`render` and `enqueue_assets` may not have ran. |
|
| 93 | - */ |
|
| 94 | - public function enqueue_editor_assets() { |
|
| 95 | - if ( $this->enqueued_assets ) { |
|
| 96 | - return; |
|
| 97 | - } |
|
| 98 | - $this->enqueue_data(); |
|
| 99 | - } |
|
| 100 | - |
|
| 101 | - /** |
|
| 102 | - * Initialize this block type. |
|
| 103 | - * |
|
| 104 | - * - Hook into WP lifecycle. |
|
| 105 | - * - Register the block with WordPress. |
|
| 106 | - */ |
|
| 107 | - protected function initialize() { |
|
| 108 | - if ( empty( $this->block_name ) ) { |
|
| 109 | - _doing_it_wrong( __METHOD__, esc_html__( 'Block name is required.', 'woocommerce' ), '4.5.0' ); |
|
| 110 | - return false; |
|
| 111 | - } |
|
| 112 | - $this->integration_registry->initialize( $this->block_name . '_block' ); |
|
| 113 | - $this->register_block_type_assets(); |
|
| 114 | - $this->register_block_type(); |
|
| 115 | - add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] ); |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - /** |
|
| 119 | - * Register script and style assets for the block type before it is registered. |
|
| 120 | - * |
|
| 121 | - * This registers the scripts; it does not enqueue them. |
|
| 122 | - */ |
|
| 123 | - protected function register_block_type_assets() { |
|
| 124 | - if ( null !== $this->get_block_type_editor_script() ) { |
|
| 125 | - $data = $this->asset_api->get_script_data( $this->get_block_type_editor_script( 'path' ) ); |
|
| 126 | - $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 127 | - |
|
| 128 | - $this->asset_api->register_script( |
|
| 129 | - $this->get_block_type_editor_script( 'handle' ), |
|
| 130 | - $this->get_block_type_editor_script( 'path' ), |
|
| 131 | - array_merge( |
|
| 132 | - $this->get_block_type_editor_script( 'dependencies' ), |
|
| 133 | - $this->integration_registry->get_all_registered_editor_script_handles() |
|
| 134 | - ), |
|
| 135 | - $has_i18n |
|
| 136 | - ); |
|
| 137 | - } |
|
| 138 | - if ( null !== $this->get_block_type_script() ) { |
|
| 139 | - $data = $this->asset_api->get_script_data( $this->get_block_type_script( 'path' ) ); |
|
| 140 | - $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 141 | - |
|
| 142 | - $this->asset_api->register_script( |
|
| 143 | - $this->get_block_type_script( 'handle' ), |
|
| 144 | - $this->get_block_type_script( 'path' ), |
|
| 145 | - array_merge( |
|
| 146 | - $this->get_block_type_script( 'dependencies' ), |
|
| 147 | - $this->integration_registry->get_all_registered_script_handles() |
|
| 148 | - ), |
|
| 149 | - $has_i18n |
|
| 150 | - ); |
|
| 151 | - } |
|
| 152 | - } |
|
| 153 | - |
|
| 154 | - /** |
|
| 155 | - * Injects Chunk Translations into the page so translations work for lazy loaded components. |
|
| 156 | - * |
|
| 157 | - * The chunk names are defined when creating lazy loaded components using webpackChunkName. |
|
| 158 | - * |
|
| 159 | - * @param string[] $chunks Array of chunk names. |
|
| 160 | - */ |
|
| 161 | - protected function register_chunk_translations( $chunks ) { |
|
| 162 | - foreach ( $chunks as $chunk ) { |
|
| 163 | - $handle = 'wc-blocks-' . $chunk . '-chunk'; |
|
| 164 | - $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), [], true ); |
|
| 165 | - wp_add_inline_script( |
|
| 166 | - $this->get_block_type_script( 'handle' ), |
|
| 167 | - wp_scripts()->print_translations( $handle, false ), |
|
| 168 | - 'before' |
|
| 169 | - ); |
|
| 170 | - wp_deregister_script( $handle ); |
|
| 171 | - } |
|
| 172 | - } |
|
| 173 | - |
|
| 174 | - /** |
|
| 175 | - * Generate an array of chunks paths for loading translation. |
|
| 176 | - * |
|
| 177 | - * @param string $chunks_folder The folder to iterate over. |
|
| 178 | - * @return string[] $chunks list of chunks to load. |
|
| 179 | - */ |
|
| 180 | - protected function get_chunks_paths( $chunks_folder ) { |
|
| 181 | - $build_path = \Automattic\WooCommerce\Blocks\Package::get_path() . 'build/'; |
|
| 182 | - $blocks = []; |
|
| 183 | - if ( ! is_dir( $build_path . $chunks_folder ) ) { |
|
| 184 | - return []; |
|
| 185 | - } |
|
| 186 | - foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $build_path . $chunks_folder ) ) as $block_name ) { |
|
| 187 | - $blocks[] = str_replace( $build_path, '', $block_name ); |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - $chunks = preg_filter( '/.js/', '', $blocks ); |
|
| 191 | - return $chunks; |
|
| 192 | - } |
|
| 193 | - /** |
|
| 194 | - * Registers the block type with WordPress. |
|
| 195 | - * |
|
| 196 | - * @return string[] Chunks paths. |
|
| 197 | - */ |
|
| 198 | - protected function register_block_type() { |
|
| 199 | - $block_settings = [ |
|
| 200 | - 'render_callback' => $this->get_block_type_render_callback(), |
|
| 201 | - 'editor_script' => $this->get_block_type_editor_script( 'handle' ), |
|
| 202 | - 'editor_style' => $this->get_block_type_editor_style(), |
|
| 203 | - 'style' => $this->get_block_type_style(), |
|
| 204 | - ]; |
|
| 205 | - |
|
| 206 | - if ( isset( $this->api_version ) && '2' === $this->api_version ) { |
|
| 207 | - $block_settings['api_version'] = 2; |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - $metadata_path = $this->asset_api->get_block_metadata_path( $this->block_name ); |
|
| 211 | - // Prefer to register with metadata if the path is set in the block's class. |
|
| 212 | - if ( ! empty( $metadata_path ) ) { |
|
| 213 | - register_block_type_from_metadata( |
|
| 214 | - $metadata_path, |
|
| 215 | - $block_settings |
|
| 216 | - ); |
|
| 217 | - return; |
|
| 218 | - } |
|
| 219 | - |
|
| 220 | - /* |
|
| 15 | + /** |
|
| 16 | + * Block namespace. |
|
| 17 | + * |
|
| 18 | + * @var string |
|
| 19 | + */ |
|
| 20 | + protected $namespace = 'woocommerce'; |
|
| 21 | + |
|
| 22 | + /** |
|
| 23 | + * Block name within this namespace. |
|
| 24 | + * |
|
| 25 | + * @var string |
|
| 26 | + */ |
|
| 27 | + protected $block_name = ''; |
|
| 28 | + |
|
| 29 | + /** |
|
| 30 | + * Tracks if assets have been enqueued. |
|
| 31 | + * |
|
| 32 | + * @var boolean |
|
| 33 | + */ |
|
| 34 | + protected $enqueued_assets = false; |
|
| 35 | + |
|
| 36 | + /** |
|
| 37 | + * Instance of the asset API. |
|
| 38 | + * |
|
| 39 | + * @var AssetApi |
|
| 40 | + */ |
|
| 41 | + protected $asset_api; |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * Instance of the asset data registry. |
|
| 45 | + * |
|
| 46 | + * @var AssetDataRegistry |
|
| 47 | + */ |
|
| 48 | + protected $asset_data_registry; |
|
| 49 | + |
|
| 50 | + /** |
|
| 51 | + * Instance of the integration registry. |
|
| 52 | + * |
|
| 53 | + * @var IntegrationRegistry |
|
| 54 | + */ |
|
| 55 | + protected $integration_registry; |
|
| 56 | + |
|
| 57 | + /** |
|
| 58 | + * Constructor. |
|
| 59 | + * |
|
| 60 | + * @param AssetApi $asset_api Instance of the asset API. |
|
| 61 | + * @param AssetDataRegistry $asset_data_registry Instance of the asset data registry. |
|
| 62 | + * @param IntegrationRegistry $integration_registry Instance of the integration registry. |
|
| 63 | + * @param string $block_name Optionally set block name during construct. |
|
| 64 | + */ |
|
| 65 | + public function __construct( AssetApi $asset_api, AssetDataRegistry $asset_data_registry, IntegrationRegistry $integration_registry, $block_name = '' ) { |
|
| 66 | + $this->asset_api = $asset_api; |
|
| 67 | + $this->asset_data_registry = $asset_data_registry; |
|
| 68 | + $this->integration_registry = $integration_registry; |
|
| 69 | + $this->block_name = $block_name ? $block_name : $this->block_name; |
|
| 70 | + $this->initialize(); |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * The default render_callback for all blocks. This will ensure assets are enqueued just in time, then render |
|
| 75 | + * the block (if applicable). |
|
| 76 | + * |
|
| 77 | + * @param array|WP_Block $attributes Block attributes, or an instance of a WP_Block. Defaults to an empty array. |
|
| 78 | + * @param string $content Block content. Default empty string. |
|
| 79 | + * @return string Rendered block type output. |
|
| 80 | + */ |
|
| 81 | + public function render_callback( $attributes = [], $content = '' ) { |
|
| 82 | + $render_callback_attributes = $this->parse_render_callback_attributes( $attributes ); |
|
| 83 | + if ( ! is_admin() && ! WC()->is_rest_api_request() ) { |
|
| 84 | + $this->enqueue_assets( $render_callback_attributes ); |
|
| 85 | + } |
|
| 86 | + return $this->render( $render_callback_attributes, $content ); |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + /** |
|
| 90 | + * Enqueue assets used for rendering the block in editor context. |
|
| 91 | + * |
|
| 92 | + * This is needed if a block is not yet within the post content--`render` and `enqueue_assets` may not have ran. |
|
| 93 | + */ |
|
| 94 | + public function enqueue_editor_assets() { |
|
| 95 | + if ( $this->enqueued_assets ) { |
|
| 96 | + return; |
|
| 97 | + } |
|
| 98 | + $this->enqueue_data(); |
|
| 99 | + } |
|
| 100 | + |
|
| 101 | + /** |
|
| 102 | + * Initialize this block type. |
|
| 103 | + * |
|
| 104 | + * - Hook into WP lifecycle. |
|
| 105 | + * - Register the block with WordPress. |
|
| 106 | + */ |
|
| 107 | + protected function initialize() { |
|
| 108 | + if ( empty( $this->block_name ) ) { |
|
| 109 | + _doing_it_wrong( __METHOD__, esc_html__( 'Block name is required.', 'woocommerce' ), '4.5.0' ); |
|
| 110 | + return false; |
|
| 111 | + } |
|
| 112 | + $this->integration_registry->initialize( $this->block_name . '_block' ); |
|
| 113 | + $this->register_block_type_assets(); |
|
| 114 | + $this->register_block_type(); |
|
| 115 | + add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] ); |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + /** |
|
| 119 | + * Register script and style assets for the block type before it is registered. |
|
| 120 | + * |
|
| 121 | + * This registers the scripts; it does not enqueue them. |
|
| 122 | + */ |
|
| 123 | + protected function register_block_type_assets() { |
|
| 124 | + if ( null !== $this->get_block_type_editor_script() ) { |
|
| 125 | + $data = $this->asset_api->get_script_data( $this->get_block_type_editor_script( 'path' ) ); |
|
| 126 | + $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 127 | + |
|
| 128 | + $this->asset_api->register_script( |
|
| 129 | + $this->get_block_type_editor_script( 'handle' ), |
|
| 130 | + $this->get_block_type_editor_script( 'path' ), |
|
| 131 | + array_merge( |
|
| 132 | + $this->get_block_type_editor_script( 'dependencies' ), |
|
| 133 | + $this->integration_registry->get_all_registered_editor_script_handles() |
|
| 134 | + ), |
|
| 135 | + $has_i18n |
|
| 136 | + ); |
|
| 137 | + } |
|
| 138 | + if ( null !== $this->get_block_type_script() ) { |
|
| 139 | + $data = $this->asset_api->get_script_data( $this->get_block_type_script( 'path' ) ); |
|
| 140 | + $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 141 | + |
|
| 142 | + $this->asset_api->register_script( |
|
| 143 | + $this->get_block_type_script( 'handle' ), |
|
| 144 | + $this->get_block_type_script( 'path' ), |
|
| 145 | + array_merge( |
|
| 146 | + $this->get_block_type_script( 'dependencies' ), |
|
| 147 | + $this->integration_registry->get_all_registered_script_handles() |
|
| 148 | + ), |
|
| 149 | + $has_i18n |
|
| 150 | + ); |
|
| 151 | + } |
|
| 152 | + } |
|
| 153 | + |
|
| 154 | + /** |
|
| 155 | + * Injects Chunk Translations into the page so translations work for lazy loaded components. |
|
| 156 | + * |
|
| 157 | + * The chunk names are defined when creating lazy loaded components using webpackChunkName. |
|
| 158 | + * |
|
| 159 | + * @param string[] $chunks Array of chunk names. |
|
| 160 | + */ |
|
| 161 | + protected function register_chunk_translations( $chunks ) { |
|
| 162 | + foreach ( $chunks as $chunk ) { |
|
| 163 | + $handle = 'wc-blocks-' . $chunk . '-chunk'; |
|
| 164 | + $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), [], true ); |
|
| 165 | + wp_add_inline_script( |
|
| 166 | + $this->get_block_type_script( 'handle' ), |
|
| 167 | + wp_scripts()->print_translations( $handle, false ), |
|
| 168 | + 'before' |
|
| 169 | + ); |
|
| 170 | + wp_deregister_script( $handle ); |
|
| 171 | + } |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + /** |
|
| 175 | + * Generate an array of chunks paths for loading translation. |
|
| 176 | + * |
|
| 177 | + * @param string $chunks_folder The folder to iterate over. |
|
| 178 | + * @return string[] $chunks list of chunks to load. |
|
| 179 | + */ |
|
| 180 | + protected function get_chunks_paths( $chunks_folder ) { |
|
| 181 | + $build_path = \Automattic\WooCommerce\Blocks\Package::get_path() . 'build/'; |
|
| 182 | + $blocks = []; |
|
| 183 | + if ( ! is_dir( $build_path . $chunks_folder ) ) { |
|
| 184 | + return []; |
|
| 185 | + } |
|
| 186 | + foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $build_path . $chunks_folder ) ) as $block_name ) { |
|
| 187 | + $blocks[] = str_replace( $build_path, '', $block_name ); |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + $chunks = preg_filter( '/.js/', '', $blocks ); |
|
| 191 | + return $chunks; |
|
| 192 | + } |
|
| 193 | + /** |
|
| 194 | + * Registers the block type with WordPress. |
|
| 195 | + * |
|
| 196 | + * @return string[] Chunks paths. |
|
| 197 | + */ |
|
| 198 | + protected function register_block_type() { |
|
| 199 | + $block_settings = [ |
|
| 200 | + 'render_callback' => $this->get_block_type_render_callback(), |
|
| 201 | + 'editor_script' => $this->get_block_type_editor_script( 'handle' ), |
|
| 202 | + 'editor_style' => $this->get_block_type_editor_style(), |
|
| 203 | + 'style' => $this->get_block_type_style(), |
|
| 204 | + ]; |
|
| 205 | + |
|
| 206 | + if ( isset( $this->api_version ) && '2' === $this->api_version ) { |
|
| 207 | + $block_settings['api_version'] = 2; |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + $metadata_path = $this->asset_api->get_block_metadata_path( $this->block_name ); |
|
| 211 | + // Prefer to register with metadata if the path is set in the block's class. |
|
| 212 | + if ( ! empty( $metadata_path ) ) { |
|
| 213 | + register_block_type_from_metadata( |
|
| 214 | + $metadata_path, |
|
| 215 | + $block_settings |
|
| 216 | + ); |
|
| 217 | + return; |
|
| 218 | + } |
|
| 219 | + |
|
| 220 | + /* |
|
| 221 | 221 | * Insert attributes and supports if we're not registering the block using metadata. |
| 222 | 222 | * These are left unset until now and only added here because if they were set when registering with metadata, |
| 223 | 223 | * the attributes and supports from $block_settings would override the values from metadata. |
| 224 | 224 | */ |
| 225 | - $block_settings['attributes'] = $this->get_block_type_attributes(); |
|
| 226 | - $block_settings['supports'] = $this->get_block_type_supports(); |
|
| 227 | - |
|
| 228 | - register_block_type( |
|
| 229 | - $this->get_block_type(), |
|
| 230 | - $block_settings |
|
| 231 | - ); |
|
| 232 | - } |
|
| 233 | - |
|
| 234 | - /** |
|
| 235 | - * Get the block type. |
|
| 236 | - * |
|
| 237 | - * @return string |
|
| 238 | - */ |
|
| 239 | - protected function get_block_type() { |
|
| 240 | - return $this->namespace . '/' . $this->block_name; |
|
| 241 | - } |
|
| 242 | - |
|
| 243 | - /** |
|
| 244 | - * Get the render callback for this block type. |
|
| 245 | - * |
|
| 246 | - * Dynamic blocks should return a callback, for example, `return [ $this, 'render' ];` |
|
| 247 | - * |
|
| 248 | - * @see $this->register_block_type() |
|
| 249 | - * @return callable|null; |
|
| 250 | - */ |
|
| 251 | - protected function get_block_type_render_callback() { |
|
| 252 | - return [ $this, 'render_callback' ]; |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - /** |
|
| 256 | - * Get the editor script data for this block type. |
|
| 257 | - * |
|
| 258 | - * @see $this->register_block_type() |
|
| 259 | - * @param string $key Data to get, or default to everything. |
|
| 260 | - * @return array|string |
|
| 261 | - */ |
|
| 262 | - protected function get_block_type_editor_script( $key = null ) { |
|
| 263 | - $script = [ |
|
| 264 | - 'handle' => 'wc-' . $this->block_name . '-block', |
|
| 265 | - 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name ), |
|
| 266 | - 'dependencies' => [ 'wc-blocks' ], |
|
| 267 | - ]; |
|
| 268 | - return $key ? $script[ $key ] : $script; |
|
| 269 | - } |
|
| 270 | - |
|
| 271 | - /** |
|
| 272 | - * Get the editor style handle for this block type. |
|
| 273 | - * |
|
| 274 | - * @see $this->register_block_type() |
|
| 275 | - * @return string|null |
|
| 276 | - */ |
|
| 277 | - protected function get_block_type_editor_style() { |
|
| 278 | - return 'wc-blocks-editor-style'; |
|
| 279 | - } |
|
| 280 | - |
|
| 281 | - /** |
|
| 282 | - * Get the frontend script handle for this block type. |
|
| 283 | - * |
|
| 284 | - * @see $this->register_block_type() |
|
| 285 | - * @param string $key Data to get, or default to everything. |
|
| 286 | - * @return array|string |
|
| 287 | - */ |
|
| 288 | - protected function get_block_type_script( $key = null ) { |
|
| 289 | - $script = [ |
|
| 290 | - 'handle' => 'wc-' . $this->block_name . '-block-frontend', |
|
| 291 | - 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name . '-frontend' ), |
|
| 292 | - 'dependencies' => [], |
|
| 293 | - ]; |
|
| 294 | - return $key ? $script[ $key ] : $script; |
|
| 295 | - } |
|
| 296 | - |
|
| 297 | - /** |
|
| 298 | - * Get the frontend style handle for this block type. |
|
| 299 | - * |
|
| 300 | - * @see $this->register_block_type() |
|
| 301 | - * @return string|null |
|
| 302 | - */ |
|
| 303 | - protected function get_block_type_style() { |
|
| 304 | - return 'wc-blocks-style'; |
|
| 305 | - } |
|
| 306 | - |
|
| 307 | - /** |
|
| 308 | - * Get the supports array for this block type. |
|
| 309 | - * |
|
| 310 | - * @see $this->register_block_type() |
|
| 311 | - * @return string; |
|
| 312 | - */ |
|
| 313 | - protected function get_block_type_supports() { |
|
| 314 | - return []; |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - /** |
|
| 318 | - * Get block attributes. |
|
| 319 | - * |
|
| 320 | - * @return array; |
|
| 321 | - */ |
|
| 322 | - protected function get_block_type_attributes() { |
|
| 323 | - return []; |
|
| 324 | - } |
|
| 325 | - |
|
| 326 | - /** |
|
| 327 | - * Parses block attributes from the render_callback. |
|
| 328 | - * |
|
| 329 | - * @param array|WP_Block $attributes Block attributes, or an instance of a WP_Block. Defaults to an empty array. |
|
| 330 | - * @return array |
|
| 331 | - */ |
|
| 332 | - protected function parse_render_callback_attributes( $attributes ) { |
|
| 333 | - return is_a( $attributes, 'WP_Block' ) ? $attributes->attributes : $attributes; |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * Render the block. Extended by children. |
|
| 338 | - * |
|
| 339 | - * @param array $attributes Block attributes. |
|
| 340 | - * @param string $content Block content. |
|
| 341 | - * @return string Rendered block type output. |
|
| 342 | - */ |
|
| 343 | - protected function render( $attributes, $content ) { |
|
| 344 | - return $content; |
|
| 345 | - } |
|
| 346 | - |
|
| 347 | - /** |
|
| 348 | - * Enqueue frontend assets for this block, just in time for rendering. |
|
| 349 | - * |
|
| 350 | - * @internal This prevents the block script being enqueued on all pages. It is only enqueued as needed. Note that |
|
| 351 | - * we intentionally do not pass 'script' to register_block_type. |
|
| 352 | - * |
|
| 353 | - * @param array $attributes Any attributes that currently are available from the block. |
|
| 354 | - */ |
|
| 355 | - protected function enqueue_assets( array $attributes ) { |
|
| 356 | - if ( $this->enqueued_assets ) { |
|
| 357 | - return; |
|
| 358 | - } |
|
| 359 | - $this->enqueue_data( $attributes ); |
|
| 360 | - $this->enqueue_scripts( $attributes ); |
|
| 361 | - $this->enqueued_assets = true; |
|
| 362 | - } |
|
| 363 | - |
|
| 364 | - /** |
|
| 365 | - * Data passed through from server to client for block. |
|
| 366 | - * |
|
| 367 | - * @param array $attributes Any attributes that currently are available from the block. |
|
| 368 | - * Note, this will be empty in the editor context when the block is |
|
| 369 | - * not in the post content on editor load. |
|
| 370 | - */ |
|
| 371 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 372 | - $registered_script_data = $this->integration_registry->get_all_registered_script_data(); |
|
| 373 | - |
|
| 374 | - foreach ( $registered_script_data as $asset_data_key => $asset_data_value ) { |
|
| 375 | - if ( ! $this->asset_data_registry->exists( $asset_data_key ) ) { |
|
| 376 | - $this->asset_data_registry->add( $asset_data_key, $asset_data_value ); |
|
| 377 | - } |
|
| 378 | - } |
|
| 379 | - |
|
| 380 | - if ( ! $this->asset_data_registry->exists( 'wcBlocksConfig' ) ) { |
|
| 381 | - $this->asset_data_registry->add( |
|
| 382 | - 'wcBlocksConfig', |
|
| 383 | - [ |
|
| 384 | - 'buildPhase' => Package::feature()->get_flag(), |
|
| 385 | - 'pluginUrl' => plugins_url( '/', dirname( __DIR__ ) ), |
|
| 386 | - 'productCount' => array_sum( (array) wp_count_posts( 'product' ) ), |
|
| 387 | - 'restApiRoutes' => [ |
|
| 388 | - '/wc/store/v1' => array_keys( $this->get_routes_from_namespace( 'wc/store/v1' ) ), |
|
| 389 | - ], |
|
| 390 | - 'defaultAvatar' => get_avatar_url( 0, [ 'force_default' => true ] ), |
|
| 391 | - |
|
| 392 | - /* |
|
| 225 | + $block_settings['attributes'] = $this->get_block_type_attributes(); |
|
| 226 | + $block_settings['supports'] = $this->get_block_type_supports(); |
|
| 227 | + |
|
| 228 | + register_block_type( |
|
| 229 | + $this->get_block_type(), |
|
| 230 | + $block_settings |
|
| 231 | + ); |
|
| 232 | + } |
|
| 233 | + |
|
| 234 | + /** |
|
| 235 | + * Get the block type. |
|
| 236 | + * |
|
| 237 | + * @return string |
|
| 238 | + */ |
|
| 239 | + protected function get_block_type() { |
|
| 240 | + return $this->namespace . '/' . $this->block_name; |
|
| 241 | + } |
|
| 242 | + |
|
| 243 | + /** |
|
| 244 | + * Get the render callback for this block type. |
|
| 245 | + * |
|
| 246 | + * Dynamic blocks should return a callback, for example, `return [ $this, 'render' ];` |
|
| 247 | + * |
|
| 248 | + * @see $this->register_block_type() |
|
| 249 | + * @return callable|null; |
|
| 250 | + */ |
|
| 251 | + protected function get_block_type_render_callback() { |
|
| 252 | + return [ $this, 'render_callback' ]; |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + /** |
|
| 256 | + * Get the editor script data for this block type. |
|
| 257 | + * |
|
| 258 | + * @see $this->register_block_type() |
|
| 259 | + * @param string $key Data to get, or default to everything. |
|
| 260 | + * @return array|string |
|
| 261 | + */ |
|
| 262 | + protected function get_block_type_editor_script( $key = null ) { |
|
| 263 | + $script = [ |
|
| 264 | + 'handle' => 'wc-' . $this->block_name . '-block', |
|
| 265 | + 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name ), |
|
| 266 | + 'dependencies' => [ 'wc-blocks' ], |
|
| 267 | + ]; |
|
| 268 | + return $key ? $script[ $key ] : $script; |
|
| 269 | + } |
|
| 270 | + |
|
| 271 | + /** |
|
| 272 | + * Get the editor style handle for this block type. |
|
| 273 | + * |
|
| 274 | + * @see $this->register_block_type() |
|
| 275 | + * @return string|null |
|
| 276 | + */ |
|
| 277 | + protected function get_block_type_editor_style() { |
|
| 278 | + return 'wc-blocks-editor-style'; |
|
| 279 | + } |
|
| 280 | + |
|
| 281 | + /** |
|
| 282 | + * Get the frontend script handle for this block type. |
|
| 283 | + * |
|
| 284 | + * @see $this->register_block_type() |
|
| 285 | + * @param string $key Data to get, or default to everything. |
|
| 286 | + * @return array|string |
|
| 287 | + */ |
|
| 288 | + protected function get_block_type_script( $key = null ) { |
|
| 289 | + $script = [ |
|
| 290 | + 'handle' => 'wc-' . $this->block_name . '-block-frontend', |
|
| 291 | + 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name . '-frontend' ), |
|
| 292 | + 'dependencies' => [], |
|
| 293 | + ]; |
|
| 294 | + return $key ? $script[ $key ] : $script; |
|
| 295 | + } |
|
| 296 | + |
|
| 297 | + /** |
|
| 298 | + * Get the frontend style handle for this block type. |
|
| 299 | + * |
|
| 300 | + * @see $this->register_block_type() |
|
| 301 | + * @return string|null |
|
| 302 | + */ |
|
| 303 | + protected function get_block_type_style() { |
|
| 304 | + return 'wc-blocks-style'; |
|
| 305 | + } |
|
| 306 | + |
|
| 307 | + /** |
|
| 308 | + * Get the supports array for this block type. |
|
| 309 | + * |
|
| 310 | + * @see $this->register_block_type() |
|
| 311 | + * @return string; |
|
| 312 | + */ |
|
| 313 | + protected function get_block_type_supports() { |
|
| 314 | + return []; |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + /** |
|
| 318 | + * Get block attributes. |
|
| 319 | + * |
|
| 320 | + * @return array; |
|
| 321 | + */ |
|
| 322 | + protected function get_block_type_attributes() { |
|
| 323 | + return []; |
|
| 324 | + } |
|
| 325 | + |
|
| 326 | + /** |
|
| 327 | + * Parses block attributes from the render_callback. |
|
| 328 | + * |
|
| 329 | + * @param array|WP_Block $attributes Block attributes, or an instance of a WP_Block. Defaults to an empty array. |
|
| 330 | + * @return array |
|
| 331 | + */ |
|
| 332 | + protected function parse_render_callback_attributes( $attributes ) { |
|
| 333 | + return is_a( $attributes, 'WP_Block' ) ? $attributes->attributes : $attributes; |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * Render the block. Extended by children. |
|
| 338 | + * |
|
| 339 | + * @param array $attributes Block attributes. |
|
| 340 | + * @param string $content Block content. |
|
| 341 | + * @return string Rendered block type output. |
|
| 342 | + */ |
|
| 343 | + protected function render( $attributes, $content ) { |
|
| 344 | + return $content; |
|
| 345 | + } |
|
| 346 | + |
|
| 347 | + /** |
|
| 348 | + * Enqueue frontend assets for this block, just in time for rendering. |
|
| 349 | + * |
|
| 350 | + * @internal This prevents the block script being enqueued on all pages. It is only enqueued as needed. Note that |
|
| 351 | + * we intentionally do not pass 'script' to register_block_type. |
|
| 352 | + * |
|
| 353 | + * @param array $attributes Any attributes that currently are available from the block. |
|
| 354 | + */ |
|
| 355 | + protected function enqueue_assets( array $attributes ) { |
|
| 356 | + if ( $this->enqueued_assets ) { |
|
| 357 | + return; |
|
| 358 | + } |
|
| 359 | + $this->enqueue_data( $attributes ); |
|
| 360 | + $this->enqueue_scripts( $attributes ); |
|
| 361 | + $this->enqueued_assets = true; |
|
| 362 | + } |
|
| 363 | + |
|
| 364 | + /** |
|
| 365 | + * Data passed through from server to client for block. |
|
| 366 | + * |
|
| 367 | + * @param array $attributes Any attributes that currently are available from the block. |
|
| 368 | + * Note, this will be empty in the editor context when the block is |
|
| 369 | + * not in the post content on editor load. |
|
| 370 | + */ |
|
| 371 | + protected function enqueue_data( array $attributes = [] ) { |
|
| 372 | + $registered_script_data = $this->integration_registry->get_all_registered_script_data(); |
|
| 373 | + |
|
| 374 | + foreach ( $registered_script_data as $asset_data_key => $asset_data_value ) { |
|
| 375 | + if ( ! $this->asset_data_registry->exists( $asset_data_key ) ) { |
|
| 376 | + $this->asset_data_registry->add( $asset_data_key, $asset_data_value ); |
|
| 377 | + } |
|
| 378 | + } |
|
| 379 | + |
|
| 380 | + if ( ! $this->asset_data_registry->exists( 'wcBlocksConfig' ) ) { |
|
| 381 | + $this->asset_data_registry->add( |
|
| 382 | + 'wcBlocksConfig', |
|
| 383 | + [ |
|
| 384 | + 'buildPhase' => Package::feature()->get_flag(), |
|
| 385 | + 'pluginUrl' => plugins_url( '/', dirname( __DIR__ ) ), |
|
| 386 | + 'productCount' => array_sum( (array) wp_count_posts( 'product' ) ), |
|
| 387 | + 'restApiRoutes' => [ |
|
| 388 | + '/wc/store/v1' => array_keys( $this->get_routes_from_namespace( 'wc/store/v1' ) ), |
|
| 389 | + ], |
|
| 390 | + 'defaultAvatar' => get_avatar_url( 0, [ 'force_default' => true ] ), |
|
| 391 | + |
|
| 392 | + /* |
|
| 393 | 393 | * translators: If your word count is based on single characters (e.g. East Asian characters), |
| 394 | 394 | * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. |
| 395 | 395 | * Do not translate into your own language. |
| 396 | 396 | */ |
| 397 | - 'wordCountType' => _x( 'words', 'Word count type. Do not translate!', 'woocommerce' ), |
|
| 398 | - ] |
|
| 399 | - ); |
|
| 400 | - } |
|
| 401 | - } |
|
| 402 | - |
|
| 403 | - /** |
|
| 404 | - * Get routes from a REST API namespace. |
|
| 405 | - * |
|
| 406 | - * @param string $namespace Namespace to retrieve. |
|
| 407 | - * @return array |
|
| 408 | - */ |
|
| 409 | - protected function get_routes_from_namespace( $namespace ) { |
|
| 410 | - $rest_server = rest_get_server(); |
|
| 411 | - $namespace_index = $rest_server->get_namespace_index( |
|
| 412 | - [ |
|
| 413 | - 'namespace' => $namespace, |
|
| 414 | - 'context' => 'view', |
|
| 415 | - ] |
|
| 416 | - ); |
|
| 417 | - |
|
| 418 | - if ( is_wp_error( $namespace_index ) ) { |
|
| 419 | - return []; |
|
| 420 | - } |
|
| 421 | - |
|
| 422 | - $response_data = $namespace_index->get_data(); |
|
| 423 | - |
|
| 424 | - return $response_data['routes'] ?? []; |
|
| 425 | - } |
|
| 426 | - |
|
| 427 | - /** |
|
| 428 | - * Register/enqueue scripts used for this block on the frontend, during render. |
|
| 429 | - * |
|
| 430 | - * @param array $attributes Any attributes that currently are available from the block. |
|
| 431 | - */ |
|
| 432 | - protected function enqueue_scripts( array $attributes = [] ) { |
|
| 433 | - if ( null !== $this->get_block_type_script() ) { |
|
| 434 | - wp_enqueue_script( $this->get_block_type_script( 'handle' ) ); |
|
| 435 | - } |
|
| 436 | - } |
|
| 397 | + 'wordCountType' => _x( 'words', 'Word count type. Do not translate!', 'woocommerce' ), |
|
| 398 | + ] |
|
| 399 | + ); |
|
| 400 | + } |
|
| 401 | + } |
|
| 402 | + |
|
| 403 | + /** |
|
| 404 | + * Get routes from a REST API namespace. |
|
| 405 | + * |
|
| 406 | + * @param string $namespace Namespace to retrieve. |
|
| 407 | + * @return array |
|
| 408 | + */ |
|
| 409 | + protected function get_routes_from_namespace( $namespace ) { |
|
| 410 | + $rest_server = rest_get_server(); |
|
| 411 | + $namespace_index = $rest_server->get_namespace_index( |
|
| 412 | + [ |
|
| 413 | + 'namespace' => $namespace, |
|
| 414 | + 'context' => 'view', |
|
| 415 | + ] |
|
| 416 | + ); |
|
| 417 | + |
|
| 418 | + if ( is_wp_error( $namespace_index ) ) { |
|
| 419 | + return []; |
|
| 420 | + } |
|
| 421 | + |
|
| 422 | + $response_data = $namespace_index->get_data(); |
|
| 423 | + |
|
| 424 | + return $response_data['routes'] ?? []; |
|
| 425 | + } |
|
| 426 | + |
|
| 427 | + /** |
|
| 428 | + * Register/enqueue scripts used for this block on the frontend, during render. |
|
| 429 | + * |
|
| 430 | + * @param array $attributes Any attributes that currently are available from the block. |
|
| 431 | + */ |
|
| 432 | + protected function enqueue_scripts( array $attributes = [] ) { |
|
| 433 | + if ( null !== $this->get_block_type_script() ) { |
|
| 434 | + wp_enqueue_script( $this->get_block_type_script( 'handle' ) ); |
|
| 435 | + } |
|
| 436 | + } |
|
| 437 | 437 | } |
@@ -62,7 +62,7 @@ discard block |
||
| 62 | 62 | * @param IntegrationRegistry $integration_registry Instance of the integration registry. |
| 63 | 63 | * @param string $block_name Optionally set block name during construct. |
| 64 | 64 | */ |
| 65 | - public function __construct( AssetApi $asset_api, AssetDataRegistry $asset_data_registry, IntegrationRegistry $integration_registry, $block_name = '' ) { |
|
| 65 | + public function __construct(AssetApi $asset_api, AssetDataRegistry $asset_data_registry, IntegrationRegistry $integration_registry, $block_name = '') { |
|
| 66 | 66 | $this->asset_api = $asset_api; |
| 67 | 67 | $this->asset_data_registry = $asset_data_registry; |
| 68 | 68 | $this->integration_registry = $integration_registry; |
@@ -78,12 +78,12 @@ discard block |
||
| 78 | 78 | * @param string $content Block content. Default empty string. |
| 79 | 79 | * @return string Rendered block type output. |
| 80 | 80 | */ |
| 81 | - public function render_callback( $attributes = [], $content = '' ) { |
|
| 82 | - $render_callback_attributes = $this->parse_render_callback_attributes( $attributes ); |
|
| 83 | - if ( ! is_admin() && ! WC()->is_rest_api_request() ) { |
|
| 84 | - $this->enqueue_assets( $render_callback_attributes ); |
|
| 81 | + public function render_callback($attributes = [], $content = '') { |
|
| 82 | + $render_callback_attributes = $this->parse_render_callback_attributes($attributes); |
|
| 83 | + if (!is_admin() && !WC()->is_rest_api_request()) { |
|
| 84 | + $this->enqueue_assets($render_callback_attributes); |
|
| 85 | 85 | } |
| 86 | - return $this->render( $render_callback_attributes, $content ); |
|
| 86 | + return $this->render($render_callback_attributes, $content); |
|
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | /** |
@@ -92,7 +92,7 @@ discard block |
||
| 92 | 92 | * This is needed if a block is not yet within the post content--`render` and `enqueue_assets` may not have ran. |
| 93 | 93 | */ |
| 94 | 94 | public function enqueue_editor_assets() { |
| 95 | - if ( $this->enqueued_assets ) { |
|
| 95 | + if ($this->enqueued_assets) { |
|
| 96 | 96 | return; |
| 97 | 97 | } |
| 98 | 98 | $this->enqueue_data(); |
@@ -105,14 +105,14 @@ discard block |
||
| 105 | 105 | * - Register the block with WordPress. |
| 106 | 106 | */ |
| 107 | 107 | protected function initialize() { |
| 108 | - if ( empty( $this->block_name ) ) { |
|
| 109 | - _doing_it_wrong( __METHOD__, esc_html__( 'Block name is required.', 'woocommerce' ), '4.5.0' ); |
|
| 108 | + if (empty($this->block_name)) { |
|
| 109 | + _doing_it_wrong(__METHOD__, esc_html__('Block name is required.', 'woocommerce'), '4.5.0'); |
|
| 110 | 110 | return false; |
| 111 | 111 | } |
| 112 | - $this->integration_registry->initialize( $this->block_name . '_block' ); |
|
| 112 | + $this->integration_registry->initialize($this->block_name . '_block'); |
|
| 113 | 113 | $this->register_block_type_assets(); |
| 114 | 114 | $this->register_block_type(); |
| 115 | - add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] ); |
|
| 115 | + add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_assets']); |
|
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | /** |
@@ -121,29 +121,29 @@ discard block |
||
| 121 | 121 | * This registers the scripts; it does not enqueue them. |
| 122 | 122 | */ |
| 123 | 123 | protected function register_block_type_assets() { |
| 124 | - if ( null !== $this->get_block_type_editor_script() ) { |
|
| 125 | - $data = $this->asset_api->get_script_data( $this->get_block_type_editor_script( 'path' ) ); |
|
| 126 | - $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 124 | + if (null !== $this->get_block_type_editor_script()) { |
|
| 125 | + $data = $this->asset_api->get_script_data($this->get_block_type_editor_script('path')); |
|
| 126 | + $has_i18n = in_array('wp-i18n', $data['dependencies'], true); |
|
| 127 | 127 | |
| 128 | 128 | $this->asset_api->register_script( |
| 129 | - $this->get_block_type_editor_script( 'handle' ), |
|
| 130 | - $this->get_block_type_editor_script( 'path' ), |
|
| 129 | + $this->get_block_type_editor_script('handle'), |
|
| 130 | + $this->get_block_type_editor_script('path'), |
|
| 131 | 131 | array_merge( |
| 132 | - $this->get_block_type_editor_script( 'dependencies' ), |
|
| 132 | + $this->get_block_type_editor_script('dependencies'), |
|
| 133 | 133 | $this->integration_registry->get_all_registered_editor_script_handles() |
| 134 | 134 | ), |
| 135 | 135 | $has_i18n |
| 136 | 136 | ); |
| 137 | 137 | } |
| 138 | - if ( null !== $this->get_block_type_script() ) { |
|
| 139 | - $data = $this->asset_api->get_script_data( $this->get_block_type_script( 'path' ) ); |
|
| 140 | - $has_i18n = in_array( 'wp-i18n', $data['dependencies'], true ); |
|
| 138 | + if (null !== $this->get_block_type_script()) { |
|
| 139 | + $data = $this->asset_api->get_script_data($this->get_block_type_script('path')); |
|
| 140 | + $has_i18n = in_array('wp-i18n', $data['dependencies'], true); |
|
| 141 | 141 | |
| 142 | 142 | $this->asset_api->register_script( |
| 143 | - $this->get_block_type_script( 'handle' ), |
|
| 144 | - $this->get_block_type_script( 'path' ), |
|
| 143 | + $this->get_block_type_script('handle'), |
|
| 144 | + $this->get_block_type_script('path'), |
|
| 145 | 145 | array_merge( |
| 146 | - $this->get_block_type_script( 'dependencies' ), |
|
| 146 | + $this->get_block_type_script('dependencies'), |
|
| 147 | 147 | $this->integration_registry->get_all_registered_script_handles() |
| 148 | 148 | ), |
| 149 | 149 | $has_i18n |
@@ -158,16 +158,16 @@ discard block |
||
| 158 | 158 | * |
| 159 | 159 | * @param string[] $chunks Array of chunk names. |
| 160 | 160 | */ |
| 161 | - protected function register_chunk_translations( $chunks ) { |
|
| 162 | - foreach ( $chunks as $chunk ) { |
|
| 161 | + protected function register_chunk_translations($chunks) { |
|
| 162 | + foreach ($chunks as $chunk) { |
|
| 163 | 163 | $handle = 'wc-blocks-' . $chunk . '-chunk'; |
| 164 | - $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), [], true ); |
|
| 164 | + $this->asset_api->register_script($handle, $this->asset_api->get_block_asset_build_path($chunk), [], true); |
|
| 165 | 165 | wp_add_inline_script( |
| 166 | - $this->get_block_type_script( 'handle' ), |
|
| 167 | - wp_scripts()->print_translations( $handle, false ), |
|
| 166 | + $this->get_block_type_script('handle'), |
|
| 167 | + wp_scripts()->print_translations($handle, false), |
|
| 168 | 168 | 'before' |
| 169 | 169 | ); |
| 170 | - wp_deregister_script( $handle ); |
|
| 170 | + wp_deregister_script($handle); |
|
| 171 | 171 | } |
| 172 | 172 | } |
| 173 | 173 | |
@@ -177,17 +177,17 @@ discard block |
||
| 177 | 177 | * @param string $chunks_folder The folder to iterate over. |
| 178 | 178 | * @return string[] $chunks list of chunks to load. |
| 179 | 179 | */ |
| 180 | - protected function get_chunks_paths( $chunks_folder ) { |
|
| 180 | + protected function get_chunks_paths($chunks_folder) { |
|
| 181 | 181 | $build_path = \Automattic\WooCommerce\Blocks\Package::get_path() . 'build/'; |
| 182 | 182 | $blocks = []; |
| 183 | - if ( ! is_dir( $build_path . $chunks_folder ) ) { |
|
| 183 | + if (!is_dir($build_path . $chunks_folder)) { |
|
| 184 | 184 | return []; |
| 185 | 185 | } |
| 186 | - foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $build_path . $chunks_folder ) ) as $block_name ) { |
|
| 187 | - $blocks[] = str_replace( $build_path, '', $block_name ); |
|
| 186 | + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($build_path . $chunks_folder)) as $block_name) { |
|
| 187 | + $blocks[] = str_replace($build_path, '', $block_name); |
|
| 188 | 188 | } |
| 189 | 189 | |
| 190 | - $chunks = preg_filter( '/.js/', '', $blocks ); |
|
| 190 | + $chunks = preg_filter('/.js/', '', $blocks); |
|
| 191 | 191 | return $chunks; |
| 192 | 192 | } |
| 193 | 193 | /** |
@@ -198,18 +198,18 @@ discard block |
||
| 198 | 198 | protected function register_block_type() { |
| 199 | 199 | $block_settings = [ |
| 200 | 200 | 'render_callback' => $this->get_block_type_render_callback(), |
| 201 | - 'editor_script' => $this->get_block_type_editor_script( 'handle' ), |
|
| 201 | + 'editor_script' => $this->get_block_type_editor_script('handle'), |
|
| 202 | 202 | 'editor_style' => $this->get_block_type_editor_style(), |
| 203 | 203 | 'style' => $this->get_block_type_style(), |
| 204 | 204 | ]; |
| 205 | 205 | |
| 206 | - if ( isset( $this->api_version ) && '2' === $this->api_version ) { |
|
| 206 | + if (isset($this->api_version) && '2' === $this->api_version) { |
|
| 207 | 207 | $block_settings['api_version'] = 2; |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | - $metadata_path = $this->asset_api->get_block_metadata_path( $this->block_name ); |
|
| 210 | + $metadata_path = $this->asset_api->get_block_metadata_path($this->block_name); |
|
| 211 | 211 | // Prefer to register with metadata if the path is set in the block's class. |
| 212 | - if ( ! empty( $metadata_path ) ) { |
|
| 212 | + if (!empty($metadata_path)) { |
|
| 213 | 213 | register_block_type_from_metadata( |
| 214 | 214 | $metadata_path, |
| 215 | 215 | $block_settings |
@@ -249,7 +249,7 @@ discard block |
||
| 249 | 249 | * @return callable|null; |
| 250 | 250 | */ |
| 251 | 251 | protected function get_block_type_render_callback() { |
| 252 | - return [ $this, 'render_callback' ]; |
|
| 252 | + return [$this, 'render_callback']; |
|
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | /** |
@@ -259,13 +259,13 @@ discard block |
||
| 259 | 259 | * @param string $key Data to get, or default to everything. |
| 260 | 260 | * @return array|string |
| 261 | 261 | */ |
| 262 | - protected function get_block_type_editor_script( $key = null ) { |
|
| 262 | + protected function get_block_type_editor_script($key = null) { |
|
| 263 | 263 | $script = [ |
| 264 | 264 | 'handle' => 'wc-' . $this->block_name . '-block', |
| 265 | - 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name ), |
|
| 266 | - 'dependencies' => [ 'wc-blocks' ], |
|
| 265 | + 'path' => $this->asset_api->get_block_asset_build_path($this->block_name), |
|
| 266 | + 'dependencies' => ['wc-blocks'], |
|
| 267 | 267 | ]; |
| 268 | - return $key ? $script[ $key ] : $script; |
|
| 268 | + return $key ? $script[$key] : $script; |
|
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | /** |
@@ -285,13 +285,13 @@ discard block |
||
| 285 | 285 | * @param string $key Data to get, or default to everything. |
| 286 | 286 | * @return array|string |
| 287 | 287 | */ |
| 288 | - protected function get_block_type_script( $key = null ) { |
|
| 288 | + protected function get_block_type_script($key = null) { |
|
| 289 | 289 | $script = [ |
| 290 | 290 | 'handle' => 'wc-' . $this->block_name . '-block-frontend', |
| 291 | - 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name . '-frontend' ), |
|
| 291 | + 'path' => $this->asset_api->get_block_asset_build_path($this->block_name . '-frontend'), |
|
| 292 | 292 | 'dependencies' => [], |
| 293 | 293 | ]; |
| 294 | - return $key ? $script[ $key ] : $script; |
|
| 294 | + return $key ? $script[$key] : $script; |
|
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | /** |
@@ -329,8 +329,8 @@ discard block |
||
| 329 | 329 | * @param array|WP_Block $attributes Block attributes, or an instance of a WP_Block. Defaults to an empty array. |
| 330 | 330 | * @return array |
| 331 | 331 | */ |
| 332 | - protected function parse_render_callback_attributes( $attributes ) { |
|
| 333 | - return is_a( $attributes, 'WP_Block' ) ? $attributes->attributes : $attributes; |
|
| 332 | + protected function parse_render_callback_attributes($attributes) { |
|
| 333 | + return is_a($attributes, 'WP_Block') ? $attributes->attributes : $attributes; |
|
| 334 | 334 | } |
| 335 | 335 | |
| 336 | 336 | /** |
@@ -340,7 +340,7 @@ discard block |
||
| 340 | 340 | * @param string $content Block content. |
| 341 | 341 | * @return string Rendered block type output. |
| 342 | 342 | */ |
| 343 | - protected function render( $attributes, $content ) { |
|
| 343 | + protected function render($attributes, $content) { |
|
| 344 | 344 | return $content; |
| 345 | 345 | } |
| 346 | 346 | |
@@ -352,12 +352,12 @@ discard block |
||
| 352 | 352 | * |
| 353 | 353 | * @param array $attributes Any attributes that currently are available from the block. |
| 354 | 354 | */ |
| 355 | - protected function enqueue_assets( array $attributes ) { |
|
| 356 | - if ( $this->enqueued_assets ) { |
|
| 355 | + protected function enqueue_assets(array $attributes) { |
|
| 356 | + if ($this->enqueued_assets) { |
|
| 357 | 357 | return; |
| 358 | 358 | } |
| 359 | - $this->enqueue_data( $attributes ); |
|
| 360 | - $this->enqueue_scripts( $attributes ); |
|
| 359 | + $this->enqueue_data($attributes); |
|
| 360 | + $this->enqueue_scripts($attributes); |
|
| 361 | 361 | $this->enqueued_assets = true; |
| 362 | 362 | } |
| 363 | 363 | |
@@ -368,33 +368,33 @@ discard block |
||
| 368 | 368 | * Note, this will be empty in the editor context when the block is |
| 369 | 369 | * not in the post content on editor load. |
| 370 | 370 | */ |
| 371 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 371 | + protected function enqueue_data(array $attributes = []) { |
|
| 372 | 372 | $registered_script_data = $this->integration_registry->get_all_registered_script_data(); |
| 373 | 373 | |
| 374 | - foreach ( $registered_script_data as $asset_data_key => $asset_data_value ) { |
|
| 375 | - if ( ! $this->asset_data_registry->exists( $asset_data_key ) ) { |
|
| 376 | - $this->asset_data_registry->add( $asset_data_key, $asset_data_value ); |
|
| 374 | + foreach ($registered_script_data as $asset_data_key => $asset_data_value) { |
|
| 375 | + if (!$this->asset_data_registry->exists($asset_data_key)) { |
|
| 376 | + $this->asset_data_registry->add($asset_data_key, $asset_data_value); |
|
| 377 | 377 | } |
| 378 | 378 | } |
| 379 | 379 | |
| 380 | - if ( ! $this->asset_data_registry->exists( 'wcBlocksConfig' ) ) { |
|
| 380 | + if (!$this->asset_data_registry->exists('wcBlocksConfig')) { |
|
| 381 | 381 | $this->asset_data_registry->add( |
| 382 | 382 | 'wcBlocksConfig', |
| 383 | 383 | [ |
| 384 | 384 | 'buildPhase' => Package::feature()->get_flag(), |
| 385 | - 'pluginUrl' => plugins_url( '/', dirname( __DIR__ ) ), |
|
| 386 | - 'productCount' => array_sum( (array) wp_count_posts( 'product' ) ), |
|
| 385 | + 'pluginUrl' => plugins_url('/', dirname(__DIR__)), |
|
| 386 | + 'productCount' => array_sum((array) wp_count_posts('product')), |
|
| 387 | 387 | 'restApiRoutes' => [ |
| 388 | - '/wc/store/v1' => array_keys( $this->get_routes_from_namespace( 'wc/store/v1' ) ), |
|
| 388 | + '/wc/store/v1' => array_keys($this->get_routes_from_namespace('wc/store/v1')), |
|
| 389 | 389 | ], |
| 390 | - 'defaultAvatar' => get_avatar_url( 0, [ 'force_default' => true ] ), |
|
| 390 | + 'defaultAvatar' => get_avatar_url(0, ['force_default' => true]), |
|
| 391 | 391 | |
| 392 | 392 | /* |
| 393 | 393 | * translators: If your word count is based on single characters (e.g. East Asian characters), |
| 394 | 394 | * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. |
| 395 | 395 | * Do not translate into your own language. |
| 396 | 396 | */ |
| 397 | - 'wordCountType' => _x( 'words', 'Word count type. Do not translate!', 'woocommerce' ), |
|
| 397 | + 'wordCountType' => _x('words', 'Word count type. Do not translate!', 'woocommerce'), |
|
| 398 | 398 | ] |
| 399 | 399 | ); |
| 400 | 400 | } |
@@ -406,7 +406,7 @@ discard block |
||
| 406 | 406 | * @param string $namespace Namespace to retrieve. |
| 407 | 407 | * @return array |
| 408 | 408 | */ |
| 409 | - protected function get_routes_from_namespace( $namespace ) { |
|
| 409 | + protected function get_routes_from_namespace($namespace) { |
|
| 410 | 410 | $rest_server = rest_get_server(); |
| 411 | 411 | $namespace_index = $rest_server->get_namespace_index( |
| 412 | 412 | [ |
@@ -415,7 +415,7 @@ discard block |
||
| 415 | 415 | ] |
| 416 | 416 | ); |
| 417 | 417 | |
| 418 | - if ( is_wp_error( $namespace_index ) ) { |
|
| 418 | + if (is_wp_error($namespace_index)) { |
|
| 419 | 419 | return []; |
| 420 | 420 | } |
| 421 | 421 | |
@@ -429,9 +429,9 @@ discard block |
||
| 429 | 429 | * |
| 430 | 430 | * @param array $attributes Any attributes that currently are available from the block. |
| 431 | 431 | */ |
| 432 | - protected function enqueue_scripts( array $attributes = [] ) { |
|
| 433 | - if ( null !== $this->get_block_type_script() ) { |
|
| 434 | - wp_enqueue_script( $this->get_block_type_script( 'handle' ) ); |
|
| 432 | + protected function enqueue_scripts(array $attributes = []) { |
|
| 433 | + if (null !== $this->get_block_type_script()) { |
|
| 434 | + wp_enqueue_script($this->get_block_type_script('handle')); |
|
| 435 | 435 | } |
| 436 | 436 | } |
| 437 | 437 | } |
@@ -5,39 +5,39 @@ |
||
| 5 | 5 | * ReviewsByCategory class. |
| 6 | 6 | */ |
| 7 | 7 | class ReviewsByCategory extends AbstractBlock { |
| 8 | - /** |
|
| 9 | - * Block name. |
|
| 10 | - * |
|
| 11 | - * @var string |
|
| 12 | - */ |
|
| 13 | - protected $block_name = 'reviews-by-category'; |
|
| 8 | + /** |
|
| 9 | + * Block name. |
|
| 10 | + * |
|
| 11 | + * @var string |
|
| 12 | + */ |
|
| 13 | + protected $block_name = 'reviews-by-category'; |
|
| 14 | 14 | |
| 15 | - /** |
|
| 16 | - * Get the frontend script handle for this block type. |
|
| 17 | - * |
|
| 18 | - * @see $this->register_block_type() |
|
| 19 | - * @param string $key Data to get, or default to everything. |
|
| 20 | - * @return array|string |
|
| 21 | - */ |
|
| 22 | - protected function get_block_type_script( $key = null ) { |
|
| 23 | - $script = [ |
|
| 24 | - 'handle' => 'wc-reviews-block-frontend', |
|
| 25 | - 'path' => $this->asset_api->get_block_asset_build_path( 'reviews-frontend' ), |
|
| 26 | - 'dependencies' => [], |
|
| 27 | - ]; |
|
| 28 | - return $key ? $script[ $key ] : $script; |
|
| 29 | - } |
|
| 15 | + /** |
|
| 16 | + * Get the frontend script handle for this block type. |
|
| 17 | + * |
|
| 18 | + * @see $this->register_block_type() |
|
| 19 | + * @param string $key Data to get, or default to everything. |
|
| 20 | + * @return array|string |
|
| 21 | + */ |
|
| 22 | + protected function get_block_type_script( $key = null ) { |
|
| 23 | + $script = [ |
|
| 24 | + 'handle' => 'wc-reviews-block-frontend', |
|
| 25 | + 'path' => $this->asset_api->get_block_asset_build_path( 'reviews-frontend' ), |
|
| 26 | + 'dependencies' => [], |
|
| 27 | + ]; |
|
| 28 | + return $key ? $script[ $key ] : $script; |
|
| 29 | + } |
|
| 30 | 30 | |
| 31 | - /** |
|
| 32 | - * Extra data passed through from server to client for block. |
|
| 33 | - * |
|
| 34 | - * @param array $attributes Any attributes that currently are available from the block. |
|
| 35 | - * Note, this will be empty in the editor context when the block is |
|
| 36 | - * not in the post content on editor load. |
|
| 37 | - */ |
|
| 38 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 39 | - parent::enqueue_data( $attributes ); |
|
| 40 | - $this->asset_data_registry->add( 'reviewRatingsEnabled', wc_review_ratings_enabled(), true ); |
|
| 41 | - $this->asset_data_registry->add( 'showAvatars', '1' === get_option( 'show_avatars' ), true ); |
|
| 42 | - } |
|
| 31 | + /** |
|
| 32 | + * Extra data passed through from server to client for block. |
|
| 33 | + * |
|
| 34 | + * @param array $attributes Any attributes that currently are available from the block. |
|
| 35 | + * Note, this will be empty in the editor context when the block is |
|
| 36 | + * not in the post content on editor load. |
|
| 37 | + */ |
|
| 38 | + protected function enqueue_data( array $attributes = [] ) { |
|
| 39 | + parent::enqueue_data( $attributes ); |
|
| 40 | + $this->asset_data_registry->add( 'reviewRatingsEnabled', wc_review_ratings_enabled(), true ); |
|
| 41 | + $this->asset_data_registry->add( 'showAvatars', '1' === get_option( 'show_avatars' ), true ); |
|
| 42 | + } |
|
| 43 | 43 | } |
@@ -19,13 +19,13 @@ discard block |
||
| 19 | 19 | * @param string $key Data to get, or default to everything. |
| 20 | 20 | * @return array|string |
| 21 | 21 | */ |
| 22 | - protected function get_block_type_script( $key = null ) { |
|
| 22 | + protected function get_block_type_script($key = null) { |
|
| 23 | 23 | $script = [ |
| 24 | 24 | 'handle' => 'wc-reviews-block-frontend', |
| 25 | - 'path' => $this->asset_api->get_block_asset_build_path( 'reviews-frontend' ), |
|
| 25 | + 'path' => $this->asset_api->get_block_asset_build_path('reviews-frontend'), |
|
| 26 | 26 | 'dependencies' => [], |
| 27 | 27 | ]; |
| 28 | - return $key ? $script[ $key ] : $script; |
|
| 28 | + return $key ? $script[$key] : $script; |
|
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | /** |
@@ -35,9 +35,9 @@ discard block |
||
| 35 | 35 | * Note, this will be empty in the editor context when the block is |
| 36 | 36 | * not in the post content on editor load. |
| 37 | 37 | */ |
| 38 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 39 | - parent::enqueue_data( $attributes ); |
|
| 40 | - $this->asset_data_registry->add( 'reviewRatingsEnabled', wc_review_ratings_enabled(), true ); |
|
| 41 | - $this->asset_data_registry->add( 'showAvatars', '1' === get_option( 'show_avatars' ), true ); |
|
| 38 | + protected function enqueue_data(array $attributes = []) { |
|
| 39 | + parent::enqueue_data($attributes); |
|
| 40 | + $this->asset_data_registry->add('reviewRatingsEnabled', wc_review_ratings_enabled(), true); |
|
| 41 | + $this->asset_data_registry->add('showAvatars', '1' === get_option('show_avatars'), true); |
|
| 42 | 42 | } |
| 43 | 43 | } |
@@ -5,88 +5,88 @@ |
||
| 5 | 5 | * AbstractDynamicBlock class. |
| 6 | 6 | */ |
| 7 | 7 | abstract class AbstractDynamicBlock extends AbstractBlock { |
| 8 | - /** |
|
| 9 | - * Get the frontend script handle for this block type. |
|
| 10 | - * |
|
| 11 | - * @param string $key Data to get, or default to everything. |
|
| 12 | - * @return null |
|
| 13 | - */ |
|
| 14 | - protected function get_block_type_script( $key = null ) { |
|
| 15 | - return null; |
|
| 16 | - } |
|
| 8 | + /** |
|
| 9 | + * Get the frontend script handle for this block type. |
|
| 10 | + * |
|
| 11 | + * @param string $key Data to get, or default to everything. |
|
| 12 | + * @return null |
|
| 13 | + */ |
|
| 14 | + protected function get_block_type_script( $key = null ) { |
|
| 15 | + return null; |
|
| 16 | + } |
|
| 17 | 17 | |
| 18 | - /** |
|
| 19 | - * Get block attributes. |
|
| 20 | - * |
|
| 21 | - * @return array |
|
| 22 | - */ |
|
| 23 | - protected function get_block_type_attributes() { |
|
| 24 | - return array(); |
|
| 25 | - } |
|
| 18 | + /** |
|
| 19 | + * Get block attributes. |
|
| 20 | + * |
|
| 21 | + * @return array |
|
| 22 | + */ |
|
| 23 | + protected function get_block_type_attributes() { |
|
| 24 | + return array(); |
|
| 25 | + } |
|
| 26 | 26 | |
| 27 | - /** |
|
| 28 | - * Get the schema for the alignment property. |
|
| 29 | - * |
|
| 30 | - * @return array Property definition for align. |
|
| 31 | - */ |
|
| 32 | - protected function get_schema_align() { |
|
| 33 | - return array( |
|
| 34 | - 'type' => 'string', |
|
| 35 | - 'enum' => array( 'left', 'center', 'right', 'wide', 'full' ), |
|
| 36 | - ); |
|
| 37 | - } |
|
| 27 | + /** |
|
| 28 | + * Get the schema for the alignment property. |
|
| 29 | + * |
|
| 30 | + * @return array Property definition for align. |
|
| 31 | + */ |
|
| 32 | + protected function get_schema_align() { |
|
| 33 | + return array( |
|
| 34 | + 'type' => 'string', |
|
| 35 | + 'enum' => array( 'left', 'center', 'right', 'wide', 'full' ), |
|
| 36 | + ); |
|
| 37 | + } |
|
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * Get the schema for a list of IDs. |
|
| 41 | - * |
|
| 42 | - * @return array Property definition for a list of numeric ids. |
|
| 43 | - */ |
|
| 44 | - protected function get_schema_list_ids() { |
|
| 45 | - return array( |
|
| 46 | - 'type' => 'array', |
|
| 47 | - 'items' => array( |
|
| 48 | - 'type' => 'number', |
|
| 49 | - ), |
|
| 50 | - 'default' => array(), |
|
| 51 | - ); |
|
| 52 | - } |
|
| 39 | + /** |
|
| 40 | + * Get the schema for a list of IDs. |
|
| 41 | + * |
|
| 42 | + * @return array Property definition for a list of numeric ids. |
|
| 43 | + */ |
|
| 44 | + protected function get_schema_list_ids() { |
|
| 45 | + return array( |
|
| 46 | + 'type' => 'array', |
|
| 47 | + 'items' => array( |
|
| 48 | + 'type' => 'number', |
|
| 49 | + ), |
|
| 50 | + 'default' => array(), |
|
| 51 | + ); |
|
| 52 | + } |
|
| 53 | 53 | |
| 54 | - /** |
|
| 55 | - * Get the schema for a boolean value. |
|
| 56 | - * |
|
| 57 | - * @param string $default The default value. |
|
| 58 | - * @return array Property definition. |
|
| 59 | - */ |
|
| 60 | - protected function get_schema_boolean( $default = true ) { |
|
| 61 | - return array( |
|
| 62 | - 'type' => 'boolean', |
|
| 63 | - 'default' => $default, |
|
| 64 | - ); |
|
| 65 | - } |
|
| 54 | + /** |
|
| 55 | + * Get the schema for a boolean value. |
|
| 56 | + * |
|
| 57 | + * @param string $default The default value. |
|
| 58 | + * @return array Property definition. |
|
| 59 | + */ |
|
| 60 | + protected function get_schema_boolean( $default = true ) { |
|
| 61 | + return array( |
|
| 62 | + 'type' => 'boolean', |
|
| 63 | + 'default' => $default, |
|
| 64 | + ); |
|
| 65 | + } |
|
| 66 | 66 | |
| 67 | - /** |
|
| 68 | - * Get the schema for a numeric value. |
|
| 69 | - * |
|
| 70 | - * @param string $default The default value. |
|
| 71 | - * @return array Property definition. |
|
| 72 | - */ |
|
| 73 | - protected function get_schema_number( $default ) { |
|
| 74 | - return array( |
|
| 75 | - 'type' => 'number', |
|
| 76 | - 'default' => $default, |
|
| 77 | - ); |
|
| 78 | - } |
|
| 67 | + /** |
|
| 68 | + * Get the schema for a numeric value. |
|
| 69 | + * |
|
| 70 | + * @param string $default The default value. |
|
| 71 | + * @return array Property definition. |
|
| 72 | + */ |
|
| 73 | + protected function get_schema_number( $default ) { |
|
| 74 | + return array( |
|
| 75 | + 'type' => 'number', |
|
| 76 | + 'default' => $default, |
|
| 77 | + ); |
|
| 78 | + } |
|
| 79 | 79 | |
| 80 | - /** |
|
| 81 | - * Get the schema for a string value. |
|
| 82 | - * |
|
| 83 | - * @param string $default The default value. |
|
| 84 | - * @return array Property definition. |
|
| 85 | - */ |
|
| 86 | - protected function get_schema_string( $default = '' ) { |
|
| 87 | - return array( |
|
| 88 | - 'type' => 'string', |
|
| 89 | - 'default' => $default, |
|
| 90 | - ); |
|
| 91 | - } |
|
| 80 | + /** |
|
| 81 | + * Get the schema for a string value. |
|
| 82 | + * |
|
| 83 | + * @param string $default The default value. |
|
| 84 | + * @return array Property definition. |
|
| 85 | + */ |
|
| 86 | + protected function get_schema_string( $default = '' ) { |
|
| 87 | + return array( |
|
| 88 | + 'type' => 'string', |
|
| 89 | + 'default' => $default, |
|
| 90 | + ); |
|
| 91 | + } |
|
| 92 | 92 | } |
@@ -11,7 +11,7 @@ discard block |
||
| 11 | 11 | * @param string $key Data to get, or default to everything. |
| 12 | 12 | * @return null |
| 13 | 13 | */ |
| 14 | - protected function get_block_type_script( $key = null ) { |
|
| 14 | + protected function get_block_type_script($key = null) { |
|
| 15 | 15 | return null; |
| 16 | 16 | } |
| 17 | 17 | |
@@ -32,7 +32,7 @@ discard block |
||
| 32 | 32 | protected function get_schema_align() { |
| 33 | 33 | return array( |
| 34 | 34 | 'type' => 'string', |
| 35 | - 'enum' => array( 'left', 'center', 'right', 'wide', 'full' ), |
|
| 35 | + 'enum' => array('left', 'center', 'right', 'wide', 'full'), |
|
| 36 | 36 | ); |
| 37 | 37 | } |
| 38 | 38 | |
@@ -57,7 +57,7 @@ discard block |
||
| 57 | 57 | * @param string $default The default value. |
| 58 | 58 | * @return array Property definition. |
| 59 | 59 | */ |
| 60 | - protected function get_schema_boolean( $default = true ) { |
|
| 60 | + protected function get_schema_boolean($default = true) { |
|
| 61 | 61 | return array( |
| 62 | 62 | 'type' => 'boolean', |
| 63 | 63 | 'default' => $default, |
@@ -70,7 +70,7 @@ discard block |
||
| 70 | 70 | * @param string $default The default value. |
| 71 | 71 | * @return array Property definition. |
| 72 | 72 | */ |
| 73 | - protected function get_schema_number( $default ) { |
|
| 73 | + protected function get_schema_number($default) { |
|
| 74 | 74 | return array( |
| 75 | 75 | 'type' => 'number', |
| 76 | 76 | 'default' => $default, |
@@ -83,7 +83,7 @@ discard block |
||
| 83 | 83 | * @param string $default The default value. |
| 84 | 84 | * @return array Property definition. |
| 85 | 85 | */ |
| 86 | - protected function get_schema_string( $default = '' ) { |
|
| 86 | + protected function get_schema_string($default = '') { |
|
| 87 | 87 | return array( |
| 88 | 88 | 'type' => 'string', |
| 89 | 89 | 'default' => $default, |
@@ -6,54 +6,54 @@ discard block |
||
| 6 | 6 | */ |
| 7 | 7 | class ProductSearch extends AbstractBlock { |
| 8 | 8 | |
| 9 | - /** |
|
| 10 | - * Block name. |
|
| 11 | - * |
|
| 12 | - * @var string |
|
| 13 | - */ |
|
| 14 | - protected $block_name = 'product-search'; |
|
| 9 | + /** |
|
| 10 | + * Block name. |
|
| 11 | + * |
|
| 12 | + * @var string |
|
| 13 | + */ |
|
| 14 | + protected $block_name = 'product-search'; |
|
| 15 | 15 | |
| 16 | - /** |
|
| 17 | - * Get the frontend script handle for this block type. |
|
| 18 | - * |
|
| 19 | - * @param string $key Data to get, or default to everything. |
|
| 20 | - * @return null |
|
| 21 | - */ |
|
| 22 | - protected function get_block_type_script( $key = null ) { |
|
| 23 | - return null; |
|
| 24 | - } |
|
| 16 | + /** |
|
| 17 | + * Get the frontend script handle for this block type. |
|
| 18 | + * |
|
| 19 | + * @param string $key Data to get, or default to everything. |
|
| 20 | + * @return null |
|
| 21 | + */ |
|
| 22 | + protected function get_block_type_script( $key = null ) { |
|
| 23 | + return null; |
|
| 24 | + } |
|
| 25 | 25 | |
| 26 | - /** |
|
| 27 | - * Render the block. |
|
| 28 | - * |
|
| 29 | - * @param array $attributes Block attributes. |
|
| 30 | - * @param string $content Block content. |
|
| 31 | - * @return string Rendered block type output. |
|
| 32 | - */ |
|
| 33 | - protected function render( $attributes, $content ) { |
|
| 34 | - static $instance_id = 0; |
|
| 26 | + /** |
|
| 27 | + * Render the block. |
|
| 28 | + * |
|
| 29 | + * @param array $attributes Block attributes. |
|
| 30 | + * @param string $content Block content. |
|
| 31 | + * @return string Rendered block type output. |
|
| 32 | + */ |
|
| 33 | + protected function render( $attributes, $content ) { |
|
| 34 | + static $instance_id = 0; |
|
| 35 | 35 | |
| 36 | - $attributes = wp_parse_args( |
|
| 37 | - $attributes, |
|
| 38 | - array( |
|
| 39 | - 'hasLabel' => true, |
|
| 40 | - 'align' => '', |
|
| 41 | - 'className' => '', |
|
| 42 | - 'label' => __( 'Search', 'woocommerce' ), |
|
| 43 | - 'placeholder' => __( 'Search products…', 'woocommerce' ), |
|
| 44 | - ) |
|
| 45 | - ); |
|
| 36 | + $attributes = wp_parse_args( |
|
| 37 | + $attributes, |
|
| 38 | + array( |
|
| 39 | + 'hasLabel' => true, |
|
| 40 | + 'align' => '', |
|
| 41 | + 'className' => '', |
|
| 42 | + 'label' => __( 'Search', 'woocommerce' ), |
|
| 43 | + 'placeholder' => __( 'Search products…', 'woocommerce' ), |
|
| 44 | + ) |
|
| 45 | + ); |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * Product Search event. |
|
| 49 | - * |
|
| 50 | - * Listens for product search form submission, and on submission fires a WP Hook named |
|
| 51 | - * `experimental__woocommerce_blocks-product-search`. This can be used by tracking extensions such as Google |
|
| 52 | - * Analytics to track searches. |
|
| 53 | - */ |
|
| 54 | - $this->asset_api->add_inline_script( |
|
| 55 | - 'wp-hooks', |
|
| 56 | - " |
|
| 47 | + /** |
|
| 48 | + * Product Search event. |
|
| 49 | + * |
|
| 50 | + * Listens for product search form submission, and on submission fires a WP Hook named |
|
| 51 | + * `experimental__woocommerce_blocks-product-search`. This can be used by tracking extensions such as Google |
|
| 52 | + * Analytics to track searches. |
|
| 53 | + */ |
|
| 54 | + $this->asset_api->add_inline_script( |
|
| 55 | + 'wp-hooks', |
|
| 56 | + " |
|
| 57 | 57 | window.addEventListener( 'DOMContentLoaded', () => { |
| 58 | 58 | const forms = document.querySelectorAll( '.wc-block-product-search form' ); |
| 59 | 59 | |
@@ -68,60 +68,60 @@ discard block |
||
| 68 | 68 | } |
| 69 | 69 | } ); |
| 70 | 70 | ", |
| 71 | - 'after' |
|
| 72 | - ); |
|
| 71 | + 'after' |
|
| 72 | + ); |
|
| 73 | 73 | |
| 74 | - $input_id = 'wc-block-search__input-' . ( ++$instance_id ); |
|
| 75 | - $wrapper_attributes = get_block_wrapper_attributes( |
|
| 76 | - array( |
|
| 77 | - 'class' => implode( |
|
| 78 | - ' ', |
|
| 79 | - array_filter( |
|
| 80 | - [ |
|
| 81 | - 'wc-block-product-search', |
|
| 82 | - $attributes['align'] ? 'align' . $attributes['align'] : '', |
|
| 83 | - ] |
|
| 84 | - ) |
|
| 85 | - ), |
|
| 86 | - ) |
|
| 87 | - ); |
|
| 74 | + $input_id = 'wc-block-search__input-' . ( ++$instance_id ); |
|
| 75 | + $wrapper_attributes = get_block_wrapper_attributes( |
|
| 76 | + array( |
|
| 77 | + 'class' => implode( |
|
| 78 | + ' ', |
|
| 79 | + array_filter( |
|
| 80 | + [ |
|
| 81 | + 'wc-block-product-search', |
|
| 82 | + $attributes['align'] ? 'align' . $attributes['align'] : '', |
|
| 83 | + ] |
|
| 84 | + ) |
|
| 85 | + ), |
|
| 86 | + ) |
|
| 87 | + ); |
|
| 88 | 88 | |
| 89 | - $label_markup = $attributes['hasLabel'] ? sprintf( |
|
| 90 | - '<label for="%s" class="wc-block-product-search__label">%s</label>', |
|
| 91 | - esc_attr( $input_id ), |
|
| 92 | - esc_html( $attributes['label'] ) |
|
| 93 | - ) : sprintf( |
|
| 94 | - '<label for="%s" class="wc-block-product-search__label screen-reader-text">%s</label>', |
|
| 95 | - esc_attr( $input_id ), |
|
| 96 | - esc_html( $attributes['label'] ) |
|
| 97 | - ); |
|
| 89 | + $label_markup = $attributes['hasLabel'] ? sprintf( |
|
| 90 | + '<label for="%s" class="wc-block-product-search__label">%s</label>', |
|
| 91 | + esc_attr( $input_id ), |
|
| 92 | + esc_html( $attributes['label'] ) |
|
| 93 | + ) : sprintf( |
|
| 94 | + '<label for="%s" class="wc-block-product-search__label screen-reader-text">%s</label>', |
|
| 95 | + esc_attr( $input_id ), |
|
| 96 | + esc_html( $attributes['label'] ) |
|
| 97 | + ); |
|
| 98 | 98 | |
| 99 | - $input_markup = sprintf( |
|
| 100 | - '<input type="search" id="%s" class="wc-block-product-search__field" placeholder="%s" name="s" />', |
|
| 101 | - esc_attr( $input_id ), |
|
| 102 | - esc_attr( $attributes['placeholder'] ) |
|
| 103 | - ); |
|
| 104 | - $button_markup = sprintf( |
|
| 105 | - '<button type="submit" class="wc-block-product-search__button" aria-label="%s"> |
|
| 99 | + $input_markup = sprintf( |
|
| 100 | + '<input type="search" id="%s" class="wc-block-product-search__field" placeholder="%s" name="s" />', |
|
| 101 | + esc_attr( $input_id ), |
|
| 102 | + esc_attr( $attributes['placeholder'] ) |
|
| 103 | + ); |
|
| 104 | + $button_markup = sprintf( |
|
| 105 | + '<button type="submit" class="wc-block-product-search__button" aria-label="%s"> |
|
| 106 | 106 | <svg aria-hidden="true" role="img" focusable="false" class="dashicon dashicons-arrow-right-alt2" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"> |
| 107 | 107 | <path d="M6 15l5-5-5-5 1-2 7 7-7 7z" /> |
| 108 | 108 | </svg> |
| 109 | 109 | </button>', |
| 110 | - esc_attr__( 'Search', 'woocommerce' ) |
|
| 111 | - ); |
|
| 110 | + esc_attr__( 'Search', 'woocommerce' ) |
|
| 111 | + ); |
|
| 112 | 112 | |
| 113 | - $field_markup = ' |
|
| 113 | + $field_markup = ' |
|
| 114 | 114 | <div class="wc-block-product-search__fields"> |
| 115 | 115 | ' . $input_markup . $button_markup . ' |
| 116 | 116 | <input type="hidden" name="post_type" value="product" /> |
| 117 | 117 | </div> |
| 118 | 118 | '; |
| 119 | 119 | |
| 120 | - return sprintf( |
|
| 121 | - '<div %s><form role="search" method="get" action="%s">%s</form></div>', |
|
| 122 | - $wrapper_attributes, |
|
| 123 | - esc_url( home_url( '/' ) ), |
|
| 124 | - $label_markup . $field_markup |
|
| 125 | - ); |
|
| 126 | - } |
|
| 120 | + return sprintf( |
|
| 121 | + '<div %s><form role="search" method="get" action="%s">%s</form></div>', |
|
| 122 | + $wrapper_attributes, |
|
| 123 | + esc_url( home_url( '/' ) ), |
|
| 124 | + $label_markup . $field_markup |
|
| 125 | + ); |
|
| 126 | + } |
|
| 127 | 127 | } |
@@ -19,7 +19,7 @@ discard block |
||
| 19 | 19 | * @param string $key Data to get, or default to everything. |
| 20 | 20 | * @return null |
| 21 | 21 | */ |
| 22 | - protected function get_block_type_script( $key = null ) { |
|
| 22 | + protected function get_block_type_script($key = null) { |
|
| 23 | 23 | return null; |
| 24 | 24 | } |
| 25 | 25 | |
@@ -30,7 +30,7 @@ discard block |
||
| 30 | 30 | * @param string $content Block content. |
| 31 | 31 | * @return string Rendered block type output. |
| 32 | 32 | */ |
| 33 | - protected function render( $attributes, $content ) { |
|
| 33 | + protected function render($attributes, $content) { |
|
| 34 | 34 | static $instance_id = 0; |
| 35 | 35 | |
| 36 | 36 | $attributes = wp_parse_args( |
@@ -39,8 +39,8 @@ discard block |
||
| 39 | 39 | 'hasLabel' => true, |
| 40 | 40 | 'align' => '', |
| 41 | 41 | 'className' => '', |
| 42 | - 'label' => __( 'Search', 'woocommerce' ), |
|
| 43 | - 'placeholder' => __( 'Search products…', 'woocommerce' ), |
|
| 42 | + 'label' => __('Search', 'woocommerce'), |
|
| 43 | + 'placeholder' => __('Search products…', 'woocommerce'), |
|
| 44 | 44 | ) |
| 45 | 45 | ); |
| 46 | 46 | |
@@ -88,18 +88,18 @@ discard block |
||
| 88 | 88 | |
| 89 | 89 | $label_markup = $attributes['hasLabel'] ? sprintf( |
| 90 | 90 | '<label for="%s" class="wc-block-product-search__label">%s</label>', |
| 91 | - esc_attr( $input_id ), |
|
| 92 | - esc_html( $attributes['label'] ) |
|
| 91 | + esc_attr($input_id), |
|
| 92 | + esc_html($attributes['label']) |
|
| 93 | 93 | ) : sprintf( |
| 94 | 94 | '<label for="%s" class="wc-block-product-search__label screen-reader-text">%s</label>', |
| 95 | - esc_attr( $input_id ), |
|
| 96 | - esc_html( $attributes['label'] ) |
|
| 95 | + esc_attr($input_id), |
|
| 96 | + esc_html($attributes['label']) |
|
| 97 | 97 | ); |
| 98 | 98 | |
| 99 | - $input_markup = sprintf( |
|
| 99 | + $input_markup = sprintf( |
|
| 100 | 100 | '<input type="search" id="%s" class="wc-block-product-search__field" placeholder="%s" name="s" />', |
| 101 | - esc_attr( $input_id ), |
|
| 102 | - esc_attr( $attributes['placeholder'] ) |
|
| 101 | + esc_attr($input_id), |
|
| 102 | + esc_attr($attributes['placeholder']) |
|
| 103 | 103 | ); |
| 104 | 104 | $button_markup = sprintf( |
| 105 | 105 | '<button type="submit" class="wc-block-product-search__button" aria-label="%s"> |
@@ -107,7 +107,7 @@ discard block |
||
| 107 | 107 | <path d="M6 15l5-5-5-5 1-2 7 7-7 7z" /> |
| 108 | 108 | </svg> |
| 109 | 109 | </button>', |
| 110 | - esc_attr__( 'Search', 'woocommerce' ) |
|
| 110 | + esc_attr__('Search', 'woocommerce') |
|
| 111 | 111 | ); |
| 112 | 112 | |
| 113 | 113 | $field_markup = ' |
@@ -120,7 +120,7 @@ discard block |
||
| 120 | 120 | return sprintf( |
| 121 | 121 | '<div %s><form role="search" method="get" action="%s">%s</form></div>', |
| 122 | 122 | $wrapper_attributes, |
| 123 | - esc_url( home_url( '/' ) ), |
|
| 123 | + esc_url(home_url('/')), |
|
| 124 | 124 | $label_markup . $field_markup |
| 125 | 125 | ); |
| 126 | 126 | } |
@@ -5,24 +5,24 @@ |
||
| 5 | 5 | * AttributeFilter class. |
| 6 | 6 | */ |
| 7 | 7 | class StockFilter extends AbstractBlock { |
| 8 | - /** |
|
| 9 | - * Block name. |
|
| 10 | - * |
|
| 11 | - * @var string |
|
| 12 | - */ |
|
| 13 | - protected $block_name = 'stock-filter'; |
|
| 8 | + /** |
|
| 9 | + * Block name. |
|
| 10 | + * |
|
| 11 | + * @var string |
|
| 12 | + */ |
|
| 13 | + protected $block_name = 'stock-filter'; |
|
| 14 | 14 | |
| 15 | - /** |
|
| 16 | - * Extra data passed through from server to client for block. |
|
| 17 | - * |
|
| 18 | - * @param array $stock_statuses Any stock statuses that currently are available from the block. |
|
| 19 | - * Note, this will be empty in the editor context when the block is |
|
| 20 | - * not in the post content on editor load. |
|
| 21 | - */ |
|
| 22 | - protected function enqueue_data( array $stock_statuses = [] ) { |
|
| 23 | - parent::enqueue_data( $stock_statuses ); |
|
| 24 | - $this->asset_data_registry->add( 'stockStatusOptions', wc_get_product_stock_status_options(), true ); |
|
| 25 | - $this->asset_data_registry->add( 'hideOutOfStockItems', 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ), true ); |
|
| 15 | + /** |
|
| 16 | + * Extra data passed through from server to client for block. |
|
| 17 | + * |
|
| 18 | + * @param array $stock_statuses Any stock statuses that currently are available from the block. |
|
| 19 | + * Note, this will be empty in the editor context when the block is |
|
| 20 | + * not in the post content on editor load. |
|
| 21 | + */ |
|
| 22 | + protected function enqueue_data( array $stock_statuses = [] ) { |
|
| 23 | + parent::enqueue_data( $stock_statuses ); |
|
| 24 | + $this->asset_data_registry->add( 'stockStatusOptions', wc_get_product_stock_status_options(), true ); |
|
| 25 | + $this->asset_data_registry->add( 'hideOutOfStockItems', 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ), true ); |
|
| 26 | 26 | |
| 27 | - } |
|
| 27 | + } |
|
| 28 | 28 | } |
@@ -19,10 +19,10 @@ |
||
| 19 | 19 | * Note, this will be empty in the editor context when the block is |
| 20 | 20 | * not in the post content on editor load. |
| 21 | 21 | */ |
| 22 | - protected function enqueue_data( array $stock_statuses = [] ) { |
|
| 23 | - parent::enqueue_data( $stock_statuses ); |
|
| 24 | - $this->asset_data_registry->add( 'stockStatusOptions', wc_get_product_stock_status_options(), true ); |
|
| 25 | - $this->asset_data_registry->add( 'hideOutOfStockItems', 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ), true ); |
|
| 22 | + protected function enqueue_data(array $stock_statuses = []) { |
|
| 23 | + parent::enqueue_data($stock_statuses); |
|
| 24 | + $this->asset_data_registry->add('stockStatusOptions', wc_get_product_stock_status_options(), true); |
|
| 25 | + $this->asset_data_registry->add('hideOutOfStockItems', 'yes' === get_option('woocommerce_hide_out_of_stock_items'), true); |
|
| 26 | 26 | |
| 27 | 27 | } |
| 28 | 28 | } |
@@ -6,19 +6,19 @@ |
||
| 6 | 6 | */ |
| 7 | 7 | class ProductTopRated extends AbstractProductGrid { |
| 8 | 8 | |
| 9 | - /** |
|
| 10 | - * Block name. |
|
| 11 | - * |
|
| 12 | - * @var string |
|
| 13 | - */ |
|
| 14 | - protected $block_name = 'product-top-rated'; |
|
| 9 | + /** |
|
| 10 | + * Block name. |
|
| 11 | + * |
|
| 12 | + * @var string |
|
| 13 | + */ |
|
| 14 | + protected $block_name = 'product-top-rated'; |
|
| 15 | 15 | |
| 16 | - /** |
|
| 17 | - * Force orderby to rating. |
|
| 18 | - * |
|
| 19 | - * @param array $query_args Query args. |
|
| 20 | - */ |
|
| 21 | - protected function set_block_query_args( &$query_args ) { |
|
| 22 | - $query_args['orderby'] = 'rating'; |
|
| 23 | - } |
|
| 16 | + /** |
|
| 17 | + * Force orderby to rating. |
|
| 18 | + * |
|
| 19 | + * @param array $query_args Query args. |
|
| 20 | + */ |
|
| 21 | + protected function set_block_query_args( &$query_args ) { |
|
| 22 | + $query_args['orderby'] = 'rating'; |
|
| 23 | + } |
|
| 24 | 24 | } |
@@ -18,7 +18,7 @@ |
||
| 18 | 18 | * |
| 19 | 19 | * @param array $query_args Query args. |
| 20 | 20 | */ |
| 21 | - protected function set_block_query_args( &$query_args ) { |
|
| 21 | + protected function set_block_query_args(&$query_args) { |
|
| 22 | 22 | $query_args['orderby'] = 'rating'; |
| 23 | 23 | } |
| 24 | 24 | } |
@@ -10,494 +10,494 @@ discard block |
||
| 10 | 10 | */ |
| 11 | 11 | abstract class AbstractProductGrid extends AbstractDynamicBlock { |
| 12 | 12 | |
| 13 | - /** |
|
| 14 | - * Attributes. |
|
| 15 | - * |
|
| 16 | - * @var array |
|
| 17 | - */ |
|
| 18 | - protected $attributes = array(); |
|
| 19 | - |
|
| 20 | - /** |
|
| 21 | - * InnerBlocks content. |
|
| 22 | - * |
|
| 23 | - * @var string |
|
| 24 | - */ |
|
| 25 | - protected $content = ''; |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * Query args. |
|
| 29 | - * |
|
| 30 | - * @var array |
|
| 31 | - */ |
|
| 32 | - protected $query_args = array(); |
|
| 33 | - |
|
| 34 | - /** |
|
| 35 | - * Meta query args. |
|
| 36 | - * |
|
| 37 | - * @var array |
|
| 38 | - */ |
|
| 39 | - protected $meta_query = array(); |
|
| 40 | - |
|
| 41 | - /** |
|
| 42 | - * Get a set of attributes shared across most of the grid blocks. |
|
| 43 | - * |
|
| 44 | - * @return array List of block attributes with type and defaults. |
|
| 45 | - */ |
|
| 46 | - protected function get_block_type_attributes() { |
|
| 47 | - return array( |
|
| 48 | - 'className' => $this->get_schema_string(), |
|
| 49 | - 'columns' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_columns', 3 ) ), |
|
| 50 | - 'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ), |
|
| 51 | - 'categories' => $this->get_schema_list_ids(), |
|
| 52 | - 'catOperator' => array( |
|
| 53 | - 'type' => 'string', |
|
| 54 | - 'default' => 'any', |
|
| 55 | - ), |
|
| 56 | - 'contentVisibility' => $this->get_schema_content_visibility(), |
|
| 57 | - 'align' => $this->get_schema_align(), |
|
| 58 | - 'alignButtons' => $this->get_schema_boolean( false ), |
|
| 59 | - 'isPreview' => $this->get_schema_boolean( false ), |
|
| 60 | - 'stockStatus' => array( |
|
| 61 | - 'type' => 'array', |
|
| 62 | - 'default' => array_keys( wc_get_product_stock_status_options() ), |
|
| 63 | - ), |
|
| 64 | - ); |
|
| 65 | - } |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * Include and render the dynamic block. |
|
| 69 | - * |
|
| 70 | - * @param array $attributes Block attributes. Default empty array. |
|
| 71 | - * @param string $content Block content. Default empty string. |
|
| 72 | - * @return string Rendered block type output. |
|
| 73 | - */ |
|
| 74 | - protected function render( $attributes = array(), $content = '' ) { |
|
| 75 | - $this->attributes = $this->parse_attributes( $attributes ); |
|
| 76 | - $this->content = $content; |
|
| 77 | - $this->query_args = $this->parse_query_args(); |
|
| 78 | - $products = array_filter( array_map( 'wc_get_product', $this->get_products() ) ); |
|
| 79 | - |
|
| 80 | - if ( ! $products ) { |
|
| 81 | - return ''; |
|
| 82 | - } |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Product List Render event. |
|
| 86 | - * |
|
| 87 | - * Fires a WP Hook named `experimental__woocommerce_blocks-product-list-render` on render so that the client |
|
| 88 | - * can add event handling when certain products are displayed. This can be used by tracking extensions such |
|
| 89 | - * as Google Analytics to track impressions. |
|
| 90 | - * |
|
| 91 | - * Provides the list of product data (shaped like the Store API responses) and the block name. |
|
| 92 | - */ |
|
| 93 | - $this->asset_api->add_inline_script( |
|
| 94 | - 'wp-hooks', |
|
| 95 | - ' |
|
| 13 | + /** |
|
| 14 | + * Attributes. |
|
| 15 | + * |
|
| 16 | + * @var array |
|
| 17 | + */ |
|
| 18 | + protected $attributes = array(); |
|
| 19 | + |
|
| 20 | + /** |
|
| 21 | + * InnerBlocks content. |
|
| 22 | + * |
|
| 23 | + * @var string |
|
| 24 | + */ |
|
| 25 | + protected $content = ''; |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * Query args. |
|
| 29 | + * |
|
| 30 | + * @var array |
|
| 31 | + */ |
|
| 32 | + protected $query_args = array(); |
|
| 33 | + |
|
| 34 | + /** |
|
| 35 | + * Meta query args. |
|
| 36 | + * |
|
| 37 | + * @var array |
|
| 38 | + */ |
|
| 39 | + protected $meta_query = array(); |
|
| 40 | + |
|
| 41 | + /** |
|
| 42 | + * Get a set of attributes shared across most of the grid blocks. |
|
| 43 | + * |
|
| 44 | + * @return array List of block attributes with type and defaults. |
|
| 45 | + */ |
|
| 46 | + protected function get_block_type_attributes() { |
|
| 47 | + return array( |
|
| 48 | + 'className' => $this->get_schema_string(), |
|
| 49 | + 'columns' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_columns', 3 ) ), |
|
| 50 | + 'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ), |
|
| 51 | + 'categories' => $this->get_schema_list_ids(), |
|
| 52 | + 'catOperator' => array( |
|
| 53 | + 'type' => 'string', |
|
| 54 | + 'default' => 'any', |
|
| 55 | + ), |
|
| 56 | + 'contentVisibility' => $this->get_schema_content_visibility(), |
|
| 57 | + 'align' => $this->get_schema_align(), |
|
| 58 | + 'alignButtons' => $this->get_schema_boolean( false ), |
|
| 59 | + 'isPreview' => $this->get_schema_boolean( false ), |
|
| 60 | + 'stockStatus' => array( |
|
| 61 | + 'type' => 'array', |
|
| 62 | + 'default' => array_keys( wc_get_product_stock_status_options() ), |
|
| 63 | + ), |
|
| 64 | + ); |
|
| 65 | + } |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * Include and render the dynamic block. |
|
| 69 | + * |
|
| 70 | + * @param array $attributes Block attributes. Default empty array. |
|
| 71 | + * @param string $content Block content. Default empty string. |
|
| 72 | + * @return string Rendered block type output. |
|
| 73 | + */ |
|
| 74 | + protected function render( $attributes = array(), $content = '' ) { |
|
| 75 | + $this->attributes = $this->parse_attributes( $attributes ); |
|
| 76 | + $this->content = $content; |
|
| 77 | + $this->query_args = $this->parse_query_args(); |
|
| 78 | + $products = array_filter( array_map( 'wc_get_product', $this->get_products() ) ); |
|
| 79 | + |
|
| 80 | + if ( ! $products ) { |
|
| 81 | + return ''; |
|
| 82 | + } |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Product List Render event. |
|
| 86 | + * |
|
| 87 | + * Fires a WP Hook named `experimental__woocommerce_blocks-product-list-render` on render so that the client |
|
| 88 | + * can add event handling when certain products are displayed. This can be used by tracking extensions such |
|
| 89 | + * as Google Analytics to track impressions. |
|
| 90 | + * |
|
| 91 | + * Provides the list of product data (shaped like the Store API responses) and the block name. |
|
| 92 | + */ |
|
| 93 | + $this->asset_api->add_inline_script( |
|
| 94 | + 'wp-hooks', |
|
| 95 | + ' |
|
| 96 | 96 | window.addEventListener( "DOMContentLoaded", () => { |
| 97 | 97 | wp.hooks.doAction( |
| 98 | 98 | "experimental__woocommerce_blocks-product-list-render", |
| 99 | 99 | { |
| 100 | 100 | products: JSON.parse( decodeURIComponent( "' . esc_js( |
| 101 | - rawurlencode( |
|
| 102 | - wp_json_encode( |
|
| 103 | - array_map( |
|
| 104 | - [ StoreApi::container()->get( SchemaController::class )->get( 'product' ), 'get_item_response' ], |
|
| 105 | - $products |
|
| 106 | - ) |
|
| 107 | - ) |
|
| 108 | - ) |
|
| 109 | - ) . '" ) ), |
|
| 101 | + rawurlencode( |
|
| 102 | + wp_json_encode( |
|
| 103 | + array_map( |
|
| 104 | + [ StoreApi::container()->get( SchemaController::class )->get( 'product' ), 'get_item_response' ], |
|
| 105 | + $products |
|
| 106 | + ) |
|
| 107 | + ) |
|
| 108 | + ) |
|
| 109 | + ) . '" ) ), |
|
| 110 | 110 | listName: "' . esc_js( $this->block_name ) . '" |
| 111 | 111 | } |
| 112 | 112 | ); |
| 113 | 113 | } ); |
| 114 | 114 | ', |
| 115 | - 'after' |
|
| 116 | - ); |
|
| 117 | - |
|
| 118 | - return sprintf( |
|
| 119 | - '<div class="%s"><ul class="wc-block-grid__products">%s</ul></div>', |
|
| 120 | - esc_attr( $this->get_container_classes() ), |
|
| 121 | - implode( '', array_map( array( $this, 'render_product' ), $products ) ) |
|
| 122 | - ); |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - /** |
|
| 126 | - * Get the schema for the contentVisibility attribute |
|
| 127 | - * |
|
| 128 | - * @return array List of block attributes with type and defaults. |
|
| 129 | - */ |
|
| 130 | - protected function get_schema_content_visibility() { |
|
| 131 | - return array( |
|
| 132 | - 'type' => 'object', |
|
| 133 | - 'properties' => array( |
|
| 134 | - 'image' => $this->get_schema_boolean( true ), |
|
| 135 | - 'title' => $this->get_schema_boolean( true ), |
|
| 136 | - 'price' => $this->get_schema_boolean( true ), |
|
| 137 | - 'rating' => $this->get_schema_boolean( true ), |
|
| 138 | - 'button' => $this->get_schema_boolean( true ), |
|
| 139 | - ), |
|
| 140 | - ); |
|
| 141 | - } |
|
| 142 | - |
|
| 143 | - /** |
|
| 144 | - * Get the schema for the orderby attribute. |
|
| 145 | - * |
|
| 146 | - * @return array Property definition of `orderby` attribute. |
|
| 147 | - */ |
|
| 148 | - protected function get_schema_orderby() { |
|
| 149 | - return array( |
|
| 150 | - 'type' => 'string', |
|
| 151 | - 'enum' => array( 'date', 'popularity', 'price_asc', 'price_desc', 'rating', 'title', 'menu_order' ), |
|
| 152 | - 'default' => 'date', |
|
| 153 | - ); |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - /** |
|
| 157 | - * Get the block's attributes. |
|
| 158 | - * |
|
| 159 | - * @param array $attributes Block attributes. Default empty array. |
|
| 160 | - * @return array Block attributes merged with defaults. |
|
| 161 | - */ |
|
| 162 | - protected function parse_attributes( $attributes ) { |
|
| 163 | - // These should match what's set in JS `registerBlockType`. |
|
| 164 | - $defaults = array( |
|
| 165 | - 'columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ), |
|
| 166 | - 'rows' => wc_get_theme_support( 'product_blocks::default_rows', 3 ), |
|
| 167 | - 'alignButtons' => false, |
|
| 168 | - 'categories' => array(), |
|
| 169 | - 'catOperator' => 'any', |
|
| 170 | - 'contentVisibility' => array( |
|
| 171 | - 'image' => true, |
|
| 172 | - 'title' => true, |
|
| 173 | - 'price' => true, |
|
| 174 | - 'rating' => true, |
|
| 175 | - 'button' => true, |
|
| 176 | - ), |
|
| 177 | - 'stockStatus' => array_keys( wc_get_product_stock_status_options() ), |
|
| 178 | - ); |
|
| 179 | - |
|
| 180 | - return wp_parse_args( $attributes, $defaults ); |
|
| 181 | - } |
|
| 182 | - |
|
| 183 | - /** |
|
| 184 | - * Parse query args. |
|
| 185 | - * |
|
| 186 | - * @return array |
|
| 187 | - */ |
|
| 188 | - protected function parse_query_args() { |
|
| 189 | - // Store the original meta query. |
|
| 190 | - $this->meta_query = WC()->query->get_meta_query(); |
|
| 191 | - |
|
| 192 | - $query_args = array( |
|
| 193 | - 'post_type' => 'product', |
|
| 194 | - 'post_status' => 'publish', |
|
| 195 | - 'fields' => 'ids', |
|
| 196 | - 'ignore_sticky_posts' => true, |
|
| 197 | - 'no_found_rows' => false, |
|
| 198 | - 'orderby' => '', |
|
| 199 | - 'order' => '', |
|
| 200 | - 'meta_query' => $this->meta_query, // phpcs:ignore WordPress.DB.SlowDBQuery |
|
| 201 | - 'tax_query' => array(), // phpcs:ignore WordPress.DB.SlowDBQuery |
|
| 202 | - 'posts_per_page' => $this->get_products_limit(), |
|
| 203 | - ); |
|
| 204 | - |
|
| 205 | - $this->set_block_query_args( $query_args ); |
|
| 206 | - $this->set_ordering_query_args( $query_args ); |
|
| 207 | - $this->set_categories_query_args( $query_args ); |
|
| 208 | - $this->set_visibility_query_args( $query_args ); |
|
| 209 | - $this->set_stock_status_query_args( $query_args ); |
|
| 210 | - |
|
| 211 | - return $query_args; |
|
| 212 | - } |
|
| 213 | - |
|
| 214 | - /** |
|
| 215 | - * Parse query args. |
|
| 216 | - * |
|
| 217 | - * @param array $query_args Query args. |
|
| 218 | - */ |
|
| 219 | - protected function set_ordering_query_args( &$query_args ) { |
|
| 220 | - if ( isset( $this->attributes['orderby'] ) ) { |
|
| 221 | - if ( 'price_desc' === $this->attributes['orderby'] ) { |
|
| 222 | - $query_args['orderby'] = 'price'; |
|
| 223 | - $query_args['order'] = 'DESC'; |
|
| 224 | - } elseif ( 'price_asc' === $this->attributes['orderby'] ) { |
|
| 225 | - $query_args['orderby'] = 'price'; |
|
| 226 | - $query_args['order'] = 'ASC'; |
|
| 227 | - } elseif ( 'date' === $this->attributes['orderby'] ) { |
|
| 228 | - $query_args['orderby'] = 'date'; |
|
| 229 | - $query_args['order'] = 'DESC'; |
|
| 230 | - } else { |
|
| 231 | - $query_args['orderby'] = $this->attributes['orderby']; |
|
| 232 | - } |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - $query_args = array_merge( |
|
| 236 | - $query_args, |
|
| 237 | - WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] ) |
|
| 238 | - ); |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * Set args specific to this block |
|
| 243 | - * |
|
| 244 | - * @param array $query_args Query args. |
|
| 245 | - */ |
|
| 246 | - abstract protected function set_block_query_args( &$query_args ); |
|
| 247 | - |
|
| 248 | - /** |
|
| 249 | - * Set categories query args. |
|
| 250 | - * |
|
| 251 | - * @param array $query_args Query args. |
|
| 252 | - */ |
|
| 253 | - protected function set_categories_query_args( &$query_args ) { |
|
| 254 | - if ( ! empty( $this->attributes['categories'] ) ) { |
|
| 255 | - $categories = array_map( 'absint', $this->attributes['categories'] ); |
|
| 256 | - |
|
| 257 | - $query_args['tax_query'][] = array( |
|
| 258 | - 'taxonomy' => 'product_cat', |
|
| 259 | - 'terms' => $categories, |
|
| 260 | - 'field' => 'term_id', |
|
| 261 | - 'operator' => 'all' === $this->attributes['catOperator'] ? 'AND' : 'IN', |
|
| 262 | - |
|
| 263 | - /* |
|
| 115 | + 'after' |
|
| 116 | + ); |
|
| 117 | + |
|
| 118 | + return sprintf( |
|
| 119 | + '<div class="%s"><ul class="wc-block-grid__products">%s</ul></div>', |
|
| 120 | + esc_attr( $this->get_container_classes() ), |
|
| 121 | + implode( '', array_map( array( $this, 'render_product' ), $products ) ) |
|
| 122 | + ); |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + /** |
|
| 126 | + * Get the schema for the contentVisibility attribute |
|
| 127 | + * |
|
| 128 | + * @return array List of block attributes with type and defaults. |
|
| 129 | + */ |
|
| 130 | + protected function get_schema_content_visibility() { |
|
| 131 | + return array( |
|
| 132 | + 'type' => 'object', |
|
| 133 | + 'properties' => array( |
|
| 134 | + 'image' => $this->get_schema_boolean( true ), |
|
| 135 | + 'title' => $this->get_schema_boolean( true ), |
|
| 136 | + 'price' => $this->get_schema_boolean( true ), |
|
| 137 | + 'rating' => $this->get_schema_boolean( true ), |
|
| 138 | + 'button' => $this->get_schema_boolean( true ), |
|
| 139 | + ), |
|
| 140 | + ); |
|
| 141 | + } |
|
| 142 | + |
|
| 143 | + /** |
|
| 144 | + * Get the schema for the orderby attribute. |
|
| 145 | + * |
|
| 146 | + * @return array Property definition of `orderby` attribute. |
|
| 147 | + */ |
|
| 148 | + protected function get_schema_orderby() { |
|
| 149 | + return array( |
|
| 150 | + 'type' => 'string', |
|
| 151 | + 'enum' => array( 'date', 'popularity', 'price_asc', 'price_desc', 'rating', 'title', 'menu_order' ), |
|
| 152 | + 'default' => 'date', |
|
| 153 | + ); |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + /** |
|
| 157 | + * Get the block's attributes. |
|
| 158 | + * |
|
| 159 | + * @param array $attributes Block attributes. Default empty array. |
|
| 160 | + * @return array Block attributes merged with defaults. |
|
| 161 | + */ |
|
| 162 | + protected function parse_attributes( $attributes ) { |
|
| 163 | + // These should match what's set in JS `registerBlockType`. |
|
| 164 | + $defaults = array( |
|
| 165 | + 'columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ), |
|
| 166 | + 'rows' => wc_get_theme_support( 'product_blocks::default_rows', 3 ), |
|
| 167 | + 'alignButtons' => false, |
|
| 168 | + 'categories' => array(), |
|
| 169 | + 'catOperator' => 'any', |
|
| 170 | + 'contentVisibility' => array( |
|
| 171 | + 'image' => true, |
|
| 172 | + 'title' => true, |
|
| 173 | + 'price' => true, |
|
| 174 | + 'rating' => true, |
|
| 175 | + 'button' => true, |
|
| 176 | + ), |
|
| 177 | + 'stockStatus' => array_keys( wc_get_product_stock_status_options() ), |
|
| 178 | + ); |
|
| 179 | + |
|
| 180 | + return wp_parse_args( $attributes, $defaults ); |
|
| 181 | + } |
|
| 182 | + |
|
| 183 | + /** |
|
| 184 | + * Parse query args. |
|
| 185 | + * |
|
| 186 | + * @return array |
|
| 187 | + */ |
|
| 188 | + protected function parse_query_args() { |
|
| 189 | + // Store the original meta query. |
|
| 190 | + $this->meta_query = WC()->query->get_meta_query(); |
|
| 191 | + |
|
| 192 | + $query_args = array( |
|
| 193 | + 'post_type' => 'product', |
|
| 194 | + 'post_status' => 'publish', |
|
| 195 | + 'fields' => 'ids', |
|
| 196 | + 'ignore_sticky_posts' => true, |
|
| 197 | + 'no_found_rows' => false, |
|
| 198 | + 'orderby' => '', |
|
| 199 | + 'order' => '', |
|
| 200 | + 'meta_query' => $this->meta_query, // phpcs:ignore WordPress.DB.SlowDBQuery |
|
| 201 | + 'tax_query' => array(), // phpcs:ignore WordPress.DB.SlowDBQuery |
|
| 202 | + 'posts_per_page' => $this->get_products_limit(), |
|
| 203 | + ); |
|
| 204 | + |
|
| 205 | + $this->set_block_query_args( $query_args ); |
|
| 206 | + $this->set_ordering_query_args( $query_args ); |
|
| 207 | + $this->set_categories_query_args( $query_args ); |
|
| 208 | + $this->set_visibility_query_args( $query_args ); |
|
| 209 | + $this->set_stock_status_query_args( $query_args ); |
|
| 210 | + |
|
| 211 | + return $query_args; |
|
| 212 | + } |
|
| 213 | + |
|
| 214 | + /** |
|
| 215 | + * Parse query args. |
|
| 216 | + * |
|
| 217 | + * @param array $query_args Query args. |
|
| 218 | + */ |
|
| 219 | + protected function set_ordering_query_args( &$query_args ) { |
|
| 220 | + if ( isset( $this->attributes['orderby'] ) ) { |
|
| 221 | + if ( 'price_desc' === $this->attributes['orderby'] ) { |
|
| 222 | + $query_args['orderby'] = 'price'; |
|
| 223 | + $query_args['order'] = 'DESC'; |
|
| 224 | + } elseif ( 'price_asc' === $this->attributes['orderby'] ) { |
|
| 225 | + $query_args['orderby'] = 'price'; |
|
| 226 | + $query_args['order'] = 'ASC'; |
|
| 227 | + } elseif ( 'date' === $this->attributes['orderby'] ) { |
|
| 228 | + $query_args['orderby'] = 'date'; |
|
| 229 | + $query_args['order'] = 'DESC'; |
|
| 230 | + } else { |
|
| 231 | + $query_args['orderby'] = $this->attributes['orderby']; |
|
| 232 | + } |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + $query_args = array_merge( |
|
| 236 | + $query_args, |
|
| 237 | + WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] ) |
|
| 238 | + ); |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * Set args specific to this block |
|
| 243 | + * |
|
| 244 | + * @param array $query_args Query args. |
|
| 245 | + */ |
|
| 246 | + abstract protected function set_block_query_args( &$query_args ); |
|
| 247 | + |
|
| 248 | + /** |
|
| 249 | + * Set categories query args. |
|
| 250 | + * |
|
| 251 | + * @param array $query_args Query args. |
|
| 252 | + */ |
|
| 253 | + protected function set_categories_query_args( &$query_args ) { |
|
| 254 | + if ( ! empty( $this->attributes['categories'] ) ) { |
|
| 255 | + $categories = array_map( 'absint', $this->attributes['categories'] ); |
|
| 256 | + |
|
| 257 | + $query_args['tax_query'][] = array( |
|
| 258 | + 'taxonomy' => 'product_cat', |
|
| 259 | + 'terms' => $categories, |
|
| 260 | + 'field' => 'term_id', |
|
| 261 | + 'operator' => 'all' === $this->attributes['catOperator'] ? 'AND' : 'IN', |
|
| 262 | + |
|
| 263 | + /* |
|
| 264 | 264 | * When cat_operator is AND, the children categories should be excluded, |
| 265 | 265 | * as only products belonging to all the children categories would be selected. |
| 266 | 266 | */ |
| 267 | - 'include_children' => 'all' === $this->attributes['catOperator'] ? false : true, |
|
| 268 | - ); |
|
| 269 | - } |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - /** |
|
| 273 | - * Set visibility query args. |
|
| 274 | - * |
|
| 275 | - * @param array $query_args Query args. |
|
| 276 | - */ |
|
| 277 | - protected function set_visibility_query_args( &$query_args ) { |
|
| 278 | - $product_visibility_terms = wc_get_product_visibility_term_ids(); |
|
| 279 | - $product_visibility_not_in = array( $product_visibility_terms['exclude-from-catalog'] ); |
|
| 280 | - |
|
| 281 | - if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) { |
|
| 282 | - $product_visibility_not_in[] = $product_visibility_terms['outofstock']; |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - $query_args['tax_query'][] = array( |
|
| 286 | - 'taxonomy' => 'product_visibility', |
|
| 287 | - 'field' => 'term_taxonomy_id', |
|
| 288 | - 'terms' => $product_visibility_not_in, |
|
| 289 | - 'operator' => 'NOT IN', |
|
| 290 | - ); |
|
| 291 | - } |
|
| 292 | - |
|
| 293 | - /** |
|
| 294 | - * Set which stock status to use when displaying products. |
|
| 295 | - * |
|
| 296 | - * @param array $query_args Query args. |
|
| 297 | - * @return void |
|
| 298 | - */ |
|
| 299 | - protected function set_stock_status_query_args( &$query_args ) { |
|
| 300 | - $stock_statuses = array_keys( wc_get_product_stock_status_options() ); |
|
| 301 | - |
|
| 302 | - // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query |
|
| 303 | - if ( isset( $this->attributes['stockStatus'] ) && $stock_statuses !== $this->attributes['stockStatus'] ) { |
|
| 304 | - // Reset meta_query then update with our stock status. |
|
| 305 | - $query_args['meta_query'] = $this->meta_query; |
|
| 306 | - $query_args['meta_query'][] = array( |
|
| 307 | - 'key' => '_stock_status', |
|
| 308 | - 'value' => array_merge( [ '' ], $this->attributes['stockStatus'] ), |
|
| 309 | - 'compare' => 'IN', |
|
| 310 | - ); |
|
| 311 | - } else { |
|
| 312 | - $query_args['meta_query'] = $this->meta_query; |
|
| 313 | - } |
|
| 314 | - // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_query |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - /** |
|
| 318 | - * Works out the item limit based on rows and columns, or returns default. |
|
| 319 | - * |
|
| 320 | - * @return int |
|
| 321 | - */ |
|
| 322 | - protected function get_products_limit() { |
|
| 323 | - if ( isset( $this->attributes['rows'], $this->attributes['columns'] ) && ! empty( $this->attributes['rows'] ) ) { |
|
| 324 | - $this->attributes['limit'] = intval( $this->attributes['columns'] ) * intval( $this->attributes['rows'] ); |
|
| 325 | - } |
|
| 326 | - return intval( $this->attributes['limit'] ); |
|
| 327 | - } |
|
| 328 | - |
|
| 329 | - /** |
|
| 330 | - * Run the query and return an array of product IDs |
|
| 331 | - * |
|
| 332 | - * @return array List of product IDs |
|
| 333 | - */ |
|
| 334 | - protected function get_products() { |
|
| 335 | - /** |
|
| 336 | - * Filters whether or not the product grid is cacheable. |
|
| 337 | - * |
|
| 338 | - * @param boolean $is_cacheable The list of script dependencies. |
|
| 339 | - * @param array $query_args Query args for the products query passed to BlocksWpQuery. |
|
| 340 | - * @return array True to enable cache, false to disable cache. |
|
| 341 | - */ |
|
| 342 | - $is_cacheable = (bool) apply_filters( 'woocommerce_blocks_product_grid_is_cacheable', true, $this->query_args ); |
|
| 343 | - $transient_version = \WC_Cache_Helper::get_transient_version( 'product_query' ); |
|
| 344 | - |
|
| 345 | - $query = new BlocksWpQuery( $this->query_args ); |
|
| 346 | - $results = wp_parse_id_list( $is_cacheable ? $query->get_cached_posts( $transient_version ) : $query->get_posts() ); |
|
| 347 | - |
|
| 348 | - // Remove ordering query arguments which may have been added by get_catalog_ordering_args. |
|
| 349 | - WC()->query->remove_ordering_args(); |
|
| 350 | - |
|
| 351 | - // Prime caches to reduce future queries. Note _prime_post_caches is private--we could replace this with our own |
|
| 352 | - // query if it becomes unavailable. |
|
| 353 | - if ( is_callable( '_prime_post_caches' ) ) { |
|
| 354 | - _prime_post_caches( $results ); |
|
| 355 | - } |
|
| 356 | - |
|
| 357 | - $this->prime_product_variations( $results ); |
|
| 358 | - |
|
| 359 | - return $results; |
|
| 360 | - } |
|
| 361 | - |
|
| 362 | - /** |
|
| 363 | - * Retrieve IDs that are not already present in the cache. |
|
| 364 | - * |
|
| 365 | - * Based on WordPress function: _get_non_cached_ids |
|
| 366 | - * |
|
| 367 | - * @param int[] $product_ids Array of IDs. |
|
| 368 | - * @param string $cache_key The cache bucket to check against. |
|
| 369 | - * @return int[] Array of IDs not present in the cache. |
|
| 370 | - */ |
|
| 371 | - protected function get_non_cached_ids( $product_ids, $cache_key ) { |
|
| 372 | - $non_cached_ids = array(); |
|
| 373 | - $cache_values = wp_cache_get_multiple( $product_ids, $cache_key ); |
|
| 374 | - |
|
| 375 | - foreach ( $cache_values as $id => $value ) { |
|
| 376 | - if ( ! $value ) { |
|
| 377 | - $non_cached_ids[] = (int) $id; |
|
| 378 | - } |
|
| 379 | - } |
|
| 380 | - |
|
| 381 | - return $non_cached_ids; |
|
| 382 | - } |
|
| 383 | - |
|
| 384 | - /** |
|
| 385 | - * Prime query cache of product variation meta data. |
|
| 386 | - * |
|
| 387 | - * Prepares values in the product_ID_variation_meta_data cache for later use in the ProductSchema::get_variations() |
|
| 388 | - * method. Doing so here reduces the total number of queries needed. |
|
| 389 | - * |
|
| 390 | - * @param int[] $product_ids Product ids to prime variation cache for. |
|
| 391 | - */ |
|
| 392 | - protected function prime_product_variations( $product_ids ) { |
|
| 393 | - $cache_group = 'product_variation_meta_data'; |
|
| 394 | - $prime_product_ids = $this->get_non_cached_ids( wp_parse_id_list( $product_ids ), $cache_group ); |
|
| 395 | - |
|
| 396 | - if ( ! $prime_product_ids ) { |
|
| 397 | - return; |
|
| 398 | - } |
|
| 399 | - |
|
| 400 | - global $wpdb; |
|
| 401 | - |
|
| 402 | - // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared |
|
| 403 | - $product_variations = $wpdb->get_results( "SELECT ID as variation_id, post_parent as product_id from {$wpdb->posts} WHERE post_parent IN ( " . implode( ',', $prime_product_ids ) . ' )', ARRAY_A ); |
|
| 404 | - $prime_variation_ids = array_column( $product_variations, 'variation_id' ); |
|
| 405 | - $variation_ids_by_parent = array_column( $product_variations, 'product_id', 'variation_id' ); |
|
| 406 | - |
|
| 407 | - if ( empty( $prime_variation_ids ) ) { |
|
| 408 | - return; |
|
| 409 | - } |
|
| 410 | - |
|
| 411 | - $all_variation_meta_data = $wpdb->get_results( |
|
| 412 | - $wpdb->prepare( |
|
| 413 | - "SELECT post_id as variation_id, meta_key as attribute_key, meta_value as attribute_value FROM {$wpdb->postmeta} WHERE post_id IN (" . implode( ',', array_map( 'esc_sql', $prime_variation_ids ) ) . ') AND meta_key LIKE %s', |
|
| 414 | - $wpdb->esc_like( 'attribute_' ) . '%' |
|
| 415 | - ) |
|
| 416 | - ); |
|
| 417 | - // phpcs:enable |
|
| 418 | - // Prepare the data to cache by indexing by the parent product. |
|
| 419 | - $primed_data = array_reduce( |
|
| 420 | - $all_variation_meta_data, |
|
| 421 | - function( $values, $data ) use ( $variation_ids_by_parent ) { |
|
| 422 | - $values[ $variation_ids_by_parent[ $data->variation_id ] ?? 0 ][] = $data; |
|
| 423 | - return $values; |
|
| 424 | - }, |
|
| 425 | - array_fill_keys( $prime_product_ids, [] ) |
|
| 426 | - ); |
|
| 427 | - |
|
| 428 | - // Cache everything. |
|
| 429 | - foreach ( $primed_data as $product_id => $variation_meta_data ) { |
|
| 430 | - wp_cache_set( |
|
| 431 | - $product_id, |
|
| 432 | - [ |
|
| 433 | - 'last_modified' => get_the_modified_date( 'U', $product_id ), |
|
| 434 | - 'data' => $variation_meta_data, |
|
| 435 | - ], |
|
| 436 | - $cache_group |
|
| 437 | - ); |
|
| 438 | - } |
|
| 439 | - } |
|
| 440 | - |
|
| 441 | - /** |
|
| 442 | - * Get the list of classes to apply to this block. |
|
| 443 | - * |
|
| 444 | - * @return string space-separated list of classes. |
|
| 445 | - */ |
|
| 446 | - protected function get_container_classes() { |
|
| 447 | - $classes = array( |
|
| 448 | - 'wc-block-grid', |
|
| 449 | - "wp-block-{$this->block_name}", |
|
| 450 | - "wc-block-{$this->block_name}", |
|
| 451 | - "has-{$this->attributes['columns']}-columns", |
|
| 452 | - ); |
|
| 453 | - |
|
| 454 | - if ( $this->attributes['rows'] > 1 ) { |
|
| 455 | - $classes[] = 'has-multiple-rows'; |
|
| 456 | - } |
|
| 457 | - |
|
| 458 | - if ( isset( $this->attributes['align'] ) ) { |
|
| 459 | - $classes[] = "align{$this->attributes['align']}"; |
|
| 460 | - } |
|
| 461 | - |
|
| 462 | - if ( ! empty( $this->attributes['alignButtons'] ) ) { |
|
| 463 | - $classes[] = 'has-aligned-buttons'; |
|
| 464 | - } |
|
| 465 | - |
|
| 466 | - if ( ! empty( $this->attributes['className'] ) ) { |
|
| 467 | - $classes[] = $this->attributes['className']; |
|
| 468 | - } |
|
| 469 | - |
|
| 470 | - return implode( ' ', $classes ); |
|
| 471 | - } |
|
| 472 | - |
|
| 473 | - /** |
|
| 474 | - * Render a single products. |
|
| 475 | - * |
|
| 476 | - * @param \WC_Product $product Product object. |
|
| 477 | - * @return string Rendered product output. |
|
| 478 | - */ |
|
| 479 | - protected function render_product( $product ) { |
|
| 480 | - $data = (object) array( |
|
| 481 | - 'permalink' => esc_url( $product->get_permalink() ), |
|
| 482 | - 'image' => $this->get_image_html( $product ), |
|
| 483 | - 'title' => $this->get_title_html( $product ), |
|
| 484 | - 'rating' => $this->get_rating_html( $product ), |
|
| 485 | - 'price' => $this->get_price_html( $product ), |
|
| 486 | - 'badge' => $this->get_sale_badge_html( $product ), |
|
| 487 | - 'button' => $this->get_button_html( $product ), |
|
| 488 | - ); |
|
| 489 | - |
|
| 490 | - /** |
|
| 491 | - * Filters the HTML for products in the grid. |
|
| 492 | - * |
|
| 493 | - * @param string $html Product grid item HTML. |
|
| 494 | - * @param array $data Product data passed to the template. |
|
| 495 | - * @param \WC_Product $product Product object. |
|
| 496 | - * @return string Updated product grid item HTML. |
|
| 497 | - */ |
|
| 498 | - return apply_filters( |
|
| 499 | - 'woocommerce_blocks_product_grid_item_html', |
|
| 500 | - "<li class=\"wc-block-grid__product\"> |
|
| 267 | + 'include_children' => 'all' === $this->attributes['catOperator'] ? false : true, |
|
| 268 | + ); |
|
| 269 | + } |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + /** |
|
| 273 | + * Set visibility query args. |
|
| 274 | + * |
|
| 275 | + * @param array $query_args Query args. |
|
| 276 | + */ |
|
| 277 | + protected function set_visibility_query_args( &$query_args ) { |
|
| 278 | + $product_visibility_terms = wc_get_product_visibility_term_ids(); |
|
| 279 | + $product_visibility_not_in = array( $product_visibility_terms['exclude-from-catalog'] ); |
|
| 280 | + |
|
| 281 | + if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) { |
|
| 282 | + $product_visibility_not_in[] = $product_visibility_terms['outofstock']; |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + $query_args['tax_query'][] = array( |
|
| 286 | + 'taxonomy' => 'product_visibility', |
|
| 287 | + 'field' => 'term_taxonomy_id', |
|
| 288 | + 'terms' => $product_visibility_not_in, |
|
| 289 | + 'operator' => 'NOT IN', |
|
| 290 | + ); |
|
| 291 | + } |
|
| 292 | + |
|
| 293 | + /** |
|
| 294 | + * Set which stock status to use when displaying products. |
|
| 295 | + * |
|
| 296 | + * @param array $query_args Query args. |
|
| 297 | + * @return void |
|
| 298 | + */ |
|
| 299 | + protected function set_stock_status_query_args( &$query_args ) { |
|
| 300 | + $stock_statuses = array_keys( wc_get_product_stock_status_options() ); |
|
| 301 | + |
|
| 302 | + // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query |
|
| 303 | + if ( isset( $this->attributes['stockStatus'] ) && $stock_statuses !== $this->attributes['stockStatus'] ) { |
|
| 304 | + // Reset meta_query then update with our stock status. |
|
| 305 | + $query_args['meta_query'] = $this->meta_query; |
|
| 306 | + $query_args['meta_query'][] = array( |
|
| 307 | + 'key' => '_stock_status', |
|
| 308 | + 'value' => array_merge( [ '' ], $this->attributes['stockStatus'] ), |
|
| 309 | + 'compare' => 'IN', |
|
| 310 | + ); |
|
| 311 | + } else { |
|
| 312 | + $query_args['meta_query'] = $this->meta_query; |
|
| 313 | + } |
|
| 314 | + // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_query |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + /** |
|
| 318 | + * Works out the item limit based on rows and columns, or returns default. |
|
| 319 | + * |
|
| 320 | + * @return int |
|
| 321 | + */ |
|
| 322 | + protected function get_products_limit() { |
|
| 323 | + if ( isset( $this->attributes['rows'], $this->attributes['columns'] ) && ! empty( $this->attributes['rows'] ) ) { |
|
| 324 | + $this->attributes['limit'] = intval( $this->attributes['columns'] ) * intval( $this->attributes['rows'] ); |
|
| 325 | + } |
|
| 326 | + return intval( $this->attributes['limit'] ); |
|
| 327 | + } |
|
| 328 | + |
|
| 329 | + /** |
|
| 330 | + * Run the query and return an array of product IDs |
|
| 331 | + * |
|
| 332 | + * @return array List of product IDs |
|
| 333 | + */ |
|
| 334 | + protected function get_products() { |
|
| 335 | + /** |
|
| 336 | + * Filters whether or not the product grid is cacheable. |
|
| 337 | + * |
|
| 338 | + * @param boolean $is_cacheable The list of script dependencies. |
|
| 339 | + * @param array $query_args Query args for the products query passed to BlocksWpQuery. |
|
| 340 | + * @return array True to enable cache, false to disable cache. |
|
| 341 | + */ |
|
| 342 | + $is_cacheable = (bool) apply_filters( 'woocommerce_blocks_product_grid_is_cacheable', true, $this->query_args ); |
|
| 343 | + $transient_version = \WC_Cache_Helper::get_transient_version( 'product_query' ); |
|
| 344 | + |
|
| 345 | + $query = new BlocksWpQuery( $this->query_args ); |
|
| 346 | + $results = wp_parse_id_list( $is_cacheable ? $query->get_cached_posts( $transient_version ) : $query->get_posts() ); |
|
| 347 | + |
|
| 348 | + // Remove ordering query arguments which may have been added by get_catalog_ordering_args. |
|
| 349 | + WC()->query->remove_ordering_args(); |
|
| 350 | + |
|
| 351 | + // Prime caches to reduce future queries. Note _prime_post_caches is private--we could replace this with our own |
|
| 352 | + // query if it becomes unavailable. |
|
| 353 | + if ( is_callable( '_prime_post_caches' ) ) { |
|
| 354 | + _prime_post_caches( $results ); |
|
| 355 | + } |
|
| 356 | + |
|
| 357 | + $this->prime_product_variations( $results ); |
|
| 358 | + |
|
| 359 | + return $results; |
|
| 360 | + } |
|
| 361 | + |
|
| 362 | + /** |
|
| 363 | + * Retrieve IDs that are not already present in the cache. |
|
| 364 | + * |
|
| 365 | + * Based on WordPress function: _get_non_cached_ids |
|
| 366 | + * |
|
| 367 | + * @param int[] $product_ids Array of IDs. |
|
| 368 | + * @param string $cache_key The cache bucket to check against. |
|
| 369 | + * @return int[] Array of IDs not present in the cache. |
|
| 370 | + */ |
|
| 371 | + protected function get_non_cached_ids( $product_ids, $cache_key ) { |
|
| 372 | + $non_cached_ids = array(); |
|
| 373 | + $cache_values = wp_cache_get_multiple( $product_ids, $cache_key ); |
|
| 374 | + |
|
| 375 | + foreach ( $cache_values as $id => $value ) { |
|
| 376 | + if ( ! $value ) { |
|
| 377 | + $non_cached_ids[] = (int) $id; |
|
| 378 | + } |
|
| 379 | + } |
|
| 380 | + |
|
| 381 | + return $non_cached_ids; |
|
| 382 | + } |
|
| 383 | + |
|
| 384 | + /** |
|
| 385 | + * Prime query cache of product variation meta data. |
|
| 386 | + * |
|
| 387 | + * Prepares values in the product_ID_variation_meta_data cache for later use in the ProductSchema::get_variations() |
|
| 388 | + * method. Doing so here reduces the total number of queries needed. |
|
| 389 | + * |
|
| 390 | + * @param int[] $product_ids Product ids to prime variation cache for. |
|
| 391 | + */ |
|
| 392 | + protected function prime_product_variations( $product_ids ) { |
|
| 393 | + $cache_group = 'product_variation_meta_data'; |
|
| 394 | + $prime_product_ids = $this->get_non_cached_ids( wp_parse_id_list( $product_ids ), $cache_group ); |
|
| 395 | + |
|
| 396 | + if ( ! $prime_product_ids ) { |
|
| 397 | + return; |
|
| 398 | + } |
|
| 399 | + |
|
| 400 | + global $wpdb; |
|
| 401 | + |
|
| 402 | + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared |
|
| 403 | + $product_variations = $wpdb->get_results( "SELECT ID as variation_id, post_parent as product_id from {$wpdb->posts} WHERE post_parent IN ( " . implode( ',', $prime_product_ids ) . ' )', ARRAY_A ); |
|
| 404 | + $prime_variation_ids = array_column( $product_variations, 'variation_id' ); |
|
| 405 | + $variation_ids_by_parent = array_column( $product_variations, 'product_id', 'variation_id' ); |
|
| 406 | + |
|
| 407 | + if ( empty( $prime_variation_ids ) ) { |
|
| 408 | + return; |
|
| 409 | + } |
|
| 410 | + |
|
| 411 | + $all_variation_meta_data = $wpdb->get_results( |
|
| 412 | + $wpdb->prepare( |
|
| 413 | + "SELECT post_id as variation_id, meta_key as attribute_key, meta_value as attribute_value FROM {$wpdb->postmeta} WHERE post_id IN (" . implode( ',', array_map( 'esc_sql', $prime_variation_ids ) ) . ') AND meta_key LIKE %s', |
|
| 414 | + $wpdb->esc_like( 'attribute_' ) . '%' |
|
| 415 | + ) |
|
| 416 | + ); |
|
| 417 | + // phpcs:enable |
|
| 418 | + // Prepare the data to cache by indexing by the parent product. |
|
| 419 | + $primed_data = array_reduce( |
|
| 420 | + $all_variation_meta_data, |
|
| 421 | + function( $values, $data ) use ( $variation_ids_by_parent ) { |
|
| 422 | + $values[ $variation_ids_by_parent[ $data->variation_id ] ?? 0 ][] = $data; |
|
| 423 | + return $values; |
|
| 424 | + }, |
|
| 425 | + array_fill_keys( $prime_product_ids, [] ) |
|
| 426 | + ); |
|
| 427 | + |
|
| 428 | + // Cache everything. |
|
| 429 | + foreach ( $primed_data as $product_id => $variation_meta_data ) { |
|
| 430 | + wp_cache_set( |
|
| 431 | + $product_id, |
|
| 432 | + [ |
|
| 433 | + 'last_modified' => get_the_modified_date( 'U', $product_id ), |
|
| 434 | + 'data' => $variation_meta_data, |
|
| 435 | + ], |
|
| 436 | + $cache_group |
|
| 437 | + ); |
|
| 438 | + } |
|
| 439 | + } |
|
| 440 | + |
|
| 441 | + /** |
|
| 442 | + * Get the list of classes to apply to this block. |
|
| 443 | + * |
|
| 444 | + * @return string space-separated list of classes. |
|
| 445 | + */ |
|
| 446 | + protected function get_container_classes() { |
|
| 447 | + $classes = array( |
|
| 448 | + 'wc-block-grid', |
|
| 449 | + "wp-block-{$this->block_name}", |
|
| 450 | + "wc-block-{$this->block_name}", |
|
| 451 | + "has-{$this->attributes['columns']}-columns", |
|
| 452 | + ); |
|
| 453 | + |
|
| 454 | + if ( $this->attributes['rows'] > 1 ) { |
|
| 455 | + $classes[] = 'has-multiple-rows'; |
|
| 456 | + } |
|
| 457 | + |
|
| 458 | + if ( isset( $this->attributes['align'] ) ) { |
|
| 459 | + $classes[] = "align{$this->attributes['align']}"; |
|
| 460 | + } |
|
| 461 | + |
|
| 462 | + if ( ! empty( $this->attributes['alignButtons'] ) ) { |
|
| 463 | + $classes[] = 'has-aligned-buttons'; |
|
| 464 | + } |
|
| 465 | + |
|
| 466 | + if ( ! empty( $this->attributes['className'] ) ) { |
|
| 467 | + $classes[] = $this->attributes['className']; |
|
| 468 | + } |
|
| 469 | + |
|
| 470 | + return implode( ' ', $classes ); |
|
| 471 | + } |
|
| 472 | + |
|
| 473 | + /** |
|
| 474 | + * Render a single products. |
|
| 475 | + * |
|
| 476 | + * @param \WC_Product $product Product object. |
|
| 477 | + * @return string Rendered product output. |
|
| 478 | + */ |
|
| 479 | + protected function render_product( $product ) { |
|
| 480 | + $data = (object) array( |
|
| 481 | + 'permalink' => esc_url( $product->get_permalink() ), |
|
| 482 | + 'image' => $this->get_image_html( $product ), |
|
| 483 | + 'title' => $this->get_title_html( $product ), |
|
| 484 | + 'rating' => $this->get_rating_html( $product ), |
|
| 485 | + 'price' => $this->get_price_html( $product ), |
|
| 486 | + 'badge' => $this->get_sale_badge_html( $product ), |
|
| 487 | + 'button' => $this->get_button_html( $product ), |
|
| 488 | + ); |
|
| 489 | + |
|
| 490 | + /** |
|
| 491 | + * Filters the HTML for products in the grid. |
|
| 492 | + * |
|
| 493 | + * @param string $html Product grid item HTML. |
|
| 494 | + * @param array $data Product data passed to the template. |
|
| 495 | + * @param \WC_Product $product Product object. |
|
| 496 | + * @return string Updated product grid item HTML. |
|
| 497 | + */ |
|
| 498 | + return apply_filters( |
|
| 499 | + 'woocommerce_blocks_product_grid_item_html', |
|
| 500 | + "<li class=\"wc-block-grid__product\"> |
|
| 501 | 501 | <a href=\"{$data->permalink}\" class=\"wc-block-grid__product-link\"> |
| 502 | 502 | {$data->image} |
| 503 | 503 | {$data->title} |
@@ -507,170 +507,170 @@ discard block |
||
| 507 | 507 | {$data->rating} |
| 508 | 508 | {$data->button} |
| 509 | 509 | </li>", |
| 510 | - $data, |
|
| 511 | - $product |
|
| 512 | - ); |
|
| 513 | - } |
|
| 514 | - |
|
| 515 | - /** |
|
| 516 | - * Get the product image. |
|
| 517 | - * |
|
| 518 | - * @param \WC_Product $product Product. |
|
| 519 | - * @return string |
|
| 520 | - */ |
|
| 521 | - protected function get_image_html( $product ) { |
|
| 522 | - if ( array_key_exists( 'image', $this->attributes['contentVisibility'] ) && false === $this->attributes['contentVisibility']['image'] ) { |
|
| 523 | - return ''; |
|
| 524 | - } |
|
| 525 | - |
|
| 526 | - $attr = array( |
|
| 527 | - 'alt' => '', |
|
| 528 | - ); |
|
| 529 | - |
|
| 530 | - if ( $product->get_image_id() ) { |
|
| 531 | - $image_alt = get_post_meta( $product->get_image_id(), '_wp_attachment_image_alt', true ); |
|
| 532 | - $attr = array( |
|
| 533 | - 'alt' => ( $image_alt ? $image_alt : $product->get_name() ), |
|
| 534 | - ); |
|
| 535 | - } |
|
| 536 | - |
|
| 537 | - return '<div class="wc-block-grid__product-image">' . $product->get_image( 'woocommerce_thumbnail', $attr ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 538 | - } |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * Get the product title. |
|
| 542 | - * |
|
| 543 | - * @param \WC_Product $product Product. |
|
| 544 | - * @return string |
|
| 545 | - */ |
|
| 546 | - protected function get_title_html( $product ) { |
|
| 547 | - if ( empty( $this->attributes['contentVisibility']['title'] ) ) { |
|
| 548 | - return ''; |
|
| 549 | - } |
|
| 550 | - |
|
| 551 | - return '<div class="wc-block-grid__product-title">' . wp_kses_post( $product->get_title() ) . '</div>'; |
|
| 552 | - } |
|
| 553 | - |
|
| 554 | - /** |
|
| 555 | - * Render the rating icons. |
|
| 556 | - * |
|
| 557 | - * @param WC_Product $product Product. |
|
| 558 | - * @return string Rendered product output. |
|
| 559 | - */ |
|
| 560 | - protected function get_rating_html( $product ) { |
|
| 561 | - if ( empty( $this->attributes['contentVisibility']['rating'] ) ) { |
|
| 562 | - return ''; |
|
| 563 | - } |
|
| 564 | - $rating_count = $product->get_rating_count(); |
|
| 565 | - $review_count = $product->get_review_count(); |
|
| 566 | - $average = $product->get_average_rating(); |
|
| 567 | - |
|
| 568 | - if ( $rating_count > 0 ) { |
|
| 569 | - return sprintf( |
|
| 570 | - '<div class="wc-block-grid__product-rating">%s</div>', |
|
| 571 | - wc_get_rating_html( $average, $rating_count ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 572 | - ); |
|
| 573 | - } |
|
| 574 | - return ''; |
|
| 575 | - } |
|
| 576 | - |
|
| 577 | - /** |
|
| 578 | - * Get the price. |
|
| 579 | - * |
|
| 580 | - * @param \WC_Product $product Product. |
|
| 581 | - * @return string Rendered product output. |
|
| 582 | - */ |
|
| 583 | - protected function get_price_html( $product ) { |
|
| 584 | - if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 585 | - return ''; |
|
| 586 | - } |
|
| 587 | - return sprintf( |
|
| 588 | - '<div class="wc-block-grid__product-price price">%s</div>', |
|
| 589 | - wp_kses_post( $product->get_price_html() ) |
|
| 590 | - ); |
|
| 591 | - } |
|
| 592 | - |
|
| 593 | - /** |
|
| 594 | - * Get the sale badge. |
|
| 595 | - * |
|
| 596 | - * @param \WC_Product $product Product. |
|
| 597 | - * @return string Rendered product output. |
|
| 598 | - */ |
|
| 599 | - protected function get_sale_badge_html( $product ) { |
|
| 600 | - if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 601 | - return ''; |
|
| 602 | - } |
|
| 603 | - |
|
| 604 | - if ( ! $product->is_on_sale() ) { |
|
| 605 | - return; |
|
| 606 | - } |
|
| 607 | - |
|
| 608 | - return '<div class="wc-block-grid__product-onsale"> |
|
| 510 | + $data, |
|
| 511 | + $product |
|
| 512 | + ); |
|
| 513 | + } |
|
| 514 | + |
|
| 515 | + /** |
|
| 516 | + * Get the product image. |
|
| 517 | + * |
|
| 518 | + * @param \WC_Product $product Product. |
|
| 519 | + * @return string |
|
| 520 | + */ |
|
| 521 | + protected function get_image_html( $product ) { |
|
| 522 | + if ( array_key_exists( 'image', $this->attributes['contentVisibility'] ) && false === $this->attributes['contentVisibility']['image'] ) { |
|
| 523 | + return ''; |
|
| 524 | + } |
|
| 525 | + |
|
| 526 | + $attr = array( |
|
| 527 | + 'alt' => '', |
|
| 528 | + ); |
|
| 529 | + |
|
| 530 | + if ( $product->get_image_id() ) { |
|
| 531 | + $image_alt = get_post_meta( $product->get_image_id(), '_wp_attachment_image_alt', true ); |
|
| 532 | + $attr = array( |
|
| 533 | + 'alt' => ( $image_alt ? $image_alt : $product->get_name() ), |
|
| 534 | + ); |
|
| 535 | + } |
|
| 536 | + |
|
| 537 | + return '<div class="wc-block-grid__product-image">' . $product->get_image( 'woocommerce_thumbnail', $attr ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 538 | + } |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * Get the product title. |
|
| 542 | + * |
|
| 543 | + * @param \WC_Product $product Product. |
|
| 544 | + * @return string |
|
| 545 | + */ |
|
| 546 | + protected function get_title_html( $product ) { |
|
| 547 | + if ( empty( $this->attributes['contentVisibility']['title'] ) ) { |
|
| 548 | + return ''; |
|
| 549 | + } |
|
| 550 | + |
|
| 551 | + return '<div class="wc-block-grid__product-title">' . wp_kses_post( $product->get_title() ) . '</div>'; |
|
| 552 | + } |
|
| 553 | + |
|
| 554 | + /** |
|
| 555 | + * Render the rating icons. |
|
| 556 | + * |
|
| 557 | + * @param WC_Product $product Product. |
|
| 558 | + * @return string Rendered product output. |
|
| 559 | + */ |
|
| 560 | + protected function get_rating_html( $product ) { |
|
| 561 | + if ( empty( $this->attributes['contentVisibility']['rating'] ) ) { |
|
| 562 | + return ''; |
|
| 563 | + } |
|
| 564 | + $rating_count = $product->get_rating_count(); |
|
| 565 | + $review_count = $product->get_review_count(); |
|
| 566 | + $average = $product->get_average_rating(); |
|
| 567 | + |
|
| 568 | + if ( $rating_count > 0 ) { |
|
| 569 | + return sprintf( |
|
| 570 | + '<div class="wc-block-grid__product-rating">%s</div>', |
|
| 571 | + wc_get_rating_html( $average, $rating_count ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 572 | + ); |
|
| 573 | + } |
|
| 574 | + return ''; |
|
| 575 | + } |
|
| 576 | + |
|
| 577 | + /** |
|
| 578 | + * Get the price. |
|
| 579 | + * |
|
| 580 | + * @param \WC_Product $product Product. |
|
| 581 | + * @return string Rendered product output. |
|
| 582 | + */ |
|
| 583 | + protected function get_price_html( $product ) { |
|
| 584 | + if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 585 | + return ''; |
|
| 586 | + } |
|
| 587 | + return sprintf( |
|
| 588 | + '<div class="wc-block-grid__product-price price">%s</div>', |
|
| 589 | + wp_kses_post( $product->get_price_html() ) |
|
| 590 | + ); |
|
| 591 | + } |
|
| 592 | + |
|
| 593 | + /** |
|
| 594 | + * Get the sale badge. |
|
| 595 | + * |
|
| 596 | + * @param \WC_Product $product Product. |
|
| 597 | + * @return string Rendered product output. |
|
| 598 | + */ |
|
| 599 | + protected function get_sale_badge_html( $product ) { |
|
| 600 | + if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 601 | + return ''; |
|
| 602 | + } |
|
| 603 | + |
|
| 604 | + if ( ! $product->is_on_sale() ) { |
|
| 605 | + return; |
|
| 606 | + } |
|
| 607 | + |
|
| 608 | + return '<div class="wc-block-grid__product-onsale"> |
|
| 609 | 609 | <span aria-hidden="true">' . esc_html__( 'Sale', 'woocommerce' ) . '</span> |
| 610 | 610 | <span class="screen-reader-text">' . esc_html__( 'Product on sale', 'woocommerce' ) . '</span> |
| 611 | 611 | </div>'; |
| 612 | - } |
|
| 613 | - |
|
| 614 | - /** |
|
| 615 | - * Get the button. |
|
| 616 | - * |
|
| 617 | - * @param \WC_Product $product Product. |
|
| 618 | - * @return string Rendered product output. |
|
| 619 | - */ |
|
| 620 | - protected function get_button_html( $product ) { |
|
| 621 | - if ( empty( $this->attributes['contentVisibility']['button'] ) ) { |
|
| 622 | - return ''; |
|
| 623 | - } |
|
| 624 | - return '<div class="wp-block-button wc-block-grid__product-add-to-cart">' . $this->get_add_to_cart( $product ) . '</div>'; |
|
| 625 | - } |
|
| 626 | - |
|
| 627 | - /** |
|
| 628 | - * Get the "add to cart" button. |
|
| 629 | - * |
|
| 630 | - * @param \WC_Product $product Product. |
|
| 631 | - * @return string Rendered product output. |
|
| 632 | - */ |
|
| 633 | - protected function get_add_to_cart( $product ) { |
|
| 634 | - $attributes = array( |
|
| 635 | - 'aria-label' => $product->add_to_cart_description(), |
|
| 636 | - 'data-quantity' => '1', |
|
| 637 | - 'data-product_id' => $product->get_id(), |
|
| 638 | - 'data-product_sku' => $product->get_sku(), |
|
| 639 | - 'rel' => 'nofollow', |
|
| 640 | - 'class' => 'wp-block-button__link add_to_cart_button', |
|
| 641 | - ); |
|
| 642 | - |
|
| 643 | - if ( |
|
| 644 | - $product->supports( 'ajax_add_to_cart' ) && |
|
| 645 | - $product->is_purchasable() && |
|
| 646 | - ( $product->is_in_stock() || $product->backorders_allowed() ) |
|
| 647 | - ) { |
|
| 648 | - $attributes['class'] .= ' ajax_add_to_cart'; |
|
| 649 | - } |
|
| 650 | - |
|
| 651 | - return sprintf( |
|
| 652 | - '<a href="%s" %s>%s</a>', |
|
| 653 | - esc_url( $product->add_to_cart_url() ), |
|
| 654 | - wc_implode_html_attributes( $attributes ), |
|
| 655 | - esc_html( $product->add_to_cart_text() ) |
|
| 656 | - ); |
|
| 657 | - } |
|
| 658 | - |
|
| 659 | - /** |
|
| 660 | - * Extra data passed through from server to client for block. |
|
| 661 | - * |
|
| 662 | - * @param array $attributes Any attributes that currently are available from the block. |
|
| 663 | - * Note, this will be empty in the editor context when the block is |
|
| 664 | - * not in the post content on editor load. |
|
| 665 | - */ |
|
| 666 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 667 | - parent::enqueue_data( $attributes ); |
|
| 668 | - $this->asset_data_registry->add( 'min_columns', wc_get_theme_support( 'product_blocks::min_columns', 1 ), true ); |
|
| 669 | - $this->asset_data_registry->add( 'max_columns', wc_get_theme_support( 'product_blocks::max_columns', 6 ), true ); |
|
| 670 | - $this->asset_data_registry->add( 'default_columns', wc_get_theme_support( 'product_blocks::default_columns', 3 ), true ); |
|
| 671 | - $this->asset_data_registry->add( 'min_rows', wc_get_theme_support( 'product_blocks::min_rows', 1 ), true ); |
|
| 672 | - $this->asset_data_registry->add( 'max_rows', wc_get_theme_support( 'product_blocks::max_rows', 6 ), true ); |
|
| 673 | - $this->asset_data_registry->add( 'default_rows', wc_get_theme_support( 'product_blocks::default_rows', 3 ), true ); |
|
| 674 | - $this->asset_data_registry->add( 'stock_status_options', wc_get_product_stock_status_options(), true ); |
|
| 675 | - } |
|
| 612 | + } |
|
| 613 | + |
|
| 614 | + /** |
|
| 615 | + * Get the button. |
|
| 616 | + * |
|
| 617 | + * @param \WC_Product $product Product. |
|
| 618 | + * @return string Rendered product output. |
|
| 619 | + */ |
|
| 620 | + protected function get_button_html( $product ) { |
|
| 621 | + if ( empty( $this->attributes['contentVisibility']['button'] ) ) { |
|
| 622 | + return ''; |
|
| 623 | + } |
|
| 624 | + return '<div class="wp-block-button wc-block-grid__product-add-to-cart">' . $this->get_add_to_cart( $product ) . '</div>'; |
|
| 625 | + } |
|
| 626 | + |
|
| 627 | + /** |
|
| 628 | + * Get the "add to cart" button. |
|
| 629 | + * |
|
| 630 | + * @param \WC_Product $product Product. |
|
| 631 | + * @return string Rendered product output. |
|
| 632 | + */ |
|
| 633 | + protected function get_add_to_cart( $product ) { |
|
| 634 | + $attributes = array( |
|
| 635 | + 'aria-label' => $product->add_to_cart_description(), |
|
| 636 | + 'data-quantity' => '1', |
|
| 637 | + 'data-product_id' => $product->get_id(), |
|
| 638 | + 'data-product_sku' => $product->get_sku(), |
|
| 639 | + 'rel' => 'nofollow', |
|
| 640 | + 'class' => 'wp-block-button__link add_to_cart_button', |
|
| 641 | + ); |
|
| 642 | + |
|
| 643 | + if ( |
|
| 644 | + $product->supports( 'ajax_add_to_cart' ) && |
|
| 645 | + $product->is_purchasable() && |
|
| 646 | + ( $product->is_in_stock() || $product->backorders_allowed() ) |
|
| 647 | + ) { |
|
| 648 | + $attributes['class'] .= ' ajax_add_to_cart'; |
|
| 649 | + } |
|
| 650 | + |
|
| 651 | + return sprintf( |
|
| 652 | + '<a href="%s" %s>%s</a>', |
|
| 653 | + esc_url( $product->add_to_cart_url() ), |
|
| 654 | + wc_implode_html_attributes( $attributes ), |
|
| 655 | + esc_html( $product->add_to_cart_text() ) |
|
| 656 | + ); |
|
| 657 | + } |
|
| 658 | + |
|
| 659 | + /** |
|
| 660 | + * Extra data passed through from server to client for block. |
|
| 661 | + * |
|
| 662 | + * @param array $attributes Any attributes that currently are available from the block. |
|
| 663 | + * Note, this will be empty in the editor context when the block is |
|
| 664 | + * not in the post content on editor load. |
|
| 665 | + */ |
|
| 666 | + protected function enqueue_data( array $attributes = [] ) { |
|
| 667 | + parent::enqueue_data( $attributes ); |
|
| 668 | + $this->asset_data_registry->add( 'min_columns', wc_get_theme_support( 'product_blocks::min_columns', 1 ), true ); |
|
| 669 | + $this->asset_data_registry->add( 'max_columns', wc_get_theme_support( 'product_blocks::max_columns', 6 ), true ); |
|
| 670 | + $this->asset_data_registry->add( 'default_columns', wc_get_theme_support( 'product_blocks::default_columns', 3 ), true ); |
|
| 671 | + $this->asset_data_registry->add( 'min_rows', wc_get_theme_support( 'product_blocks::min_rows', 1 ), true ); |
|
| 672 | + $this->asset_data_registry->add( 'max_rows', wc_get_theme_support( 'product_blocks::max_rows', 6 ), true ); |
|
| 673 | + $this->asset_data_registry->add( 'default_rows', wc_get_theme_support( 'product_blocks::default_rows', 3 ), true ); |
|
| 674 | + $this->asset_data_registry->add( 'stock_status_options', wc_get_product_stock_status_options(), true ); |
|
| 675 | + } |
|
| 676 | 676 | } |
@@ -46,8 +46,8 @@ discard block |
||
| 46 | 46 | protected function get_block_type_attributes() { |
| 47 | 47 | return array( |
| 48 | 48 | 'className' => $this->get_schema_string(), |
| 49 | - 'columns' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_columns', 3 ) ), |
|
| 50 | - 'rows' => $this->get_schema_number( wc_get_theme_support( 'product_blocks::default_rows', 3 ) ), |
|
| 49 | + 'columns' => $this->get_schema_number(wc_get_theme_support('product_blocks::default_columns', 3)), |
|
| 50 | + 'rows' => $this->get_schema_number(wc_get_theme_support('product_blocks::default_rows', 3)), |
|
| 51 | 51 | 'categories' => $this->get_schema_list_ids(), |
| 52 | 52 | 'catOperator' => array( |
| 53 | 53 | 'type' => 'string', |
@@ -55,11 +55,11 @@ discard block |
||
| 55 | 55 | ), |
| 56 | 56 | 'contentVisibility' => $this->get_schema_content_visibility(), |
| 57 | 57 | 'align' => $this->get_schema_align(), |
| 58 | - 'alignButtons' => $this->get_schema_boolean( false ), |
|
| 59 | - 'isPreview' => $this->get_schema_boolean( false ), |
|
| 58 | + 'alignButtons' => $this->get_schema_boolean(false), |
|
| 59 | + 'isPreview' => $this->get_schema_boolean(false), |
|
| 60 | 60 | 'stockStatus' => array( |
| 61 | 61 | 'type' => 'array', |
| 62 | - 'default' => array_keys( wc_get_product_stock_status_options() ), |
|
| 62 | + 'default' => array_keys(wc_get_product_stock_status_options()), |
|
| 63 | 63 | ), |
| 64 | 64 | ); |
| 65 | 65 | } |
@@ -71,13 +71,13 @@ discard block |
||
| 71 | 71 | * @param string $content Block content. Default empty string. |
| 72 | 72 | * @return string Rendered block type output. |
| 73 | 73 | */ |
| 74 | - protected function render( $attributes = array(), $content = '' ) { |
|
| 75 | - $this->attributes = $this->parse_attributes( $attributes ); |
|
| 74 | + protected function render($attributes = array(), $content = '') { |
|
| 75 | + $this->attributes = $this->parse_attributes($attributes); |
|
| 76 | 76 | $this->content = $content; |
| 77 | 77 | $this->query_args = $this->parse_query_args(); |
| 78 | - $products = array_filter( array_map( 'wc_get_product', $this->get_products() ) ); |
|
| 78 | + $products = array_filter(array_map('wc_get_product', $this->get_products())); |
|
| 79 | 79 | |
| 80 | - if ( ! $products ) { |
|
| 80 | + if (!$products) { |
|
| 81 | 81 | return ''; |
| 82 | 82 | } |
| 83 | 83 | |
@@ -101,13 +101,13 @@ discard block |
||
| 101 | 101 | rawurlencode( |
| 102 | 102 | wp_json_encode( |
| 103 | 103 | array_map( |
| 104 | - [ StoreApi::container()->get( SchemaController::class )->get( 'product' ), 'get_item_response' ], |
|
| 104 | + [StoreApi::container()->get(SchemaController::class)->get('product'), 'get_item_response'], |
|
| 105 | 105 | $products |
| 106 | 106 | ) |
| 107 | 107 | ) |
| 108 | 108 | ) |
| 109 | 109 | ) . '" ) ), |
| 110 | - listName: "' . esc_js( $this->block_name ) . '" |
|
| 110 | + listName: "' . esc_js($this->block_name) . '" |
|
| 111 | 111 | } |
| 112 | 112 | ); |
| 113 | 113 | } ); |
@@ -117,8 +117,8 @@ discard block |
||
| 117 | 117 | |
| 118 | 118 | return sprintf( |
| 119 | 119 | '<div class="%s"><ul class="wc-block-grid__products">%s</ul></div>', |
| 120 | - esc_attr( $this->get_container_classes() ), |
|
| 121 | - implode( '', array_map( array( $this, 'render_product' ), $products ) ) |
|
| 120 | + esc_attr($this->get_container_classes()), |
|
| 121 | + implode('', array_map(array($this, 'render_product'), $products)) |
|
| 122 | 122 | ); |
| 123 | 123 | } |
| 124 | 124 | |
@@ -131,11 +131,11 @@ discard block |
||
| 131 | 131 | return array( |
| 132 | 132 | 'type' => 'object', |
| 133 | 133 | 'properties' => array( |
| 134 | - 'image' => $this->get_schema_boolean( true ), |
|
| 135 | - 'title' => $this->get_schema_boolean( true ), |
|
| 136 | - 'price' => $this->get_schema_boolean( true ), |
|
| 137 | - 'rating' => $this->get_schema_boolean( true ), |
|
| 138 | - 'button' => $this->get_schema_boolean( true ), |
|
| 134 | + 'image' => $this->get_schema_boolean(true), |
|
| 135 | + 'title' => $this->get_schema_boolean(true), |
|
| 136 | + 'price' => $this->get_schema_boolean(true), |
|
| 137 | + 'rating' => $this->get_schema_boolean(true), |
|
| 138 | + 'button' => $this->get_schema_boolean(true), |
|
| 139 | 139 | ), |
| 140 | 140 | ); |
| 141 | 141 | } |
@@ -148,7 +148,7 @@ discard block |
||
| 148 | 148 | protected function get_schema_orderby() { |
| 149 | 149 | return array( |
| 150 | 150 | 'type' => 'string', |
| 151 | - 'enum' => array( 'date', 'popularity', 'price_asc', 'price_desc', 'rating', 'title', 'menu_order' ), |
|
| 151 | + 'enum' => array('date', 'popularity', 'price_asc', 'price_desc', 'rating', 'title', 'menu_order'), |
|
| 152 | 152 | 'default' => 'date', |
| 153 | 153 | ); |
| 154 | 154 | } |
@@ -159,11 +159,11 @@ discard block |
||
| 159 | 159 | * @param array $attributes Block attributes. Default empty array. |
| 160 | 160 | * @return array Block attributes merged with defaults. |
| 161 | 161 | */ |
| 162 | - protected function parse_attributes( $attributes ) { |
|
| 162 | + protected function parse_attributes($attributes) { |
|
| 163 | 163 | // These should match what's set in JS `registerBlockType`. |
| 164 | 164 | $defaults = array( |
| 165 | - 'columns' => wc_get_theme_support( 'product_blocks::default_columns', 3 ), |
|
| 166 | - 'rows' => wc_get_theme_support( 'product_blocks::default_rows', 3 ), |
|
| 165 | + 'columns' => wc_get_theme_support('product_blocks::default_columns', 3), |
|
| 166 | + 'rows' => wc_get_theme_support('product_blocks::default_rows', 3), |
|
| 167 | 167 | 'alignButtons' => false, |
| 168 | 168 | 'categories' => array(), |
| 169 | 169 | 'catOperator' => 'any', |
@@ -174,10 +174,10 @@ discard block |
||
| 174 | 174 | 'rating' => true, |
| 175 | 175 | 'button' => true, |
| 176 | 176 | ), |
| 177 | - 'stockStatus' => array_keys( wc_get_product_stock_status_options() ), |
|
| 177 | + 'stockStatus' => array_keys(wc_get_product_stock_status_options()), |
|
| 178 | 178 | ); |
| 179 | 179 | |
| 180 | - return wp_parse_args( $attributes, $defaults ); |
|
| 180 | + return wp_parse_args($attributes, $defaults); |
|
| 181 | 181 | } |
| 182 | 182 | |
| 183 | 183 | /** |
@@ -202,11 +202,11 @@ discard block |
||
| 202 | 202 | 'posts_per_page' => $this->get_products_limit(), |
| 203 | 203 | ); |
| 204 | 204 | |
| 205 | - $this->set_block_query_args( $query_args ); |
|
| 206 | - $this->set_ordering_query_args( $query_args ); |
|
| 207 | - $this->set_categories_query_args( $query_args ); |
|
| 208 | - $this->set_visibility_query_args( $query_args ); |
|
| 209 | - $this->set_stock_status_query_args( $query_args ); |
|
| 205 | + $this->set_block_query_args($query_args); |
|
| 206 | + $this->set_ordering_query_args($query_args); |
|
| 207 | + $this->set_categories_query_args($query_args); |
|
| 208 | + $this->set_visibility_query_args($query_args); |
|
| 209 | + $this->set_stock_status_query_args($query_args); |
|
| 210 | 210 | |
| 211 | 211 | return $query_args; |
| 212 | 212 | } |
@@ -216,15 +216,15 @@ discard block |
||
| 216 | 216 | * |
| 217 | 217 | * @param array $query_args Query args. |
| 218 | 218 | */ |
| 219 | - protected function set_ordering_query_args( &$query_args ) { |
|
| 220 | - if ( isset( $this->attributes['orderby'] ) ) { |
|
| 221 | - if ( 'price_desc' === $this->attributes['orderby'] ) { |
|
| 219 | + protected function set_ordering_query_args(&$query_args) { |
|
| 220 | + if (isset($this->attributes['orderby'])) { |
|
| 221 | + if ('price_desc' === $this->attributes['orderby']) { |
|
| 222 | 222 | $query_args['orderby'] = 'price'; |
| 223 | 223 | $query_args['order'] = 'DESC'; |
| 224 | - } elseif ( 'price_asc' === $this->attributes['orderby'] ) { |
|
| 224 | + } elseif ('price_asc' === $this->attributes['orderby']) { |
|
| 225 | 225 | $query_args['orderby'] = 'price'; |
| 226 | 226 | $query_args['order'] = 'ASC'; |
| 227 | - } elseif ( 'date' === $this->attributes['orderby'] ) { |
|
| 227 | + } elseif ('date' === $this->attributes['orderby']) { |
|
| 228 | 228 | $query_args['orderby'] = 'date'; |
| 229 | 229 | $query_args['order'] = 'DESC'; |
| 230 | 230 | } else { |
@@ -234,7 +234,7 @@ discard block |
||
| 234 | 234 | |
| 235 | 235 | $query_args = array_merge( |
| 236 | 236 | $query_args, |
| 237 | - WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] ) |
|
| 237 | + WC()->query->get_catalog_ordering_args($query_args['orderby'], $query_args['order']) |
|
| 238 | 238 | ); |
| 239 | 239 | } |
| 240 | 240 | |
@@ -243,16 +243,16 @@ discard block |
||
| 243 | 243 | * |
| 244 | 244 | * @param array $query_args Query args. |
| 245 | 245 | */ |
| 246 | - abstract protected function set_block_query_args( &$query_args ); |
|
| 246 | + abstract protected function set_block_query_args(&$query_args); |
|
| 247 | 247 | |
| 248 | 248 | /** |
| 249 | 249 | * Set categories query args. |
| 250 | 250 | * |
| 251 | 251 | * @param array $query_args Query args. |
| 252 | 252 | */ |
| 253 | - protected function set_categories_query_args( &$query_args ) { |
|
| 254 | - if ( ! empty( $this->attributes['categories'] ) ) { |
|
| 255 | - $categories = array_map( 'absint', $this->attributes['categories'] ); |
|
| 253 | + protected function set_categories_query_args(&$query_args) { |
|
| 254 | + if (!empty($this->attributes['categories'])) { |
|
| 255 | + $categories = array_map('absint', $this->attributes['categories']); |
|
| 256 | 256 | |
| 257 | 257 | $query_args['tax_query'][] = array( |
| 258 | 258 | 'taxonomy' => 'product_cat', |
@@ -274,11 +274,11 @@ discard block |
||
| 274 | 274 | * |
| 275 | 275 | * @param array $query_args Query args. |
| 276 | 276 | */ |
| 277 | - protected function set_visibility_query_args( &$query_args ) { |
|
| 277 | + protected function set_visibility_query_args(&$query_args) { |
|
| 278 | 278 | $product_visibility_terms = wc_get_product_visibility_term_ids(); |
| 279 | - $product_visibility_not_in = array( $product_visibility_terms['exclude-from-catalog'] ); |
|
| 279 | + $product_visibility_not_in = array($product_visibility_terms['exclude-from-catalog']); |
|
| 280 | 280 | |
| 281 | - if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) { |
|
| 281 | + if ('yes' === get_option('woocommerce_hide_out_of_stock_items')) { |
|
| 282 | 282 | $product_visibility_not_in[] = $product_visibility_terms['outofstock']; |
| 283 | 283 | } |
| 284 | 284 | |
@@ -296,16 +296,16 @@ discard block |
||
| 296 | 296 | * @param array $query_args Query args. |
| 297 | 297 | * @return void |
| 298 | 298 | */ |
| 299 | - protected function set_stock_status_query_args( &$query_args ) { |
|
| 300 | - $stock_statuses = array_keys( wc_get_product_stock_status_options() ); |
|
| 299 | + protected function set_stock_status_query_args(&$query_args) { |
|
| 300 | + $stock_statuses = array_keys(wc_get_product_stock_status_options()); |
|
| 301 | 301 | |
| 302 | 302 | // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query |
| 303 | - if ( isset( $this->attributes['stockStatus'] ) && $stock_statuses !== $this->attributes['stockStatus'] ) { |
|
| 303 | + if (isset($this->attributes['stockStatus']) && $stock_statuses !== $this->attributes['stockStatus']) { |
|
| 304 | 304 | // Reset meta_query then update with our stock status. |
| 305 | 305 | $query_args['meta_query'] = $this->meta_query; |
| 306 | 306 | $query_args['meta_query'][] = array( |
| 307 | 307 | 'key' => '_stock_status', |
| 308 | - 'value' => array_merge( [ '' ], $this->attributes['stockStatus'] ), |
|
| 308 | + 'value' => array_merge([''], $this->attributes['stockStatus']), |
|
| 309 | 309 | 'compare' => 'IN', |
| 310 | 310 | ); |
| 311 | 311 | } else { |
@@ -320,10 +320,10 @@ discard block |
||
| 320 | 320 | * @return int |
| 321 | 321 | */ |
| 322 | 322 | protected function get_products_limit() { |
| 323 | - if ( isset( $this->attributes['rows'], $this->attributes['columns'] ) && ! empty( $this->attributes['rows'] ) ) { |
|
| 324 | - $this->attributes['limit'] = intval( $this->attributes['columns'] ) * intval( $this->attributes['rows'] ); |
|
| 323 | + if (isset($this->attributes['rows'], $this->attributes['columns']) && !empty($this->attributes['rows'])) { |
|
| 324 | + $this->attributes['limit'] = intval($this->attributes['columns']) * intval($this->attributes['rows']); |
|
| 325 | 325 | } |
| 326 | - return intval( $this->attributes['limit'] ); |
|
| 326 | + return intval($this->attributes['limit']); |
|
| 327 | 327 | } |
| 328 | 328 | |
| 329 | 329 | /** |
@@ -339,22 +339,22 @@ discard block |
||
| 339 | 339 | * @param array $query_args Query args for the products query passed to BlocksWpQuery. |
| 340 | 340 | * @return array True to enable cache, false to disable cache. |
| 341 | 341 | */ |
| 342 | - $is_cacheable = (bool) apply_filters( 'woocommerce_blocks_product_grid_is_cacheable', true, $this->query_args ); |
|
| 343 | - $transient_version = \WC_Cache_Helper::get_transient_version( 'product_query' ); |
|
| 342 | + $is_cacheable = (bool) apply_filters('woocommerce_blocks_product_grid_is_cacheable', true, $this->query_args); |
|
| 343 | + $transient_version = \WC_Cache_Helper::get_transient_version('product_query'); |
|
| 344 | 344 | |
| 345 | - $query = new BlocksWpQuery( $this->query_args ); |
|
| 346 | - $results = wp_parse_id_list( $is_cacheable ? $query->get_cached_posts( $transient_version ) : $query->get_posts() ); |
|
| 345 | + $query = new BlocksWpQuery($this->query_args); |
|
| 346 | + $results = wp_parse_id_list($is_cacheable ? $query->get_cached_posts($transient_version) : $query->get_posts()); |
|
| 347 | 347 | |
| 348 | 348 | // Remove ordering query arguments which may have been added by get_catalog_ordering_args. |
| 349 | 349 | WC()->query->remove_ordering_args(); |
| 350 | 350 | |
| 351 | 351 | // Prime caches to reduce future queries. Note _prime_post_caches is private--we could replace this with our own |
| 352 | 352 | // query if it becomes unavailable. |
| 353 | - if ( is_callable( '_prime_post_caches' ) ) { |
|
| 354 | - _prime_post_caches( $results ); |
|
| 353 | + if (is_callable('_prime_post_caches')) { |
|
| 354 | + _prime_post_caches($results); |
|
| 355 | 355 | } |
| 356 | 356 | |
| 357 | - $this->prime_product_variations( $results ); |
|
| 357 | + $this->prime_product_variations($results); |
|
| 358 | 358 | |
| 359 | 359 | return $results; |
| 360 | 360 | } |
@@ -368,12 +368,12 @@ discard block |
||
| 368 | 368 | * @param string $cache_key The cache bucket to check against. |
| 369 | 369 | * @return int[] Array of IDs not present in the cache. |
| 370 | 370 | */ |
| 371 | - protected function get_non_cached_ids( $product_ids, $cache_key ) { |
|
| 371 | + protected function get_non_cached_ids($product_ids, $cache_key) { |
|
| 372 | 372 | $non_cached_ids = array(); |
| 373 | - $cache_values = wp_cache_get_multiple( $product_ids, $cache_key ); |
|
| 373 | + $cache_values = wp_cache_get_multiple($product_ids, $cache_key); |
|
| 374 | 374 | |
| 375 | - foreach ( $cache_values as $id => $value ) { |
|
| 376 | - if ( ! $value ) { |
|
| 375 | + foreach ($cache_values as $id => $value) { |
|
| 376 | + if (!$value) { |
|
| 377 | 377 | $non_cached_ids[] = (int) $id; |
| 378 | 378 | } |
| 379 | 379 | } |
@@ -389,48 +389,48 @@ discard block |
||
| 389 | 389 | * |
| 390 | 390 | * @param int[] $product_ids Product ids to prime variation cache for. |
| 391 | 391 | */ |
| 392 | - protected function prime_product_variations( $product_ids ) { |
|
| 392 | + protected function prime_product_variations($product_ids) { |
|
| 393 | 393 | $cache_group = 'product_variation_meta_data'; |
| 394 | - $prime_product_ids = $this->get_non_cached_ids( wp_parse_id_list( $product_ids ), $cache_group ); |
|
| 394 | + $prime_product_ids = $this->get_non_cached_ids(wp_parse_id_list($product_ids), $cache_group); |
|
| 395 | 395 | |
| 396 | - if ( ! $prime_product_ids ) { |
|
| 396 | + if (!$prime_product_ids) { |
|
| 397 | 397 | return; |
| 398 | 398 | } |
| 399 | 399 | |
| 400 | 400 | global $wpdb; |
| 401 | 401 | |
| 402 | 402 | // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared |
| 403 | - $product_variations = $wpdb->get_results( "SELECT ID as variation_id, post_parent as product_id from {$wpdb->posts} WHERE post_parent IN ( " . implode( ',', $prime_product_ids ) . ' )', ARRAY_A ); |
|
| 404 | - $prime_variation_ids = array_column( $product_variations, 'variation_id' ); |
|
| 405 | - $variation_ids_by_parent = array_column( $product_variations, 'product_id', 'variation_id' ); |
|
| 403 | + $product_variations = $wpdb->get_results("SELECT ID as variation_id, post_parent as product_id from {$wpdb->posts} WHERE post_parent IN ( " . implode(',', $prime_product_ids) . ' )', ARRAY_A); |
|
| 404 | + $prime_variation_ids = array_column($product_variations, 'variation_id'); |
|
| 405 | + $variation_ids_by_parent = array_column($product_variations, 'product_id', 'variation_id'); |
|
| 406 | 406 | |
| 407 | - if ( empty( $prime_variation_ids ) ) { |
|
| 407 | + if (empty($prime_variation_ids)) { |
|
| 408 | 408 | return; |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | 411 | $all_variation_meta_data = $wpdb->get_results( |
| 412 | 412 | $wpdb->prepare( |
| 413 | - "SELECT post_id as variation_id, meta_key as attribute_key, meta_value as attribute_value FROM {$wpdb->postmeta} WHERE post_id IN (" . implode( ',', array_map( 'esc_sql', $prime_variation_ids ) ) . ') AND meta_key LIKE %s', |
|
| 414 | - $wpdb->esc_like( 'attribute_' ) . '%' |
|
| 413 | + "SELECT post_id as variation_id, meta_key as attribute_key, meta_value as attribute_value FROM {$wpdb->postmeta} WHERE post_id IN (" . implode(',', array_map('esc_sql', $prime_variation_ids)) . ') AND meta_key LIKE %s', |
|
| 414 | + $wpdb->esc_like('attribute_') . '%' |
|
| 415 | 415 | ) |
| 416 | 416 | ); |
| 417 | 417 | // phpcs:enable |
| 418 | 418 | // Prepare the data to cache by indexing by the parent product. |
| 419 | 419 | $primed_data = array_reduce( |
| 420 | 420 | $all_variation_meta_data, |
| 421 | - function( $values, $data ) use ( $variation_ids_by_parent ) { |
|
| 422 | - $values[ $variation_ids_by_parent[ $data->variation_id ] ?? 0 ][] = $data; |
|
| 421 | + function($values, $data) use ($variation_ids_by_parent) { |
|
| 422 | + $values[$variation_ids_by_parent[$data->variation_id] ?? 0][] = $data; |
|
| 423 | 423 | return $values; |
| 424 | 424 | }, |
| 425 | - array_fill_keys( $prime_product_ids, [] ) |
|
| 425 | + array_fill_keys($prime_product_ids, []) |
|
| 426 | 426 | ); |
| 427 | 427 | |
| 428 | 428 | // Cache everything. |
| 429 | - foreach ( $primed_data as $product_id => $variation_meta_data ) { |
|
| 429 | + foreach ($primed_data as $product_id => $variation_meta_data) { |
|
| 430 | 430 | wp_cache_set( |
| 431 | 431 | $product_id, |
| 432 | 432 | [ |
| 433 | - 'last_modified' => get_the_modified_date( 'U', $product_id ), |
|
| 433 | + 'last_modified' => get_the_modified_date('U', $product_id), |
|
| 434 | 434 | 'data' => $variation_meta_data, |
| 435 | 435 | ], |
| 436 | 436 | $cache_group |
@@ -451,23 +451,23 @@ discard block |
||
| 451 | 451 | "has-{$this->attributes['columns']}-columns", |
| 452 | 452 | ); |
| 453 | 453 | |
| 454 | - if ( $this->attributes['rows'] > 1 ) { |
|
| 454 | + if ($this->attributes['rows'] > 1) { |
|
| 455 | 455 | $classes[] = 'has-multiple-rows'; |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | - if ( isset( $this->attributes['align'] ) ) { |
|
| 458 | + if (isset($this->attributes['align'])) { |
|
| 459 | 459 | $classes[] = "align{$this->attributes['align']}"; |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | - if ( ! empty( $this->attributes['alignButtons'] ) ) { |
|
| 462 | + if (!empty($this->attributes['alignButtons'])) { |
|
| 463 | 463 | $classes[] = 'has-aligned-buttons'; |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | - if ( ! empty( $this->attributes['className'] ) ) { |
|
| 466 | + if (!empty($this->attributes['className'])) { |
|
| 467 | 467 | $classes[] = $this->attributes['className']; |
| 468 | 468 | } |
| 469 | 469 | |
| 470 | - return implode( ' ', $classes ); |
|
| 470 | + return implode(' ', $classes); |
|
| 471 | 471 | } |
| 472 | 472 | |
| 473 | 473 | /** |
@@ -476,15 +476,15 @@ discard block |
||
| 476 | 476 | * @param \WC_Product $product Product object. |
| 477 | 477 | * @return string Rendered product output. |
| 478 | 478 | */ |
| 479 | - protected function render_product( $product ) { |
|
| 479 | + protected function render_product($product) { |
|
| 480 | 480 | $data = (object) array( |
| 481 | - 'permalink' => esc_url( $product->get_permalink() ), |
|
| 482 | - 'image' => $this->get_image_html( $product ), |
|
| 483 | - 'title' => $this->get_title_html( $product ), |
|
| 484 | - 'rating' => $this->get_rating_html( $product ), |
|
| 485 | - 'price' => $this->get_price_html( $product ), |
|
| 486 | - 'badge' => $this->get_sale_badge_html( $product ), |
|
| 487 | - 'button' => $this->get_button_html( $product ), |
|
| 481 | + 'permalink' => esc_url($product->get_permalink()), |
|
| 482 | + 'image' => $this->get_image_html($product), |
|
| 483 | + 'title' => $this->get_title_html($product), |
|
| 484 | + 'rating' => $this->get_rating_html($product), |
|
| 485 | + 'price' => $this->get_price_html($product), |
|
| 486 | + 'badge' => $this->get_sale_badge_html($product), |
|
| 487 | + 'button' => $this->get_button_html($product), |
|
| 488 | 488 | ); |
| 489 | 489 | |
| 490 | 490 | /** |
@@ -518,8 +518,8 @@ discard block |
||
| 518 | 518 | * @param \WC_Product $product Product. |
| 519 | 519 | * @return string |
| 520 | 520 | */ |
| 521 | - protected function get_image_html( $product ) { |
|
| 522 | - if ( array_key_exists( 'image', $this->attributes['contentVisibility'] ) && false === $this->attributes['contentVisibility']['image'] ) { |
|
| 521 | + protected function get_image_html($product) { |
|
| 522 | + if (array_key_exists('image', $this->attributes['contentVisibility']) && false === $this->attributes['contentVisibility']['image']) { |
|
| 523 | 523 | return ''; |
| 524 | 524 | } |
| 525 | 525 | |
@@ -527,14 +527,14 @@ discard block |
||
| 527 | 527 | 'alt' => '', |
| 528 | 528 | ); |
| 529 | 529 | |
| 530 | - if ( $product->get_image_id() ) { |
|
| 531 | - $image_alt = get_post_meta( $product->get_image_id(), '_wp_attachment_image_alt', true ); |
|
| 530 | + if ($product->get_image_id()) { |
|
| 531 | + $image_alt = get_post_meta($product->get_image_id(), '_wp_attachment_image_alt', true); |
|
| 532 | 532 | $attr = array( |
| 533 | - 'alt' => ( $image_alt ? $image_alt : $product->get_name() ), |
|
| 533 | + 'alt' => ($image_alt ? $image_alt : $product->get_name()), |
|
| 534 | 534 | ); |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | - return '<div class="wc-block-grid__product-image">' . $product->get_image( 'woocommerce_thumbnail', $attr ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 537 | + return '<div class="wc-block-grid__product-image">' . $product->get_image('woocommerce_thumbnail', $attr) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 538 | 538 | } |
| 539 | 539 | |
| 540 | 540 | /** |
@@ -543,12 +543,12 @@ discard block |
||
| 543 | 543 | * @param \WC_Product $product Product. |
| 544 | 544 | * @return string |
| 545 | 545 | */ |
| 546 | - protected function get_title_html( $product ) { |
|
| 547 | - if ( empty( $this->attributes['contentVisibility']['title'] ) ) { |
|
| 546 | + protected function get_title_html($product) { |
|
| 547 | + if (empty($this->attributes['contentVisibility']['title'])) { |
|
| 548 | 548 | return ''; |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | - return '<div class="wc-block-grid__product-title">' . wp_kses_post( $product->get_title() ) . '</div>'; |
|
| 551 | + return '<div class="wc-block-grid__product-title">' . wp_kses_post($product->get_title()) . '</div>'; |
|
| 552 | 552 | } |
| 553 | 553 | |
| 554 | 554 | /** |
@@ -557,18 +557,18 @@ discard block |
||
| 557 | 557 | * @param WC_Product $product Product. |
| 558 | 558 | * @return string Rendered product output. |
| 559 | 559 | */ |
| 560 | - protected function get_rating_html( $product ) { |
|
| 561 | - if ( empty( $this->attributes['contentVisibility']['rating'] ) ) { |
|
| 560 | + protected function get_rating_html($product) { |
|
| 561 | + if (empty($this->attributes['contentVisibility']['rating'])) { |
|
| 562 | 562 | return ''; |
| 563 | 563 | } |
| 564 | 564 | $rating_count = $product->get_rating_count(); |
| 565 | 565 | $review_count = $product->get_review_count(); |
| 566 | 566 | $average = $product->get_average_rating(); |
| 567 | 567 | |
| 568 | - if ( $rating_count > 0 ) { |
|
| 568 | + if ($rating_count > 0) { |
|
| 569 | 569 | return sprintf( |
| 570 | 570 | '<div class="wc-block-grid__product-rating">%s</div>', |
| 571 | - wc_get_rating_html( $average, $rating_count ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 571 | + wc_get_rating_html($average, $rating_count) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
|
| 572 | 572 | ); |
| 573 | 573 | } |
| 574 | 574 | return ''; |
@@ -580,13 +580,13 @@ discard block |
||
| 580 | 580 | * @param \WC_Product $product Product. |
| 581 | 581 | * @return string Rendered product output. |
| 582 | 582 | */ |
| 583 | - protected function get_price_html( $product ) { |
|
| 584 | - if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 583 | + protected function get_price_html($product) { |
|
| 584 | + if (empty($this->attributes['contentVisibility']['price'])) { |
|
| 585 | 585 | return ''; |
| 586 | 586 | } |
| 587 | 587 | return sprintf( |
| 588 | 588 | '<div class="wc-block-grid__product-price price">%s</div>', |
| 589 | - wp_kses_post( $product->get_price_html() ) |
|
| 589 | + wp_kses_post($product->get_price_html()) |
|
| 590 | 590 | ); |
| 591 | 591 | } |
| 592 | 592 | |
@@ -596,18 +596,18 @@ discard block |
||
| 596 | 596 | * @param \WC_Product $product Product. |
| 597 | 597 | * @return string Rendered product output. |
| 598 | 598 | */ |
| 599 | - protected function get_sale_badge_html( $product ) { |
|
| 600 | - if ( empty( $this->attributes['contentVisibility']['price'] ) ) { |
|
| 599 | + protected function get_sale_badge_html($product) { |
|
| 600 | + if (empty($this->attributes['contentVisibility']['price'])) { |
|
| 601 | 601 | return ''; |
| 602 | 602 | } |
| 603 | 603 | |
| 604 | - if ( ! $product->is_on_sale() ) { |
|
| 604 | + if (!$product->is_on_sale()) { |
|
| 605 | 605 | return; |
| 606 | 606 | } |
| 607 | 607 | |
| 608 | 608 | return '<div class="wc-block-grid__product-onsale"> |
| 609 | - <span aria-hidden="true">' . esc_html__( 'Sale', 'woocommerce' ) . '</span> |
|
| 610 | - <span class="screen-reader-text">' . esc_html__( 'Product on sale', 'woocommerce' ) . '</span> |
|
| 609 | + <span aria-hidden="true">' . esc_html__('Sale', 'woocommerce') . '</span> |
|
| 610 | + <span class="screen-reader-text">' . esc_html__('Product on sale', 'woocommerce') . '</span> |
|
| 611 | 611 | </div>'; |
| 612 | 612 | } |
| 613 | 613 | |
@@ -617,11 +617,11 @@ discard block |
||
| 617 | 617 | * @param \WC_Product $product Product. |
| 618 | 618 | * @return string Rendered product output. |
| 619 | 619 | */ |
| 620 | - protected function get_button_html( $product ) { |
|
| 621 | - if ( empty( $this->attributes['contentVisibility']['button'] ) ) { |
|
| 620 | + protected function get_button_html($product) { |
|
| 621 | + if (empty($this->attributes['contentVisibility']['button'])) { |
|
| 622 | 622 | return ''; |
| 623 | 623 | } |
| 624 | - return '<div class="wp-block-button wc-block-grid__product-add-to-cart">' . $this->get_add_to_cart( $product ) . '</div>'; |
|
| 624 | + return '<div class="wp-block-button wc-block-grid__product-add-to-cart">' . $this->get_add_to_cart($product) . '</div>'; |
|
| 625 | 625 | } |
| 626 | 626 | |
| 627 | 627 | /** |
@@ -630,7 +630,7 @@ discard block |
||
| 630 | 630 | * @param \WC_Product $product Product. |
| 631 | 631 | * @return string Rendered product output. |
| 632 | 632 | */ |
| 633 | - protected function get_add_to_cart( $product ) { |
|
| 633 | + protected function get_add_to_cart($product) { |
|
| 634 | 634 | $attributes = array( |
| 635 | 635 | 'aria-label' => $product->add_to_cart_description(), |
| 636 | 636 | 'data-quantity' => '1', |
@@ -641,18 +641,18 @@ discard block |
||
| 641 | 641 | ); |
| 642 | 642 | |
| 643 | 643 | if ( |
| 644 | - $product->supports( 'ajax_add_to_cart' ) && |
|
| 644 | + $product->supports('ajax_add_to_cart') && |
|
| 645 | 645 | $product->is_purchasable() && |
| 646 | - ( $product->is_in_stock() || $product->backorders_allowed() ) |
|
| 646 | + ($product->is_in_stock() || $product->backorders_allowed()) |
|
| 647 | 647 | ) { |
| 648 | 648 | $attributes['class'] .= ' ajax_add_to_cart'; |
| 649 | 649 | } |
| 650 | 650 | |
| 651 | 651 | return sprintf( |
| 652 | 652 | '<a href="%s" %s>%s</a>', |
| 653 | - esc_url( $product->add_to_cart_url() ), |
|
| 654 | - wc_implode_html_attributes( $attributes ), |
|
| 655 | - esc_html( $product->add_to_cart_text() ) |
|
| 653 | + esc_url($product->add_to_cart_url()), |
|
| 654 | + wc_implode_html_attributes($attributes), |
|
| 655 | + esc_html($product->add_to_cart_text()) |
|
| 656 | 656 | ); |
| 657 | 657 | } |
| 658 | 658 | |
@@ -663,14 +663,14 @@ discard block |
||
| 663 | 663 | * Note, this will be empty in the editor context when the block is |
| 664 | 664 | * not in the post content on editor load. |
| 665 | 665 | */ |
| 666 | - protected function enqueue_data( array $attributes = [] ) { |
|
| 667 | - parent::enqueue_data( $attributes ); |
|
| 668 | - $this->asset_data_registry->add( 'min_columns', wc_get_theme_support( 'product_blocks::min_columns', 1 ), true ); |
|
| 669 | - $this->asset_data_registry->add( 'max_columns', wc_get_theme_support( 'product_blocks::max_columns', 6 ), true ); |
|
| 670 | - $this->asset_data_registry->add( 'default_columns', wc_get_theme_support( 'product_blocks::default_columns', 3 ), true ); |
|
| 671 | - $this->asset_data_registry->add( 'min_rows', wc_get_theme_support( 'product_blocks::min_rows', 1 ), true ); |
|
| 672 | - $this->asset_data_registry->add( 'max_rows', wc_get_theme_support( 'product_blocks::max_rows', 6 ), true ); |
|
| 673 | - $this->asset_data_registry->add( 'default_rows', wc_get_theme_support( 'product_blocks::default_rows', 3 ), true ); |
|
| 674 | - $this->asset_data_registry->add( 'stock_status_options', wc_get_product_stock_status_options(), true ); |
|
| 666 | + protected function enqueue_data(array $attributes = []) { |
|
| 667 | + parent::enqueue_data($attributes); |
|
| 668 | + $this->asset_data_registry->add('min_columns', wc_get_theme_support('product_blocks::min_columns', 1), true); |
|
| 669 | + $this->asset_data_registry->add('max_columns', wc_get_theme_support('product_blocks::max_columns', 6), true); |
|
| 670 | + $this->asset_data_registry->add('default_columns', wc_get_theme_support('product_blocks::default_columns', 3), true); |
|
| 671 | + $this->asset_data_registry->add('min_rows', wc_get_theme_support('product_blocks::min_rows', 1), true); |
|
| 672 | + $this->asset_data_registry->add('max_rows', wc_get_theme_support('product_blocks::max_rows', 6), true); |
|
| 673 | + $this->asset_data_registry->add('default_rows', wc_get_theme_support('product_blocks::default_rows', 3), true); |
|
| 674 | + $this->asset_data_registry->add('stock_status_options', wc_get_product_stock_status_options(), true); |
|
| 675 | 675 | } |
| 676 | 676 | } |