LittleDemon WebShell


Linux webm001.cluster123.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
Path : /home/lapjouc/www/wp-content/plugins/pmpro-woocommerce/
File Upload :
Command :
Current File : /home/lapjouc/www/wp-content/plugins/pmpro-woocommerce/pmpro-woocommerce.php

<?php
/**
 * Plugin Name: Paid Memberships Pro - WooCommerce Add On
 * Plugin URI: https://www.paidmembershipspro.com/add-ons/pmpro-woocommerce/
 * Description: Integrate Paid Memberships Pro With WooCommerce.
 * Version: 1.10
 * WC requires at least: 7.0.0
 * WC tested up to: 8.9.1
 * Author: Paid Memberships Pro
 * Author URI: https://www.paidmembershipspro.com/
 * Text Domain: pmpro-woocommerce
 * Domain Path: /languages
 */

//constants
define( 'PMPROWC_DIR', dirname( __FILE__ ) );
define( 'PMPROWC_BASENAME', plugin_basename( __FILE__ ) );

// Includes
require_once( PMPROWC_DIR . '/includes/functions.php' );
require_once( PMPROWC_DIR . '/includes/admin.php' );

/**
 * Loads modules and globals on init
 */
function pmprowoo_init() {
	// Get all Product Membership Levels
	global $pmprowoo_product_levels;
	$pmprowoo_product_levels = get_option( '_pmprowoo_product_levels' );
	if ( empty( $pmprowoo_product_levels ) ) {
		$pmprowoo_product_levels = array();
	}
	
	// Get all Gift Membership Codes
	global $pmprowoo_gift_codes;
	$pmprowoo_gift_codes = get_option( '_pmprowoo_gift_codes' );
	if ( empty( $pmprowoo_gift_codes ) ) {
		$pmprowoo_gift_codes = array();
	}
	
	// Get all Membership Discounts
	global $pmprowoo_member_discounts;
	$pmprowoo_member_discounts = get_option( '_pmprowoo_member_discounts' );
	if ( empty( $pmprowoo_member_discounts ) ) {
		$pmprowoo_member_discounts = array();
	}
	
	// Apply Discounts to Subscriptions
	global $pmprowoo_discounts_on_subscriptions;
	$pmprowoo_discounts_on_subscriptions = get_option( 'pmpro_pmprowoo_discounts_on_subscriptions' );	
	if ( empty( $pmprowoo_discounts_on_subscriptions ) ) {
		$pmprowoo_discounts_on_subscriptions = false;
	}

	// Load gift levels module if that addon is active.
	if ( function_exists( 'pmprogl_plugin_row_meta' ) ) {
		require_once( dirname( __FILE__ ) . '/includes/pmpro-gift-levels.php' );
	}

	// If MMPU is active, allow for multiple membership products in your cart
	if ( defined( 'PMPROMMPU_VER') ) {
		remove_filter( 'woocommerce_is_purchasable', 'pmprowoo_is_purchasable', 10, 2 );
	}
}
add_action( 'init', 'pmprowoo_init' );

/**
 * Disable other membership products if a membership product is in the cart already
 *
 * @param bool        $is_purchasable
 * @param \WC_Product $product
 *
 * @return bool
 */
function pmprowoo_is_purchasable( $is_purchasable, $product ) {
	
	global $pmprowoo_product_levels;
	
	// Not purchasable for some other reason.
	if( ! $is_purchasable ) {
		return $is_purchasable;
	}

	// If the product is not a membership product, we don't need to check.
	$product_id = $product->get_id();
	if ( ! array_key_exists( $product_id, $pmprowoo_product_levels ) ) {
		return $is_purchasable;
	}

	// Backwards compatibility for pre 3.0 versions of PMPro.
	if ( ! function_exists( 'pmpro_get_group_id_for_level' ) ) {
		// If the cart already has a membership product, let's disable the purchase.
		if ( pmprowoo_cart_has_membership() ) {
			add_action( 'woocommerce_single_product_summary', 'pmprowoo_purchase_disabled' );
			return false;
		}
		return $is_purchasable;
	}

	// Get the level group ID for the product.
	$group_id = pmpro_get_group_id_for_level( $pmprowoo_product_levels[ $product_id ] );
	if ( empty( $group_id ) ) {
		return $is_purchasable;
	}

	// If the level group allows purchasing multiple levels in the group, we can allow purchasing this product.
	$group = pmpro_get_level_group( $group_id );
	if ( empty( $group ) || (bool) $group->allow_multiple_selections ) {
		return $is_purchasable;
	}

	// This group only allows users to have one level from the group.
	// Check if the cart already has a membership product for this group.
	$products_in_cart = pmprowoo_get_memberships_from_cart();
	foreach ( $products_in_cart as $product_id ) {
		// If this is not a product level, continue.
		if ( ! array_key_exists( $product_id, $pmprowoo_product_levels ) ) {
			continue;
		}

		// If the cart product is the same as the product passed into this function, continue.
		if ( $product_id === $product->get_id() ) {
			continue;
		}

		// Get the group ID for the product in the cart.
		$group_id_in_cart = pmpro_get_group_id_for_level( $pmprowoo_product_levels[ $product_id ] );
		if ( empty( $group_id_in_cart ) ) {
			continue;
		}

		// If the group ID in the cart matches the group ID of the product we are viewing, let's disable the purchase.
		if ( (int)$group_id_in_cart === (int)$group_id ) {
			add_action( 'woocommerce_single_product_summary', 'pmprowoo_purchase_disabled' );
			return false;
		}
	}
	
	return $is_purchasable;
}
add_filter( 'woocommerce_is_purchasable', 'pmprowoo_is_purchasable', 10, 2 );

