| |
| <?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| add_action('llms_content_sync_complete', 'llms_populate_course_details', 10, 3);
|
|
|
| function llms_populate_course_details($course_id, $sync_post_id, $is_update) {
|
|
|
|
|
| if (!class_exists('LLMS_Course')) {
|
| return;
|
| }
|
|
|
|
|
| $detail_transient = 'llms_detail_lock_' . $sync_post_id;
|
| if (get_transient($detail_transient)) {
|
| return;
|
| }
|
| set_transient($detail_transient, 1, 120);
|
|
|
| try {
|
|
|
| $course = new LLMS_Course($course_id);
|
|
|
| if (!$course || !$course->get('id')) {
|
| return;
|
| }
|
|
|
|
|
| llms_populate_course_structure($course, $sync_post_id);
|
|
|
|
|
| llms_populate_enrollment_data($course, $sync_post_id);
|
|
|
|
|
| llms_populate_certificates_achievements($course_id, $sync_post_id);
|
|
|
|
|
| if (function_exists('update_field')) {
|
| llms_populate_acf_fields($course, $sync_post_id);
|
| }
|
|
|
|
|
| delete_transient($detail_transient);
|
|
|
| } catch (Exception $e) {
|
| error_log('LifterLMS Detail Population Error: ' . $e->getMessage());
|
| delete_transient($detail_transient);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function llms_populate_course_structure($course, $sync_post_id) {
|
|
|
| $course_structure = array();
|
| $all_lessons_data = array();
|
| $all_quizzes = array();
|
|
|
|
|
| $sections = $course->get_sections('sections');
|
|
|
| if (empty($sections)) {
|
| update_post_meta($sync_post_id, '_course_structure', array());
|
| return;
|
| }
|
|
|
| foreach ($sections as $section) {
|
| $section_data = array(
|
| 'id' => $section->get('id'),
|
| 'title' => $section->get('title'),
|
| 'order' => $section->get('order'),
|
| 'lessons' => array()
|
| );
|
|
|
|
|
| $lessons = $section->get_lessons('lessons');
|
|
|
| foreach ($lessons as $lesson) {
|
| $lesson_data = array(
|
| 'id' => $lesson->get('id'),
|
| 'title' => $lesson->get('title'),
|
| 'excerpt' => $lesson->get('excerpt'),
|
| 'order' => $lesson->get('order'),
|
| 'permalink' => get_permalink($lesson->get('id')),
|
| 'parent_section' => $lesson->get('parent_section'),
|
| 'parent_course' => $lesson->get('parent_course'),
|
| 'has_quiz' => $lesson->has_quiz(),
|
| 'quiz_enabled' => $lesson->is_quiz_enabled(),
|
| 'points' => $lesson->get('points'),
|
| 'has_prerequisite' => $lesson->has_prerequisite(),
|
| 'prerequisite' => $lesson->get('prerequisite'),
|
| 'drip_method' => $lesson->get('drip_method'),
|
| 'drip_days' => $lesson->get('days_before_available'),
|
| 'require_passing_grade' => $lesson->get('require_passing_grade'),
|
| 'video_embed' => $lesson->get('video_embed'),
|
| 'audio_embed' => $lesson->get('audio_embed'),
|
| 'featured_image' => get_the_post_thumbnail_url($lesson->get('id'), 'medium')
|
| );
|
|
|
|
|
| if ($lesson->has_quiz()) {
|
| $quiz_id = $lesson->get('quiz');
|
| $quiz_data = llms_extract_quiz_data($quiz_id);
|
| $lesson_data['quiz'] = $quiz_data;
|
| $all_quizzes[] = $quiz_data;
|
| }
|
|
|
|
|
| if ($lesson->get('assignment_enabled') === 'yes') {
|
| $lesson_data['has_assignment'] = true;
|
| $lesson_data['assignment_id'] = $lesson->get('assignment');
|
| }
|
|
|
| $section_data['lessons'][] = $lesson_data;
|
| $all_lessons_data[] = $lesson_data;
|
|
|
|
|
| unset($lesson, $lesson_data);
|
| }
|
|
|
| $course_structure[] = $section_data;
|
|
|
|
|
| unset($section, $section_data, $lessons);
|
| }
|
|
|
|
|
| update_post_meta($sync_post_id, '_course_structure', $course_structure);
|
| update_post_meta($sync_post_id, '_all_lessons', $all_lessons_data);
|
| update_post_meta($sync_post_id, '_all_quizzes', $all_quizzes);
|
| update_post_meta($sync_post_id, '_quiz_count', count($all_quizzes));
|
|
|
|
|
| unset($course_structure, $all_lessons_data, $all_quizzes);
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function llms_extract_quiz_data($quiz_id) {
|
|
|
| if (!class_exists('LLMS_Quiz')) {
|
| return array();
|
| }
|
|
|
| $quiz = new LLMS_Quiz($quiz_id);
|
|
|
| if (!$quiz || !$quiz->get('id')) {
|
| return array();
|
| }
|
|
|
| $quiz_data = array(
|
| 'id' => $quiz->get('id'),
|
| 'title' => $quiz->get('title'),
|
| 'content' => $quiz->get('content'),
|
| 'lesson_id' => $quiz->get('lesson_id'),
|
| 'passing_percent' => $quiz->get('passing_percent'),
|
| 'time_limit' => $quiz->get('time_limit'),
|
| 'limit_time' => $quiz->has_time_limit(),
|
| 'limit_attempts' => $quiz->has_attempt_limit(),
|
| 'allowed_attempts' => $quiz->get('allowed_attempts'),
|
| 'show_correct_answer' => $quiz->get('show_correct_answer'),
|
| 'random_answers' => $quiz->get('random_answers'),
|
| 'show_results' => $quiz->get('show_results'),
|
| 'questions' => array()
|
| );
|
|
|
|
|
| $questions = $quiz->get_questions();
|
|
|
| if (!empty($questions)) {
|
| $question_count = 0;
|
| foreach ($questions as $question) {
|
|
|
| if ($question_count >= 50) {
|
| break;
|
| }
|
|
|
| $question_data = array(
|
| 'id' => $question->get('id'),
|
| 'title' => $question->get('title'),
|
| 'description' => $question->get('description'),
|
| 'type' => $question->get('question_type'),
|
| 'points' => $question->get('points'),
|
| 'choices_count' => count($question->get_choices())
|
| );
|
|
|
| $quiz_data['questions'][] = $question_data;
|
| $question_count++;
|
|
|
| unset($question, $question_data);
|
| }
|
| }
|
|
|
| $quiz_data['question_count'] = count($quiz_data['questions']);
|
|
|
| return $quiz_data;
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function llms_populate_enrollment_data($course, $sync_post_id) {
|
|
|
| $course_id = $course->get('id');
|
|
|
|
|
| $transient_key = 'llms_enrollment_count_' . $course_id;
|
| $enrollment_count = get_transient($transient_key);
|
|
|
| if (false === $enrollment_count) {
|
|
|
| global $wpdb;
|
| $enrollment_count = $wpdb->get_var($wpdb->prepare("
|
| SELECT COUNT(DISTINCT user_id)
|
| FROM {$wpdb->prefix}lifterlms_user_postmeta
|
| WHERE post_id = %d
|
| AND meta_key = '_status'
|
| AND meta_value = 'enrolled'
|
| ", $course_id));
|
|
|
|
|
| set_transient($transient_key, $enrollment_count, HOUR_IN_SECONDS);
|
| }
|
|
|
| update_post_meta($sync_post_id, '_enrollment_count', $enrollment_count);
|
|
|
|
|
| $completion_transient = 'llms_completion_count_' . $course_id;
|
| $completion_count = get_transient($completion_transient);
|
|
|
| if (false === $completion_count) {
|
| global $wpdb;
|
| $completion_count = $wpdb->get_var($wpdb->prepare("
|
| SELECT COUNT(DISTINCT user_id)
|
| FROM {$wpdb->prefix}lifterlms_user_postmeta
|
| WHERE post_id = %d
|
| AND meta_key = '_is_complete'
|
| AND meta_value = 'yes'
|
| ", $course_id));
|
|
|
| set_transient($completion_transient, $completion_count, HOUR_IN_SECONDS);
|
| }
|
|
|
| update_post_meta($sync_post_id, '_completion_count', $completion_count);
|
|
|
|
|
| if ($enrollment_count > 0) {
|
| $completion_rate = round(($completion_count / $enrollment_count) * 100, 2);
|
| update_post_meta($sync_post_id, '_completion_rate', $completion_rate);
|
| }
|
|
|
|
|
| $is_free = ($course->is_free()) ? 'yes' : 'no';
|
| update_post_meta($sync_post_id, '_is_free_course', $is_free);
|
|
|
|
|
| $access_plans = $course->get_access_plans();
|
| $plan_count = is_array($access_plans) ? count($access_plans) : 0;
|
| update_post_meta($sync_post_id, '_access_plan_count', $plan_count);
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function llms_populate_certificates_achievements($course_id, $sync_post_id) {
|
|
|
|
|
| $certificates = get_posts(array(
|
| 'post_type' => 'llms_certificate',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => '_llms_engagement_trigger_post',
|
| 'value' => $course_id
|
| )
|
| ),
|
| 'fields' => 'ids'
|
| ));
|
|
|
| update_post_meta($sync_post_id, '_certificate_templates', $certificates);
|
| update_post_meta($sync_post_id, '_has_certificate', !empty($certificates) ? 'yes' : 'no');
|
|
|
|
|
| $achievements = get_posts(array(
|
| 'post_type' => 'llms_achievement',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => '_llms_engagement_trigger_post',
|
| 'value' => $course_id
|
| )
|
| ),
|
| 'fields' => 'ids'
|
| ));
|
|
|
| update_post_meta($sync_post_id, '_achievement_templates', $achievements);
|
| update_post_meta($sync_post_id, '_has_achievement', !empty($achievements) ? 'yes' : 'no');
|
|
|
|
|
| $engagements = get_posts(array(
|
| 'post_type' => 'llms_engagement',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => '_llms_engagement_trigger_post',
|
| 'value' => $course_id
|
| )
|
| )
|
| ));
|
|
|
| $engagement_data = array();
|
| foreach ($engagements as $engagement) {
|
| $engagement_data[] = array(
|
| 'id' => $engagement->ID,
|
| 'title' => $engagement->post_title,
|
| 'trigger' => get_post_meta($engagement->ID, '_llms_engagement_trigger_type', true),
|
| 'type' => get_post_meta($engagement->ID, '_llms_engagement_type', true)
|
| );
|
| unset($engagement);
|
| }
|
|
|
| update_post_meta($sync_post_id, '_engagements', $engagement_data);
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function llms_populate_acf_fields($course, $sync_post_id) {
|
|
|
|
|
| if (!function_exists('update_field')) {
|
| return;
|
| }
|
|
|
| $course_id = $course->get('id');
|
|
|
|
|
|
|
|
|
|
|
| update_field('course_difficulty', $course->get('difficulty'), $sync_post_id);
|
| update_field('course_length', $course->get('length'), $sync_post_id);
|
|
|
|
|
| update_field('lesson_count', get_post_meta($sync_post_id, '_lesson_count', true), $sync_post_id);
|
| update_field('section_count', get_post_meta($sync_post_id, '_section_count', true), $sync_post_id);
|
| update_field('quiz_count', get_post_meta($sync_post_id, '_quiz_count', true), $sync_post_id);
|
|
|
|
|
| update_field('enrollment_count', get_post_meta($sync_post_id, '_enrollment_count', true), $sync_post_id);
|
| update_field('completion_count', get_post_meta($sync_post_id, '_completion_count', true), $sync_post_id);
|
| update_field('completion_rate', get_post_meta($sync_post_id, '_completion_rate', true), $sync_post_id);
|
|
|
|
|
| update_field('is_free_course', $course->is_free(), $sync_post_id);
|
| update_field('has_certificate', get_post_meta($sync_post_id, '_has_certificate', true) === 'yes', $sync_post_id);
|
| update_field('has_achievement', get_post_meta($sync_post_id, '_has_achievement', true) === 'yes', $sync_post_id);
|
| update_field('has_prerequisite', $course->has_prerequisite('course'), $sync_post_id);
|
|
|
|
|
| if ($course->has_prerequisite('course')) {
|
| $prereq_id = $course->get('prerequisite');
|
| update_field('prerequisite_course', $prereq_id, $sync_post_id);
|
| }
|
|
|
|
|
| update_field('course_url', get_permalink($course_id), $sync_post_id);
|
|
|
|
|
| update_field('course_content', $course->get('content'), $sync_post_id);
|
|
|
|
|
| $thumbnail_id = get_post_thumbnail_id($course_id);
|
| if ($thumbnail_id) {
|
| update_field('course_featured_image', $thumbnail_id, $sync_post_id);
|
| }
|
|
|
|
|
| $course_structure = get_post_meta($sync_post_id, '_course_structure', true);
|
| if (!empty($course_structure) && is_array($course_structure)) {
|
|
|
| $repeater_data = array();
|
|
|
| foreach ($course_structure as $section) {
|
| $section_row = array(
|
| 'section_title' => $section['title'],
|
| 'section_order' => $section['order'],
|
| 'lesson_count' => count($section['lessons'])
|
| );
|
| $repeater_data[] = $section_row;
|
| }
|
|
|
|
|
| if (count($repeater_data) <= 50) {
|
| update_field('course_sections', $repeater_data, $sync_post_id);
|
| }
|
| }
|
|
|
|
|
| $all_lessons = get_post_meta($sync_post_id, '_all_lessons', true);
|
| if (!empty($all_lessons)) {
|
| update_field('course_lessons_data', $all_lessons, $sync_post_id);
|
| }
|
|
|
|
|
| $categories = wp_get_post_terms($course_id, 'course_cat', array('fields' => 'ids'));
|
| if (!empty($categories)) {
|
| update_field('course_categories', $categories, $sync_post_id);
|
| }
|
|
|
| $tags = wp_get_post_terms($course_id, 'course_tag', array('fields' => 'ids'));
|
| if (!empty($tags)) {
|
| update_field('course_tags', $tags, $sync_post_id);
|
| }
|
|
|
|
|
| update_field('last_sync_date', current_time('Y-m-d H:i:s'), $sync_post_id);
|
| }
|
|
|
|
|
|
|
|
|
|
|
| add_action('lifterlms_course_completed', 'llms_invalidate_sync_cache', 10, 2);
|
| add_action('llms_user_enrolled_in_course', 'llms_invalidate_sync_cache', 10, 2);
|
| add_action('llms_user_removed_from_course', 'llms_invalidate_sync_cache', 10, 2);
|
|
|
| function llms_invalidate_sync_cache($user_id, $course_id) {
|
|
|
| delete_transient('llms_enrollment_count_' . $course_id);
|
| delete_transient('llms_completion_count_' . $course_id);
|
|
|
|
|
|
|
| $synced = get_posts(array(
|
| 'post_type' => 'llms_content_sync',
|
| 'posts_per_page' => 1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => '_source_course_id',
|
| 'value' => $course_id
|
| )
|
| ),
|
| 'fields' => 'ids'
|
| ));
|
|
|
| if (!empty($synced)) {
|
| $sync_post_id = $synced[0];
|
|
|
|
|
| $course = new LLMS_Course($course_id);
|
| llms_populate_enrollment_data($course, $sync_post_id);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function llms_get_synced_post_id($course_id) {
|
| $synced = get_posts(array(
|
| 'post_type' => 'llms_content_sync',
|
| 'posts_per_page' => 1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => '_source_course_id',
|
| 'value' => $course_id
|
| )
|
| ),
|
| 'fields' => 'ids'
|
| ));
|
|
|
| return !empty($synced) ? $synced[0] : 0;
|
| }
|
|
|
|
|
|
|
|
|
| function llms_clear_detail_locks() {
|
| global $wpdb;
|
| $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_llms_detail_lock_%'");
|
| $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_llms_detail_lock_%'");
|
| }
|
| |
| |
Comments