Merge branch 'trunk' into update/51111-payments-menu-item
This commit is contained in:
commit
ddbfb1cf59
|
@ -6,6 +6,7 @@
|
|||
align-items: stretch;
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__category-item {
|
||||
|
@ -132,15 +133,18 @@
|
|||
top: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
width: 50px;
|
||||
width: 100px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__category-navigation-button--prev {
|
||||
background: linear-gradient(to right, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
|
||||
left: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.woocommerce-marketplace__category-navigation-button--next {
|
||||
background: linear-gradient(to left, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
|
||||
right: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -179,6 +179,11 @@ const renderInnerBlocks = ( {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Return scripts without manipulation.
|
||||
if ( parsedElement?.type === 'script' ) {
|
||||
return parsedElement;
|
||||
}
|
||||
|
||||
const renderedChildren = node.childNodes.length
|
||||
? renderInnerBlocks( {
|
||||
block,
|
||||
|
|
|
@ -32,7 +32,9 @@ const defaultTemplate = [
|
|||
],
|
||||
[
|
||||
'core/list',
|
||||
{},
|
||||
{
|
||||
className: 'is-style-checkmark-list',
|
||||
},
|
||||
[
|
||||
[
|
||||
'core/list-item',
|
||||
|
|
|
@ -9,6 +9,7 @@ import { PRIVACY_URL, TERMS_URL } from '@woocommerce/block-settings';
|
|||
import { ValidatedTextInput } from '@woocommerce/blocks-components';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { VALIDATION_STORE_KEY } from '@woocommerce/block-data';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
|
||||
const termsPageLink = TERMS_URL ? (
|
||||
<a href={ TERMS_URL } target="_blank" rel="noreferrer">
|
||||
|
@ -26,6 +27,67 @@ const privacyPageLink = PRIVACY_URL ? (
|
|||
<span>{ __( 'Privacy Policy', 'woocommerce' ) }</span>
|
||||
);
|
||||
|
||||
const PasswordField = ( {
|
||||
isLoading,
|
||||
password,
|
||||
setPassword,
|
||||
}: {
|
||||
isLoading: boolean;
|
||||
password: string;
|
||||
setPassword: ( password: string ) => void;
|
||||
} ) => {
|
||||
const [ passwordStrength, setPasswordStrength ] = useState( 0 );
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ValidatedTextInput
|
||||
disabled={ isLoading }
|
||||
type="password"
|
||||
label={ __( 'Password', 'woocommerce' ) }
|
||||
className={ `wc-block-components-address-form__password` }
|
||||
value={ password }
|
||||
required={ true }
|
||||
errorId={ 'account-password' }
|
||||
customValidityMessage={ (
|
||||
validity: ValidityState
|
||||
): string | undefined => {
|
||||
if (
|
||||
validity.valueMissing ||
|
||||
validity.badInput ||
|
||||
validity.typeMismatch
|
||||
) {
|
||||
return __(
|
||||
'Please enter a valid password',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
} }
|
||||
customValidation={ ( inputObject ) => {
|
||||
if ( passwordStrength < 2 ) {
|
||||
inputObject.setCustomValidity(
|
||||
__(
|
||||
'Please create a stronger password',
|
||||
'woocommerce'
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} }
|
||||
onChange={ ( value: string ) => setPassword( value ) }
|
||||
feedback={
|
||||
<PasswordStrengthMeter
|
||||
password={ password }
|
||||
onChange={ ( strength: number ) =>
|
||||
setPasswordStrength( strength )
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Form = ( {
|
||||
attributes: blockAttributes,
|
||||
isEditor,
|
||||
|
@ -35,7 +97,6 @@ const Form = ( {
|
|||
} ) => {
|
||||
const [ isLoading, setIsLoading ] = useState( false );
|
||||
const [ password, setPassword ] = useState( '' );
|
||||
const [ passwordStrength, setPasswordStrength ] = useState( 0 );
|
||||
const hasValidationError = useSelect( ( select ) =>
|
||||
select( VALIDATION_STORE_KEY ).getValidationError( 'account-password' )
|
||||
);
|
||||
|
@ -44,6 +105,13 @@ const Form = ( {
|
|||
( isEditor ? 'customer@email.com' : '' );
|
||||
const nonceToken = blockAttributes?.nonceToken || '';
|
||||
|
||||
// Passwords might not be required based on settings.
|
||||
const registrationGeneratePassword = getSetting(
|
||||
'registrationGeneratePassword',
|
||||
false
|
||||
);
|
||||
const needsPassword = ! registrationGeneratePassword && ! password;
|
||||
|
||||
return (
|
||||
<form
|
||||
className={ 'wc-block-order-confirmation-create-account-form' }
|
||||
|
@ -58,66 +126,29 @@ const Form = ( {
|
|||
setIsLoading( true );
|
||||
} }
|
||||
>
|
||||
<p>
|
||||
{ createInterpolateElement(
|
||||
__( 'Set a password for <email/>', 'woocommerce' ),
|
||||
{
|
||||
email: <strong>{ customerEmail }</strong>,
|
||||
}
|
||||
) }
|
||||
</p>
|
||||
<div>
|
||||
<ValidatedTextInput
|
||||
disabled={ isLoading }
|
||||
type="password"
|
||||
label={ __( 'Password', 'woocommerce' ) }
|
||||
className={ `wc-block-components-address-form__password` }
|
||||
value={ password }
|
||||
required={ true }
|
||||
errorId={ 'account-password' }
|
||||
customValidityMessage={ (
|
||||
validity: ValidityState
|
||||
): string | undefined => {
|
||||
if (
|
||||
validity.valueMissing ||
|
||||
validity.badInput ||
|
||||
validity.typeMismatch
|
||||
) {
|
||||
return __(
|
||||
'Please enter a valid password',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
} }
|
||||
customValidation={ ( inputObject ) => {
|
||||
if ( passwordStrength < 2 ) {
|
||||
inputObject.setCustomValidity(
|
||||
__(
|
||||
'Please create a stronger password',
|
||||
'woocommerce'
|
||||
)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} }
|
||||
onChange={ ( value: string ) => setPassword( value ) }
|
||||
feedback={
|
||||
<PasswordStrengthMeter
|
||||
password={ password }
|
||||
onChange={ ( strength: number ) =>
|
||||
setPasswordStrength( strength )
|
||||
{ ! registrationGeneratePassword && (
|
||||
<>
|
||||
<p>
|
||||
{ createInterpolateElement(
|
||||
__( 'Set a password for <email/>', 'woocommerce' ),
|
||||
{
|
||||
email: <strong>{ customerEmail }</strong>,
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
</p>
|
||||
<PasswordField
|
||||
isLoading={ isLoading }
|
||||
password={ password }
|
||||
setPassword={ setPassword }
|
||||
/>
|
||||
</>
|
||||
) }
|
||||
<Button
|
||||
className={
|
||||
'wc-block-order-confirmation-create-account-button'
|
||||
}
|
||||
type="submit"
|
||||
disabled={ !! hasValidationError || ! password || isLoading }
|
||||
disabled={ !! hasValidationError || needsPassword || isLoading }
|
||||
showSpinner={ isLoading }
|
||||
>
|
||||
{ __( 'Create account', 'woocommerce' ) }
|
||||
|
@ -126,16 +157,26 @@ const Form = ( {
|
|||
<input type="hidden" name="password" value={ password } />
|
||||
<input type="hidden" name="create-account" value="1" />
|
||||
<input type="hidden" name="_wpnonce" value={ nonceToken } />
|
||||
<p className={ 'wc-block-order-confirmation-create-account-terms' }>
|
||||
{ createInterpolateElement(
|
||||
/* translators: %1$s terms page link, %2$s privacy page link. */
|
||||
__(
|
||||
'By creating an account you agree to our <terms/> and <privacy/>.',
|
||||
'woocommerce'
|
||||
),
|
||||
{ terms: termsPageLink, privacy: privacyPageLink }
|
||||
<div className="wc-block-order-confirmation-create-account-description">
|
||||
{ registrationGeneratePassword && (
|
||||
<p>
|
||||
{ __(
|
||||
"We'll email you a link to set up an account password.",
|
||||
'woocommerce'
|
||||
) }
|
||||
</p>
|
||||
) }
|
||||
</p>
|
||||
<p>
|
||||
{ createInterpolateElement(
|
||||
/* translators: %1$s terms page link, %2$s privacy page link. */
|
||||
__(
|
||||
'By creating an account you agree to our <terms/> and <privacy/>.',
|
||||
'woocommerce'
|
||||
),
|
||||
{ terms: termsPageLink, privacy: privacyPageLink }
|
||||
) }
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -53,13 +53,15 @@
|
|||
padding: 1em;
|
||||
}
|
||||
|
||||
.wc-block-order-confirmation-create-account-terms {
|
||||
@include font-size(small);
|
||||
text-align: center;
|
||||
.wc-block-order-confirmation-create-account-description {
|
||||
p {
|
||||
@include font-size(small);
|
||||
text-align: center;
|
||||
|
||||
a,
|
||||
span {
|
||||
white-space: nowrap;
|
||||
a,
|
||||
span {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: tweak
|
||||
Comment: Delayed account creation: Support option to send password setup link to customer via email.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: fix
|
||||
|
||||
Fix marketplace category selector scrollbars and buttons
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Ensure QuantityLimits::limit_to_multiple() receives correct values to prevent fatal errors.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Ensure session is loaded in cart functions to prevent fatal errors.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix script tag handling for inner blocks in the cart
|
|
@ -358,16 +358,21 @@ class WC_Shortcode_My_Account {
|
|||
/**
|
||||
* Handles resetting the user's password.
|
||||
*
|
||||
* @since 9.4.0 This will log the user in after resetting the password/session.
|
||||
*
|
||||
* @param object $user The user.
|
||||
* @param string $new_pass New password for the user in plaintext.
|
||||
*/
|
||||
public static function reset_password( $user, $new_pass ) {
|
||||
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
|
||||
do_action( 'password_reset', $user, $new_pass );
|
||||
|
||||
wp_set_password( $new_pass, $user->ID );
|
||||
update_user_meta( $user->ID, 'default_password_nag', false );
|
||||
self::set_reset_password_cookie();
|
||||
wc_set_customer_auth_cookie( $user->ID );
|
||||
|
||||
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
|
||||
if ( ! apply_filters( 'woocommerce_disable_password_change_notification', false ) ) {
|
||||
wp_password_change_notification( $user );
|
||||
}
|
||||
|
|
|
@ -412,13 +412,13 @@ function wc_cart_round_discount( $value, $precision ) {
|
|||
* @return string[]
|
||||
*/
|
||||
function wc_get_chosen_shipping_method_ids() {
|
||||
$method_ids = array();
|
||||
$chosen_methods = array();
|
||||
|
||||
if ( is_callable( array( WC()->session, 'get' ) ) ) {
|
||||
$chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() );
|
||||
if ( ! is_callable( array( WC()->session, 'get' ) ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() );
|
||||
$method_ids = array();
|
||||
|
||||
foreach ( $chosen_methods as $chosen_method ) {
|
||||
if ( ! is_string( $chosen_method ) ) {
|
||||
continue;
|
||||
|
@ -439,11 +439,15 @@ function wc_get_chosen_shipping_method_ids() {
|
|||
* @return string|bool Either the chosen method ID or false if nothing is chosen yet.
|
||||
*/
|
||||
function wc_get_chosen_shipping_method_for_package( $key, $package ) {
|
||||
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
|
||||
if ( ! is_callable( array( WC()->session, 'get' ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() );
|
||||
$chosen_method = isset( $chosen_methods[ $key ] ) ? $chosen_methods[ $key ] : false;
|
||||
$changed = wc_shipping_methods_have_changed( $key, $package );
|
||||
|
||||
// This is deprecated but here for BW compat. TODO: Remove in 4.0.0.
|
||||
// This is deprecated but here for BW compat. Remove in 4.0.0.
|
||||
$method_counts = WC()->session->get( 'shipping_method_counts' );
|
||||
|
||||
if ( ! empty( $method_counts[ $key ] ) ) {
|
||||
|
@ -465,6 +469,12 @@ function wc_get_chosen_shipping_method_for_package( $key, $package ) {
|
|||
WC()->session->set( 'chosen_shipping_methods', $chosen_methods );
|
||||
WC()->session->set( 'shipping_method_counts', $method_counts );
|
||||
|
||||
/**
|
||||
* Fires when a shipping method is chosen.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @param string $chosen_method Chosen shipping method. e.g. flat_rate:1.
|
||||
*/
|
||||
do_action( 'woocommerce_shipping_method_chosen', $chosen_method );
|
||||
}
|
||||
return $chosen_method;
|
||||
|
@ -536,6 +546,10 @@ function wc_get_default_shipping_method_for_package( $key, $package, $chosen_met
|
|||
* @return bool
|
||||
*/
|
||||
function wc_shipping_methods_have_changed( $key, $package ) {
|
||||
if ( ! is_callable( array( WC()->session, 'get' ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lookup previous methods from session.
|
||||
$previous_shipping_methods = WC()->session->get( 'previous_shipping_methods' );
|
||||
// Get new and old rates.
|
||||
|
|
|
@ -40,7 +40,7 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
|
|||
* @return \WP_Error|int
|
||||
*/
|
||||
protected function process_form_post( $order ) {
|
||||
if ( ! isset( $_POST['create-account'], $_POST['email'], $_POST['password'], $_POST['_wpnonce'] ) ) {
|
||||
if ( ! isset( $_POST['create-account'], $_POST['email'], $_POST['_wpnonce'] ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,6 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
|
|||
}
|
||||
|
||||
$user_email = sanitize_email( wp_unslash( $_POST['email'] ) );
|
||||
$password = wp_unslash( $_POST['password'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
// Does order already have user?
|
||||
if ( $order->get_customer_id() ) {
|
||||
|
@ -61,8 +60,16 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
|
|||
return new \WP_Error( 'email_mismatch', __( 'The email address provided does not match the email address on this order.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( empty( $password ) || strlen( $password ) < 8 ) {
|
||||
return new \WP_Error( 'password_too_short', __( 'Password must be at least 8 characters.', 'woocommerce' ) );
|
||||
$generate_password = get_option( 'woocommerce_registration_generate_password', false );
|
||||
|
||||
if ( $generate_password ) {
|
||||
$password = ''; // Will be generated by wc_create_new_customer.
|
||||
} else {
|
||||
$password = wp_unslash( $_POST['password'] ?? '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
if ( empty( $password ) || strlen( $password ) < 8 ) {
|
||||
return new \WP_Error( 'password_too_short', __( 'Password must be at least 8 characters.', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
|
||||
$customer_id = wc_create_new_customer(
|
||||
|
@ -171,4 +178,17 @@ class CreateAccount extends AbstractOrderConfirmationBlock {
|
|||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra data passed through from server to client for block.
|
||||
*
|
||||
* @param array $attributes Any attributes that currently are available from the block.
|
||||
* Note, this will be empty in the editor context when the block is
|
||||
* not in the post content on editor load.
|
||||
*/
|
||||
protected function enqueue_data( array $attributes = [] ) {
|
||||
parent::enqueue_data( $attributes );
|
||||
|
||||
$this->asset_data_registry->add( 'registrationGeneratePassword', filter_var( get_option( 'woocommerce_registration_generate_password' ), FILTER_VALIDATE_BOOLEAN ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,16 @@ final class QuantityLimits {
|
|||
];
|
||||
}
|
||||
|
||||
$multiple_of = (int) $this->filter_value( 1, 'multiple_of', $cart_item );
|
||||
$minimum = (int) $this->filter_value( 1, 'minimum', $cart_item );
|
||||
$maximum = (int) $this->filter_value( $this->get_product_quantity_limit( $product ), 'maximum', $cart_item );
|
||||
$editable = (bool) $this->filter_value( ! $product->is_sold_individually(), 'editable', $cart_item );
|
||||
$multiple_of = $this->filter_numeric_value( 1, 'multiple_of', $cart_item );
|
||||
$minimum = $this->filter_numeric_value( 1, 'minimum', $cart_item );
|
||||
$maximum = $this->filter_numeric_value( $this->get_product_quantity_limit( $product ), 'maximum', $cart_item );
|
||||
$editable = $this->filter_boolean_value( ! $product->is_sold_individually(), 'editable', $cart_item );
|
||||
|
||||
// Minimum must be at least 1.
|
||||
$minimum = max( $minimum, 1 );
|
||||
|
||||
// Maximum must be at least minimum.
|
||||
$maximum = max( $maximum, $minimum );
|
||||
|
||||
return [
|
||||
'minimum' => $this->limit_to_multiple( $minimum, $multiple_of, 'ceil' ),
|
||||
|
@ -50,9 +56,15 @@ final class QuantityLimits {
|
|||
* @return array
|
||||
*/
|
||||
public function get_add_to_cart_limits( \WC_Product $product ) {
|
||||
$multiple_of = $this->filter_value( 1, 'multiple_of', $product );
|
||||
$minimum = $this->filter_value( 1, 'minimum', $product );
|
||||
$maximum = $this->filter_value( $this->get_product_quantity_limit( $product ), 'maximum', $product );
|
||||
$multiple_of = $this->filter_numeric_value( 1, 'multiple_of', $product );
|
||||
$minimum = $this->filter_numeric_value( 1, 'minimum', $product );
|
||||
$maximum = $this->filter_numeric_value( $this->get_product_quantity_limit( $product ), 'maximum', $product );
|
||||
|
||||
// Minimum must be at least 1.
|
||||
$minimum = max( $minimum, 1 );
|
||||
|
||||
// Maximum must be at least minimum.
|
||||
$maximum = max( $maximum, $minimum );
|
||||
|
||||
return [
|
||||
'minimum' => $this->limit_to_multiple( $minimum, $multiple_of, 'ceil' ),
|
||||
|
@ -148,6 +160,8 @@ final class QuantityLimits {
|
|||
$limits[] = $this->get_remaining_stock( $product );
|
||||
}
|
||||
|
||||
$limit = max( min( array_filter( $limits ) ), 1 );
|
||||
|
||||
/**
|
||||
* Filters the quantity limit for a product being added to the cart via the Store API.
|
||||
*
|
||||
|
@ -159,7 +173,10 @@ final class QuantityLimits {
|
|||
* @param \WC_Product $product Product instance.
|
||||
* @return integer
|
||||
*/
|
||||
return apply_filters( 'woocommerce_store_api_product_quantity_limit', max( min( array_filter( $limits ) ), 1 ), $product );
|
||||
$filtered_limit = apply_filters( 'woocommerce_store_api_product_quantity_limit', $limit, $product );
|
||||
|
||||
// Only return the filtered limit if it's numeric, otherwise return the original limit.
|
||||
return is_numeric( $filtered_limit ) ? (int) $filtered_limit : $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,15 +201,16 @@ final class QuantityLimits {
|
|||
/**
|
||||
* Get a quantity for a product or cart item by running it through a filter hook.
|
||||
*
|
||||
* @param int|null $value Value to filter.
|
||||
* @param int $value Value to filter.
|
||||
* @param string $value_type Type of value. Used for filter suffix.
|
||||
* @param \WC_Product|array $cart_item_or_product Either a cart item or a product instance.
|
||||
* @return mixed
|
||||
* @return int
|
||||
*/
|
||||
protected function filter_value( $value, string $value_type, $cart_item_or_product ) {
|
||||
protected function filter_numeric_value( int $value, string $value_type, $cart_item_or_product ) {
|
||||
$is_product = $cart_item_or_product instanceof \WC_Product;
|
||||
$product = $is_product ? $cart_item_or_product : $cart_item_or_product['data'];
|
||||
$cart_item = $is_product ? null : $cart_item_or_product;
|
||||
|
||||
/**
|
||||
* Filters the quantity minimum for a cart item in Store API. This allows extensions to control the minimum qty
|
||||
* of items already within the cart.
|
||||
|
@ -207,6 +225,40 @@ final class QuantityLimits {
|
|||
* @param array|null $cart_item The cart item if the product exists in the cart, or null.
|
||||
* @return mixed
|
||||
*/
|
||||
return apply_filters( "woocommerce_store_api_product_quantity_{$value_type}", $value, $product, $cart_item );
|
||||
$filtered_value = apply_filters( "woocommerce_store_api_product_quantity_{$value_type}", $value, $product, $cart_item );
|
||||
|
||||
return is_numeric( $filtered_value ) ? (int) $filtered_value : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a quantity for a product or cart item by running it through a filter hook.
|
||||
*
|
||||
* @param bool $value Value to filter.
|
||||
* @param string $value_type Type of value. Used for filter suffix.
|
||||
* @param \WC_Product|array $cart_item_or_product Either a cart item or a product instance.
|
||||
* @return bool
|
||||
*/
|
||||
protected function filter_boolean_value( $value, string $value_type, $cart_item_or_product ) {
|
||||
$is_product = $cart_item_or_product instanceof \WC_Product;
|
||||
$product = $is_product ? $cart_item_or_product : $cart_item_or_product['data'];
|
||||
$cart_item = $is_product ? null : $cart_item_or_product;
|
||||
|
||||
/**
|
||||
* Filters the quantity minimum for a cart item in Store API. This allows extensions to control the minimum qty
|
||||
* of items already within the cart.
|
||||
*
|
||||
* The suffix of the hook will vary depending on the value being filtered.
|
||||
* For example, minimum, maximum, multiple_of, editable.
|
||||
*
|
||||
* @since 6.8.0
|
||||
*
|
||||
* @param mixed $value The value being filtered.
|
||||
* @param \WC_Product $product The product object.
|
||||
* @param array|null $cart_item The cart item if the product exists in the cart, or null.
|
||||
* @return mixed
|
||||
*/
|
||||
$filtered_value = apply_filters( "woocommerce_store_api_product_quantity_{$value_type}", $value, $product, $cart_item );
|
||||
|
||||
return is_bool( $filtered_value ) ? (bool) $filtered_value : $value;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue