PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.6
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.6
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / TemplateHooks / Admin / Tools / AdminCourseTools.php

AdminCourseTools.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.6, at inc/TemplateHooks/Admin/Tools/AdminCourseTools.php

381 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin templates for LearnPress tools.
4 *
5 * @package LearnPress\TemplateHooks\Admin\Tools
6 * @since 4.4.6
7 * @version 1.0.0
8 */
9
10 namespace LearnPress\TemplateHooks\Admin\Tools;
11
12 use Exception;
13 use LearnPress\Databases\DataBase;
14 use LearnPress\Databases\UserItemsDB;
15 use LearnPress\Filters\UserItemsFilter;
16 use LearnPress\Helpers\Singleton;
17 use LearnPress\Helpers\Template;
18 use LearnPress\Models\CourseModel;
19 use LearnPress\Models\UserItems\UserCourseModel;
20 use LearnPress\Models\UserModel;
21 use LP_Helper;
22 use stdClass;
23 use Throwable;
24
25 defined( 'ABSPATH' ) || exit;
26
27 /**
28 * Class AdminCourseTools
29 */
30 class AdminCourseTools {
31 use Singleton;
32
33 /**
34 * Hooks initialization.
35 */
36 public function init(): void {
37 add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
38 }
39
40 /**
41 * Register AJAX callbacks allowed for loading content via AJAX.
42 *
43 * @param array $callbacks List of allowed callbacks.
44 *
45 * @return array
46 */
47 public function allow_callback( array $callbacks ): array {
48 $callbacks[] = self::class . ':render_courses_to_reset_progress';
49 $callbacks[] = self::class . ':render_items_to_reset_progress';
50
51 return $callbacks;
52 }
53
54 /**
55 * Render paginated list of course items (lesson, quiz, etc.) for reset progress.
56 *
57 * @param array $data Request arguments.
58 *
59 * @return stdClass
60 * @since 4.4.6
61 * @version 1.0.0
62 */
63 public static function render_items_to_reset_progress( array $data ): stdClass {
64 $content = new stdClass();
65
66 try {
67 // Check permission
68 if ( ! current_user_can( UserModel::ROLE_ADMINISTRATOR ) ) {
69 throw new Exception( __( 'You do not have permission to perform this action.', 'learnpress' ) );
70 }
71
72 $item_selecting = $data['item_selecting'] ?? [];
73 $search_item = trim( $data['lp-search-item'] ?? '' );
74 $search_course = trim( $data['lp-search-course'] ?? '' );
75 $search_user = trim( $data['lp-search-user'] ?? '' );
76 $item_type = trim( $data['lp-item-type'] ?? '' );
77 $paged = max( 1, intval( $data['paged'] ?? 1 ) );
78
79 $selected_compare = new stdClass();
80 if ( ! empty( $item_selecting ) && is_array( $item_selecting ) ) {
81 foreach ( $item_selecting as $item ) {
82 if ( ! isset( $item['id'] ) ) {
83 continue;
84 }
85 $selected_compare->{$item['id']} = true;
86 }
87 }
88
89 $limit = 10;
90
91 $db = UserItemsDB::getInstance();
92 $total_rows = 0;
93 $filter = new UserItemsFilter();
94 $filter->limit = $limit;
95 $filter->page = $paged;
96 $filter->only_fields = [
97 'DISTINCT(ui.user_item_id)',
98 'ui.item_id',
99 'ui.user_id',
100 'ui.item_type',
101 'ui.ref_id',
102 ];
103
104 // Filter by ref_type = course (items belong to a course)
105 $filter->ref_type = LP_COURSE_CPT;
106
107 // Get only user_id > 0
108 $filter->where[] = 'AND ui.user_id > 0';
109
110 // Filter by item type
111 if ( ! empty( $item_type ) ) {
112 $filter->item_type = $item_type;
113 } else {
114 $item_types = CourseModel::item_types_support();
115 $types_format = LP_Helper::db_format_array( $item_types, '%s' );
116 // phpcs:disable WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
117 $filter->where[] = $db->wpdb->prepare(
118 'AND ui.item_type IN (' . $types_format . ')',
119 ...$item_types
120 );
121 // phpcs:enable WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
122 }
123
124 // Search item by title
125 if ( ! empty( $search_item ) ) {
126 $filter->join[] = "INNER JOIN {$db->tb_posts} AS p ON ui.item_id = p.ID";
127 $filter->where[] = $db->wpdb->prepare(
128 'AND p.post_title LIKE %s',
129 '%' . $db->wpdb->esc_like( $search_item ) . '%'
130 );
131 }
132
133 // Search course by title
134 if ( ! empty( $search_course ) ) {
135 $filter->join[] = "INNER JOIN {$db->tb_posts} AS pc ON ui.ref_id = pc.ID";
136 $filter->where[] = $db->wpdb->prepare(
137 'AND pc.post_title LIKE %s',
138 '%' . $db->wpdb->esc_like( $search_course ) . '%'
139 );
140 }
141
142 // Search user
143 if ( ! empty( $search_user ) ) {
144 $filter->join[] = "INNER JOIN {$db->tb_users} AS u ON ui.user_id = u.ID";
145 $esc_search_user = '%' . $db->wpdb->esc_like( $search_user ) . '%';
146 $filter->where[] = $db->wpdb->prepare(
147 'AND (u.display_name LIKE %s OR u.user_login LIKE %s OR u.user_email LIKE %s)',
148 $esc_search_user,
149 $esc_search_user,
150 $esc_search_user
151 );
152 }
153
154 $userItems = $db->get_user_items( $filter, $total_rows );
155 $total_pages = DataBase::get_total_pages( $limit, $total_rows );
156
157 $html_lis = '';
158 if ( empty( $userItems ) ) {
159 $html_lis = Template::print_message(
160 esc_html__( 'No data found', 'learnpress' ),
161 'info',
162 false
163 );
164 } else {
165 foreach ( $userItems as $userItem ) {
166 $user_item_id = intval( $userItem->user_item_id ?? 0 );
167 if ( empty( $user_item_id ) ) {
168 continue;
169 }
170
171 $checked = '';
172 if ( isset( $selected_compare->{$user_item_id} ) ) {
173 $checked = ' checked="checked"';
174 }
175
176 $item_title_raw = get_the_title( $userItem->item_id );
177 $item_title = $item_title_raw ? $item_title_raw : __( 'Unknown', 'learnpress' );
178 $course_title_raw = get_the_title( $userItem->ref_id );
179 $course_title = $course_title_raw ? $course_title_raw : __( 'Unknown', 'learnpress' );
180 $userModel = UserModel::find( $userItem->user_id, true );
181 $user_name = $userModel ? $userModel->get_display_name() : __( 'Unknown', 'learnpress' );
182
183 $title_display = sprintf(
184 '<span class="title">%s <strong>(#%d)</strong> - %s - %s (#%d)</span>',
185 esc_html( $item_title ),
186 esc_html( $userItem->item_id ),
187 esc_html( $course_title ),
188 esc_html( $user_name ),
189 esc_html( $userItem->user_id )
190 );
191
192 $html_lis .= sprintf(
193 '<li class="lp-select-item">%s%s</li>',
194 sprintf(
195 '<input name="lp-select-item"
196 value="%1$s"
197 data-id="%1$d"
198 data-title="%2$s"
199 %3$s
200 type="checkbox" />',
201 esc_attr( $user_item_id ),
202 esc_attr( $title_display ),
203 esc_attr( $checked )
204 ),
205 $title_display,
206 );
207 }
208 }
209
210 $section = [
211 'ul' => '<ul class="list-items">',
212 'items' => $html_lis,
213 'ul_end' => '</ul>',
214 'pagination' => Template::instance()->html_pagination(
215 [
216 'total_pages' => $total_pages,
217 'paged' => $paged,
218 ]
219 ),
220 ];
221
222 $content->content = Template::combine_components( $section );
223 } catch ( Throwable $exception ) {
224 $content->content = Template::print_message( $exception->getMessage(), 'error', false );
225 }
226
227 return $content;
228 }
229
230 /**
231 * Render paginated list of courses that have enrolled users.
232 *
233 * @param array $data Request arguments.
234 *
235 * @return stdClass
236 * @since 4.4.6
237 * @version 1.0.0
238 */
239 public static function render_courses_to_reset_progress( array $data ): stdClass {
240 $content = new stdClass();
241
242 try {
243 $item_selecting = $data['item_selecting'] ?? [];
244 $search_course = trim( $data['lp-search-course'] ?? '' );
245 $search_user = trim( $data['lp-search-user'] ?? '' );
246 $paged = max( 1, intval( $data['paged'] ?? 1 ) );
247
248 $selected_compare = new stdClass();
249 if ( ! empty( $item_selecting ) && is_array( $item_selecting ) ) {
250 foreach ( $item_selecting as $item ) {
251 if ( ! isset( $item['id'] ) ) {
252 continue;
253 }
254 $selected_compare->{$item['id']} = true;
255 }
256 }
257
258 $limit = 10;
259
260 $db = UserItemsDB::getInstance();
261 $total_rows = 0;
262 $filter = new UserItemsFilter();
263 $filter->limit = $limit;
264 $filter->page = $paged;
265 $filter->item_type = LP_COURSE_CPT;
266 $filter->only_fields = [ 'DISTINCT(ui.user_item_id)', 'ui.item_id', 'ui.user_id' ];
267
268 // Get only courses has items attendance
269 $filter_course_attendance = new UserItemsFilter();
270 $filter_course_attendance->only_fields = [ 'parent_id' ];
271 $filter_course_attendance->ref_type = LP_COURSE_CPT;
272 $filter_course_attendance->return_string_query = 1;
273 $filter_course_attendance->limit = -1;
274 $query_course_attendance = $db->get_user_items( $filter_course_attendance );
275 $filter->where[] = "AND ui.user_item_id IN ({$query_course_attendance})";
276 // End get only courses has items attendance
277
278 // Get only user_id > 0
279 $filter->where[] = 'AND ui.user_id > 0';
280
281 // Search course
282 if ( ! empty( $search_course ) ) {
283 $filter->only_fields[] = 'post_title';
284 $filter->join[] = "INNER JOIN {$db->tb_lp_courses} AS c ON ui.item_id = c.ID";
285 $filter->where[] = $db->wpdb->prepare(
286 'AND c.post_title LIKE %s',
287 '%' . $db->wpdb->esc_like( $search_course ) . '%'
288 );
289 }
290
291 // Search user
292 if ( ! empty( $search_user ) ) {
293 $filter->join[] = "INNER JOIN {$db->tb_users} AS u ON ui.user_id = u.ID";
294 $esc_search_user = '%' . $db->wpdb->esc_like( $search_user ) . '%';
295 $filter->where[] = $db->wpdb->prepare(
296 'AND (u.display_name LIKE %s OR u.user_login LIKE %s OR u.user_email LIKE %s)',
297 $esc_search_user,
298 $esc_search_user,
299 $esc_search_user
300 );
301 }
302
303 $userCourses = $db->get_user_items( $filter, $total_rows );
304 $total_pages = DataBase::get_total_pages( $limit, $total_rows );
305
306 $html_lis = '';
307 if ( empty( $userCourses ) ) {
308 $html_lis = Template::print_message(
309 esc_html__( 'No data found', 'learnpress' ),
310 'info',
311 false
312 );
313 } else {
314 foreach ( $userCourses as $userCourse ) {
315 $userCourseModel = UserCourseModel::find( $userCourse->user_id, $userCourse->item_id, true );
316 if ( ! $userCourseModel ) {
317 continue;
318 }
319
320 $courseModel = $userCourseModel->get_course_model();
321 $checked = '';
322 if ( isset( $selected_compare->{$userCourseModel->get_user_item_id()} ) ) {
323 $checked = ' checked="checked"';
324 }
325
326 $userModel = $userCourseModel->get_user_model();
327 $user_id = $userModel ? $userModel->get_id() : 0;
328
329 $students_text = sprintf(
330 /* translators: %d: number of enrolled students */
331 __( '%1$s (#%2$d)', 'learnpress' ),
332 $user_id ? $userModel->get_display_name() : esc_html__( 'Unknown', 'learnpress' ),
333 $user_id
334 );
335
336 $title_display = sprintf(
337 '<span class="title">%s<strong>(#%d - %s)</strong></span>',
338 esc_html( $courseModel ? $courseModel->get_title() : __( 'Unknown', 'learnpress' ) ),
339 esc_html( $courseModel ? $courseModel->get_id() : 0 ),
340 esc_html( $students_text )
341 );
342
343 $html_lis .= sprintf(
344 '<li class="lp-select-item">%s%s</li>',
345 sprintf(
346 '<input name="lp-select-item"
347 value="%1$s"
348 data-id="%1$d"
349 data-title="%2$s"
350 %3$s
351 type="checkbox" />',
352 esc_attr( $userCourseModel->get_user_item_id() ),
353 esc_attr( $title_display ),
354 esc_attr( $checked )
355 ),
356 $title_display,
357 );
358 }
359 }
360
361 $section = [
362 'ul' => '<ul class="list-items">',
363 'items' => $html_lis,
364 'ul_end' => '</ul>',
365 'pagination' => Template::instance()->html_pagination(
366 [
367 'total_pages' => $total_pages,
368 'paged' => $paged,
369 ]
370 ),
371 ];
372
373 $content->content = Template::combine_components( $section );
374 } catch ( Throwable $exception ) {
375 $content->content = Template::print_message( $exception->getMessage(), 'error', false );
376 }
377
378 return $content;
379 }
380 }
381