ID, '_wp_page_template', true ); if ( 'academy-canvas.php' === basename( $page_template ) ) { $template = ACADEMY_ROOT_DIR_PATH . 'templates/academy-canvas.php'; } return $template; } } if ( ! function_exists( 'academy_single_course_sidebar' ) ) { function academy_single_course_sidebar() { Helper::get_template( 'single-course/sidebar.php' ); } } if ( ! function_exists( 'academy_single_course_header' ) ) { function academy_single_course_header() { $difficulty_level = get_post_meta( get_the_ID(), 'academy_course_difficulty_level', true ); $preview_video = Helper::get_course_preview_video( get_the_ID() ); Helper::get_template( 'single-course/header.php', apply_filters( 'academy/single_course_header_args', [ 'difficulty_level' => $difficulty_level, 'preview_video' => $preview_video, ] ) ); } } if ( ! function_exists( 'academy_single_course_description' ) ) { function academy_single_course_description() { Helper::get_template( 'single-course/description.php' ); } } if ( ! function_exists( 'academy_single_course_curriculums' ) ) { function academy_single_course_curriculums() { $course_id = get_the_ID(); $curriculums = Helper::get_course_curriculum( $course_id, false ); $topics_first_item_open_status = (bool) Helper::get_settings( 'is_opened_course_single_first_topic', true ); Helper::get_template( 'single-course/curriculums.php', array( 'curriculums' => $curriculums, 'topics_first_item_open_status' => $topics_first_item_open_status, 'course_id' => $course_id, ) ); } }//end if if ( ! function_exists( 'academy_single_course_instructors' ) ) { function academy_single_course_instructors() { global $post; $author_id = $post->post_author; if ( Helper::get_addon_active_status( 'multi_instructor' ) ) { $instructors = Helper::get_instructors_by_course_id( get_the_ID() ); } else { $instructors = Helper::get_instructor_by_author_id( $author_id ); } $instructor_reviews_status = (bool) Helper::get_settings( 'is_enabled_instructor_review', true ); if ( ! $instructors ) { return; } Helper::get_template( 'single-course/instructors.php', apply_filters( 'academy/single_course_content_instructors_args', [ 'instructors' => $instructors, 'instructor_reviews_status' => $instructor_reviews_status, ] ) ); } }//end if if ( ! function_exists( 'academy_single_course_benefits' ) ) { function academy_single_course_benefits() { $benefits = Academy\Helper::string_to_array( get_post_meta( get_the_ID(), 'academy_course_benefits', true ) ); Helper::get_template( 'single-course/benefits.php', apply_filters( 'academy/single_course_content_benefits_args', [ 'benefits' => $benefits ] ) ); } } if ( ! function_exists( 'academy_single_course_additional_info' ) ) { function academy_single_course_additional_info() { $audience = Academy\Helper::string_to_array( get_post_meta( get_the_ID(), 'academy_course_audience', true ) ); $requirements = Academy\Helper::string_to_array( get_post_meta( get_the_ID(), 'academy_course_requirements', true ) ); $materials = Academy\Helper::string_to_array( get_post_meta( get_the_ID(), 'academy_course_materials_included', true ) ); $tabs_nav = []; $tabs_content = []; if ( is_array( $audience ) && count( $audience ) > 0 ) { $tabs_nav['audience'] = esc_html__( 'Targeted Audience', 'academy' ); $tabs_content['audience'] = $audience; } if ( is_array( $requirements ) && count( $requirements ) > 0 ) { $tabs_nav['requirements'] = esc_html__( 'Requirements', 'academy' ); $tabs_content['requirements'] = $requirements; } if ( is_array( $materials ) && count( $materials ) > 0 ) { $tabs_nav['materials'] = esc_html__( 'Materials Included', 'academy' ); $tabs_content['materials'] = $materials; } Helper::get_template( 'single-course/additional-info.php', apply_filters( 'academy/single_course_content_additional_info_args', [ 'tabs_nav' => $tabs_nav, 'tabs_content' => $tabs_content, ] ) ); } }//end if if ( ! function_exists( 'academy_single_course_feedback' ) ) { function academy_single_course_feedback() { $course_id = get_the_ID(); if ( ! (bool) Helper::get_settings( 'is_enabled_course_review', true ) || (bool) get_post_meta( $course_id, 'academy_is_disabled_course_review', true ) ) { return; } $rating = Helper::get_course_rating( $course_id ); Helper::get_template( 'single-course/feedback.php', array( 'rating' => $rating ) ); } } if ( ! function_exists( 'academy_single_course_reviews' ) ) { function academy_single_course_reviews() { if ( comments_open() || get_comments_number() ) { comments_template(); } } } if ( ! function_exists( 'academy_archive_course_header' ) ) { function academy_archive_course_header() { Helper::get_template( 'archive/header.php' ); } } if ( ! function_exists( 'academy_archive_course_header_filter' ) ) { function academy_archive_course_header_filter() { global $wp_query; // Not get_query_var( 'orderby' ): pre_get_posts rewrites the main // query's orderby into a compound array (sticky courses first, then // the chosen field) before this renders, and passing that array into // selected() below throws "Array to string conversion" once per // option. The dropdown's own GET param still holds the plain value // the visitor picked. // A visitor who hasn't picked anything is still seeing the site's // configured default order (pre_get_posts applies it either way) — so // without a ?orderby= fall back to that setting for what shows // selected, or the dropdown always read "Default Sorting" even when // the site was actually sorted by name, date, etc. $orderby = ! empty( $_GET['orderby'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only archive sort param. ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended : Helper::get_settings( 'course_archive_courses_order', 'DESC' ); ?>

found_posts ); ?>

