Viewing File: /home/rtsgrob/ww3/wp-content/plugins/tutor-pro/addons/course-bundle/src/Models/BundleModel.php
<?php
/**
* Model for bundle data.
*
* @package TutorPro\CourseBundle
* @subpackage Models
* @author Themeum <support@themeum.com>
* @link https://themeum.com
* @since 2.2.0
*/
namespace TutorPro\CourseBundle\Models;
use Tutor\Cache\TutorCache;
use Tutor\Helpers\QueryHelper;
use Tutor\Models\CourseModel;
use Tutor\Models\QuizModel;
use TutorPro\CourseBundle\CustomPosts\CourseBundle;
/**
* BundleModel Class.
*
* @since 2.2.0
*/
class BundleModel {
/**
* Ribbon types
*
* @var string
*/
const RIBBON_PERCENTAGE = 'in_percentage';
const RIBBON_AMOUNT = 'in_amount';
const RIBBON_NONE = 'none';
/**
* Get bundle courses
*
* @since 2.2.0
*
* @param int $bundle_id bundle id.
*
* @return mixed
*/
public static function get_bundle_courses( $bundle_id ) {
$course_ids = self::get_bundle_course_ids( $bundle_id );
if ( 0 === count( $course_ids ) ) {
return array();
}
global $wpdb;
$in_clause = QueryHelper::prepare_in_clause( $course_ids );
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$courses = $wpdb->get_results(
$wpdb->prepare(
"SELECT * from {$wpdb->posts}
WHERE post_type=%s
AND ID IN({$in_clause})
",
CourseModel::POST_TYPE
)
);
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $courses;
}
/**
* Get bundle meta data like total course, topic, quiz etc.
*
* @since 2.2.0
*
* @param int $bundle_id bundle id.
*
* @return array
*/
public static function get_bundle_meta( $bundle_id ) {
$cache_key = "bundle_meta_{$bundle_id}";
$arr = TutorCache::get( $cache_key );
if ( false === $arr ) {
$arr = array(
'total_courses' => 0,
'total_topics' => 0,
'total_quizzes' => 0,
'total_assignments' => 0,
'total_video_contents' => 0,
'total_video_duration' => 0,
'total_resources' => 0,
'total_duration' => 0,
);
$course_ids = self::get_bundle_course_ids( $bundle_id );
$meta = tutor_utils()->get_course_meta_data( $course_ids );
if ( is_array( $meta ) && count( $meta ) ) {
foreach ( $meta as $course_id => $course_meta ) {
$arr['total_topics'] += $course_meta['topics'];
$arr['total_assignments'] += $course_meta['tutor_assignments'];
$arr['total_quizzes'] += $course_meta['tutor_quiz'];
}
}
$total_lessons = count( $course_ids ) ? tutor_utils()->get_course_content_ids_by( tutor()->lesson_post_type, tutor()->course_post_type, $course_ids ) : array();
$arr['total_courses'] = count( $course_ids );
$arr['total_duration'] = self::get_bundle_duration( $course_ids );
$arr['total_video_contents'] = count( $total_lessons );
foreach ( $course_ids as $course_id ) {
$total_attachments = tutor_utils()->get_attachments(
$course_id,
CourseModel::ATTACHMENT_META_KEY,
true
);
$arr['total_resources'] += $total_attachments;
}
TutorCache::set( $cache_key, $arr );
}
return $arr;
}
/**
* Get bundle subtotal price.
*
* @since 2.2.0
*
* @param int $bundle_id bundle id.
*
* @return int|float
*/
public static function get_bundle_subtotal( $bundle_id ) {
$courses = self::get_bundle_course_ids( $bundle_id );
$total = 0;
foreach ( $courses as $course_id ) {
$price = tutils()->get_raw_course_price( $course_id );
if ( $price->regular_price > 0 ) {
$total += $price->regular_price;
}
}
return $total;
}
/**
* Count total courses in a bundle.
*
* @since 2.2.0
*
* @param int $bundle_id bundle id.
*
* @return int
*/
public static function get_total_courses_in_bundle( $bundle_id ) {
$course_ids = self::get_bundle_course_ids( $bundle_id );
return count( $course_ids );
}
/**
* Get bundle course ids.
*
* @since 2.2.0
*
* @param int $bundle_id course bundle id.
*
* @return array
*/
public static function get_bundle_course_ids( $bundle_id ) {
$id_str = get_post_meta( $bundle_id, CourseBundle::BUNDLE_COURSE_IDS_META_KEY, true );
return empty( $id_str ) ? array() : explode( ',', $id_str );
}
/**
* Get bundle course authors.
*
* @since 2.2.0
*
* @param int $bundle_id course bundle id.
*
* @return mixed
*/
public static function get_bundle_course_authors( $bundle_id ) {
$courses = self::get_bundle_course_ids( $bundle_id );
if ( 0 === count( $courses ) ) {
return array();
}
global $wpdb;
$in_clause = QueryHelper::prepare_in_clause( $courses );
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$authors = $wpdb->get_results(
$wpdb->prepare(
"SELECT
DISTINCT um.user_id,
u.display_name,
u.user_email,
tutor_job_title.meta_value AS designation
FROM {$wpdb->usermeta} um
LEFT JOIN {$wpdb->users} u
ON u.ID = um.user_id
LEFT JOIN {$wpdb->usermeta} tutor_job_title
ON tutor_job_title.user_id = um.user_id
AND tutor_job_title.meta_key = '_tutor_profile_job_title'
WHERE um.meta_key=%s
AND um.meta_value IN ({$in_clause})",
'_tutor_instructor_course_id'
)
);
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $authors;
}
/**
* Get bundle course categories.
*
* @since 2.2.0
*
* @param int $bundle_id course bundle id.
*
* @return mixed
*/
public static function get_bundle_course_categories( $bundle_id ) {
$courses = self::get_bundle_course_ids( $bundle_id );
if ( 0 === count( $courses ) ) {
return array();
}
global $wpdb;
$in_clause = QueryHelper::prepare_in_clause( $courses );
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$categories = $wpdb->get_results(
$wpdb->prepare(
"SELECT
DISTINCT terms.term_id, terms.name, terms.slug
FROM
{$wpdb->terms} AS terms
INNER JOIN {$wpdb->term_taxonomy} AS taxonomy ON terms.term_id = taxonomy.term_id
INNER JOIN {$wpdb->term_relationships} AS relationships ON taxonomy.term_taxonomy_id = relationships.term_taxonomy_id
WHERE
relationships.object_id IN ({$in_clause})
AND taxonomy.taxonomy = %s",
'course-category'
)
);
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return $categories;
}
/**
* Get total sold number of a course bundle.
*
* @since 2.2.0
*
* @param int $bundle_id course bundle id.
*
* @return int
*/
public static function get_total_bundle_sold( $bundle_id ) {
global $wpdb;
$cache_key = "tutor_bundle_sold_{$bundle_id}";
$count = TutorCache::get( $cache_key );
if ( false === $count ) {
$count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*)
FROM {$wpdb->posts}
WHERE post_type = %s
AND post_status = %s
AND post_parent = %d",
'tutor_enrolled',
'completed',
$bundle_id
)
);
TutorCache::set( $cache_key, $count );
}
return $count;
}
/**
* Get bundle id by course id.
*
* @since 2.2.0
*
* @param int $course_id course id.
*
* @return int|bool bundle id or false if course is not in a bundle.
*/
public static function get_bundle_id_by_course( $course_id ) {
global $wpdb;
$data = $wpdb->get_row(
$wpdb->prepare(
"SELECT *
FROM {$wpdb->postmeta}
WHERE meta_key = %s
AND meta_value LIKE %s",
'bundle-course-ids',
"%{$course_id}%"
)
);
return is_object( $data ) ? $data->post_id : false;
}
/**
* Delete a course bundle.
*
* @since 2.2.0
*
* @param int $bundle_id course bundle id.
*
* @return bool
*/
public static function delete_bundle( $bundle_id ) {
if ( get_post_type( $bundle_id ) !== CourseBundle::POST_TYPE ) {
return false;
}
wp_delete_post( $bundle_id, true );
return true;
}
/**
* Update course bundle ids
*
* @since 2.2.0
*
* @param int $bundle_id bundle id.
* @param array $course_ids course ids array, ex: [1,2,3].
*
* @return bool
*/
public static function update_bundle_course_ids( int $bundle_id, array $course_ids ): bool {
// Validate.
if ( ! $bundle_id ) {
return false;
}
if ( CourseBundle::POST_TYPE !== get_post_type( $bundle_id ) ) {
return false;
}
// Update post meta.
update_post_meta(
$bundle_id,
CourseBundle::BUNDLE_COURSE_IDS_META_KEY,
implode( ',', $course_ids )
);
return true;
}
/**
* Remove a course from bundle & update bundle course ids meta
*
* @since 2.2.0
*
* @param integer $course_id course id to remove.
* @param integer $bundle_id bundle id.
*
* @return bool
*/
public static function remove_course_from_bundle( int $course_id, int $bundle_id ) {
$course_ids = self::get_bundle_course_ids( $bundle_id );
// Remove course from bundle.
$course_ids = array_diff( $course_ids, array( $course_id ) );
return self::update_bundle_course_ids( $bundle_id, $course_ids );
}
/**
* Get bundles by a instructor
*
* @since 2.2.0
*
* @param integer $instructor_id instructor id.
* @param array|string $post_status post status.
* @param integer $offset offset.
* @param integer $limit limit.
* @param boolean $count_only count only.
*
* @return array|null|object
*/
public static function get_bundles_by_instructor( $instructor_id = 0, $post_status = array( 'publish' ), int $offset = 0, int $limit = PHP_INT_MAX, $count_only = false ) {
global $wpdb;
$offset = sanitize_text_field( $offset );
$limit = sanitize_text_field( $limit );
$instructor_id = tutils()->get_user_id( $instructor_id );
if ( empty( $post_status ) || 'any' === $post_status ) {
$where_post_status = '';
} else {
if ( ! is_array( $post_status ) ) {
$post_status = array( $post_status );
}
$statuses = "'" . implode( "','", $post_status ) . "'";
$where_post_status = "AND $wpdb->posts.post_status IN({$statuses}) ";
}
$select_col = $count_only ? " COUNT(DISTINCT $wpdb->posts.ID) " : " $wpdb->posts.* ";
$limit_offset = $count_only ? '' : " LIMIT $offset, $limit ";
//phpcs:disable
$query = $wpdb->prepare(
"SELECT $select_col
FROM $wpdb->posts
WHERE 1 = 1 {$where_post_status}
AND $wpdb->posts.post_type = %s
AND $wpdb->posts.post_author = %d
ORDER BY $wpdb->posts.post_date DESC $limit_offset",
CourseBundle::POST_TYPE,
$instructor_id
);
return $count_only ? $wpdb->get_var( $query ) : $wpdb->get_results( $query, OBJECT );
//phpcs:enable
}
/**
* Get bundle duration in seconds
*
* It will merge all the course durations and return in seconds
*
* @since 2.2.0
*
* @param array $course_ids course ids array.
*
* @return integer
*/
public static function get_bundle_duration( array $course_ids ): int {
$total_duration = 0;
if ( ! count( $course_ids ) ) {
return $total_duration;
}
// Merge all course durations.
foreach ( $course_ids as $id ) {
$duration = get_post_meta( $id, '_course_duration', true );
$duration_hours = (int) tutor_utils()->avalue_dot( 'hours', $duration ) * 3600;
$duration_minutes = (int) tutor_utils()->avalue_dot( 'minutes', $duration ) * 60;
$duration_seconds = (int) tutor_utils()->avalue_dot( 'seconds', $duration );
$total_duration += $duration_hours + $duration_minutes + $duration_seconds;
}
return $total_duration;
}
/**
* Convert seconds to human readable time
*
* It will convert seconds in hour, min & seconds
*
* @since 2.2.0
*
* @param int $seconds seconds.
* @param bool $echo echo or return.
*
* @return string|void
*/
public static function convert_seconds_into_human_readable_time( int $seconds, $echo = true ) {
$hours = floor( $seconds / 3600 );
$minutes = floor( ( $seconds % 3600 ) / 60 );
$remaining_seconds = $seconds % 60;
$human_readable_time = sprintf( '%02d:%02d:%02d', $hours, $minutes, $remaining_seconds );
if ( $echo ) {
echo esc_html( $human_readable_time );
} else {
return $human_readable_time;
}
}
/**
* Get bundle ribbon options
*
* @since 2.2.0
*
* @return array
*/
public static function get_ribbon_display_options(): array {
$currency_symbol = tutor_utils()->currency_symbol();
$options = array(
self::RIBBON_PERCENTAGE => __( 'Show Discount % Off', 'tutor-pro' ),
self::RIBBON_AMOUNT => sprintf( __( 'Show Discounted Amount (%s)', 'tutor-pro' ), $currency_symbol ), //phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment
self::RIBBON_NONE => __( 'Show None', 'tutor-pro' ),
);
return apply_filters( 'tutor_pro_bundle_ribbon_display_options', $options );
}
/**
* Enroll a user to bundle courses
*
* @since 2.2.2
*
* @param int $bundle_id bundle id.
* @param int $user_id user id.
*
* @return void
*/
public static function enroll_to_bundle_courses( $bundle_id, $user_id ) {
$bundle_course_ids = self::get_bundle_course_ids( $bundle_id );
if ( count( $bundle_course_ids ) > 0 ) {
foreach ( $bundle_course_ids as $course_id ) {
add_filter(
'tutor_enroll_data',
function( $data ) {
$data['post_status'] = 'completed';
return $data;
}
);
tutor_utils()->do_enroll( $course_id, 0, $user_id );
}
}
}
}
Back to Directory
File Manager