/**
 * Info message when attempting to add a 2nd membership level to the cart
 */
function pmprowoo_purchase_disabled() {
	$cart_url = wc_get_cart_url();
	$product = wc_get_product();
	$product_id = $product->get_id();

	// Get cart contents and see if they're a membership product
	$membership_products_in_cart = pmprowoo_get_memberships_from_cart();

	$membership_in_cart = in_array( $product_id, $membership_products_in_cart );

	if ( ! $membership_in_cart ) {
		$message = sprintf( __( "You may only add one membership to your %scart%s.", 'pmpro-woocommerce' ),
				sprintf( '<a href="%1$s" title="%2$s">', esc_url( $cart_url ), esc_html__( 'Cart', 'pmpro-woocommerce' ) ),
				'</a>' );
	} else {
		$message = sprintf( __( "%s is already in your %scart%s.", 'pmpro-woocommerce' ),
				$product->get_name(),
				sprintf( '<a href="%1$s" title="%2$s">', esc_url( $cart_url ), esc_html__( 'Cart', 'pmpro-woocommerce' ) ),
				'</a>' );
	}
	?>
    <div class="woocommerce">
        <div class="woocommerce-info wc-nonpurchasable-message">
			<?php echo $message; ?>
        </div>
    </div>
	<?php
}


/**
 * Add users to membership levels after order is completed.
 *
 * @param int $order_id
 */