get_row( $wpdb->prepare( "SELECT * from {$wpdb->usermeta} WHERE user_id = %d AND meta_key = 'academy_course_wishlist' AND meta_value = %d;", $user_id, $course_id ) ); } Helper::get_template( 'loop/header.php', array( 'is_already_in_wishlist' => $is_already_in_wishlist, 'wishlists_status' => $wishlists_status ) ); } } if ( ! function_exists( 'academy_course_loop_content' ) ) { function academy_course_loop_content() { $card_style = \Academy\Helper::get_settings( 'course_card_style' ); switch ( $card_style ) { case 'layout_two': Helper::get_template( 'loop/content-layout-two.php' ); break; case 'layout_three': Helper::get_template( 'loop/content-layout-three.php' ); break; case 'layout_four': Helper::get_template( 'loop/content-layout-four.php' ); break; default: Helper::get_template( 'loop/content.php' ); break; } } } if ( ! function_exists( 'academy_course_loop_footer' ) ) { function academy_course_loop_footer() { Helper::get_template( 'loop/footer.php' ); } } if ( ! function_exists( 'academy_course_loop_rating' ) ) { function academy_course_loop_rating( $card_style ) { $rating = Helper::get_course_rating( get_the_ID() ); $reviews_status = Helper::get_settings( 'is_enabled_course_review', true ); if ( $reviews_status && 'default' === $card_style ) { Helper::get_template( 'loop/rating.php', [ 'rating' => $rating ] ); } } } if ( ! function_exists( 'academy_course_loop_enroll' ) ) { function academy_course_loop_enroll() { Helper::get_template( 'loop/enroll.php' ); } } if ( ! function_exists( 'academy_course_loop_footer_inner_price' ) ) { function academy_course_loop_footer_inner_price( $card_style ) { $course_id = get_the_ID(); if ( 'layout_two' !== $card_style && 'alms_course_bundle' !== get_post( $course_id )->post_type ) { $course_type = Helper::get_course_type( $course_id ); $is_paid = Helper::is_course_purchasable( $course_id ); $price = ''; if ( Helper::is_active_woocommerce() && $is_paid ) { $product_id = Academy\Helper::get_course_product_id( $course_id ); if ( $product_id ) { $product = wc_get_product( $product_id ); if ( $product ) { $price = $product->get_price_html(); } } } if ( $is_paid && empty( $price ) && 'storeengine' === Academy\Helper::monetization_engine() ) { $price = Academy\Helper::get_storeengine_price_html( $course_id, 'storeengine/academylms' ); } // No WooCommerce/StoreEngine product price found — fall back to // the plain `academy_course_price` meta the course builder writes // directly in that case, so a paid course still shows an // actual amount instead of just the generic "Paid" text. if ( $is_paid && empty( $price ) ) { $price = Academy\Helper::get_plain_course_price_html( $course_id ); } Helper::get_template( 'loop/price.php', apply_filters('academy/template/loop/price_args', array( 'price' => $price, 'is_paid' => $is_paid, 'course_type' => $course_type, ), $course_id ) ); }//end if } }//end if if ( ! function_exists( 'academy_course_loop_footer_form' ) ) { function academy_course_loop_footer_form( $card_style ) { $course_id = get_the_ID(); $post_type = get_post_type( $course_id ); if ( 'default' !== $card_style && 'alms_course_bundle' !== $post_type ) { $course_type = Helper::get_course_type( $course_id ); $is_paid = Helper::is_course_purchasable( $course_id ); $monetization_engine = \Academy\Helper::monetization_engine(); $product_id = 0; $download_id = 0; if ( $is_paid ) { $product_id = Academy\Helper::get_course_product_id( $course_id ); $download_id = get_post_meta( $course_id, 'academy_course_download_id', true ); } if ( 'paid-memberships-pro' === $monetization_engine ) { $required_levels = AcademyProPaidMembershipsPro\Helper::has_course_access( $course_id ); if ( is_array( $required_levels ) && count( $required_levels ) ) { $pmp_levels = $required_levels; } } Helper::get_template( 'loop/footer-form.php', apply_filters('academy/template/loop/footer_form', array( 'is_paid' => $is_paid, 'course_type' => $course_type, 'product_id' => $product_id, 'download_id' => $download_id, 'required_levels' => $pmp_levels ?? '', 'engine' => $monetization_engine, ), $course_id ) ); }//end if } }//end if if ( ! function_exists( 'academy_review_lists' ) ) { function academy_review_lists( $comment, $args, $depth ) { Helper::get_template( 'single-course/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth, ) ); } } if ( ! function_exists( 'academy_review_display_gravatar' ) ) { /** * Display the review authors gravatar * * @param array $comment WP_Comment. * @return void */ function academy_review_display_gravatar( $comment ) { echo get_avatar( $comment->comment_author_email, apply_filters( 'academy/review_gravatar_size', '80' ), '' ); } } if ( ! function_exists( 'academy_review_display_rating' ) ) { /** * Display the reviewers star rating * * @return void */ function academy_review_display_rating() { if ( post_type_supports( 'academy_courses', 'comments' ) ) { $reviews_status = (bool) Helper::get_settings( 'is_enabled_course_review', true ); if ( $reviews_status ) { Helper::get_template( 'single-course/review-rating.php' ); } } } } if ( ! function_exists( 'academy_review_rating_edit_icon' ) ) { /** * Display the reviewers star rating * * @param mixed $comment * * @return void */ function academy_review_rating_edit_icon( $comment ) { if ( post_type_supports( 'academy_courses', 'comments' ) ) { $rating = intval( get_comment_meta( $comment->comment_ID, 'academy_rating', true ) ); if ( \Academy\Helper::get_settings( 'is_enable_course_review_edit', false ) && get_current_user_id() === (int) $comment->user_id ) { ?> '; comment_text(); echo ''; } } if ( ! function_exists( 'academy_review_display_comment_text_update_form' ) ) { function academy_review_display_comment_text_update_form( $comment ) { $edit_permission = \Academy\Helper::get_settings( 'is_enable_course_review_edit', false ); $rating = intval( get_comment_meta( $comment->comment_ID, 'academy_rating', true ) ); ob_start(); if ( $edit_permission && get_current_user_id() === (int) $comment->user_id ) : ?> post_type ) ) { return $required; } if ( 'academy_courses' !== $post->post_type ) { return $required; } $user_id = get_current_user_id(); // If enrolled → bypass password completely if ( $user_id && \Academy\Helper::is_enrolled( $post->ID, $user_id ) ) { return false; } // Only store transient when password is actually required if ( $required ) { set_transient( 'academy_course_password_post_id_' . $user_id, (int) $post->ID, 2 * MINUTE_IN_SECONDS ); } return $required; } }//end if if ( ! function_exists( 'handle_academy_course_password_submit' ) ) { function handle_academy_course_password_submit() { $user_id = get_current_user_id(); $post_id = (int) get_transient( 'academy_course_password_post_id_' . $user_id ); if ( ! $post_id ) { return; } if ( post_password_required( $post_id ) ) { delete_transient( 'academy_course_password_post_id_' . $user_id ); set_transient( 'academy_course_password_error_' . $user_id, esc_html__( 'Invalid password', 'academy' ), 1 * MINUTE_IN_SECONDS ); } } }//end if if ( ! function_exists( 'academy_single_course_enroll_content' ) ) { function academy_single_course_enroll_content() { $course_id = get_the_ID(); $is_public = Helper::is_public_course( $course_id ); $duration = Helper::get_course_duration( $course_id ); $total_lessons = Helper::get_total_number_of_course_lesson( $course_id ); $total_resource = Helper::get_total_number_of_course_lesson_resource( $course_id ); $total_enroll_count_status = Helper::get_settings( 'is_enabled_course_single_enroll_count', true ); $total_enrolled = Helper::count_course_enrolled( $course_id ); $skill = Helper::get_course_difficulty_level( $course_id ); $language = get_post_meta( $course_id, 'academy_course_language', true ); $max_students = (int) get_post_meta( $course_id, 'academy_course_max_students', true ); $last_update = get_the_modified_time( get_option( 'date_format' ), $course_id ); $course_expired_date = \Academy\Helper::get_settings( 'is_expire_course_enrollment', false ) ? \Academy\Helper::get_course_expire_duration( $course_id ) : 0; ob_start(); Helper::get_template( 'single-course/enroll/content.php', apply_filters( 'academy/single/course_content_args', array( 'duration' => $duration, 'total_lessons' => $total_lessons, 'total_enroll_count_status' => $total_enroll_count_status, 'total_enrolled' => $total_enrolled, 'total_resource' => $total_resource, 'skill' => $skill, 'language' => $language, 'max_students' => $max_students, 'last_update' => $last_update, 'course_expired_date' => $course_expired_date, 'course_id' => $course_id, ), $course_id ) ); $output = ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo apply_filters( 'academy/templates/single_course/enroll_content_args', $output, $course_id ); } }//end if if ( ! function_exists( 'academy_course_pricing_type' ) ) { function academy_course_pricing_type( $course_id = null ) { $course_id = intval( ! empty( $course_id ) ? $course_id : get_the_ID() ); $is_public = Helper::is_public_course( $course_id ); $enrolled = Helper::is_enrolled( $course_id, get_current_user_id() ); $is_paid = (bool) Helper::is_course_purchasable( $course_id ); $price = ''; $monetization = Helper::get_settings( 'monetization_engine', 'woocommerce' ); if ( $is_paid && ( Helper::is_active_woocommerce() || Helper::is_active_easy_digital_downloads() ) ) { if ( 'woocommerce' === $monetization ) { $product_id = Academy\Helper::get_course_product_id( $course_id ); if ( $product_id ) { $product = wc_get_product( $product_id ); if ( $product ) { $price = $product->get_price_html(); } } } if ( 'edd' === $monetization ) { $download_id = Academy\Helper::get_course_download_id( $course_id ); if ( $download_id ) { $download = edd_get_download( $download_id ); if ( $download ) { $price = edd_price( $download_id, false ); } } } } // No WooCommerce/EDD product price found (StoreEngine, or no engine // configured at all) — fall back to the plain `academy_course_price` // meta the course builder writes directly in that case, so a paid // course still shows an actual amount instead of just "Paid". if ( $is_paid && empty( $price ) ) { $price = Academy\Helper::get_plain_course_price_html( $course_id ); } ob_start(); Helper::get_template( 'single-course/enroll/pricing.php', apply_filters( 'academy/single/enroll_content_args', array( 'enrolled' => $enrolled, 'is_paid' => $is_paid, 'is_public' => $is_public, 'price' => $price, ), $course_id ) ); $output = ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo apply_filters( 'academy/templates/single_course/enroll_content', $output, $course_id ); } }//end if if ( ! function_exists( 'academy_course_enroll_form' ) ) { function academy_course_enroll_form( $course_id = null ) { global $post; $original_post = $post; if ( $course_id ) { // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $GLOBALS['post'] = get_post( $course_id ); } $user_ID = get_current_user_id(); $enrolled = Helper::is_enrolled( get_the_ID(), get_current_user_id(), 'any' ); // Course Materials Access $is_administrator = current_user_can( 'manage_options' ); $is_instructor = Helper::is_instructor_of_this_course( $user_ID, get_the_ID() ); $is_public_course = Helper::is_public_course( get_the_ID() ); ob_start(); // is private course if ( ( $enrolled && 'completed' === $enrolled->enrolled_status ) || $is_administrator || $is_instructor || $is_public_course ) { $completed = Helper::is_completed_course( get_the_ID(), $user_ID, true ); Helper::get_template( 'single-course/enroll/continue.php', [ 'enrolled' => $enrolled, 'completed' => $completed ] ); } // is public course if ( ! $is_public_course ) { if ( 'private' === get_post_status( $course_id ) && ! current_user_can( 'manage_academy_instructor' ) && ! $enrolled ) { Helper::get_template( 'single-course/enroll/private-course.php' ); } elseif ( $enrolled && 'completed' === $enrolled->enrolled_status ) { $is_completed_course = Helper::is_completed_course( get_the_ID(), $user_ID ); $is_show_complete_form = apply_filters( 'academy/single/is_show_complete_form', true, $is_completed_course, get_the_ID() ); if ( $is_show_complete_form ) { Helper::get_template( 'single-course/enroll/complete-form.php', array( 'is_completed_course' => $is_completed_course ) ); } } elseif ( $enrolled && ( 'on-hold' === $enrolled->enrolled_status || 'processing' === $enrolled->enrolled_status ) ) { Helper::get_template( 'single-course/enroll/notice.php', array( 'status' => $enrolled->enrolled_status ) ); } elseif ( Helper::is_course_fully_booked( get_the_ID() ) ) { Helper::get_template( 'single-course/enroll/closed-enrollment.php' ); } elseif ( 'woocommerce' === Helper::monetization_engine() && Helper::is_course_purchasable( get_the_ID() ) ) { $product_id = Academy\Helper::get_course_product_id( get_the_ID() ); $is_enabled_academy_login = Helper::get_settings( 'is_enabled_academy_login', true ); $force_login_before_enroll = $is_enabled_academy_login && Helper::get_settings( 'woo_force_login_before_enroll', true ); Helper::get_template( 'single-course/enroll/add-to-cart-form.php', array( 'product_id' => $product_id, 'force_login_before_enroll' => $force_login_before_enroll ) ); } elseif ( 'edd' === Helper::monetization_engine() && Helper::is_course_purchasable( get_the_ID() ) ) { $download_id = Academy\Helper::get_course_download_id( get_the_ID() ); $is_enabled_academy_login = Helper::get_settings( 'is_enabled_academy_login', true ); $force_login_before_enroll = $is_enabled_academy_login && Helper::get_settings( 'woo_force_login_before_enroll', true ); Helper::get_template( 'single-course/enroll/add-to-cart-form.php', array( 'download_id' => $download_id, 'force_login_before_enroll' => $force_login_before_enroll ) ); } elseif ( 'storeengine' === Helper::monetization_engine() && Helper::is_course_purchasable( get_the_ID() ) ) {// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElseif // phpcs:ignore PSR2.ControlStructures.ElseIfDeclaration.NotAllowed } else { $is_enabled_academy_login = Helper::get_settings( 'is_enabled_academy_login', true ); Helper::get_template( 'single-course/enroll/enroll-form.php', array( 'is_enabled_academy_login' => $is_enabled_academy_login ) ); }//end if }//end if $output = ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo apply_filters( 'academy/templates/single_course/enroll_form', $output, get_the_ID() ); if ( $course_id ) { // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $GLOBALS['post'] = $original_post; } } }//end if if ( ! function_exists( 'academy_course_enroll_wishlist_and_share' ) ) { function academy_course_enroll_wishlist_and_share() { global $wpdb; $course_id = get_the_ID(); $user_id = get_current_user_id(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $is_already_in_wishlist = $wpdb->get_row( $wpdb->prepare( "SELECT * from {$wpdb->usermeta} WHERE user_id = %d AND meta_key = 'academy_course_wishlist' AND meta_value = %d;", $user_id, $course_id ) ); $is_show_wishlist = (bool) Helper::get_settings( 'is_enabled_course_wishlist', true ); $is_show_course_share = (bool) Helper::get_settings( 'is_enabled_course_share', true ); if ( $is_show_wishlist || $is_show_course_share ) { Helper::get_template( 'single-course/enroll/wishlist-and-share.php', apply_filters( 'academy/single/course_enroll_wishlist_and_share_args', [ 'is_already_in_wishlist' => $is_already_in_wishlist, 'is_show_wishlist' => $is_show_wishlist, 'is_show_course_share' => $is_show_course_share, ] ) ); } } }//end if if ( ! function_exists( 'academy_archive_course_filter_widget' ) ) { function academy_archive_course_filter_widget() { $filters = Helper::get_settings( 'course_archive_filters', [ [ 'search' => true, ], [ 'category' => true, ], [ 'tags' => true, ], [ 'levels' => true, ], [ 'type' => true, ], ] ); // make it single array $filters = array_reduce($filters, function ( $carry, $item ) { return array_merge( $carry, (array) $item ); }, []); $filters = apply_filters( 'academy/archive/course_filter_widget_args', $filters ); foreach ( $filters as $key => $value ) { $filter_function = 'academy_archive_course_filter_by_' . $key; if ( $value && function_exists( $filter_function ) ) { $filter_function(); } } } }//end if if ( ! function_exists( 'academy_archive_course_filter_by_search' ) ) { function academy_archive_course_filter_by_search() { Helper::get_template( 'archive/widgets/search.php', apply_filters( 'academy/archive/course_filter_by_search_args', [] ) ); } } if ( ! function_exists( 'academy_archive_course_filter_by_category' ) ) { function academy_archive_course_filter_by_category() { $categories = Academy\Helper::get_all_courses_category_lists(); $use_dropdown = (bool) Helper::get_settings( 'course_archive_category_filter_dropdown', false ); Helper::get_template( $use_dropdown ? 'archive/widgets/category-dropdown.php' : 'archive/widgets/category.php', apply_filters( 'academy/archive/course_filter_by_category_args', [ 'categories' => $categories, ] ) ); } } if ( ! function_exists( 'academy_archive_course_filter_by_tags' ) ) { function academy_archive_course_filter_by_tags() { $tags = get_terms( array( 'taxonomy' => 'academy_courses_tag', 'hide_empty' => true, ) ); Helper::get_template( 'archive/widgets/tags.php', apply_filters( 'academy/archive/course_filter_by_tags_args', [ 'tags' => $tags, ] ) ); } }//end if if ( ! function_exists( 'academy_archive_course_filter_by_levels' ) ) { function academy_archive_course_filter_by_levels() { $levels = array( 'all_levels' => __( 'All Levels', 'academy' ), 'beginner' => __( 'Beginner', 'academy' ), 'intermediate' => __( 'Intermediate', 'academy' ), 'experts' => __( 'Expert', 'academy' ), ); Helper::get_template( 'archive/widgets/levels.php', apply_filters( 'academy/archive/course_filter_by_levels_args', [ 'levels' => $levels, ] ) ); } }//end if if ( ! function_exists( 'academy_archive_course_filter_by_type' ) ) { function academy_archive_course_filter_by_type() { $type = apply_filters('academy/get_course_filter_types', array( 'free' => __( 'Free', 'academy' ), 'paid' => __( 'Paid', 'academy' ), )); Helper::get_template( 'archive/widgets/type.php', apply_filters( 'academy/archive/course_filter_by_type_args', [ 'type' => $type, ] ) ); } } if ( ! function_exists( 'academy_archive_course_sidebar' ) ) { function academy_archive_course_sidebar() { Helper::get_template( 'archive/sidebar.php' ); } } if ( ! function_exists( 'academy_instructor_public_profile_sidebar' ) ) { function academy_instructor_public_profile_sidebar() { $author_ID = Academy\Helper::get_the_author_id(); $reviews = Helper::get_instructor_ratings( $author_ID ); $website_url = get_user_meta( $author_ID, 'academy_website_url', true ); $facebook_url = get_user_meta( $author_ID, 'academy_facebook_url', true ); $github_url = get_user_meta( $author_ID, 'academy_github_url', true ); $twitter_url = get_user_meta( $author_ID, 'academy_twitter_url', true ); $linkdin_url = get_user_meta( $author_ID, 'academy_linkedin_url', true ); $is_enabled_instructor_review = Helper::get_settings( 'is_enabled_instructor_review', true ); Helper::get_template( 'instructor/sidebar.php', apply_filters( 'academy/instructor/instructor_public_profile_sidebar_args', [ 'author_ID' => $author_ID, 'reviews' => $reviews, 'website_url' => $website_url, 'facebook_url' => $facebook_url, 'github_url' => $github_url, 'twitter_url' => $twitter_url, 'linkdin_url' => $linkdin_url, 'is_enabled_instructor_review' => $is_enabled_instructor_review, ] ) ); } }//end if if ( ! function_exists( 'academy_global_courses' ) ) { function academy_global_courses() { Helper::get_template( 'global/courses.php' ); } } if ( ! function_exists( 'academy_instructor_public_profile_header' ) ) { function academy_instructor_public_profile_header() { $author_ID = Academy\Helper::get_the_author_id(); $cover_photo_url = get_the_author_meta( 'academy_cover_photo', $author_ID ); if ( empty( $cover_photo_url ) ) { $cover_photo_url = apply_filters( 'academy/instructor/public_profile_placeholder_cover_photo_url', ACADEMY_ASSETS_URI . 'images/banner.jpg' ); } $share_config = array( 'title' => Academy\Helper::get_the_author_name( $author_ID ), 'text' => get_the_author_meta( 'academy_profile_designation', $author_ID ), 'image' => esc_url( Academy\Helper::get_the_author_thumbnail_url( $author_ID ) ), ); Helper::get_template( 'instructor/header.php', apply_filters( 'academy/instructor/public_profile_header_args', [ 'cover_photo_url' => $cover_photo_url, 'share_config' => $share_config, ] ) ); } }//end if if ( ! function_exists( 'academy_instructor_public_profile_tabs_nav' ) ) { function academy_instructor_public_profile_tabs_nav() { $is_enabled_instructor_review = (bool) Helper::get_settings( 'is_enabled_instructor_review', true ); Helper::get_template( 'instructor/tab-navbar.php', apply_filters( 'academy/instructor/public_profile_tabs_nav_args', [ 'is_enabled_instructor_review' => $is_enabled_instructor_review ] ) ); } } if ( ! function_exists( 'academy_instructor_public_profile_tabs_content' ) ) { function academy_instructor_public_profile_tabs_content() { $is_enabled_instructor_review = (bool) Helper::get_settings( 'is_enabled_instructor_review', true ); Helper::get_template( 'instructor/tab-content.php', apply_filters( 'academy/instructor/public_profile_tabs_content_args', [ 'is_enabled_instructor_review' => $is_enabled_instructor_review ] ) ); } } if ( ! function_exists( 'academy_instructor_public_profile_reviews' ) ) { function academy_instructor_public_profile_reviews() { $author_ID = get_query_var( 'author' ); $reviews = Helper::get_reviews_by_instructor( $author_ID ); $results = []; if ( is_array( $reviews ) ) { foreach ( $reviews as $review ) { $review->post_title = get_the_title( $review->comment_post_ID ); $review->post_permalink = esc_url( get_the_permalink( $review->comment_post_ID ) ); $results[] = $review; } } Helper::get_template( 'instructor/reviews.php', apply_filters( 'academy/instructor/public_profile_reviews_args', [ 'reviews' => $results ] ) ); } }//end if if ( ! function_exists( 'academy_update_avatar_url' ) ) { function academy_update_avatar_url( $url, $user ) { if ( is_object( $user ) ) { $profile_photo = get_user_meta( $user->ID, 'academy_profile_photo', true ); if ( ! empty( $profile_photo ) ) { return esc_url( $profile_photo ); } } return $url; } } if ( ! function_exists( 'academy_update_avatar_data' ) ) { function academy_update_avatar_data( $args, $user_id ) { if ( $user_id ) { $profile_photo = get_user_meta( $user_id, 'academy_profile_photo', true ); if ( ! empty( $profile_photo ) ) { $args['url'] = esc_url( $profile_photo ); return $args; } } return $args; } } if ( ! function_exists( 'academy_get_the_canvas_container_class' ) ) { function academy_get_the_canvas_container_class() { global $post; $class_name = apply_filters( 'academy/templates/canvas_container_class', 'academy-container', $post->ID ); echo esc_attr( $class_name ); } } if ( ! function_exists( 'academy_frontend_dashbaord_container_class' ) ) { function academy_frontend_dashbaord_container_class( $class_name, $page_id ) { if ( current_user_can( 'manage_academy_instructor' ) && (int) Helper::get_settings( 'frontend_dashboard_page' ) === $page_id ) { return $class_name . '-fluid'; } return $class_name; } } if ( ! function_exists( 'academy_get_preloader_html' ) ) { function academy_get_preloader_html() { ob_start(); ?>
=' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) { ?> > >
=' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) { if ( apply_filters( 'academy/templates/is_allow_block_theme_footer', true ) ) : ?>
meta = $lesson_meta; do_action( 'academy/templates/curriculums/before_render_lesson_content', $lesson, $course_id, $topic_id ); $has_permission = \Academy\Helper::has_permission_to_access_lesson_curriculum( $course_id, $lesson ? $lesson->ID : null, get_current_user_id() ); if ( ! apply_filters( 'academy/templates/curriculums/has_access_lesson_content', $has_permission ) ) { return; } // The next-lesson URL feeds the player's auto-load-next behaviour, so it // has to be resolved whenever that setting is on. $next_topic_play_url = ''; if ( \Academy\Helper::is_auto_load_next_lesson() ) { $curriculums = \Academy\Helper::get_course_curriculum_array( $course_id ); if ( ! empty( $curriculums ) ) { $next_topic = \Academy\Helper::get_next_topic( $curriculums, $lesson->ID, 'lesson' ); if ( ! empty( $next_topic['id'] ) ) { $lesson_data = \Academy\Helper::get_lesson( $next_topic['id'] ); $next_topic['slug'] = $lesson_data->lesson_name ?? ''; $next_topic_play_url = \Academy\Helper::get_topic_play_link( $next_topic ) ?? ''; } } } if ( $lesson ) { \Academy\Helper::get_template( 'curriculums/lesson.php', array( 'lesson' => $lesson, 'lesson_meta' => $lesson_meta, 'course_id' => $course_id, 'next_topic_play_url' => $next_topic_play_url, ) ); } else { \Academy\Helper::get_template( 'curriculums/not-found.php' ); } do_action( 'academy/templates/curriculums/after_render_lesson_content', $lesson, $course_id, $topic_id ); } }//end if if ( ! function_exists( 'academy_curriculum_previous_next_template' ) ) { function academy_curriculum_previous_next_template() { $result = \Academy\Helper::get_prev_and_next_details_of_curriculum(); $course_id = \Academy\Helper::get_the_current_course_id(); $current_type = get_query_var( 'curriculum_type' ); $current_slug = get_query_var( 'name' ); $current_id = \Academy\Helper::get_topic_id_by_topic_name_and_topic_type( $current_slug, $current_type ); \Academy\Helper::get_template( 'curriculums/prev-next-btn.php', array( 'previous' => $result['previous'], 'next' => $result['next'], 'course_id' => $course_id, 'current_type' => $current_type, 'current_id' => $current_id, ) ); } } function academy_frontend_dashboard_content() { global $wp; if ( ! empty( $wp->query_vars ) ) { foreach ( $wp->query_vars as $key => $value ) { // Ignore pagename param. if ( 'pagename' === $key || 'academy_dashboard_page' !== $key ) { continue; } if ( has_action( 'academy_frontend_dashboard_' . $value . '_endpoint' ) ) { do_action( 'academy_frontend_dashboard_' . $value . '_endpoint', $value ); return; } } } // No endpoint found? Default to dashboard. $home = academy_frontend_dashboard_home_data(); \Academy\Helper::get_template( 'frontend-dashboard/pages/dashboard.php', [ 'data' => $home['data'], 'course_ids' => $home['course_ids'], 'is_teaching' => $home['is_teaching'], 'view' => $home['view'], ] ); } /** * What the dashboard's home page shows for the current person and view: its * number cards, and the instructor's courses when teaching. * * @return array data, course_ids, is_teaching, view. */ function academy_frontend_dashboard_home_data() { // Several dashboard blocks read it on one page. static $home = null; if ( null !== $home ) { return $home; } $user_id = get_current_user_id(); $total_course = \Academy\Helper::get_course_ids_by_instructor_id( $user_id ); // The landing answers the question the current view is asking. It used to // answer all of them at once — a learner's two cards with an instructor's // six appended, in one undifferentiated grid. $academy_view = \Academy\Helper::current_dashboard_view(); $is_teaching = 'teaching' === $academy_view && current_user_can( 'manage_academy_instructor' ); $data = [ 'enrolled_course' => [ 'label' => esc_html__( 'Enrolled Courses', 'academy' ), 'value' => count( \Academy\Helper::get_enrolled_courses_ids_by_user( $user_id ) ), 'color' => 'course', 'icon' => 'academy-icon academy-icon--course-enrolled-two', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'enrolled-courses' ) ) ], 'completed_course' => [ 'label' => esc_html__( 'Completed Courses', 'academy' ), 'value' => count( \Academy\Helper::get_completed_courses_ids_by_user( $user_id ) ), 'color' => 'complete', 'icon' => 'academy-icon academy-icon--certificate', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'complete-courses' ) ) ] ]; // Family answers about the children, not about the guardian's own courses — // a parent who never enrolls in anything was being shown two zeroes. if ( 'family' === $academy_view && class_exists( '\Academy\Guardian\Store' ) ) { $children = (array) \Academy\Guardian\Store::get_children( $user_id ); $enrolled = 0; $finished = 0; foreach ( $children as $child_id ) { $courses = (array) \Academy\Guardian\Store::child_courses( $child_id ); $enrolled += count( $courses ); $finished += count( array_filter( $courses, function ( $course ) { return ! empty( $course['is_completed'] ); } ) ); } $family_link = esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'guardian' ) ); $data = [ 'children' => [ 'label' => esc_html__( 'Children', 'academy' ), 'value' => count( $children ), 'color' => 'instructor', 'icon' => 'academy-icon academy-icon--students-two', 'link' => $family_link, ], 'children_courses' => [ 'label' => esc_html__( 'Their Courses', 'academy' ), 'value' => $enrolled, 'color' => 'course', 'icon' => 'academy-icon academy-icon--course-enrolled-two', 'link' => $family_link, ], 'children_completed' => [ 'label' => esc_html__( 'Completed', 'academy' ), 'value' => $finished, 'color' => 'complete', 'icon' => 'academy-icon academy-icon--certificate', 'link' => $family_link, ], ]; }//end if if ( $is_teaching ) { // Teaching stands on its own numbers, not on top of the learner ones. $data = []; $data['total_students'] = [ 'label' => esc_html__( 'Total Students', 'academy' ), 'value' => \Academy\Helper::get_total_number_of_students_by_instructor( $user_id ), 'color' => 'instructor', 'icon' => 'academy-icon academy-icon--students-two', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'students' ) ) ]; $data['total_courses'] = [ 'label' => esc_html__( 'Total Courses', 'academy' ), 'value' => is_array( $total_course ) ? count( $total_course ) : 0, 'color' => 'students', 'icon' => 'academy-icon academy-icon--total-course', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'courses' ) ) ]; $data['total_lessons'] = [ 'label' => esc_html__( 'Total Lessons', 'academy' ), 'value' => \Academy\Helper::get_total_number_of_lessons_by_instructor( $user_id ), 'color' => 'lesson', 'icon' => 'academy-icon academy-icon--lessons', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'lessons' ) ) ]; $data['total_questions'] = [ 'label' => esc_html__( 'Total Questions', 'academy' ), 'value' => \Academy\Classes\Query::get_total_number_of_questions_by_instructor_id( $user_id ), 'color' => 'question', 'icon' => 'academy-icon academy-icon--questions-fill', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'question-answer' ) ) ]; }//end if if ( \Academy\Helper::get_addon_active_status( 'quizzes' ) && $is_teaching ) { $data['total_quizzes'] = array( 'label' => esc_html__( 'Total Quizzes', 'academy' ), 'value' => \AcademyQuizzes\Classes\Query::get_total_number_of_quizzes_by_instructor_id( $user_id ), 'color' => 'quiz', 'icon' => 'academy-icon academy-icon--quiz-fill', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'quizzes' ) ) ); } if ( \Academy\Helper::get_addon_active_status( 'assignments', true ) && $is_teaching ) { $data['total_assignments'] = array( 'label' => esc_html__( 'Total Assignments', 'academy' ), 'value' => \AcademyProAssignments\Classes\Query::get_total_number_of_assignments_by_instructor_id( $user_id ), 'color' => 'assignment', 'icon' => 'academy-icon academy-icon--assignment-two', 'link' => esc_url( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'assignments' ) ) ); } /** * The home page's cards, key => [ label, value, color, icon, link ]. * * @param array $data Cards. * @param string $view learning|teaching|family. */ $data = apply_filters( 'academy/frontend_dashboard/home_cards', $data, $academy_view ); $home = [ 'data' => $data, 'course_ids' => $total_course, 'is_teaching' => $is_teaching, 'view' => $academy_view, ]; return $home; } function academy_frontend_dashboard_menu() { // Standing on a page from another area moves the sidebar with you, so the // menu always contains the page being looked at. $page = (string) get_query_var( 'academy_dashboard_page' ); if ( $page ) { $area = \Academy\Helper::dashboard_area_of( $page ); if ( $area ) { \Academy\Helper::set_dashboard_view( $area ); } } $menu_lists = \Academy\Helper::get_frontend_dashboard_menu_items(); $menu_lists = array_filter( $menu_lists, array( '\Academy\Helper', 'dashboard_item_in_view' ) ); // A parent can span areas while its children don't — Campus is a family's // record in one view and a teacher's working area in another. The full set // stays registered so every child keeps its rewrite rule; only the display // is narrowed. foreach ( $menu_lists as $key => $item ) { if ( empty( $item['child_items'] ) ) { continue; } $menu_lists[ $key ]['child_items'] = array_filter( $item['child_items'], array( '\Academy\Helper', 'dashboard_item_in_view' ) ); } uasort($menu_lists, function ( $a, $b ) { return $a['priority'] <=> $b['priority']; }); \Academy\Helper::get_template( 'frontend-dashboard/menu.php', array( 'menu_lists' => $menu_lists ) ); } function academy_frontend_dashboard_content_topbar() { $path = get_query_var( 'academy_dashboard_page' ); $sub_path = get_query_var( 'academy_dashboard_sub_page' ); $page_title = \Academy\Helper::get_frontend_dashboard_page_title( $path ? $path : 'index', $sub_path ); \Academy\Helper::get_template( 'frontend-dashboard/topbar.php', [ 'page_title' => $page_title ] ); } function academy_frontend_dashboard_become_an_instructor_page() { $instructor_status = get_user_meta( get_current_user_id(), 'academy_instructor_status', true ); if ( ! current_user_can( 'manage_academy_instructor' ) ) { \Academy\Helper::get_template( 'frontend-dashboard/pages/become-an-instructor.php', [ 'instructor_status' => $instructor_status, ] ); } } function academy_frontend_dashboard_profile_page() { $user_id = get_current_user_id(); $user_info = get_userdata( $user_id ); $user_role = in_array( 'academy_student', (array) $user_info->roles, true ) ? 'student' : 'instructor'; $user_fields = \Academy\Helper::get_form_builder_fields( $user_role ); $user_meta = \Academy\Helper::prepare_user_meta_data( $user_fields, $user_id ); $user_data = [ 'registration_date' => [ 'label' => esc_html__( 'Registration Date', 'academy' ), 'value' => get_date_from_gmt( $user_info->user_registered, get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) ], 'first_name' => [ 'label' => esc_html__( 'First Name', 'academy' ), 'value' => get_user_meta( $user_id, 'first_name', true ) ], 'last_name' => [ 'label' => esc_html__( 'Last Name', 'academy' ), 'value' => get_user_meta( $user_id, 'last_name', true ) ], 'nicename' => [ 'label' => esc_html__( 'User Name', 'academy' ), 'value' => $user_info->data->user_nicename ], 'email' => [ 'label' => esc_html__( 'Email', 'academy' ), 'value' => $user_info->data->user_email ], 'designation' => [ 'label' => esc_html__( 'Designation', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_profile_designation', true ) ], 'phone_number' => [ 'label' => esc_html__( 'Phone Number', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_phone_number', true ) ], 'bio' => [ 'label' => esc_html__( 'Bio', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_profile_bio', true ) ], 'website_url' => [ 'label' => esc_html__( 'Website URL', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_website_url', true ) ], 'github_url' => [ 'label' => esc_html__( 'Github URL', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_github_url', true ) ], 'facebook_url' => [ 'label' => esc_html__( 'Facebook URL', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_facebook_url', true ) ], 'twitter_url' => [ 'label' => esc_html__( 'Twitter / X URL', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_twitter_url', true ) ], 'linkedin_url' => [ 'label' => esc_html__( 'Linkedin URL', 'academy' ), 'value' => get_user_meta( $user_id, 'academy_linkedin_url', true ) ], ]; $user_data = array_filter( $user_data, function ( $data ) { return ! empty( $data['value'] ); }); $user_data = array_merge( $user_data, array_column( $user_meta, null, 'type' ) ); \Academy\Helper::get_template( 'frontend-dashboard/pages/my-profile.php', [ 'user_id' => $user_id, 'user_data' => $user_data, ] ); } function academy_frontend_dashboard_enrolled_courses_page() { // get enroll courses $user_id = get_current_user_id(); $enrolled_courses = \Academy\Helper::get_enrolled_courses_ids_by_user( $user_id ); $pending_enrolled_courses = \Academy\Helper::get_pending_enrolled_courses_ids_by_user( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/enrolled-courses.php', [ 'enrolled_courses' => $enrolled_courses, 'pending_enrolled_courses' => $pending_enrolled_courses ] ); } function academy_frontend_dashboard_active_courses_page() { // get active courses $user_id = get_current_user_id(); $enrolled_courses = \Academy\Helper::get_enrolled_courses_ids_by_user( $user_id ); $completed_courses = \Academy\Helper::get_completed_courses_ids_by_user( $user_id ); $active_courses = array_diff( $enrolled_courses, $completed_courses ); $pending_enrolled_courses = \Academy\Helper::get_pending_enrolled_courses_ids_by_user( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/active-courses.php', [ 'active_courses' => $active_courses, 'pending_enrolled_courses' => $pending_enrolled_courses ] ); } function academy_frontend_dashboard_completed_courses_page() { // get completed courses $user_id = get_current_user_id(); $completed_courses = \Academy\Helper::get_completed_courses_ids_by_user( $user_id ); $pending_enrolled_courses = \Academy\Helper::get_pending_enrolled_courses_ids_by_user( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/completed-courses.php', [ 'completed_courses' => $completed_courses, 'pending_enrolled_courses' => $pending_enrolled_courses ] ); } function academy_frontend_dashboard_download_certificate_page() { // get completed courses $user_id = get_current_user_id(); $completed_courses = \Academy\Helper::get_completed_courses_ids_by_user( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/download-certificate.php', [ 'completed_courses' => $completed_courses, ] ); } function academy_frontend_dashboard_grades_page() { $user_id = get_current_user_id(); // One enrolment record per enrolment, so a course a student enrolled in // more than once comes back more than once and would render a duplicate row. $enrolled_courses = array_values( array_unique( (array) \Academy\Helper::get_enrolled_courses_ids_by_user( $user_id ) ) ); $completed_courses = \Academy\Helper::get_completed_courses_ids_by_user( $user_id ); // The menu item is already gated on the quizzes addon, but the endpoint // stays reachable by direct URL and the menu can be re-added through // academy/frontend_dashboard_menu_items, so re-check here. $quizzes_active = \Academy\Helper::get_addon_active_status( 'quizzes' ) && class_exists( '\AcademyQuizzes\Classes\Query' ); // The GradeBook addon (Pro) is the only source of a letter/scale grade — // core only has raw percentages. Pro's own AcademyProGradeBook\Helper // already stores a grade_name per user/course/quiz (populated on every // quiz submission via its own academy_quizzes/after_quiz_insert hook), so // this reads that directly rather than recomputing a grade scale in core. $grade_book_active = \Academy\Helper::get_addon_active_status( 'grade_book', true ) && class_exists( '\AcademyProGradeBook\Helper' ); $courses = []; foreach ( (array) $enrolled_courses as $course_id ) { $total_topics = \Academy\Helper::get_total_number_of_course_topics( $course_id ); $completed_topics = \Academy\Helper::get_total_number_of_completed_course_topics_by_course_and_student_id( $course_id, $user_id ); $quiz_results = []; if ( $quizzes_active ) { $attempts_by_quiz_id = []; foreach ( \AcademyQuizzes\Classes\Query::get_students_own_quiz_grades_by_course( $user_id, $course_id ) as $attempt ) { $attempts_by_quiz_id[ (int) $attempt->quiz_id ] = $attempt; } foreach ( \AcademyQuizzes\Classes\Query::get_course_quiz_ids( $course_id ) as $quiz_id ) { $attempt = $attempts_by_quiz_id[ $quiz_id ] ?? null; $grade_letter = null; if ( $grade_book_active && $attempt ) { $grade_result = \AcademyProGradeBook\Helper::get_student_quiz_grade_by_course_quiz_and_user_id( array( 'user_id' => $user_id, 'course_id' => $course_id, 'quiz_id' => $quiz_id, ) ); if ( ! empty( $grade_result ) ) { $grade_letter = current( $grade_result )->grade_name; } } $quiz_results[] = [ 'quiz_id' => $quiz_id, 'quiz_title' => html_entity_decode( get_the_title( $quiz_id ) ), 'attempt' => $attempt, 'grade_letter' => $grade_letter, ]; } }//end if $attempted_quizzes = array_filter( $quiz_results, function ( $quiz ) { return null !== $quiz['attempt']; } ); $courses[] = [ 'course_id' => $course_id, 'course_title' => html_entity_decode( get_the_title( $course_id ) ), 'course_permalink' => get_permalink( $course_id ), 'progress_percentage' => \Academy\Helper::calculate_percentage( $total_topics, $completed_topics ), 'is_completed' => in_array( (int) $course_id, array_map( 'intval', (array) $completed_courses ), true ), 'quiz_results' => $quiz_results, 'quiz_summary' => [ 'total' => count( $quiz_results ), 'attempted' => count( $attempted_quizzes ), 'passed' => count( array_filter( $attempted_quizzes, function ( $quiz ) { return 'passed' === $quiz['attempt']->attempt_status; } ) ), ], ]; }//end foreach \Academy\Helper::get_template( 'frontend-dashboard/pages/grades.php', [ 'courses' => $courses, 'grade_book_active' => $grade_book_active, ] ); } function academy_frontend_dashboard_reviews_page() { // get given reviews $user_id = get_current_user_id(); $reviews = \Academy\Helper::get_reviews_by_user( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/given-reviews.php', [ 'reviews' => $reviews ] ); } function academy_frontend_dashboard_received_reviews_page() { // get given reviews $user_id = get_current_user_id(); $reviews = \Academy\Helper::get_reviews_by_instructor( $user_id ); \Academy\Helper::get_template( 'frontend-dashboard/pages/received-reviews.php', [ 'reviews' => $reviews ] ); } function academy_frontend_dashboard_purchase_history_page() { $user_id = get_current_user_id(); $orders = \Academy\Helper::get_orders_by_user_id( $user_id ); $results = []; if ( 'woocommerce' === Helper::get_settings( 'monetization_engine' ) && is_array( $orders ) ) { foreach ( $orders as $order ) { $courses_order = \Academy\Helper::get_course_enrolled_ids_by_order_id( $order->ID ); $courses = []; if ( is_array( $courses_order ) ) { foreach ( $courses_order as $course ) { $courses[] = [ 'ID' => $course['course_id'], 'title' => get_the_title( $course['course_id'] ), 'permalink' => esc_url( get_the_permalink( $course['course_id'] ) ), ]; } } $wc_order = wc_get_order( $order->ID ); $price = $wc_order->get_total(); $status = \Academy\Helper::order_status_context( $order->post_status ); $results[] = [ 'ID' => $order->ID, 'courses' => $courses, 'price' => wc_price( $price, array( 'currency' => $wc_order->get_currency() ) ), 'status' => $status, 'date' => date_i18n( get_option( 'date_format' ), strtotime( $order->post_date ) ), ]; }//end foreach }//end if \Academy\Helper::get_template( 'frontend-dashboard/pages/purchase-history.php', apply_filters( 'academy/get_courses_purchase_history', [ 'orders' => $results ], $user_id ) ); } function academy_frontend_dashboard_wishlist_page() { // get wishlist courses $user_id = get_current_user_id(); $wishlist_courses = \Academy\Helper::get_wishlist_courses_by_user( $user_id, array( 'private', 'publish' ) ); \Academy\Helper::get_template( 'frontend-dashboard/pages/wishlist.php', [ 'wishlist_courses' => $wishlist_courses ] ); } function academy_frontend_dashboard_courses_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/courses.php' ); } function academy_frontend_dashboard_lessons_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/lessons.php' ); } function academy_frontend_dashboard_announcements_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/announcements.php' ); } function academy_frontend_dashboard_question_answer_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/question-answer.php' ); } function academy_frontend_dashboard_students_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/students.php' ); } function academy_frontend_dashboard_settings_page() { $user_id = get_current_user_id(); \Academy\Helper::get_template( 'frontend-dashboard/pages/settings.php', [ 'user_id' => $user_id ] ); } function academy_frontend_dashboard_reset_password_page() { \Academy\Helper::get_template( 'frontend-dashboard/pages/reset-password.php' ); } function academy_frontend_dashboard_withdrawal_page() { $user_id = get_current_user_id(); $monetize_engine = \Academy\Helper::get_settings( 'monetization_engine' ); $withdraw_history = \Academy\Helper::get_withdraw_history_by_user_id( $user_id ); $earning = (object) \Academy\Helper::get_earning_by_user_id( $user_id ); $earning->withdraw_currency_symbol = '$'; if ( 'woocommerce' === $monetize_engine && \Academy\Helper::is_active_woocommerce() ) { $earning->withdraw_currency_symbol = html_entity_decode( get_woocommerce_currency_symbol(), ENT_HTML5, 'UTF-8' ); } elseif ( 'storeengine' === $monetize_engine && \Academy\Helper::is_plugin_active( 'storeengine/storeengine.php' ) ) { $earning->withdraw_currency_symbol = \StoreEngine\Utils\Helper::get_currency_symbol(); } $withdraw_method_type = get_user_meta( $user_id, 'academy_instructor_withdraw_method_type', true ); \Academy\Helper::get_template( 'frontend-dashboard/pages/withdrawal.php', [ 'user_id' => $user_id, 'withdraw_history' => $withdraw_history, 'withdraw_method_type' => $withdraw_method_type, 'earning' => $earning, ] ); } function academy_frontend_dashboard_withdraw_page() { $user_id = get_current_user_id(); $monetize_engine = \Academy\Helper::get_settings( 'monetization_engine' ); $currency_symbol = '$'; if ( 'woocommerce' === $monetize_engine && \Academy\Helper::is_active_woocommerce() ) { $currency_symbol = html_entity_decode( get_woocommerce_currency_symbol(), ENT_HTML5, 'UTF-8' ); } elseif ( 'storeengine' === $monetize_engine && \Academy\Helper::is_plugin_active( 'storeengine/storeengine.php' ) ) { $currency_symbol = \StoreEngine\Utils\Helper::get_currency_symbol(); } \Academy\Helper::get_template( 'frontend-dashboard/pages/withdraw.php', [ 'user_id' => $user_id, 'currency' => $currency_symbol ] ); } function academy_frontend_dashboard_withdraw_echeck_page() { $user_id = get_current_user_id(); \Academy\Helper::get_template( 'frontend-dashboard/pages/withdraw-echeck.php', [ 'user_id' => $user_id ] ); } function academy_frontend_dashboard_withdraw_bank_page() { $user_id = get_current_user_id(); \Academy\Helper::get_template( 'frontend-dashboard/pages/withdraw-bank.php', [ 'user_id' => $user_id ] ); } function academy_allow_iframe_in_cpt_content( $tags, $context ) { if ( 'post' === $context ) { $tags['iframe'] = array( 'src' => true, 'width' => true, 'height' => true, 'frameborder' => true, 'allowfullscreen' => true, 'allow' => true, ); } return $tags; } if ( ! function_exists( 'academy_allowed_third_party_assets' ) ) { function academy_allowed_third_party_assets( $allowed ) { if ( \Academy\Helper::is_plugin_active( 'mathjax-latex/mathjax-latex.php' ) ) { $obj = new MathJax_Latex(); $obj->add_script(); $allowed[] = 'mathjax-latex'; } if ( \Academy\Helper::is_plugin_active( 'quizpress/quizpress.php' ) ) { $allowed[] = 'quizpress'; } return $allowed; } } if ( ! function_exists( 'academy_custom_reset_password_message' ) ) { function academy_custom_reset_password_message( $message, $key, $user_login, $user_data ) { $reset_url = add_query_arg( [ 'reset_key' => $key, 'login' => rawurlencode( $user_login ), ], site_url( '/academy-retrieve-password/' ) ); $message = sprintf( /* translators: %s: user display name */ __( 'Hello %s,', 'academy' ), $user_data->display_name ); $message .= "\n\n"; $message .= __( 'Someone requested a password reset for your account.', 'academy' ); $message .= "\n\n"; $message .= __( 'Click the link below to reset your password:', 'academy' ); $message .= "\n\n"; $message .= $reset_url; $message .= "\n\n"; $message .= __( 'If you did not request this, you can safely ignore this email.', 'academy' ); return $message; } }//end if if ( ! function_exists( 'academy_handle_password_reset' ) ) { function academy_handle_password_reset() { if ( ! isset( $_POST['academy_reset_submit'] ) ) { return; } if ( ! isset( $_POST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['security'] ) ), 'academy_nonce' ) ) { wp_die( esc_html__( 'Invalid request', 'academy' ) ); } $key = isset( $_GET['reset_key'] ) ? sanitize_text_field( wp_unslash( $_GET['reset_key'] ) ) : ''; $login = isset( $_GET['login'] ) ? sanitize_text_field( wp_unslash( $_GET['login'] ) ) : ''; // 🔒 This is the magic line $user = check_password_reset_key( $key, $login ); if ( is_wp_error( $user ) ) { wp_die( 'Invalid or expired reset link' ); } // Passwords are never sanitized — that would silently change them. Unslash only, as core does. $pass1 = isset( $_POST['new_password'] ) ? wp_unslash( $_POST['new_password'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $pass2 = isset( $_POST['confirm_new_password'] ) ? wp_unslash( $_POST['confirm_new_password'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( $pass1 !== $pass2 || empty( $pass1 ) ) { wp_die( 'Passwords do not match' ); } // Reset securely reset_password( $user, $pass1 ); // Auto-login wp_set_current_user( $user->ID ); wp_set_auth_cookie( $user->ID ); wp_safe_redirect( \Academy\Helper::get_frontend_dashboard_endpoint_url( 'dashboard' ) ); exit; } }//end if if ( ! function_exists( 'academy_auto_enroll_after_registration' ) || \Academy\Helper::get_settings( 'enable_auto_enroll_after_registration' ) ) { function academy_auto_enroll_after_registration( $user_id ) { $courses = (array) \Academy\Helper::get_settings( 'after_registration_auto_enroll_courses_id' ); $selected_roles = (array) \Academy\Helper::get_settings( 'user_roles_for_auto_enroll' ); if ( empty( $courses ) || empty( $selected_roles ) ) { return; } $user = get_userdata( $user_id ); if ( ! $user || empty( $user->roles ) ) { return; } $roles = (array) $user->roles; // Check if user has at least one allowed role $role_values = array_values( $selected_roles ); $matched_roles = array_intersect( $roles, $role_values ); if ( empty( $matched_roles ) && ! in_array( 'all', $role_values, true ) ) { return; } foreach ( $courses as $course_id ) { $course_id = absint( $course_id ); if ( ! $course_id ) { continue; } \Academy\Helper::do_enroll( $course_id, $user_id ); } } }//end if if ( ! function_exists( 'academy_loco_translate_sync' ) ) { function academy_loco_translate_sync(): void { if ( empty( get_current_user_id() ) && ! defined( 'LOCO_TEST' ) ) { define( 'LOCO_TEST', false ); } ob_start(); LocoTranslateSync::start( 'academy/academy.php' ); ob_end_flush(); } } if ( ! function_exists( 'academy_allowed_learnpage_content_tags' ) ) { function academy_allowed_learnpage_content_tags( $content, $author_id = null ) { $content = \Academy\Classes\ColorConverter::rgb_to_hex( $content ); unset( $author_id ); $allowed_tags = wp_kses_allowed_html( 'post' ); $allowed_tags['input'] = array( 'type' => true, 'name' => true, 'value' => true, 'class' => true, 'style' => true, ); $allowed_tags['form'] = array( 'action' => true, 'method' => true, 'class' => true, 'style' => true, ); $allowed_tags['iframe'] = array( 'src' => true, 'width' => true, 'height' => true, 'frameborder' => true, 'allow' => true, 'allowfullscreen' => true, 'style' => true, ); add_filter( 'safe_style_css', function ( $styles ) { $styles[] = 'display'; $styles[] = 'align-items'; $styles[] = 'justify-content'; return $styles; }); $sanitize_content = wp_kses( $content, $allowed_tags ); remove_all_filters( 'safe_style_css' ); return $sanitize_content; } }//end if