PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.0
Tutor LMS – eLearning and online course solution v4.0.0
4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / templates / dashboard / my-courses.php
tutor / templates / dashboard Last commit date
account 1 day ago components 1 day ago courses 1 day ago discussions 1 day ago elements 1 day ago instructor 1 day ago my-courses 1 year ago my-quiz-attempts 1 day ago quiz-attempts 1 day ago student 1 day ago wishlist 1 day ago announcements.php 1 day ago courses.php 1 day ago create-course.php 1 day ago dashboard.php 1 day ago discussions.php 1 day ago index.php 3 years ago logged-in.php 3 years ago my-courses.php 1 day ago my-quiz-attempts.php 1 day ago quiz-attempts.php 1 day ago registration.php 1 day ago wishlist.php 1 day ago
my-courses.php
400 lines
1 <?php
2 /**
3 * My Courses Page
4 *
5 * @package Tutor\Templates
6 * @subpackage Dashboard
7 * @author Themeum <support@themeum.com>
8 * @link https://themeum.com
9 * @since 1.4.3
10 */
11
12 defined( 'ABSPATH' ) || exit;
13
14 use Tutor\Components\Constants\Size;
15 use Tutor\Components\Constants\Variant;
16 use Tutor\Components\ConfirmationModal;
17 use Tutor\Components\EmptyState;
18 use Tutor\Components\DropdownFilter;
19 use Tutor\Components\Pagination;
20 use Tutor\Components\SearchFilter;
21 use Tutor\Components\Sorting;
22 use TUTOR\Icon;
23 use Tutor\Components\SvgIcon;
24 use Tutor\Components\Constants\Color;
25 use TUTOR\Input;
26 use Tutor\Models\CourseModel;
27
28 // Get the user ID and active tab.
29 $current_user_id = get_current_user_id();
30 ! isset( $active_tab ) ? $active_tab = 'my-courses' : 0;
31
32 // Map required course status according to page.
33 $status_map = array(
34 'my-courses' => CourseModel::STATUS_PUBLISH,
35 'my-courses/draft-courses' => CourseModel::STATUS_DRAFT,
36 'my-courses/pending-courses' => CourseModel::STATUS_PENDING,
37 'my-courses/schedule-courses' => CourseModel::STATUS_FUTURE,
38 );
39
40 // Set currently required course status fo rcurrent tab.
41 $course_status = isset( $status_map[ $active_tab ] ) ? $status_map[ $active_tab ] : CourseModel::STATUS_PUBLISH;
42 $course_post_type = apply_filters( 'tutor_dashboard_course_list_post_type', array( tutor()->course_post_type ) );
43
44 $order_filter = Input::get( 'order', 'DESC' );
45 $search_term = Input::get( 'search', '' );
46
47 // Get counts for course tabs.
48 $count_map = array(
49 'publish' => CourseModel::get_courses_by_instructor( $current_user_id, CourseModel::STATUS_PUBLISH, 0, 0, true, $course_post_type, $search_term ),
50 'pending' => CourseModel::get_courses_by_instructor( $current_user_id, CourseModel::STATUS_PENDING, 0, 0, true, $course_post_type, $search_term ),
51 'draft' => CourseModel::get_courses_by_instructor( $current_user_id, CourseModel::STATUS_DRAFT, 0, 0, true, $course_post_type, $search_term ),
52 'future' => CourseModel::get_courses_by_instructor( $current_user_id, CourseModel::STATUS_FUTURE, 0, 0, true, $course_post_type, $search_term ),
53 );
54
55 $item_per_page = tutor_utils()->get_option( 'pagination_per_page', 10 );
56 $current_page = Input::get( 'current_page', 1, Input::TYPE_INT );
57 $offset = $item_per_page * ( $current_page - 1 );
58 $results = CourseModel::get_courses_by_instructor( $current_user_id, $course_status, $offset, $item_per_page, false, $course_post_type, $search_term, $order_filter );
59 $show_course_delete = true;
60 $post_type_query = Input::get( 'type', '' );
61 $post_type_args = $post_type_query ? array( 'type' => $post_type_query ) : array();
62
63 $current_url = add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( $active_tab ) );
64
65 $dropdown_options = array(
66 array(
67 'label' => __( 'Published', 'tutor' ),
68 'count' => $count_map['publish'] ?? 0,
69 'url' => add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'my-courses' ) ),
70 'active' => 'my-courses' === $active_tab,
71 ),
72 array(
73 'label' => __( 'Pending', 'tutor' ),
74 'count' => $count_map['pending'] ?? 0,
75 'url' => add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'my-courses/pending-courses' ) ),
76 'active' => 'my-courses/pending-courses' === $active_tab,
77 ),
78 array(
79 'label' => __( 'Draft', 'tutor' ),
80 'count' => $count_map['draft'] ?? 0,
81 'url' => add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'my-courses/draft-courses' ) ),
82 'active' => 'my-courses/draft-courses' === $active_tab,
83 ),
84 array(
85 'label' => __( 'Schedule', 'tutor' ),
86 'count' => $count_map['future'] ?? 0,
87 'url' => add_query_arg( $post_type_args, tutor_utils()->get_tutor_dashboard_page_permalink( 'my-courses/schedule-courses' ) ),
88 'active' => 'my-courses/schedule-courses' === $active_tab,
89 ),
90 );
91
92 if ( ! current_user_can( 'administrator' ) && ! tutor_utils()->get_option( 'instructor_can_delete_course' ) ) {
93 $show_course_delete = false;
94 }
95 ?>
96
97 <div class="tutor-dashboard-my-courses" x-data="tutorMyCourses()">
98 <div class="tutor-hidden tutor-sm-flex tutor-items-center tutor-justify-between tutor-mb-5">
99 <h4 class="tutor-h4"><?php esc_html_e( 'Courses', 'tutor' ); ?></h4>
100 <?php ob_start(); ?>
101 <button
102 class="tutor-btn tutor-btn-primary tutor-btn-x-small tutor-gap-2"
103 :class="createMutation.isPending ? 'tutor-btn-loading' : ''"
104 @click="handleCreateCourse()"
105 :disabled="createMutation.isPending"
106 >
107 <?php SvgIcon::make()->name( Icon::ADD )->render(); ?>
108 <?php esc_html_e( 'New Course', 'tutor' ); ?>
109 </button>
110 <?php echo apply_filters( 'tutor_course_create_mobile_button', ob_get_clean() ); //phpcs:ignore ?>
111 </div>
112 <div class="tutor-surface-l1 tutor-border tutor-rounded-2xl">
113 <div class="tutor-flex tutor-flex-wrap tutor-gap-4 tutor-items-center tutor-justify-between tutor-px-6 tutor-py-5 tutor-sm-p-5 tutor-border-b">
114 <?php DropdownFilter::make()->variant( Variant::PRIMARY_SOFT )->size( Size::SMALL )->options( $dropdown_options )->render(); ?>
115 <div class="tutor-hidden tutor-sm-block">
116 <?php do_action( 'tutor_dashboard_my_courses_filter' ); ?>
117 </div>
118 <div class="tutor-flex tutor-items-center tutor-gap-5 tutor-sm-hidden">
119 <?php do_action( 'tutor_course_create_button' ); ?>
120 <button
121 class="tutor-btn tutor-btn-primary tutor-btn-small tutor-gap-2"
122 :class="createMutation.isPending ? 'tutor-btn-loading' : ''"
123 @click="handleCreateCourse()"
124 :disabled="createMutation.isPending"
125 >
126 <?php SvgIcon::make()->name( Icon::ADD )->render(); ?>
127 <?php esc_html_e( 'New Course', 'tutor' ); ?>
128 </button>
129 </div>
130 </div>
131 <div class="tutor-flex tutor-flex-wrap tutor-gap-4 tutor-items-center tutor-justify-between tutor-py-5 tutor-px-6 tutor-sm-p-5 tutor-border-b">
132 <?php
133 $hidden_inputs = array();
134 if ( ! empty( $post_type_query ) ) {
135 $hidden_inputs['type'] = $post_type_query;
136 }
137
138 SearchFilter::make()
139 ->form_id( 'tutor-my-courses-search-form' )
140 ->placeholder( __( 'Search courses...', 'tutor' ) )
141 ->size( Size::SMALL )
142 ->action( $current_url )
143 ->hidden_inputs( $hidden_inputs )
144 ->attr( 'class', 'tutor-sm-flex-1' )
145 ->render();
146 ?>
147 <div class="tutor-flex tutor-items-center tutor-gap-3">
148 <div class="tutor-sm-hidden">
149 <?php do_action( 'tutor_dashboard_my_courses_filter' ); ?>
150 </div>
151 <?php Sorting::make()->order( $order_filter )->render(); ?>
152 </div>
153 </div>
154
155 <?php if ( empty( $results ) ) : ?>
156 <?php
157 EmptyState::make()
158 ->title( 'No Courses Found' )
159 ->icon( tutor_utils()->get_themed_svg( 'images/illustrations/learning-empty.svg' ) )
160 ->render();
161 ?>
162 <?php else : ?>
163 <div class="tutor-my-courses-card-wrapper">
164 <?php
165 global $post;
166 $tutor_nonce_value = wp_create_nonce( tutor()->nonce_action );
167 foreach ( $results as $post ) :
168 setup_postdata( $post );
169 $tutor_course_img = get_tutor_course_thumbnail_src();
170 $course_duration = tutor_utils()->get_course_duration( $post->ID, false );
171 $course_students = tutor_utils()->count_enrolled_users_by_course();
172 $is_main_instructor = CourseModel::is_main_instructor( $post->ID );
173 $course_edit_link = apply_filters( 'tutor_dashboard_course_list_edit_link', tutor_utils()->course_edit_link( $post->ID, tutor()->has_pro ? 'frontend' : 'backend' ), $post );
174 ?>
175 <div class="tutor-my-courses-card">
176 <div class="tutor-my-courses-card-body">
177 <div class="tutor-my-courses-card-thumb">
178 <?php do_action( 'tutor_my_courses_before_thumbnail', $post->ID ); ?>
179 <img src="<?php echo empty( $tutor_course_img ) ? esc_url( $placeholder_img ) : esc_url( $tutor_course_img ); ?>" alt="<?php the_title(); ?>" loading="lazy">
180 <div class="tutor-my-courses-card-actions">
181 <a href="<?php echo esc_url( $course_edit_link ); ?>" class="tutor-btn tutor-btn-secondary tutor-btn-x-small tutor-btn-icon" aria-label="<?php esc_attr_e( 'Edit Course', 'tutor' ); ?>">
182 <?php SvgIcon::make()->name( Icon::EDIT_2 )->render(); ?>
183 </a>
184 <a href="<?php echo esc_url( get_the_permalink() ); ?>" class="tutor-btn tutor-btn-secondary tutor-btn-x-small tutor-btn-icon" aria-label="<?php esc_attr_e( 'View Course', 'tutor' ); ?>">
185 <?php SvgIcon::make()->name( Icon::EYE_LINE )->render(); ?>
186 </a>
187 </div>
188 </div>
189 <div class="tutor-my-courses-card-content">
190 <?php do_action( 'tutor_my_courses_before_meta', get_the_ID() ); ?>
191
192 <div class="tutor-tiny tutor-text-secondary tutor-flex tutor-items-center tutor-gap-2 tutor-mb-2">
193 <?php SvgIcon::make()->name( Icon::CALENDAR_CHECK )->size( 14 )->color( Color::BRAND )->render(); ?>
194 <?php echo esc_html( get_the_date() ); ?> - <?php echo esc_html( get_the_time() ); ?>
195 </div>
196
197 <a href="<?php echo esc_url( $course_edit_link ); ?>" class="tutor-p2 tutor-font-medium tutor-line-clamp-3">
198 <?php the_title(); ?>
199 </a>
200
201 <?php if ( ! empty( $course_duration ) || ! empty( $course_students ) ) : ?>
202 <div class="tutor-tiny tutor-text-subdued tutor-flex tutor-items-center tutor-gap-6 tutor-mt-4">
203 <?php if ( ! empty( $course_students ) ) : ?>
204 <div class="tutor-flex tutor-items-center tutor-gap-2">
205 <?php SvgIcon::make()->name( Icon::PASSED )->size( 14 )->render(); ?>
206 <?php echo esc_html( $course_students ); ?>
207 </div>
208 <?php endif; ?>
209
210 <?php if ( ! empty( $course_duration ) ) : ?>
211 <div class="tutor-flex tutor-items-center tutor-gap-2">
212 <?php SvgIcon::make()->name( Icon::TIME )->size( 14 )->render(); ?>
213 <?php echo esc_html( $course_duration ); ?>
214 </div>
215 <?php endif; ?>
216 </div>
217 <?php endif; ?>
218 </div>
219 </div>
220 <div class="tutor-my-courses-card-footer">
221 <div class="tutor-flex tutor-items-center tutor-gap-2 tutor-overflow-hidden">
222 <?php if ( apply_filters( 'tutor_membership_only_mode', false ) ) : ?>
223 <span class="tutor-font-medium tutor-text-subdued">
224 <?php esc_html_e( 'Plan:', 'tutor' ); ?>
225 </span>
226 <?php endif ?>
227 <?php
228 if ( null === tutor_utils()->get_course_price() ) {
229 esc_html_e( 'Free', 'tutor' );
230 } else {
231 echo wp_kses_post( tutor_utils()->get_course_price() );
232 }
233 ?>
234 </div>
235 <div
236 class="tutor-my-courses-card-footer-actions"
237 x-data="tutorPopover({
238 placement: 'top-end',
239 offset: 4,
240 onShow: () => { $el.classList.add('tutor-popover-open') },
241 onHide: () => { $el.classList.remove('tutor-popover-open') }
242 })"
243 >
244 <button x-ref="trigger" @click="toggle()" class="tutor-btn tutor-btn-ghost tutor-btn-x-small tutor-btn-icon" aria-label="<?php esc_attr_e( 'Course Actions', 'tutor' ); ?>">
245 <?php SvgIcon::make()->name( Icon::THREE_DOTS_VERTICAL )->size( 16 )->color( Color::SECONDARY )->render(); ?>
246 </button>
247
248 <div
249 x-ref="content"
250 x-show="open"
251 x-cloak
252 @click.outside="handleClickOutside()"
253 class="tutor-popover"
254 >
255 <div class="tutor-popover-menu" style="min-width: 182px;">
256 <!-- Submit Action -->
257 <?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_DRAFT ), true ) ) : ?>
258 <?php
259 $params = http_build_query(
260 array(
261 'tutor_action' => 'update_course_status',
262 'status' => CourseModel::STATUS_PENDING,
263 'course_id' => $post->ID,
264 tutor()->nonce => $tutor_nonce_value,
265 )
266 );
267 ?>
268 <a href="?<?php echo esc_attr( $params ); ?>" class="tutor-popover-menu-item">
269 <?php SvgIcon::make()->name( Icon::PUBLISH )->size( 20 )->render(); ?>
270 <span>
271 <?php
272 $can_publish_course = current_user_can( 'administrator' ) || (bool) tutor_utils()->get_option( 'instructor_can_publish_course' );
273 if ( $can_publish_course ) {
274 esc_html_e( 'Publish', 'tutor' );
275 } else {
276 esc_html_e( 'Submit', 'tutor' );
277 }
278 ?>
279 </span>
280 </a>
281 <?php endif; ?>
282 <!-- # Submit Action -->
283
284 <!-- Cancel Submission -->
285 <?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_PENDING ), true ) ) : ?>
286 <?php
287 $params = http_build_query(
288 array(
289 'tutor_action' => 'update_course_status',
290 'status' => CourseModel::STATUS_DRAFT,
291 'course_id' => $post->ID,
292 tutor()->nonce => $tutor_nonce_value,
293 )
294 );
295 ?>
296 <a href="?<?php echo esc_attr( $params ); ?>" class="tutor-popover-menu-item">
297 <?php SvgIcon::make()->name( Icon::CROSS_2 )->size( 20 )->render(); ?>
298 <?php esc_html_e( 'Cancel Submission', 'tutor' ); ?>
299 </a>
300 <?php endif; ?>
301 <!-- # Cancel Submission -->
302
303 <!-- Edit Link -->
304 <a href="<?php echo esc_url( $course_edit_link ); ?>" class="tutor-popover-menu-item tutor-popover-menu-item-edit">
305 <?php SvgIcon::make()->name( Icon::EDIT_2 )->size( 20 )->render(); ?>
306 <?php esc_html_e( 'Edit', 'tutor' ); ?>
307 </a>
308 <!-- Edit Link -->
309
310 <!-- View Link -->
311 <a href="<?php echo esc_url( get_the_permalink() ); ?>" class="tutor-popover-menu-item tutor-popover-menu-item-overview">
312 <?php SvgIcon::make()->name( Icon::EYE_LINE )->size( 20 )->render(); ?>
313 <?php esc_html_e( 'Overview', 'tutor' ); ?>
314 </a>
315 <!-- View Link -->
316
317 <!-- Duplicate Action -->
318 <?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_PUBLISH, CourseModel::STATUS_PENDING, CourseModel::STATUS_DRAFT, CourseModel::STATUS_FUTURE ), true ) ) : ?>
319 <?php
320 $params = http_build_query(
321 array(
322 'tutor_action' => 'duplicate_course',
323 'course_id' => $post->ID,
324 )
325 );
326 ?>
327 <a href="?<?php echo esc_attr( $params ); ?>" class="tutor-popover-menu-item">
328 <?php SvgIcon::make()->name( Icon::COPY_2 )->size( 20 )->render(); ?>
329 <?php esc_html_e( 'Duplicate', 'tutor' ); ?>
330 </a>
331 <?php endif; ?>
332 <!-- # Duplicate Action -->
333
334 <!-- Move to Draft Action -->
335 <?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_PUBLISH, CourseModel::STATUS_FUTURE ), true ) ) : ?>
336 <?php
337 $params = http_build_query(
338 array(
339 'tutor_action' => 'update_course_status',
340 'status' => CourseModel::STATUS_DRAFT,
341 'course_id' => $post->ID,
342 tutor()->nonce => $tutor_nonce_value,
343 )
344 );
345 ?>
346 <a href="?<?php echo esc_attr( $params ); ?>" class="tutor-popover-menu-item">
347 <?php SvgIcon::make()->name( Icon::MOVE )->size( 20 )->render(); ?>
348 <?php esc_html_e( 'Move to Draft', 'tutor' ); ?>
349 </a>
350 <?php endif; ?>
351 <!-- # Move to Draft Action -->
352
353 <!-- Delete Action -->
354 <?php if ( $show_course_delete && $is_main_instructor && in_array( $post->post_status, array( CourseModel::STATUS_PUBLISH, CourseModel::STATUS_DRAFT, CourseModel::STATUS_FUTURE ), true ) ) : ?>
355 <button
356 class="tutor-popover-menu-item tutor-popover-menu-item-delete"
357 @click="hide(); TutorCore.modal.showModal('tutor-course-delete-modal', { courseId: <?php echo esc_html( $post->ID ); ?> });"
358 >
359 <?php SvgIcon::make()->name( Icon::DELETE_2 )->size( 20 )->render(); ?>
360 <?php esc_html_e( 'Delete', 'tutor' ); ?>
361 </button>
362 <?php endif; ?>
363 <!-- # Delete Action -->
364 </div>
365 </div>
366 </div>
367 </div>
368 </div>
369 <?php
370 endforeach;
371 wp_reset_postdata();
372 ?>
373 </div>
374 <?php endif; ?>
375
376 <?php
377 Pagination::make()
378 ->current( $current_page )
379 ->total( (int) $count_map[ $course_status ] )
380 ->limit( $item_per_page )
381 ->attr( 'class', 'tutor-px-6 tutor-pb-6 tutor-sm-px-5 tutor-sm-pb-5' )
382 ->render();
383 ?>
384 </div>
385
386 <?php if ( ! empty( $results ) && $show_course_delete ) : ?>
387 <?php
388 ConfirmationModal::make()
389 ->id( 'tutor-course-delete-modal' )
390 ->title( __( 'Delete This Course?', 'tutor' ) )
391 ->message( __( 'Are you sure you want to delete this course permanently from the site? Please confirm your choice.', 'tutor' ) )
392 ->icon( tutor_utils()->get_themed_svg( 'images/illustrations/delete.svg' ), 80, 80, ConfirmationModal::ICON_TYPE_HTML )
393 ->confirm_text( __( 'Yes, Delete This', 'tutor' ) )
394 ->confirm_handler( 'handleDeleteCourse(payload?.courseId)' )
395 ->mutation_state( 'deleteMutation' )
396 ->render();
397 ?>
398 <?php endif; ?>
399 </div>
400