function pmprowoo_add_membership_from_order( $order_id ) {
	global $wpdb, $pmprowoo_product_levels;
	
	// quitely exit if PMPro isn't active
	if ( ! defined( 'PMPRO_DIR' ) && ! function_exists( 'pmpro_init' ) ) {
		return;
	}
	
	//don't bother if array is empty
	if ( empty( $pmprowoo_product_levels ) ) {
		return;
	}
	
	/*
		does this order contain a membership product?
	*/
	//membership product ids
	$membership_product_ids = pmprowoo_get_membership_products_from_order( $order_id );
	
	//get order
	$order = new WC_Order( $order_id );
	
	//does the order have a user id and some products?
	$user_id = $order->get_user_id();
	if ( ! empty( $user_id ) && sizeof( $order->get_items() ) > 0 ) {
		foreach ( $order->get_items() as $item ) {
			// Get the product object from the ID of the item in the order.
			$_product = wc_get_product( $item['product_id'] );

			if ( $_product->is_type( 'variation' ) ) {
			    $product_id = $_product->get_parent_id();
			} else {
			    $product_id = $_product->get_id();
			}

			if ( ! empty( $product_id ) &&
			     in_array( $product_id, $membership_product_ids ) ) {    //not sure when a product has id 0, but the Woo code checks this
				
				// Check to see if the order is a renewal order for a subscription. If it is, bail.
					if ( function_exists( 'wcs_order_contains_renewal' ) ) {
					// If the user already has the level, let's just leave it and assume it's a renewal order.
					if ( wcs_order_contains_renewal( $order )  ) {
						if ( pmprowoo_user_has_active_membership_product_for_level( $user_id, $pmprowoo_product_levels[ $product_id ] ) ) {
							return;
						}
					}
				}
				
				//is there a membership level for this product?
				//get user id and level
				$pmpro_level = pmpro_getLevel( $pmprowoo_product_levels[ $product_id ] );
				
				//if checking out for the same level they have, keep their old start date
				$sqlQuery = $wpdb->prepare(
					"SELECT startdate
                                FROM {$wpdb->pmpro_memberships_users}
                                WHERE user_id = %d
                                  AND membership_id = %d
                                  AND status = 'active'
                                ORDER BY id DESC
                                LIMIT 1",
					$user_id,
					$pmpro_level->id
				);
				
				$old_startdate = $wpdb->get_var( $sqlQuery );
				if ( ! empty( $old_startdate ) ) {
					$startdate = "'" . $old_startdate . "'";
				} else {
					$startdate = "'" . current_time( 'mysql' ) . "'";
				}
				
				//create custom level to mimic PMPro checkout
				$custom_level = array(
					'user_id'         => $user_id,
					'membership_id'   => $pmpro_level->id,
					'code_id'         => '', //will support PMPro discount codes later
					'initial_payment' => $item['line_total'],
					'billing_amount'  => '',
					'cycle_number'    => '',
					'cycle_period'    => '',
					'billing_limit'   => '',
					'trial_amount'    => '',
					'trial_limit'     => '',
					'startdate'       => sanitize_text_field( $startdate ),
					'enddate'         => '0000-00-00 00:00:00',
				);
				
				//set enddate
				if ( ! empty( $pmpro_level->expiration_number ) ) {
					$custom_level['enddate'] = date( "Y-m-d H:i:00", strtotime( "+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time( 'timestamp' ) ) );
				}

				/** 
				 * Filter for the level object.
				 */
				$custom_level = apply_filters( 'pmprowoo_checkout_level', $custom_level );
				
				// Is MMPU activated?
				if ( function_exists( 'pmprommpu_addMembershipLevel' ) ) {
					// Allow filter to force add levels (ignore MMPU group level settings).
					$mmpu_force_add_level = apply_filters( 'pmprowoo_mmpu_force_add_level', false );
					pmprommpu_addMembershipLevel( $custom_level, $user_id, $mmpu_force_add_level );
				} else {
					// Only add the first membership level found.
					pmpro_changeMembershipLevel( $custom_level, $user_id );
					break;
				}
			}
		}
	}
}
add_action( 'woocommerce_order_status_completed', 'pmprowoo_add_membership_from_order' );

/**
 * Cancel memberships when orders go into pending, processing, refunded, failed, or on hold.
 *
 * @param int $order_id
 */
function pmprowoo_cancel_membership_from_order( $order_id ) {
	global $pmprowoo_product_levels;

	// quitely exit if PMPro isn't active
	if ( ! defined( 'PMPRO_DIR' ) && ! function_exists( 'pmpro_init' ) ) {
		return;
	}
	
	//don't bother if array is empty
	if ( empty( $pmprowoo_product_levels ) ) {
		return;
	}
	
	//membership product ids
	$membership_product_ids = pmprowoo_get_membership_products_from_order( $order_id );
	
	//get order
	$order = new WC_Order( $order_id );
	
	//does the order have a user id and some products?
	$user_id = $order->get_user_id();
	if ( ! empty( $user_id ) && sizeof( $order->get_items() ) > 0 ) {
		foreach ( $order->get_items() as $item ) {
			//not sure when a product has id 0, but the Woo code checks this
			if ( ! empty( $item['product_id'] ) && in_array( $item['product_id'], $membership_product_ids ) ) {
	
				//check if another active subscription exists
				if ( ! pmprowoo_user_has_active_membership_product_for_level( $user_id, $pmprowoo_product_levels[ $item['product_id'] ] ) ) {
					//is there a membership level for this product?
					//remove the user from the level
					pmpro_cancelMembershipLevel( $pmprowoo_product_levels[$item['product_id']], $user_id, 'cancelled' );
				}
			}
		}
	}
}
add_action( "woocommerce_order_status_refunded", "pmprowoo_cancel_membership_from_order" );
add_action( "woocommerce_order_status_failed", "pmprowoo_cancel_membership_from_order" );
add_action( 'woocommerce_subscription_status_on-hold_to_active', 'pmprowoo_activated_subscription' );
add_action( "woocommerce_order_status_cancelled", "pmprowoo_cancel_membership_from_order" );

/**
 * Activate memberships when WooCommerce subscriptions change status.
 *
 * @param \WC_Subscription $subscription
 */
function pmprowoo_activated_subscription( $subscription ) {
	global $pmprowoo_product_levels;

	// quitely exit if PMPro isn't active
	if ( ! defined( 'PMPRO_DIR' ) && ! function_exists( 'pmpro_init' ) ) {
		return;
	}
	
	//don't bother if array is empty
	if ( empty( $pmprowoo_product_levels ) ) {
		return;
	}
	
	if ( is_numeric( $subscription ) ) {
		$subscription = wcs_get_subscription( $subscription );
	}
	/*
		Does this order contain a membership product?
		Since v2 of WCSubs, we need to check all line items
	*/
	$order_id = $subscription->get_last_order();
	if( version_compare( get_option( 'woocommerce_subscriptions_active_version' ), '2.0', '>' ) ) {
		$user_id = $subscription->get_user_id();
		$items = $subscription->get_items();
	} else {
		$order    = wc_get_order( $order_id );
		$items    = $order->get_items();
		$user_id  = $order->get_user_id();
	}
	
	if ( ! empty( $items ) && ! empty( $user_id ) ) {
		//membership product ids
		$membership_product_ids = pmprowoo_get_membership_products_from_order( $order_id );
		
		//does the order item have a user id and a product?
		foreach ( $items as $item ) {
			
			if ( ! empty( $item['product_id'] ) && in_array( $item['product_id'], $membership_product_ids ) ) {
				// Is MMPU activated?
				if ( function_exists( 'pmprommpu_addMembershipLevel' ) ) {
					// Allow filter to force add levels (ignore MMPU group level settings).
					$mmpu_force_add_level = apply_filters( 'pmprowoo_mmpu_force_add_level', false );
					pmprommpu_addMembershipLevel( $pmprowoo_product_levels[ $item['product_id'] ], $user_id, $mmpu_force_add_level );
				} else {
					// Only add the first membership level found.
					pmpro_changeMembershipLevel( $pmprowoo_product_levels[ $item['product_id'] ], $user_id );
					break;
				}
			}
		}
	}
}
add_action( 'woocommerce_subscription_status_active', 'pmprowoo_activated_subscription' );
add_action( 'woocommerce_subscription_status_on-hold_to_active', 'pmprowoo_activated_subscription' );

/**
 * Cancel memberships when WooCommerce subscriptions change status.
 *
 * @param \WC_Subscription $subscription
 */
function pmprowoo_cancelled_subscription( $subscription ) {
	global $pmprowoo_product_levels;

	// quitely exit if PMPro isn't active
	if ( ! defined( 'PMPRO_DIR' ) && ! function_exists( 'pmpro_init' ) ) {
		return;
	}
	
	//don't bother if array is empty
	if ( empty( $pmprowoo_product_levels ) ) {
		return;
	}
	
	if ( is_numeric( $subscription ) ) {
        $subscription = wcs_get_subscription( $subscription );
    }
      
	/*
		Does this order contain a membership product?
		Since v2 of WCSubs, we need to check all line items
	*/
	$order_id = $subscription->get_last_order();
	if( version_compare( get_option( 'woocommerce_subscriptions_active_version' ), '2.0', '>' ) ) {
		$user_id = $subscription->get_user_id();
		$items = $subscription->get_items();
	} else {
		$order    = wc_get_order( $order_id );
		$items    = $order->get_items();
		$user_id  = $order->get_user_id();
	}
	
	if ( ! empty( $items ) && ! empty( $user_id ) ) {
		//membership product ids
		$membership_product_ids = pmprowoo_get_membership_products_from_order( $order_id );
		
		foreach ( $items as $item ) {
			//does the order have a user id and some products?
			if ( ! empty( $item['product_id']  && in_array($item['product_id'], $membership_product_ids)) ) {
				//check if another active subscription exists
				if (  ! pmprowoo_user_has_active_membership_product_for_level( $user_id, $pmprowoo_product_levels[ $item['product_id'] ] ) ) {	
					//is there a membership level for this product?
					if( in_array($item['product_id'], $membership_product_ids) ){
						//remove the user from the level
						pmpro_cancelMembershipLevel($pmprowoo_product_levels[$item['product_id']], $user_id);
					}
				}
			}
		}
	}
}

//WooCommerce Subscriptions v2 hooks
add_action( 'woocommerce_subscription_status_cancelled', 'pmprowoo_cancelled_subscription', 10 );
add_action( 'woocommerce_subscription_status_trash', 'pmprowoo_cancelled_subscription', 10 );
add_action( 'woocommerce_subscription_status_expired', 'pmprowoo_cancelled_subscription', 10 );
add_action( 'woocommerce_subscription_status_on-hold', 'pmprowoo_cancelled_subscription', 10 );
add_action( 'woocommerce_scheduled_subscription_end_of_prepaid_term', 'pmprowoo_cancelled_subscription', 10 );

/**
 * Update Product Prices with Membership Price and/or Discount
 *
 * @param float      $price
 * @param WC_Product $product
 *
 * @return string
 */
function pmprowoo_get_membership_price( $price, $product ) {
	global $current_user, $pmprowoo_member_discounts, $pmprowoo_product_levels, $pmprowoo_discounts_on_subscriptions;

	// quitely exit if PMPro isn't active
	if ( ! defined( 'PMPRO_DIR' ) && ! function_exists( 'pmpro_init' ) ) {
		return $price;
	}

	// make sure $product is a product object
	if (! is_object( $product ) ) {
		$product = wc_get_product( $product );
	}

	// no product? bail
	if ( empty( $product ) ) {
		return $price;
	}

	// Get the ID for the product that we are currently getting a membership price for.
	if ( $product->get_type() === 'variation' ) {
		$product_id = $product->get_parent_id(); //for variations	
	} else {
		$product_id = $product->get_id();
	}
	
	$membership_product_ids = array_keys( $pmprowoo_product_levels );
	$items       = is_object( WC()->cart ) ? WC()->cart->get_cart_contents() : array(); // items in the cart

	//ignore membership products and subscriptions if we are set that way
	if ( ( ! $pmprowoo_discounts_on_subscriptions || $pmprowoo_discounts_on_subscriptions == 'No' ) && ( $product->is_type( array( 'subscription', 'variable-subscription', 'subscription_variation' ) ) || in_array( $product_id, $membership_product_ids, false ) ) ) {
		return $price;
	}

	// Get all membership level ids that will be given to the user after checkout.
	// Ignore the product that we are currently getting a membership price for.
	$cart_level_ids = array();
	foreach ( $items as $item ) {
		if ( $item['product_id'] != $product->get_id() && in_array( $item['product_id'], $membership_product_ids ) ) {
			$cart_level_ids[] = $pmprowoo_product_levels[ $item['product_id'] ];
		}
	}

	// Get the membership level ids that the user already has.
	$user_levels = pmpro_getMembershipLevelsForUser( $current_user->ID );
	$user_level_ids = empty( $user_levels ) ? array() : wp_list_pluck( $user_levels, 'id' );

	// Merge the cart levels and user levels and remove duplicates to get all levels that could discount this product.
	$discount_level_ids = array_unique( array_merge( $cart_level_ids, $user_level_ids ) );

	// Find the lowest membership price for this product.
	$lowest_price = (float) $price;
	$lowest_price_level = null; // Needed for backwards compatibility for pmprowoo_get_membership_price filter.
	foreach ( $discount_level_ids as $level_id ) {
		$level_price = get_post_meta( $product_id, '_level_' . $level_id . '_price', true );
		if ( ! empty( $level_price ) || $level_price === '0' || $level_price === '0.00' || $level_price === '0,00' ) {
			$level_price = (float) $level_price;
			if ( $level_price < $lowest_price ) {
				$lowest_price = $level_price;
				$lowest_price_level = $level_id;
			}
		}
	}

	// Find the highest membership discount for this product.
	$highest_discount = 0;
	foreach ( $discount_level_ids as $level_id ) {
		if ( ! empty( $pmprowoo_member_discounts ) && ! empty( $pmprowoo_member_discounts[ $level_id ] ) ) {
			$level_discount = (float) $pmprowoo_member_discounts[ $level_id ];
			if ( $level_discount > $highest_discount ) {
				$highest_discount = $level_discount;
			}
		}
	}
	$discount_price = $lowest_price - ( $lowest_price * $highest_discount );

	// Filter the result.
	return apply_filters( 'pmprowoo_get_membership_price', $discount_price, $lowest_price_level, $price, $product );
}


// only change price if this is on the front end
if ( ! is_admin() || defined( 'DOING_AJAX' ) ) {
	add_filter( "woocommerce_product_get_price", "pmprowoo_get_membership_price", 10, 2 );
	add_filter( "woocommerce_product_variation_get_price", "pmprowoo_get_membership_price", 10, 5 );
	add_filter( "woocommerce_variable_price_html", "pmprowoo_woocommerce_variable_price_html", 10, 2 );
}

/**
 * Update Variable Product Price Range
 *
 * @param string               $variation_range_html
 * @param \WC_Product_Variable $product
 *
 * @return string
 */
function pmprowoo_woocommerce_variable_price_html( $variation_range_html, $product ) {
	$prices = $product->get_variation_prices( true );
	$prices_product_ids = array_keys( $prices['price']) ;

	$min_price = current( $prices['price'] );
	$min_price_product_id = current( $prices_product_ids );
	$max_price = end( $prices['price'] );
	$max_price_product_id = end( $prices_product_ids );
	
	$member_min_price = pmprowoo_get_membership_price( $min_price, $min_price_product_id );
	$member_max_price = pmprowoo_get_membership_price( $max_price, $max_price_product_id );
	
	// If variation price for min and max price are identical, show one price only.
	if ( $member_min_price === $member_max_price ) {
		return wc_price( $member_max_price );
	}

	return wc_format_price_range( $member_min_price, $member_max_price );
}

/**
 * Add PMPro Tab to Edit Products page
 */
function pmprowoo_tab_options_tab() {
	?>
    <li class="pmprowoo_tab"><a href="#pmprowoo_tab_data"><span><?php esc_html_e( 'Membership', 'pmpro-woocommerce' ); ?></span></a></li>
	<?php
}

add_action( 'woocommerce_product_write_panel_tabs', 'pmprowoo_tab_options_tab' );

/**
 * Add Fields to PMPro Tab
 */
function pmprowoo_tab_options() {
	
	global $membership_levels, $post;
	
	$membership_level_options = array( 'None' );
	
	foreach ( $membership_levels as $option ) {
		$key                              = $option->id;
		$membership_level_options[ $key ] = $option->name;
	}
	?>
    <div id="pmprowoo_tab_data" class="panel woocommerce_options_panel">

		<div class="options_group pmprowoo_options_group-membership_product">
			<h3><?php esc_html_e( 'Give Customers a Membership Level', 'pmpro-woocommerce' ); ?></h3>
			<?php
			// Membership Product
			// woocommerce_wp_select() escapes attributes for us.
			woocommerce_wp_select(
				array(
					'id'      => '_membership_product_level',
					'label'   => __( 'Membership Product', 'pmpro-woocommerce' ),
					'options' => $membership_level_options, // phpcs:ignore WordPress.Security.EscapeOutput
				)
			);

			// Membership Product
			if ( ! empty( $post->ID ) ) {
				$cbvalue = get_post_meta( $post->ID, '_membership_product_autocomplete', true );
			}

			if ( empty( $cbvalue ) ) {
				$cbvalue = NULL;
			}

			// woocommerce_wp_checkbox() escapes attributes for us.
			woocommerce_wp_checkbox(
				array(
					'id'          => '_membership_product_autocomplete',
					'label'       => __( 'Autocomplete Order Status', 'pmpro-woocommerce' ),
					'description' => __( "Check this to mark the order as completed immediately after checkout to activate the associated membership.", 'pmpro-woocommerce' ),
					'cbvalue'     => $cbvalue, // phpcs:ignore WordPress.Security.EscapeOutput
				)
			);

			?>
        </div> <!-- end pmprowoo_options_group-membership_product -->
		<div class="options-group pmprowoo_options_group-membership_discount">
			<h3><?php esc_html_e( 'Member Discount Pricing', 'pmpro-woocommerce' ); ?></h3>
			<p><?php printf( __( 'Set the custom price based on Membership Level. <a href="%s">Edit your membership levels</a> to set a global percent discount for all products.', 'pmpro-woocommerce' ), esc_url( admin_url( 'admin.php?page=pmpro-membershiplevels' ) ) ); ?></p>
            <?php
			// For each membership level, create respective price field
			foreach ( $membership_levels as $level ) {
				woocommerce_wp_text_input(
					array(
						'id'          => '_level_' . $level->id . '_price',
						'label'       => sprintf( esc_html__( '%s Price (%s)', 'pmpro-woocommerce' ), $level->name, get_woocommerce_currency_symbol() ),
						'placeholder' => '',
						'type'        => 'text',
						'desc_tip'    => 'true',
						'data_type'   => 'price',
					)
				);
			}
			?>
        </div> <!-- end pmprowoo_options_group-membership_discount -->
		<?php do_action( 'pmprowoo_extra_tab_options' ); ?>
    </div>
	<?php
}

add_action( 'woocommerce_product_data_panels', 'pmprowoo_tab_options' );

/**
 * Process PMPro Meta
 */
function pmprowoo_process_product_meta() {
	
	global $membership_levels, $post_id, $pmprowoo_product_levels;
	
	// get values from post
	if ( isset( $_POST['_membership_product_level'] ) ) {
		$level = intval( $_POST['_membership_product_level'] );
	}

	if ( isset( $_POST['_membership_product_autocomplete'] ) 
		&& !empty($_POST['_membership_product_autocomplete'] )
		&& $_POST['_membership_product_autocomplete'] !== 'no' ) {
		$autocomplete = 1;
	} else {
		$autocomplete = 0;
	}

	// update post meta for the autocomplete option
	if ( isset ( $autocomplete ) ) {
		update_post_meta( $post_id, '_membership_product_autocomplete', $autocomplete );
	}

	// update array of product levels
	if ( ! empty( $level ) ) {
		$pmprowoo_product_levels[ $post_id ] = $level;
	} else if ( isset( $pmprowoo_product_levels[ $post_id ] ) ) {
		unset( $pmprowoo_product_levels[ $post_id ] );
	}
	
	// update post meta for level and prices
	if ( isset( $level ) ) {
		update_post_meta( $post_id, '_membership_product_level', $level );
		update_option( '_pmprowoo_product_levels', $pmprowoo_product_levels );
		
		// Save each membership level price
		$decimal_separator = wc_get_price_decimal_separator();
		foreach ( $membership_levels as $level ) {
			$price = str_replace( $decimal_separator, '.', sanitize_text_field( $_POST[ '_level_' . $level->id . "_price" ] ) );
			update_post_meta( $post_id, '_level_' . $level->id . '_price', $price );
		}
	}
	
}
add_action( 'woocommerce_process_product_meta', 'pmprowoo_process_product_meta' );

/**
 * Add Membership Discount Field to Edit Membership Page
 */
function pmprowoo_add_membership_discount() {
	global $pmprowoo_member_discounts;
	$level_id = intval( $_REQUEST['edit'] );
	if ( $level_id > 0 && ! empty( $pmprowoo_member_discounts ) && ! empty( $pmprowoo_member_discounts[ $level_id ] ) ) {
		$membership_discount = $pmprowoo_member_discounts[ $level_id ] * 100;
	} //convert back to %
	else {
		$membership_discount = '';
	}
	?>
	<hr />
    <h2 class="title"><?php esc_html_e( "Set Membership Discount", "pmpro-woocommerce" ); ?></h2>
    <p><?php esc_html_e( "Set a membership discount for this level which will be applied when a user with this membership level is logged in. The discount is applied to the product's regular price, sale price, or level-specific price set on the edit product page.", "pmpro-woocommerce" ); ?></p>
    <table>
        <tbody class="form-table">
        <tr>
            <th scope="row" valign="top"><label
                        for="membership_discount"><?php esc_html_e( "Membership Discount (%):", "pmpro-woocommerce" ); ?></label>
            </th>
            <td>
                <input type="number" min="0" max="100" name="membership_discount"
                       value="<?php echo esc_attr( $membership_discount ); ?>"/>
            </td>
        </tr>
        </tbody>
    </table>
	<?php
}
add_action( "pmpro_membership_level_after_other_settings", "pmprowoo_add_membership_discount" );

/**
 * Update Membership Level Discount
 *
 * @param int $level_id
 */
function pmprowoo_save_membership_level( $level_id ) {
	global $pmprowoo_member_discounts;
	
	//convert % to decimal
	$member_discount = ! empty( $_POST['membership_discount'] ) ? ( (float) sanitize_text_field( $_POST['membership_discount'] ) / 100 ) : 0;
	$pmprowoo_member_discounts[$level_id] = $member_discount;
	update_option( '_pmprowoo_member_discounts', $pmprowoo_member_discounts );
}
add_action( "pmpro_save_membership_level", "pmprowoo_save_membership_level" );

/**
 *  Add Discounts on Subscriptions to PMPro Advanced Settings - will uncomment when filter is added to core
 *
 * @param mixed $fields
 *
 * @return array
 */
function pmprowoo_custom_settings( $fields ) {
	if ( ! is_array( $fields ) ) {
		$fields = array();
	}
	
	$fields[] = array(
		'field_name' => 'pmprowoo_discounts_on_subscriptions',
		'field_type' => 'select',
		'label'      => esc_html__( 'Apply Member Discounts to WooCommerce Subscription and Membership Products?', 'pmpro-woocommerce' ),
		'value'      => esc_html__( 'No', 'pmpro-woocommerce' ),
		'options'    => array( esc_html__( 'Yes', 'pmpro-woocommerce' ), esc_html__( 'No', 'pmpro-woocommerce' ) ),
	);
	
	return $fields;
}
add_filter( 'pmpro_custom_advanced_settings', 'pmprowoo_custom_settings' );

/**
 * Force account creation at WooCommerce checkout if the cart includes a membership product.
 */
function pmprowoo_woocommerce_after_checkout_registration_form() {
	global $woocommerce, $pmprowoo_product_levels;
	
	// grab items from the cart	
	$items = $woocommerce->cart->cart_contents;
	
	//membership product ids
	$membership_product_ids = array_keys( $pmprowoo_product_levels );
	
	// Search for any membership level products. IF found, use first one as the cart membership level.
	foreach ( $items as $item ) {
		if ( in_array( $item['product_id'], $membership_product_ids ) ) {
			$cart_membership_level = $pmprowoo_product_levels[ $item['product_id'] ];
			break;
		}
	}
	
	if ( ! empty( $cart_membership_level ) ) {
		?>
        <script>
            jQuery('#createaccount').prop('checked', true);
            jQuery('#createaccount').parent().hide();
        </script>
		<?php
	}
}
add_action( 'woocommerce_after_checkout_registration_form', 'pmprowoo_woocommerce_after_checkout_registration_form' );

/**
 * When the Woo Commerce Billing Address fields are updated, update the equivalent PMPro Fields
 *
 * @param int    $meta_id
 * @param int    $object_id
 * @param string $meta_key
 * @param mixed  $meta_value
 */
function pmprowoo_update_user_meta( $meta_id, $object_id, $meta_key, $meta_value ) {
	//tracks updates that are made
	global $pmprowoo_updated_user_meta;
	if ( empty( $pmprowoo_updated_user_meta ) ) {
		$pmprowoo_updated_user_meta = array();
	}
	if ( empty( $pmprowoo_updated_user_meta[ $object_id ] ) ) {
		$pmprowoo_updated_user_meta[ $object_id ] = array();
	}
	
	//array of user meta to mirror
	$um = array(
		"billing_first_name" => "pmpro_bfirstname",
		"billing_last_name"  => "pmpro_blastname",
		"billing_address_1"  => "pmpro_baddress1",
		"billing_address_2"  => "pmpro_baddress2",
		"billing_city"       => "pmpro_bcity",
		"billing_postcode"   => "pmpro_bzipcode",
		"billing_state"      => "pmpro_bstate",
		"billing_country"    => "pmpro_bcountry",
		"billing_phone"      => "pmpro_bphone",
		"billing_email"      => "pmpro_bemail",
		"pmpro_bfirstname"   => "billing_first_name",
		"pmpro_blastname"    => "billing_last_name",
		"pmpro_baddress1"    => "billing_address_1",
		"pmpro_baddress2"    => "billing_address_2",
		"pmpro_bcity"        => "billing_city",
		"pmpro_bzipcode"     => "billing_postcode",
		"pmpro_bstate"       => "billing_state",
		"pmpro_bcountry"     => "billing_country",
		"pmpro_bphone"       => "billing_phone",
		"pmpro_bemail"       => "billing_email",
	);
	
	//check if this user meta is to be mirrored
	foreach ( $um as $left => $right ) {
		if ( $meta_key == $left && ! in_array( $left, $pmprowoo_updated_user_meta[ $object_id ] ) ) {
			$pmprowoo_updated_user_meta[ $object_id ][] = $left;
			update_user_meta( $object_id, $right, $meta_value );
		}
	}
}
add_action( 'update_user_meta', 'pmprowoo_update_user_meta', 10, 4 );

/**
 * Need to add the meta_id for add filter
 *
 * @param int    $object_id
 * @param string $meta_key
 * @param mixed  $meta_value
 */
function pmprowoo_add_user_meta( $object_id, $meta_key, $meta_value ) {
	pmprowoo_update_user_meta( null, $object_id, $meta_key, $meta_value );
}
add_action( 'add_user_meta', 'pmprowoo_add_user_meta', 10, 3 );

/**
 * Apply end date extension filter to woo commerce checkouts as well
 *
 * $level_obj in the function is an object with the stored values for the level
 *
 * @param array $level_array - custom_level array for the pmpro_changeMembershipLevel call
 *
 * @return array
 */
function pmprowoo_checkout_level_extend_memberships( $level_array ) {
	$level_obj = pmpro_getLevel( $level_array['membership_id'] );
	
	//does this level expire? are they an existing user of this level?
	if ( ! empty( $level_obj ) && ! empty( $level_obj->expiration_number ) && pmpro_hasMembershipLevel( $level_obj->id, $level_array['user_id'] ) ) {
		//get the current enddate of their membership
		$user                   = get_userdata( $level_array['user_id'] );
		$user->membership_level = pmpro_getSpecificMembershipLevelForUser( $user->ID, $level_obj->id );
		$expiration_date        = $user->membership_level->enddate;

		
		// Is user renewing an existing membership?
		if ( ! empty( $expiration_date ) && $expiration_date > current_time( 'timestamp' ) ) {
			// Extend membership
			$level_array['enddate'] = date( "Y-m-d H:i:00", strtotime( "+ $level_obj->expiration_number $level_obj->expiration_period", $expiration_date ) );
		}
	}
	
	return $level_array;
}
add_filter( 'pmprowoo_checkout_level', 'pmprowoo_checkout_level_extend_memberships' );

/**
 * Enqueue Admin CSS
 */
function pmprowoo_admin_enqueue_css() {
	wp_register_style( 'pmpro-woocommerce-admin', plugins_url( '/css/admin.css', __FILE__ ), null );
	wp_enqueue_style( 'pmpro-woocommerce-admin' );
}
add_action( 'admin_enqueue_scripts', 'pmprowoo_admin_enqueue_css' );

/**
 * Check if Autocomplete setting is active for the product.
 *
 * @param int $order_id
 */
function pmprowoo_order_autocomplete( $order_id ) {
	//get the existing order
	$order = new WC_Order( $order_id );
	
	//assume we won't autocomplete
	$autocomplete = false;
	
	//get line items
	if ( count( $order->get_items() ) > 0 ) {
		foreach ( $order->get_items() as $item ) {
			if ( $item['type'] == 'line_item' ) {

				//get product info and check if product is marked to autocomplete
				$_product = wc_get_product( $item['product_id'] );

				if( ! $_product instanceof \WC_Product ) {
					continue;
				}

				if ( $_product->is_type( 'variation' ) ) {
				    $product_id = $_product->get_parent_id();
				} else {
				    $product_id = $_product->get_id();
				}

				$product_autocomplete = get_post_meta( $product_id, '_membership_product_autocomplete', true );

				//if any product is not virtual and not marked for autocomplete, we won't autocomplete
				if ( ! $_product->is_virtual() && ! $product_autocomplete ) {
					//found a non-virtual, non-membership product in the cart
					$autocomplete = false;
					break;
				} else if ( $product_autocomplete ) {
					//found a membership product in the cart marked to autocomplete
					$autocomplete = true;
				}
			}
		}
	}
	
	//change status if needed
	if ( ! empty( $autocomplete ) ) {
		$order->update_status( 'completed', esc_html__( 'Autocomplete via PMPro WooCommerce.', 'pmpro-woocommerce' ) );
	}
}
add_filter( 'woocommerce_order_status_processing', 'pmprowoo_order_autocomplete' );

/**
 * Get products that are in the cart that are attached to a level ID.
 * Return product ID's of membership level products in the cart.
 *
 * @return array $levels The products and levels.
 */
function pmprowoo_get_memberships_from_cart() {
	global $woocommerce, $pmprowoo_product_levels;

	$membership_product_ids = array_keys( $pmprowoo_product_levels );
	$cart_items  = $woocommerce->cart->cart_contents;
	$membership_product_ids_in_cart = array();
	
	// Nothing in the cart, just bail.
	if ( empty( $cart_items ) ) {
		return $membership_product_ids_in_cart;
	}

	// Get all product IDs in the cart
	$product_ids = array();
	foreach( $cart_items as $item ) {
		$product_ids[] = $item['product_id'];
	}

	// Compare values between the two arrays of membership products and items in the cart.
	$membership_product_ids_in_cart = array_values( array_intersect( $membership_product_ids, $product_ids ) );

	return $membership_product_ids_in_cart;
}

function pmpro_woocommerce_load_textdomain() {
  load_plugin_textdomain( 'pmpro-woocommerce', false, basename( dirname( __FILE__ ) ) . '/languages' ); 
}
add_action( 'plugins_loaded', 'pmpro_woocommerce_load_textdomain' );

/**
 * Confirm that PMPro WooCommerce is compatible with HPOS (Custom Order Tables).
 * Generally we store things to products, not orders.
 * 
 * @since 1.8
 */
function pmprowoo_compatible_for_hpos() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
	}
}
add_action( 'before_woocommerce_init', 'pmprowoo_compatible_for_hpos' );

LittleDemon - FACEBOOK
[ KELUAR ]