|
Server : LiteSpeed System : Linux server104.web-hosting.com 4.18.0-513.24.1.lve.1.el8.x86_64 #1 SMP Thu May 9 15:10:09 UTC 2024 x86_64 User : saleoqej ( 6848) PHP Version : 8.0.30 Disable Function : NONE Directory : /home/saleoqej/www/wp-content/plugins/learndash-woocommerce/ |
<?php
/**
* Plugin Name: LearnDash LMS - WooCommerce Integration
* Plugin URI: http://www.learndash.com/work/woocommerce/
* Description: LearnDash LMS addon plugin to integrate LearnDash LMS with WooCommerce.
* Version: 1.9.6
* Author: LearnDash
* Author URI: http://www.learndash.com
* Domain Path: /languages/
* Text Domain: learndash-woocommerce
* WC requires at least: 3.0.0
* WC tested up to: 7.0.0
*/
class Learndash_WooCommerce {
public $debug = false;
public function __construct() {
self::setup_constants();
self::check_dependency();
add_action( 'plugins_loaded', function() {
if ( LearnDash_Dependency_Check_LD_WooCommerce::get_instance()->check_dependency_results() ) {
self::includes();
self::hooks();
}
} );
}
public static function hooks()
{
// Setup translation
add_action( 'plugins_loaded', array( __CLASS__, 'load_translation' ) );
// Meta box
add_filter( 'product_type_selector', array( __CLASS__, 'add_product_type' ), 10, 1 );
add_action( 'woocommerce_product_options_general_product_data', array( __CLASS__, 'render_course_selector' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_scripts' ), 1 );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'deregister_admin_scripts' ), 20 );
add_action( 'save_post', array( __CLASS__, 'store_related_courses' ), 10, 2 );
// Product variation hooks
add_action( 'woocommerce_product_after_variable_attributes', array( __CLASS__, 'render_variation_course_selector' ), 10, 3 );
add_action( 'woocommerce_save_product_variation', array( __CLASS__, 'store_variation_related_courses' ), 10, 2 );
// Order hook
add_action( 'woocommerce_order_status_processing', array( __CLASS__, 'add_course_access' ), 10, 1 );
add_action( 'woocommerce_order_status_completed', array( __CLASS__, 'add_course_access' ), 10, 1 );
add_action( 'woocommerce_payment_complete', array( __CLASS__, 'add_course_access' ), 10, 1 );
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'remove_course_access_on_refund' ), 10, 2 );
add_action( 'woocommerce_order_status_cancelled', array( __CLASS__, 'remove_course_access' ), 10, 1 );
add_action( 'woocommerce_order_status_failed', array( __CLASS__, 'remove_course_access' ), 10, 1 );
add_action( 'wp_trash_post', [ __CLASS__, 'delete_order' ], 10, 1 );
add_action( 'before_delete_post', [ __CLASS__, 'delete_order' ], 10, 1 );
add_action( 'untrashed_post', [ __CLASS__, 'restore_order' ], 30, 1 );
add_action( 'woocommerce_process_shop_order_meta', [ __CLASS__, 'update_order_meta' ] );
add_action( 'woocommerce_before_subscription_object_save', [ __CLASS__, 'update_subscription_meta' ] );
add_action( 'woocommerce_new_order_item', [ __CLASS__, 'process_new_order_item' ], 10, 3 );
add_action( 'woocommerce_before_delete_order_item', array( __CLASS__, 'delete_order_item' ), 10, 1 );
add_filter( 'woocommerce_order_get_items', array( __CLASS__, 'filter_subscription_products_out' ), 10, 3 );
// New hooks for WC subscription
add_action( 'woocommerce_subscription_status_cancelled', array( __CLASS__, 'remove_subscription_course_access' ) );
// add_action( 'woocommerce_subscription_status_on-hold', array( __CLASS__, 'remove_subscription_course_access' ) );
if ( 'no' === get_option( 'learndash_woocommerce_disable_access_removal_on_expiration', 'no' ) ) {
add_action( 'woocommerce_subscription_status_expired', array( __CLASS__, 'remove_subscription_course_access' ) );
}
add_action( 'woocommerce_subscription_status_active', array( __CLASS__, 'add_subscription_course_access' ) );
add_filter( 'woocommerce_subscription_settings', array( __CLASS__, 'add_subscription_settings' ), 20, 1 );
// add_filter( 'ld_woocommerce_remove_subscription_course_access', array( __CLASS__, 'check_subscription_course_access_removal' ), 10, 3 );
add_filter( 'ld_woocommerce_add_subscription_course_access', array( __CLASS__, 'check_subscription_course_access_addition' ), 10, 3 );
add_action( 'woocommerce_subscription_renewal_payment_complete', array( __CLASS__, 'remove_course_access_on_billing_cycle_completion' ), 10, 2 );
// WC Subscription switcher
add_action( 'woocommerce_subscription_checkout_switch_order_processed', array( __CLASS__, 'switch_subscription' ), 10, 2 );
// Silent background course enrollment process
add_action( 'learndash_woocommerce_cron', array( __CLASS__, 'process_silent_course_enrollment' ) );
// Force user to log in or create account if there is LD course in WC cart
add_action( 'woocommerce_checkout_init', array( __CLASS__, 'enable_signup_on_checkout' ), 10, 1 );
add_filter( 'woocommerce_checkout_registration_enabled', [ __CLASS__, 'enable_registration' ], 20 );
// Auto complete course transaction
add_action( 'woocommerce_payment_complete', array( __CLASS__, 'auto_complete_transaction' ) );
add_action( 'woocommerce_thankyou', array( __CLASS__, 'auto_complete_transaction' ) );
// Remove course increment record if a course unenrolled manually
add_action( 'learndash_delete_user_data', array( __CLASS__, 'remove_access_increment_count' ) );
}
public static function setup_constants() {
if ( ! defined( 'LEARNDASH_WOOCOMMERCE_VERSION' ) ) {
define( 'LEARNDASH_WOOCOMMERCE_VERSION', '1.9.6' );
}
// Plugin file
if ( ! defined( 'LEARNDASH_WOOCOMMERCE_FILE' ) ) {
define( 'LEARNDASH_WOOCOMMERCE_FILE', __FILE__ );
}
// Plugin folder path
if ( ! defined( 'LEARNDASH_WOOCOMMERCE_PLUGIN_PATH' ) ) {
define( 'LEARNDASH_WOOCOMMERCE_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
}
// Plugin folder URL
if ( ! defined( 'LEARNDASH_WOOCOMMERCE_PLUGIN_URL' ) ) {
define( 'LEARNDASH_WOOCOMMERCE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
}
}
/**
* Check and set dependencies
*
* @return void
*/
public static function check_dependency()
{
include LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'includes/class-dependency-check.php';
LearnDash_Dependency_Check_LD_WooCommerce::get_instance()->set_dependencies(
array(
'sfwd-lms/sfwd_lms.php' => array(
'label' => '<a href="https://learndash.com">LearnDash LMS</a>',
'class' => 'SFWD_LMS',
'min_version' => '3.0.0',
),
'woocommerce/woocommerce.php' => array(
'label' => '<a href="https://woocommerce.com/">WooCommerce</a>',
'class' => 'WooCommerce',
'min_version' => '4.5.0',
),
)
);
LearnDash_Dependency_Check_LD_WooCommerce::get_instance()->set_message(
__( 'LearnDash LMS - WooCommerce Integration Add-on requires the following plugin(s) to be active:', 'learndash-woocommerce' )
);
}
public static function includes() {
include LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'includes/class-upgrade.php';
include LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'includes/class-cron.php';
include LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'includes/class-tools.php';
}
public static function load_translation()
{
global $wp_version;
// Set filter for plugin language directory
$lang_dir = dirname( plugin_basename( __FILE__ ) ) . '/languages/';
$lang_dir = apply_filters( 'ld_woocommerce_languages_directory', $lang_dir );
$get_locale = get_locale();
if ( $wp_version >= '4.7' ) {
$get_locale = get_user_locale();
}
$mofile = sprintf( '%s-%s.mo', 'learndash-woocommerce', $get_locale );
$mofile = WP_LANG_DIR . 'plugins/' . $mofile;
if ( file_exists( $mofile ) ) {
load_textdomain( 'learndash-woocommerce', $mofile );
} else {
load_plugin_textdomain( 'learndash-woocommerce', $deprecated = false, $lang_dir );
}
// include translations/update class
include LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'includes/class-translations-ld-woocommerce.php';
}
public static function add_product_type( $types ) {
$types['course'] = learndash_get_custom_label( 'course' );
return $types;
}
public static function enqueue_admin_scripts() {
$screen = get_current_screen();
if ( $screen->id == 'product' && $screen->base == 'post' ) {
wp_enqueue_style( 'learndash-woocommerce-select2', LEARNDASH_WOOCOMMERCE_PLUGIN_URL . 'lib/select2/select2.min.css', [], '4.0.13', 'screen' );
wp_enqueue_script( 'learndash-woocommerce-select2', LEARNDASH_WOOCOMMERCE_PLUGIN_URL . 'lib/select2/select2.full.min.js', [ 'jquery' ], '4.0.13', false );
wp_enqueue_style( 'learndash-woocommerce-product', LEARNDASH_WOOCOMMERCE_PLUGIN_URL . 'assets/css/product.min.css', [], LEARNDASH_WOOCOMMERCE_VERSION, 'screen' );
wp_enqueue_script( 'learndash-woocommerce-product', LEARNDASH_WOOCOMMERCE_PLUGIN_URL . 'assets/js/product.min.js', [ 'jquery' ], LEARNDASH_WOOCOMMERCE_VERSION, true );
}
}
public static function deregister_admin_scripts()
{
$screen = get_current_screen();
if ( $screen->id == 'product' && $screen->base == 'post' ) {
wp_deregister_script( 'learndash-select2-jquery-script' );
wp_deregister_style( 'learndash-select2-jquery-style' );
}
}
public static function add_front_scripts() {
wp_enqueue_script( 'ld_wc_front', plugins_url( '/front.js', __FILE__ ), array( 'jquery' ), LEARNDASH_WOOCOMMERCE_VERSION );
}
public static function render_course_selector() {
global $post;
$courses_options = self::list_courses();
$groups_options = self::list_groups();
/**
* Filter for course selector class names
*
* @param string Default class names
* @param object $post WP_Post object
* @var string New modified class names
*/
$class = apply_filters( 'learndash_woocommerce_course_selector_class', 'options_group show_if_course show_if_simple', $post );
echo '<div class="' . $class . '">';
wp_nonce_field( 'save_post', 'ld_wc_nonce' );
$values = (array) get_post_meta( $post->ID, '_related_course', true );
if ( ! $values ) {
$values = array();
}
$groups_values = (array) get_post_meta( $post->ID, '_related_group', true );
if ( ! $groups_values ) {
$groups_values = array();
}
?>
<p><?php printf( __( '<strong>Important:</strong> When customers checkout with 5 or more associated courses and groups in a single cart, course enrollment process is done in the background and you will need to set up a cron job. To set up a cron job please follow <a href="%s" target="_blank">these steps</a>.', 'learndash-woocommerce' ), 'https://www.learndash.com/support/docs/faqs/email-notifications-send-time/#create-cron-job-in-cpanel' ); ?></p>
<?php
self::woocommerce_wp_select_multiple( array(
'id' => '_related_course[]',
'class' => 'select2 regular-width select short ld_related_courses',
'label' => sprintf( _x( 'LearnDash %s', 'LearnDash Courses', 'learndash-woocommerce' ), learndash_get_custom_label( 'courses' ) ),
'options' => $courses_options,
'desc_tip' => true,
'value' => $values,
) );
self::woocommerce_wp_select_multiple( array(
'id' => '_related_group[]',
'class' => 'select2 regular-width select short ld_related_groups',
'label' => sprintf( _x( 'LearnDash %s', 'LearnDash Groups', 'learndash-woocommerce' ), learndash_get_custom_label( 'groups' ) ),
'options' => $groups_options,
'desc_tip' => true,
'value' => $groups_values,
) );
echo '</div>';
}
public static function store_related_courses( $id, $post ) {
if ( ! isset( $_POST['ld_wc_nonce'] ) || ! wp_verify_nonce( $_POST['ld_wc_nonce'], 'save_post' ) ) {
return;
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
if ( ! $post->post_type === 'product' ) {
return;
}
// Delete the meta and bail if product is variable type
$product = wc_get_product( $id );
if ( false !== $product ) {
if ( in_array( $product->get_type(), [ 'variable', 'variable-subscription' ] ) ) {
delete_post_meta( $id, '_related_course' );
delete_post_meta( $id, '_related_group' );
return;
}
}
if ( isset( $_POST['_related_course'] ) && ! empty( $_POST['_related_course'] ) ) {
$related_courses = array_map( 'intval', $_POST['_related_course'] );
update_post_meta( $id, '_related_course', $related_courses );
} else {
delete_post_meta( $id, '_related_course' );
}
if ( isset( $_POST['_related_group'] ) && ! empty( $_POST['_related_group'] ) ) {
$related_groups = array_map( 'intval', $_POST['_related_group'] );
update_post_meta( $id, '_related_group', $related_groups );
} else {
delete_post_meta( $id, '_related_group' );
}
}
public static function render_variation_course_selector( $loop, $data, $variation )
{
$courses_options = self::list_courses();
$groups_options = self::list_groups();
echo '<div class="form-field form-row form-row-full">';
wp_nonce_field( 'save_post', 'ld_wc_nonce' );
$values = (array) get_post_meta( $variation->ID, '_related_course', true );
if ( ! $values ) {
$values = array();
}
$groups_values = (array) get_post_meta( $variation->ID, '_related_group', true );
if ( ! $groups_values ) {
$groups_values = array();
}
?>
<p><?php printf( __( '<strong>Important:</strong> When customers checkout with 5 or more associated courses and groups in a single cart, course enrollment process is done in the background and you will need to set up a cron job. To set up a cron job please follow <a href="%s" target="_blank">these steps</a>.', 'learndash-woocommerce' ), 'https://www.learndash.com/support/docs/faqs/email-notifications-send-time/#create-cron-job-in-cpanel' ); ?></p>
<?php
self::woocommerce_wp_select_multiple( array(
'id' => '_related_course['. $loop . '][]',
'class' => 'select2 full-width select short ld_related_courses_variation',
'label' => sprintf( _x( 'LearnDash %s', 'LearnDash Courses', 'learndash-woocommerce' ), learndash_get_custom_label( 'courses' ) ),
'options' => $courses_options,
'desc_tip' => true,
'value' => $values,
) );
self::woocommerce_wp_select_multiple( array(
'id' => '_related_group['. $loop . '][]',
'class' => 'select2 full-width select short ld_related_groups_variation',
'label' => sprintf( _x( 'LearnDash %s', 'LearnDash Groups', 'learndash-woocommerce' ), learndash_get_custom_label( 'groups' ) ),
'options' => $groups_options,
'desc_tip' => true,
'value' => $groups_values,
) );
echo '</div>';
}
public static function store_variation_related_courses( $variation_id, $loop )
{
if ( ! isset( $_POST['ld_wc_nonce'] ) || ! wp_verify_nonce( $_POST['ld_wc_nonce'], 'save_post' ) ) {
return;
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
if ( ! $post->post_type === 'product' ) {
return;
}
if ( isset( $_POST['_related_course'] ) && ! empty( $_POST['_related_course'] ) ) {
$related_courses = array();
foreach ( $_POST['_related_course'] as $key => $value ) {
if ( isset( $value ) && ! empty( $value ) ) {
$related_courses[ $key ] = array_map( 'intval', $value );
} else {
$related_courses[ $key ] = array();
}
update_post_meta( $variation_id, '_related_course', $related_courses[ $loop ] );
}
} else {
delete_post_meta( $variation_id, '_related_course' );
}
if ( isset( $_POST['_related_group'] ) && ! empty( $_POST['_related_group'] ) ) {
$related_groups = array();
foreach ( $_POST['_related_group'] as $key => $value ) {
if ( isset( $value ) && ! empty( $value ) ) {
$related_groups[ $key ] = array_map( 'intval', $value );
} else {
$related_groups[ $key ] = array();
}
update_post_meta( $variation_id, '_related_group', $related_groups[ $loop ] );
}
} else {
delete_post_meta( $variation_id, '_related_group' );
}
}
/**
* Remove course when order is refunded
* @param int $order_id Order ID
* @param int $customer_id Customer ID (optional)
* @param array $products Custom products if exists
*/
public static function remove_course_access( $order_id, $customer_id = null, $products = [] )
{
$order = wc_get_order( $order_id );
if ( $order !== false && is_a( $order, 'WC_Order' ) ) {
/**
* Only get items for non-subscription products
*
* The $learndash_woocommerce_get_items_filter_out_subscriptions variable is required to be "true" for the filter to work
*
* @see Learndash_WooCommerce::filter_subscription_products_out() Filter subscription products out when getting items for course access update
* @var array
*/
global $learndash_woocommerce_get_items_filter_out_subscriptions;
$learndash_woocommerce_get_items_filter_out_subscriptions = true;
if ( empty( $products ) ) {
$products = $order->get_items();
}
$customer_id = ! empty( $customer_id ) && is_numeric( $customer_id ) ? $customer_id : $order->get_user_id();
foreach ( $products as $product ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses_id = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups_id = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses_id = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups_id = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
if ( $courses_id && is_array( $courses_id ) ) {
foreach ( $courses_id as $course_id ) {
self::update_remove_course_access( $course_id, $customer_id, $order_id );
}
}
if ( $groups_id && is_array( $groups_id ) ) {
foreach ( $groups_id as $group_id ) {
self::update_remove_group_access( $group_id, $customer_id, $order_id );
}
}
}
}
}
/**
* Remove course access on order refund
*
* @param int $order_id
* @return void
*/
public static function remove_course_access_on_refund( $order_id, $refund_id )
{
$order = wc_get_order( $order_id );
$products = [];
$refunds = $order->get_refunds();
foreach ( $refunds as $refund ) {
$refunded_products = $refund->get_items();
$products = array_merge( $products, $refunded_products );
}
self::remove_course_access( $order_id, null, $products );
}
/**
* Enroll customer into order's associated courses and groups
*
* @param int $order_id WC_Order ID
* @param int $customer_id Customer ID (optional)
* @return void
*/
public static function add_course_access( $order_id, $customer_id = null )
{
$order = wc_get_order( $order_id );
if ( $order !== false && is_a( $order, 'WC_Order' ) ) {
/**
* Only get items for non-subscription products
*
* @see Learndash_WooCommerce::filter_subscription_products_out() Filter subscription products out when getting items for course access update
* @var array
*/
global $learndash_woocommerce_get_items_filter_out_subscriptions;
$learndash_woocommerce_get_items_filter_out_subscriptions = true;
$products = $order->get_items();
$customer_id = ! empty( $customer_id ) && is_numeric( $customer_id ) ? $customer_id : $order->get_user_id();
$courses_count = 0;
$groups_count = 0;
array_walk( $products, function( $product ) use ( &$courses_count, &$groups_count ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
$courses_count += count( $courses );
$groups_count += count( $groups );
} );
if ( ( $courses_count + $groups_count ) >= self::get_products_count_for_silent_course_enrollment() && current_filter() !== 'learndash_woocommerce_cron' && current_filter() !== 'wp_ajax_ld_wc_retroactive_access' ) {
self::enqueue_silent_course_enrollment( array( 'order_id' => $order_id ) );
} else {
foreach ( $products as $product ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses_id = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups_id = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses_id = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups_id = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
if ( $courses_id && is_array( $courses_id ) ) {
foreach ( $courses_id as $course_id ) {
self::update_add_course_access( $course_id, $customer_id, $order_id );
}
}
if ( $groups_id && is_array( $groups_id ) ) {
foreach ( $groups_id as $group_id ) {
self::update_add_group_access( $group_id, $customer_id, $order_id );
}
}
}
}
}
}
/**
* Handler when an order is deleted, hooked to
* wp_trash_post and before_delete_post
*
* @param int $post_id
* @return void
*/
public static function delete_order( $post_id )
{
$post_type = get_post_type( $post_id );
if ( 'shop_order' == $post_type ) {
self::remove_course_access( $post_id );
} elseif ( 'shop_subscription' == $post_type ) {
if ( function_exists( 'wcs_get_subscription' ) ) {
$subscription = wcs_get_subscription( $post_id );
if ( $subscription ) {
self::remove_subscription_course_access( $subscription );
}
}
}
}
/**
* Handler when an order is restored/untrashed, hooked to
* untrash_post
*
* @param int $post_id
* @return void
*/
public static function restore_order( $post_id )
{
$post_type = get_post_type( $post_id );
if ( 'shop_order' == $post_type ) {
$order = wc_get_order( $post_id );
if ( in_array( $order->get_status(), [ 'processing', 'completed' ] ) ) {
self::add_course_access( $post_id );
}
} elseif ( 'shop_subscription' == $post_type ) {
if ( function_exists( 'wcs_get_subscription' ) ) {
$subscription = wcs_get_subscription( $post_id );
if ( in_array( $subscription->get_status(), [ 'active' ] ) ) {
self::add_subscription_course_access( $subscription );
}
}
}
}
/**
* Handler when an order is updated, hooked to
* woocommerce_process_shop_order_meta
*
* This method is used to handle course access update
* in some scenarios such as:
* 1. Order's customer change
*
* @param int $order_id
* @return void
*/
public static function update_order_meta( $order_id )
{
$order = wc_get_order( $order_id );
// try to validate again.
if ( ! is_object( $order ) ) {
// break out so no fatal.
return;
}
$old_customer = $order->get_customer_id();
$new_customer = isset( $_POST['customer_user'] ) ? intval( $_POST['customer_user'] ) : false;
if ( $old_customer && $new_customer && $old_customer != $new_customer ) {
if ( in_array( $order->get_status(), [ 'processing', 'completed' ] ) ) {
self::remove_course_access( $order_id, $old_customer );
self::add_course_access( $order_id, $new_customer );
}
}
}
/**
* Handler when an subscription is updated, hooked to
* woocommerce_process_shop_subscription_meta
*
* This method is used to handle course access update
* in some scenarios such as:
* 1. Order's customer change
*
* @param int $subscription_id
* @return void
*/
public static function update_subscription_meta( $subscription_id )
{
if ( is_object( $subscription_id ) ) {
$subscription = $subscription_id;
} else {
$subscription = wcs_get_subscription( $subscription_id );
}
if ( ! is_object( $subscription ) ) {
return;
}
if ( empty( $subscription->get_id() ) ) {
return;
}
$old_customer = $subscription->get_customer_id();
$new_customer = isset( $_POST['customer_user'] ) ? intval( $_POST['customer_user'] ) : false;
if ( $old_customer && $new_customer && $old_customer != $new_customer ) {
if ( in_array( $subscription->get_status(), [ 'active' ] ) ) {
self::remove_subscription_course_access( $subscription, [], $old_customer );
self::add_subscription_course_access( $subscription, [], $new_customer );
}
}
}
/**
* Process new order item added to existing order or subscription
*
* @param int $item_id Order item ID
* @param WC_Order_Item $item WC order item object
* @param int $order_id WooCommerce order ID
* @return void
*/
public static function process_new_order_item( $item_id, $item, $order_id )
{
$order = wc_get_order( $order_id );
if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
return;
}
if ( function_exists( 'wcs_is_subscription') && wcs_is_subscription( $order ) ) {
$subscription = wcs_get_subscription( $order_id );
if ( in_array( $subscription->get_status(), array( 'active' ) ) ) {
self::add_subscription_course_access( $subscription );
}
} elseif ( $order->get_type() === 'shop_order' ) {
if ( in_array( $order->get_status(), array( 'processing', 'completed' ) ) ) {
self::add_course_access( $order_id );
}
}
}
/**
* Process order item deletion from order or subscription
*
* @param int $item_id WooCommerce order item ID
* @return void
*/
public static function delete_order_item( $item_id )
{
$order_id = wc_get_order_id_by_order_item_id( $item_id );
$order = wc_get_order( $order_id );
if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
return;
}
$order_item = new WC_Order_Item_Product( $item_id );
if ( function_exists( 'wcs_is_subscription') && wcs_is_subscription( $order ) ) {
$subscription = wcs_get_subscription( $order_id );
self::remove_subscription_course_access( $subscription, [ $order_item ] );
} elseif ( $order->get_type() === 'shop_order' ) {
self::remove_course_access( $order_id, null, [ $order_item ] );
}
}
/**
* Filter only subscription products out from order processing methods
*
* @param array $items Original items
* @param array $order Order object
* @param array $types Item typs
* @return array Modified $items
*/
public static function filter_subscription_products_out( $items, $order, $types ) {
global $learndash_woocommerce_get_items_filter_out_subscriptions;
if ( $learndash_woocommerce_get_items_filter_out_subscriptions ) {
$learndash_woocommerce_get_items_filter_out_subscriptions = false;
$items = array_filter( $items, function( $item ) {
$product = $item->get_product();
if ( $product && is_a( $product, 'WC_Product' ) ) {
return $product->get_type() != 'subscription';
} else {
return true;
}
} );
}
return $items;
}
public static function debug( $msg ) {
$original_log_errors = ini_get( 'log_errors' );
$original_error_log = ini_get( 'error_log' );
ini_set( 'log_errors', true );
ini_set( 'error_log', dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'debug.log' );
global $ld_sf_processing_id;
if ( empty( $ld_sf_processing_id ) ) {
$ld_sf_processing_id = time();
}
if ( isset( $_GET['debug'] ) || self::debug ) {
error_log( "[$ld_sf_processing_id] " . print_r( $msg, true ) );
} //Comment This line to stop logging debug messages.
ini_set( 'log_errors', $original_log_errors );
ini_set( 'error_log', $original_error_log );
}
/**
* Get available courses
*
* @return array<int, string>
*/
public static function list_courses() {
$courses = get_posts( array(
'post_type' => learndash_get_post_type_slug( 'course' ),
'posts_per_page' => -1,
'suppress_filters' => true,
) );
$returned_courses = array();
foreach( $courses as $course ) {
$returned_courses[ $course->ID ] = $course->post_title;
}
return $returned_courses;
}
/**
* Get available groups
*
* @return array<int, string>
*/
public static function list_groups() {
$groups = get_posts( array(
'post_type' => learndash_get_post_type_slug( 'group' ),
'posts_per_page' => -1,
'suppress_filters' => true,
) );
$returned_groups = array();
foreach( $groups as $group ) {
$returned_groups[ $group->ID ] = $group->post_title;
}
return $returned_groups;
}
/**
* Handle subscription status change to remove LD course access
* @param object $subscription WC_Subscription object
* @param WC_Order_Item[] $products WC order items
* @param int $customer_id Customer ID (optional)
* @return void
*/
public static function remove_subscription_course_access( $subscription, $products = [], $customer_id = null )
{
if ( ! apply_filters( 'ld_woocommerce_remove_subscription_course_access', true, $subscription, current_filter() ) ) {
return;
}
if ( empty( $products ) ) {
// Get products related to this order
$products = $subscription->get_items();
}
$customer_id = ! empty( $customer_id ) && is_numeric( $customer_id ) ? $customer_id : $subscription->get_user_id();
foreach ( $products as $product ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses_id = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups_id = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses_id = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups_id = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
if ( $courses_id && is_array( $courses_id ) ) {
foreach ( $courses_id as $course_id ) {
self::update_remove_course_access( $course_id, $customer_id, $subscription->get_id() );
foreach ( $subscription->get_related_orders() as $order_id ) {
self::update_remove_course_access( $course_id, $customer_id, $order_id );
}
}
}
if ( $groups_id && is_array( $groups_id ) ) {
foreach ( $groups_id as $group_id ) {
self::update_remove_group_access( $group_id, $customer_id, $subscription->get_id() );
foreach ( $subscription->get_related_orders() as $order_id ) {
self::update_remove_group_access( $group_id, $customer_id, $order_id );
}
}
}
}
}
/**
* Handle subscription status change to add LD course access
* @param object $subscription WC_Subscription object
* @param WC_Order_Item[] $products WC order items
* @param int $customer_id WC Customer ID (optional)
* @return void
*/
public static function add_subscription_course_access( $subscription, $products = [], $customer_id = null )
{
if ( false === $subscription || ! is_a( $subscription, 'WC_Subscription' ) ) {
return;
}
if ( ! apply_filters( 'ld_woocommerce_add_subscription_course_access', true, $subscription, current_filter() ) ) {
return;
}
if ( empty( $products ) ) {
// Get products related to this order
$products = $subscription->get_items();
}
$customer_id = ! empty( $customer_id ) && is_numeric( $customer_id ) ? $customer_id : $subscription->get_user_id();
$start_date = $subscription->get_date( 'date_created' );
$courses_count = 0;
$groups_count = 0;
array_walk( $products, function( $product ) use ( &$courses_count, &$groups_count ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
$courses_count += count( $courses );
$groups_count += count( $groups );
} );
if ( ( $courses_count + $groups_count ) >= self::get_products_count_for_silent_course_enrollment() && current_filter() !== 'learndash_woocommerce_cron' && current_filter() !== 'wp_ajax_ld_wc_retroactive_access' ) {
self::enqueue_silent_course_enrollment( array( 'subscription_id' => $subscription->get_id() ) );
} else {
foreach ( $products as $product ) {
if ( ! empty( $product->get_variation_id() ) ) {
$courses_id = (array) get_post_meta( $product->get_variation_id(), '_related_course', true );
$groups_id = (array) get_post_meta( $product->get_variation_id(), '_related_group', true );
} else {
$courses_id = (array) get_post_meta( $product['product_id'], '_related_course', true );
$groups_id = (array) get_post_meta( $product['product_id'], '_related_group', true );
}
// Update access to the courses
if ( $courses_id && is_array( $courses_id ) ) {
foreach ( $courses_id as $course_id ) {
self::update_add_course_access( $course_id, $customer_id, $subscription->get_id() );
// Replace start date to keep the drip feeding working
if ( apply_filters( 'learndash_woocommerce_reset_subscription_course_access_from', true, $course_id, $subscription ) ) {
update_user_meta( $customer_id, 'course_' . $course_id . '_access_from', strtotime( $start_date ) );
}
}
}
if ( $groups_id && is_array( $groups_id ) ) {
foreach ( $groups_id as $group_id ) {
self::update_add_group_access( $group_id, $customer_id, $subscription->get_id() );
// Replace start date to keep the drip feeding working
if ( apply_filters( 'learndash_woocommerce_reset_subscription_group_access_from', true, $group_id, $subscription ) ) {
update_user_meta( $customer_id, 'learndash_group_enrolled_' . $group_id, strtotime( $start_date ) );
}
}
}
}
}
}
/**
* Add subscription settings related to LearnDash
*
* @param array $settings Original settings array
*/
public static function add_subscription_settings( $settings )
{
return array_merge( $settings, [
array(
'name' => 'LearnDash',
'type' => 'title',
'desc' => __( 'WooCommerce subscription settings related to LearnDash.', 'learndash-woocommerce' ),
'id' => 'learndash_woocommerce_section',
),
array(
'name' => __( 'Access Removal on Expiration', 'learndash-woocommerce' ),
'desc' => __( 'Disable', 'learndash-woocommerce' ),
'desc_tip' => __( 'Check the box to disable course access removal on subscription expiration. By default, course access will be revoked when a subscription expires.', 'learndash-woocommerce' ),
'id' => 'learndash_woocommerce_disable_access_removal_on_expiration',
'css' => '',
'type' => 'checkbox',
'default' => 'no',
),
array( 'type' => 'sectionend', 'id' => 'learndash_woocommerce_section' ),
] );
}
/**
* Filter hook function to check subscription course access removal
* @param bool $remove True to remove|false otherwise
* @param object $subscription WC_Subscription object
* @param string $filter Current filter hook
* @return bool Returned $remove value
*/
public static function check_subscription_course_access_removal( $remove, $subscription, $filter )
{
$backtrace = wp_debug_backtrace_summary();
if (
$filter === 'woocommerce_subscription_status_on-hold'
&& (
strpos( $backtrace, 'process_renewal' ) !== false
|| strpos( $backtrace, 'Renewal_Order' ) !== false
)
) {
return false;
}
return $remove;
}
/**
* Filter hook function to check subscription course access addition
* @param bool $add True to remove|false otherwise
* @param object $subscription WC_Subscription object
* @param string $filter Current filter hook
* @return bool Returned $add value
*/
public static function check_subscription_course_access_addition( $add, $subscription, $filter )
{
$backtrace = wp_debug_backtrace_summary();
if (
$filter === 'woocommerce_subscription_status_active'
&& (
strpos( $backtrace, 'process_renewal' ) !== false
|| strpos( $backtrace, 'Renewal_Order' ) !== false
)
) {
return false;
}
return $add;
}
/**
* Remove course access when user completes billing cycle
*
* @param object $subscription WC_Subscription object
* @param array $last_order Last order details
*/
public static function remove_course_access_on_billing_cycle_completion( $subscription, $last_order )
{
if ( self::is_course_access_removed_on_subscription_billing_cycle_completion( $subscription ) ) {
$next_payment_date = $subscription->calculate_date( 'next_payment' );
// Check if there's no next payment date
// See calculate_date() in class-wc-subscriptions.php
if ( 0 == $next_payment_date ) {
self::remove_subscription_course_access( $subscription );
}
}
}
/**
* Handle course access when subscription switching happens
* @param Automattic\WooCommerce\Admin\Overrides\Order $order WC order object
* @param array $data WC order data
* @return void
*/
public static function switch_subscription( $order, $data )
{
foreach ( $data as $subscription_id => $subscription_data ) {
foreach ( $subscription_data['switches'] as $switch_item_id => $switch_data ) {
$subscriptions = wcs_get_subscriptions_for_switch_order( $order );
if ( ! empty( $switch_data['remove_line_item'] ) ) {
$old_order = wc_get_order( wc_get_order_id_by_order_item_id( $switch_data['remove_line_item'] ) );
if ( $old_order && is_a( $old_order, 'WC_Order' ) ) {
foreach ( $subscriptions as $subscription ) {
self::remove_subscription_course_access( $subscription, $old_order->get_items() );
}
}
}
if ( ! empty( $switch_data['add_line_item'] ) ) {
self::add_subscription_course_access( $subscription, $order->get_items() );
}
}
}
}
/**
* Enqueue course enrollment in database for product with many courses
*
* @param array $args Order/subscription arg in this format:
* array( 'order_id' => $order_id ) OR
* array( 'subscription_id' => $subscription_id )
* @return void
*/
public static function enqueue_silent_course_enrollment( $args ) {
$queue = get_option( 'learndash_woocommerce_silent_course_enrollment_queue', array() );
if ( ! empty( $args['order_id'] ) ) {
$queue[ $args['order_id'] ] = $args;
} elseif( ! empty( $args['subscription_id'] ) ) {
$queue[ $args['subscription_id'] ] = $args;
}
update_option( 'learndash_woocommerce_silent_course_enrollment_queue', $queue, false );
}
/**
* Process silent background course enrollment using cron
*
* @return void
*/
public static function process_silent_course_enrollment() {
$queue = get_option( 'learndash_woocommerce_silent_course_enrollment_queue', array() );
$queue_count = apply_filters( 'learndash_woocommerce_process_silent_course_enrollment_queue_count', 1 );
$processed_queue = array_slice( $queue, 0, $queue_count, true );
foreach ( $processed_queue as $id => $args ) {
if ( ! empty( $args['order_id'] ) ) {
self::add_course_access( $args['order_id'] );
} elseif ( ! empty( $args['subscription_id'] ) ) {
self::add_subscription_course_access( wcs_get_subscription( $args['subscription_id'] ) );
}
unset( $queue[ $id ] );
}
update_option( 'learndash_woocommerce_silent_course_enrollment_queue', $queue, false );
}
/**
* Force user to login when there is a LD course in cart
*
* @param object $checkout Checkout object
*/
public static function enable_signup_on_checkout( $checkout )
{
$wc_cart = WC()->cart;
if ( is_a( $wc_cart, 'WC_Cart' ) ) {
$cart_items = $wc_cart->cart_contents;
foreach ( $cart_items as $key => $item ) {
$courses = (array) get_post_meta( $item['data']->get_id(), '_related_course', true );
$courses = maybe_unserialize( $courses );
$groups = (array) get_post_meta( $item['data']->get_id(), '_related_group', true );
$groups = maybe_unserialize( $groups );
if ( isset( $courses ) && is_array( $courses ) ) {
foreach ( $courses as $course ) {
if ( $course != 0 ) {
self::add_front_scripts();
break 2;
}
}
}
if ( isset( $groups ) && is_array( $groups ) ) {
foreach ( $groups as $group ) {
if ( $group != 0 ) {
self::add_front_scripts();
break 2;
}
}
}
}
}
}
/**
* Filter WooCommerce registration enabled setting.
*
* Always enable registration setting if user cart contains product(s)
* that are associated with LearnDash course(s) or group(s).
*
* @param bool $enabled
* @return bool
*/
public static function enable_registration( $enabled )
{
$wc_cart = WC()->cart;
if ( is_a( $wc_cart, 'WC_Cart' ) ) {
$cart_items = $wc_cart->cart_contents;
$ld_object_found = false;
foreach ( $cart_items as $key => $item ) {
$courses = (array) get_post_meta( $item['data']->get_id(), '_related_course', true );
$courses = maybe_unserialize( $courses );
$groups = (array) get_post_meta( $item['data']->get_id(), '_related_group', true );
$groups = maybe_unserialize( $groups );
// Filter out invalid courses and groups first.
$courses = array_filter( $courses, function( $course_id ) {
$course = get_post( $course_id );
return $course && $course->post_status == 'publish' && $course->post_type == 'sfwd-courses';
} );
$groups = array_filter( $groups, function( $group_id ) {
$group = get_post( $group_id );
return $group && $group->post_status == 'publish' && $group->post_type == 'groups';
} );
if ( ! empty( $courses ) ) {
$ld_object_found = true;
}
if ( ! empty( $groups ) ) {
$ld_object_found = true;
}
}
if ( $ld_object_found && ! is_user_logged_in() ) {
$enabled = true;
}
}
return $enabled;
}
/**
* Autocomplete transaction if all cart items are course items
* @param int $order_id
*/
public static function auto_complete_transaction( $order_id )
{
if ( ! apply_filters( 'learndash_woocommerce_auto_complete_order', true, $order_id ) ) {
return;
}
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
return;
}
if ( ! $order->is_paid() ) {
return;
}
if ( 'completed' == $order->get_status() ) {
return;
}
$items = $order->get_items();
$payment_method = $order->get_payment_method();
$manual_payment_methods = apply_filters( 'learndash_woocommerce_manual_payment_methods', array(
'bacs', 'cheque', 'cod'
) );
// If using manual payment, bail
if ( in_array( $payment_method, $manual_payment_methods ) ) {
return;
}
$found = array();
foreach ( $items as $item ) {
// If variation product
if ( $item->get_variation_id() > 0 ) {
$item_id = $item->get_variation_id();
$courses = (array) get_post_meta( $item->get_variation_id(), '_related_course', true );
$groups = (array) get_post_meta( $item->get_variation_id(), '_related_group', true );
}
// Else if normal product
elseif ( $item->get_product_id() > 0 ) {
$item_id = $item->get_product_id();
$courses = (array) get_post_meta( $item->get_product_id(), '_related_course', true );
$groups = (array) get_post_meta( $item->get_product_id(), '_related_group', true );
}
// Filter out invalid courses and groups first
$courses = array_map( function( $course_id ) {
$course = get_post( $course_id );
return $course && $course->post_status == 'publish' && $course->post_type == 'sfwd-courses';
}, $courses );
$groups = array_map( function( $group_id ) {
$group = get_post( $group_id );
return $group && $group->post_status == 'publish' && $group->post_type == 'groups';
}, $groups );
if (
( is_array( $courses ) && ! empty( $courses ) && ! in_array( 0, $courses ) )
|| (
is_array( $courses ) && count( $courses ) > 1 && in_array( 0, $courses )
|| ( $item->is_type( 'virtual' ) || $item->is_type( 'downloadable' ) )
)
|| ( is_array( $groups ) && ! empty( $groups ) && ! in_array( 0, $groups ) )
|| (
is_array( $groups ) && count( $groups ) > 1 && in_array( 0, $groups )
|| ( $item->is_type( 'virtual' ) || $item->is_type( 'downloadable' ) )
)
) {
$found[] = $item_id;
}
}
// Autocomplete transaction if all items are course
if ( count( $found ) == count( $items ) ) {
$order->update_status( 'completed' );
}
}
/**
* Remove course access count if user data is removed
*
* @param int $user_id
*/
public static function remove_access_increment_count( $user_id ) {
delete_user_meta( $user_id, '_learndash_woocommerce_enrolled_courses_access_counter' );
}
/**
* Add course access
*
* @param int $course_id ID of a course
* @param int $user_id ID of a user
*/
private static function update_add_course_access( $course_id, $user_id, $order_id )
{
self::increment_course_access_counter( $course_id, $user_id, $order_id );
// check if user already enrolled
if ( ! self::is_user_enrolled_to_course( $user_id, $course_id ) ) {
ld_update_course_access( $user_id, $course_id );
} elseif ( self::is_user_enrolled_to_course( $user_id, $course_id ) && ld_course_access_expired( $course_id, $user_id ) ) {
// Remove access first
// @todo: only remove access counter from old WC orders
self::reset_course_access_counter( $course_id, $user_id );
ld_update_course_access( $user_id, $course_id, $remove = true );
// Re-enroll to get new access from value
self::increment_course_access_counter( $course_id, $user_id, $order_id );
ld_update_course_access( $user_id, $course_id );
}
}
/**
* Remove course access
*
* @param int $course_id ID of a course
* @param int $user_id ID of a user
* @param int $order_id ID of an order
*/
private static function update_remove_course_access( $course_id, $user_id, $order_id )
{
$courses = self::decrement_course_access_counter( $course_id, $user_id, $order_id );
if ( ! isset( $courses[ $course_id ] ) || empty( $courses[ $course_id ] ) ) {
ld_update_course_access( $user_id, $course_id, $remove = true );
}
}
/**
* Add group access
*
* @param int $group_id LearnDash group ID
* @param int $user_id WP_User ID
* @param int $order_id WC order ID
* @return void
*/
private static function update_add_group_access( $group_id, $user_id, $order_id )
{
self::increment_course_access_counter( $group_id, $user_id, $order_id );
if ( ! learndash_is_user_in_group( $user_id, $group_id ) ) {
ld_update_group_access( $user_id, $group_id );
}
}
/**
* Remove group acess
*
* @param int $group_id LearnDash group ID
* @param int $user_id WP_User ID
* @param int $order_id WC order ID
* @return void
*/
private static function update_remove_group_access( $group_id, $user_id, $order_id )
{
$access = self::decrement_course_access_counter( $group_id, $user_id, $order_id );
if ( ! isset( $access[ $group_id ] ) || empty( $access[ $group_id ] ) ) {
ld_update_group_access( $user_id, $group_id, $remove = true );
}
}
/**
* Check if a user is already enrolled to a course
*
* @param integer $user_id User ID
* @param integer $course_id Course ID
* @return boolean True if enrolled|false otherwise
*/
private static function is_user_enrolled_to_course( $user_id = 0, $course_id = 0 ) {
$enrolled_courses = learndash_user_get_enrolled_courses( $user_id );
if ( is_array( $enrolled_courses ) && in_array( $course_id, $enrolled_courses ) ) {
return true;
}
return false;
}
/**
* Get all LearnDash courses
*
* @return object LearnDash course
*/
private static function get_learndash_courses()
{
global $wpdb;
$query = "SELECT posts.* FROM $wpdb->posts posts WHERE posts.post_type = 'sfwd-courses' AND posts.post_status = 'publish' ORDER BY posts.post_title";
return $wpdb->get_results( $query, OBJECT );
}
/**
* Add enrolled course record to a user
*
* @param int $course_id ID of a course
* @param int $user_id ID of a user
* @param int $order_id ID of an order
*/
private static function increment_course_access_counter( $course_id, $user_id, $order_id )
{
$courses = self::get_courses_access_counter( $user_id );
if ( isset( $courses[ $course_id ] ) && ! is_array( $courses[ $course_id ] ) ) {
$courses[ $course_id ] = array();
}
if ( ! isset( $courses[ $course_id ] ) || ( isset( $courses[ $course_id] ) && array_search( $order_id, $courses[ $course_id ] ) === false ) ) {
// Add order ID to course access counter
$courses[ $course_id ][] = $order_id;
}
update_user_meta( $user_id, '_learndash_woocommerce_enrolled_courses_access_counter', $courses );
return $courses;
}
/**
* Delete enrolled course record from a user
*
* @param int $course_id ID of a course
* @param int $user_id ID of a user
* @param int $order_id ID of an order
*/
private static function decrement_course_access_counter( $course_id, $user_id, $order_id )
{
$courses = self::get_courses_access_counter( $user_id );
if ( isset( $courses[ $course_id ] ) && ! is_array( $courses[ $course_id ] ) ) {
$courses[ $course_id ] = array();
}
if ( isset( $courses[ $course_id ] ) ) {
$keys = array_keys( $courses[ $course_id ], $order_id );
if ( is_array( $keys ) ) {
foreach ( $keys as $key ) {
unset( $courses[ $course_id ][ $key ] );
}
}
}
update_user_meta( $user_id, '_learndash_woocommerce_enrolled_courses_access_counter', $courses );
return $courses;
}
/**
* Reset course access counter
*
* @param int $course_id Course ID
* @param int $user_id User ID
* @return void
*/
private static function reset_course_access_counter( $course_id, $user_id ) {
$courses = self::get_courses_access_counter( $user_id );
if ( isset( $courses[ $course_id ] ) ) {
unset( $courses[ $course_id ] );
}
update_user_meta( $user_id, '_learndash_woocommerce_enrolled_courses_access_counter', $courses );
}
/**
* Get user enrolled course access counter
*
* @param int $user_id ID of a user
* @return array Course access counter array
*/
private static function get_courses_access_counter( $user_id )
{
$courses = get_user_meta( $user_id, '_learndash_woocommerce_enrolled_courses_access_counter', true );
if ( ! empty( $courses ) ) {
$courses = maybe_unserialize( $courses );
} else {
$courses = array();
}
return $courses;
}
/**
* Get setting if course access should be removed when user completeng subscription payment billing cycle
*
* @param object $subscription WC_Subscription object
* @return boolean
*/
public static function is_course_access_removed_on_subscription_billing_cycle_completion( $subscription )
{
return apply_filters( 'learndash_woocommerce_remove_course_access_on_subscription_billing_cycle_completion', false, $subscription );
}
/**
* Output a select input box.
*
* @param array $field
*/
public static function woocommerce_wp_select_multiple( $field ) {
global $thepostid, $post;
?>
<script type="text/javascript">
jQuery( document ).ready( function( $ ) {
$( '.select2.regular-width' ).show().select2({
closeOnSelect: false,
allowClear: true,
scrollAfterSelect: false,
placeholder: ''
});
$( '.select2.full-width' ).show().select2({
width: '100%',
closeOnSelect: false,
allowClear: true,
scrollAfterSelect: false,
placeholder: ''
});
});
</script>
<?php
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['style'] = isset( $field['style'] ) ? $field['style'] : '';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = isset( $field['value'] ) ? $field['value'] : get_post_meta( $thepostid, $field['id'], true );
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['desc_tip'] = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
// Custom attribute handling
$custom_attributes = array();
if ( ! empty( $field['custom_attributes'] ) && is_array( $field['custom_attributes'] ) ) {
foreach ( $field['custom_attributes'] as $attribute => $value ) {
$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
}
}
echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
<label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label>';
if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
echo wc_help_tip( $field['description'] );
}
echo '<select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="' . esc_attr( $field['class'] ) . '" style="' . esc_attr( $field['style'] ) . '" ' . implode( ' ', $custom_attributes ) . ' multiple="multiple">';
foreach ( $field['options'] as $key => $value ) {
$selected = in_array( $key, $field['value'] ) ? 'selected="selected"' : '';
echo '<option value="' . esc_attr( $key ) . '" ' . $selected . '>' . esc_html( $value ) . '</option>';
}
echo '</select> ';
if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
echo '</p>';
}
public static function get_products_count_for_silent_course_enrollment() {
return apply_filters( 'learndash_woocommerce_products_count_for_silent_course_enrollment', 5 );
}
/**
* Output a custom error log file
* @param mixed $message Message
*/
public static function log( $message = '' ) {
$file = LEARNDASH_WOOCOMMERCE_PLUGIN_PATH . 'error.log';
if ( ! file_exists( $file ) ) {
$handle = fopen( $file, 'a+' );
fclose( $handle );
}
error_log( print_r( $message, true ), 3, $file );
}
}
new Learndash_WooCommerce();
add_action( 'init', 'learndash_woocommerce_set_course_as_virtual' );
/**
* Establish the Course Product type that is virtual, and sold individually
*/
function learndash_woocommerce_set_course_as_virtual() {
if (class_exists('WC_Product')) {
class WC_Product_Course extends WC_Product {
/**
* Initialize course product.
*
* @param mixed $product
*/
public function __construct( $product ) {
parent::__construct( $product );
$this->supports = array(
'ajax_add_to_cart',
);
$this->set_virtual( true );
$this->set_sold_individually( true );
}
public function get_type()
{
return 'course';
}
/**
* Get the add to cart button text
*
* @return string
*/
public function add_to_cart_text() {
$text = $this->is_purchasable() ? __( 'Add to cart', 'learndash-woocommerce' ) : __( 'Read More', 'learndash-woocommerce' );
return apply_filters( 'woocommerce_product_add_to_cart_text', $text, $this );
}
/**
* Set the add to cart button URL used on the /shop/ page
*
* @return string
* @since 1.3.1
*/
public function add_to_cart_url() {
// Code copied from WP Simple Product function of same name
$url = $this->is_purchasable() && $this->is_in_stock() ? remove_query_arg( 'added-to-cart', add_query_arg( 'add-to-cart', $this->get_id() ) ) : get_permalink( $this->get_id() );
return apply_filters( 'woocommerce_product_add_to_cart_url', $url, $this );
}
}
}
}
/**
* Add To Cart template, use the simple template
*/
add_action( 'woocommerce_course_add_to_cart', 'woocommerce_simple_add_to_cart', 30 );