File: /home/mobilech/alliancelaptoptraining.com.np/wp-content/plugins/tutor/models/EnrollmentModel.php
<?php
/**
* Enrollment Model
*
* @package Tutor\Models
* @author Themeum <support@themeum.com>
* @link https://themeum.com
* @since 4.0.0
*/
namespace Tutor\Models;
use Tutor\Cache\TutorCache;
use TUTOR\Course;
use Tutor\Helpers\QueryHelper;
use TUTOR\User;
/**
* Class EnrollmentModel
*
* @since 4.0.0
*/
class EnrollmentModel {
/**
* Enrollment status constants
*
* @since 4.0.0
*
* @var string
*/
const STATUS_COMPLETED = 'completed';
const STATUS_PENDING = 'pending';
const STATUS_CANCEL = 'cancel';
/**
* Enrollment post type
*
* @since 4.0.0
*
* @var string
*/
const POST_TYPE = 'tutor_enrolled';
/**
* Enrollment meta
*
* @since 4.0.0
*/
const ENROLLMENT_ORDER_ID_META = '_tutor_enrolled_by_order_id';
const ENROLLMENT_PRODUCT_ID_META = '_tutor_enrolled_by_product_id';
/**
* Saving enroll information to posts table
* post_author = enrolled_student_id (wp_users id)
* post_parent = enrolled course id
*
* @since 1.0.0
* @since 2.6.0 Return enrolled id
* @since 3.3.0 Added $fire_hook parameter.
*
* @param int $course_id course id.
* @param int $order_id order id.
* @param int $user_id user id.
* @param bool $fire_hook fire hook.
*
* @return int enrolled id
*/
public static function do_enroll( $course_id = 0, $order_id = 0, $user_id = 0, $fire_hook = true ) {
$enrolled_id = 0;
if ( ! CourseModel::is_course_accessible( $course_id ) ) {
return $enrolled_id;
}
$can_enroll = apply_filters( 'tutor_allow_course_enrollment', true, $course_id );
if ( is_wp_error( $can_enroll ) ) {
return $enrolled_id;
}
$fire_hook ? do_action( 'tutor_before_enroll', $course_id ) : null;
$user_id = tutor_utils()->get_user_id( $user_id );
$title = __( 'Course Enrolled', 'tutor' ) . ' – ' . gmdate( get_option( 'date_format' ) ) . ' @ ' . gmdate( get_option( 'time_format' ) );
if ( $course_id && $user_id ) {
$enrolled_info = self::is_enrolled( $course_id, $user_id );
if ( $enrolled_info ) {
return $enrolled_info->ID;
}
}
$enrolment_status = self::STATUS_COMPLETED;
if ( tutor_utils()->is_course_purchasable( $course_id ) ) {
$enrolment_status = self::STATUS_PENDING;
}
$enroll_data = apply_filters(
'tutor_enroll_data',
array(
'post_type' => self::POST_TYPE,
'post_title' => $title,
'post_status' => $enrolment_status,
'post_author' => $user_id,
'post_parent' => $course_id,
'post_date_gmt' => current_time( 'mysql', true ),
)
);
// Insert the post into the database.
$is_enrolled = wp_insert_post( $enroll_data );
if ( $is_enrolled ) {
// Run this hook for both of pending and completed enrollment.
$fire_hook ? do_action( 'tutor_after_enroll', $course_id, $is_enrolled ) : null;
// Mark Current User as Students with user meta data.
update_user_meta( $user_id, User::TUTOR_STUDENT_META, tutor_time() );
if ( $order_id ) {
// Mark order for course and user.
$product_id = tutor_utils()->get_course_product_id( $course_id );
update_post_meta( $is_enrolled, self::ENROLLMENT_ORDER_ID_META, $order_id );
update_post_meta( $is_enrolled, self::ENROLLMENT_PRODUCT_ID_META, $product_id );
$monetize_by = tutor_utils()->get_option( 'monetize_by' );
if ( 'wc' === $monetize_by ) {
$order = wc_get_order( $order_id );
$order->update_meta_data( Course::IS_TUTOR_ORDER_FOR_COURSE_META, tutor_time() );
$order->update_meta_data( Course::TUTOR_ORDER_FOR_COURSE_ID_META . $course_id, $is_enrolled );
$order->save();
} elseif ( 'edd' === $monetize_by ) {
$payment = new \EDD_Payment( $order_id );
$payment->update_meta( Course::IS_TUTOR_ORDER_FOR_COURSE_META, tutor_time() );
$payment->update_meta( Course::TUTOR_ORDER_FOR_COURSE_ID_META . $course_id, $is_enrolled );
$payment->save();
} else {
update_post_meta( $order_id, Course::IS_TUTOR_ORDER_FOR_COURSE_META, tutor_time() );
update_post_meta( $order_id, Course::TUTOR_ORDER_FOR_COURSE_ID_META . $course_id, $is_enrolled );
}
}
$enrolled_id = $is_enrolled;
// Run this hook for completed enrollment regardless of payment provider and free/paid mode.
if ( $fire_hook && self::STATUS_COMPLETED === $enroll_data['post_status'] ) {
do_action( 'tutor_after_enrolled', $course_id, $user_id, $enrolled_id );
}
}
return $enrolled_id;
}
/**
* Check if current user has been enrolled or not
*
* @since 1.0.0
*
* @since 3.0.0 $is_complete parameter added to check with completed status
* Default value set true for backward compatibility. It set
* false then it will just check record.
*
* @since 3.3.0 param $is_complete added to cache key.
* @since 4.0.0 enrollment order_id and product_id added to enrollment info.
*
* @param int $course_id course id.
* @param int $user_id user id.
* @param bool $is_complete Whether to enrollment completed or not.
*
* @return array|bool|null|object
*/
public static function is_enrolled( $course_id = 0, $user_id = 0, bool $is_complete = true ) {
global $wpdb;
$course_id = tutor_utils()->get_post_id( $course_id );
$user_id = tutor_utils()->get_user_id( $user_id );
$cache_key = "tutor_is_enrolled_{$course_id}_{$user_id}_{$is_complete}";
$cached = TutorCache::get( $cache_key );
if ( false !== $cached ) {
return $cached;
}
do_action( 'tutor_is_enrolled_before', $course_id, $user_id );
$status_clause = '';
if ( $is_complete ) {
$status_clause = $wpdb->prepare( 'AND post_status = %s ', self::STATUS_COMPLETED );
}
//phpcs:disable
$get_enrolled_info = $wpdb->get_row(
$wpdb->prepare(
"SELECT ID,
post_author,
post_date,
post_date_gmt,
post_title
FROM {$wpdb->posts}
WHERE post_author > 0
AND post_parent > 0
AND post_type = %s
AND post_parent = %d
AND post_author = %d
{$status_clause};
",
self::POST_TYPE,
$course_id,
$user_id
)
);
//phpcs:enable
if ( $get_enrolled_info ) {
$get_enrolled_info->order_id = (int) get_post_meta( $get_enrolled_info->ID, self::ENROLLMENT_ORDER_ID_META, true );
$get_enrolled_info->product_id = (int) get_post_meta( $get_enrolled_info->ID, self::ENROLLMENT_PRODUCT_ID_META, true );
}
TutorCache::set( $cache_key, $get_enrolled_info );
if ( $get_enrolled_info ) {
return apply_filters( 'tutor_is_enrolled', $get_enrolled_info, $course_id, $user_id );
}
return false;
}
/**
* Get enrollment by enrol_id
*
* @since 1.6.9
*
* @param int $enrol_id enrol id.
*
* @return array|object
*/
public static function get_enrolment_by_enrol_id( $enrol_id = 0 ) {
global $wpdb;
$enrolment = $wpdb->get_row(
$wpdb->prepare(
"SELECT enrol.id AS enrol_id,
enrol.post_author AS student_id,
enrol.post_date AS enrol_date,
enrol.post_title AS enrol_title,
enrol.post_status AS status,
enrol.post_parent AS course_id,
course.post_title AS course_title,
student.user_nicename,
student.user_email,
student.display_name,
student.ID
FROM {$wpdb->posts} enrol
INNER JOIN {$wpdb->posts} course
ON enrol.post_parent = course.id
INNER JOIN {$wpdb->users} student
ON enrol.post_author = student.id
WHERE enrol.id = %d;
",
$enrol_id
)
);
if ( $enrolment ) {
return $enrolment;
}
return false;
}
/**
* Get single or list of enrolled course data by a user
*
* @since 2.0.5
*
* @param integer $user_id user id.
* @param integer $course_id cousrs id.
*
* @return object|mixed
*/
public static function get_enrolled_data( $user_id = 0, $course_id = 0 ) {
global $wpdb;
// If course ID provided, it will return single row data.
if ( $course_id > 0 ) {
return $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->posts}
WHERE post_type = %s
AND post_parent = %d
AND post_status = %s
AND post_author = %d;",
self::POST_TYPE,
$course_id,
self::STATUS_COMPLETED,
$user_id
)
);
} else {
// Return all enrolled data by user ID.
return $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$wpdb->posts}
WHERE post_type = %s
AND post_status = %s
AND post_author = %d;",
self::POST_TYPE,
self::STATUS_COMPLETED,
$user_id
)
);
}
}
/**
* Execute bulk action for enrollment list ex: complete | cancel
*
* @since 2.0.3
* @since 3.2.0 $trigger_hook param added.
*
* @param string $status hold status for updating.
* @param array $enrollment_ids ids that need to update.
* @param bool $trigger_hook optional - trigger hook or not.
*
* @return bool
*/
public static function update_enrollments( string $status, array $enrollment_ids, bool $trigger_hook = true ): bool {
global $wpdb;
$enrollment_ids_in = QueryHelper::prepare_in_clause( $enrollment_ids );
$status = 'complete' === $status ? 'completed' : $status;
$post_table = $wpdb->posts;
//phpcs:disable
$wpdb->query(
$wpdb->prepare(
"UPDATE {$post_table}
SET post_status = %s
WHERE ID IN ($enrollment_ids_in)
",
$status
)
);
//phpcs:enable
if ( $trigger_hook ) {
// Run action hook.
foreach ( $enrollment_ids as $id ) {
do_action( 'tutor_enrollment/after/' . $status, $id );
}
}
return true;
}
/**
* Delete enrollment record by providing the student and course id
*
* @since 3.4.0
*
* @param int $student_id Student id.
* @param int $course_id Course id.
*
* @return bool
*/
public static function delete_enrollment_record( int $student_id, int $course_id ): bool {
return QueryHelper::delete(
'posts',
array(
'post_author' => $student_id,
'post_parent' => $course_id,
'post_type' => self::POST_TYPE,
)
);
}
}