PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.6.0
Tutor LMS – eLearning and online course solution v1.6.0
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 / classes / Utils.php
tutor / classes Last commit date
Addons.php 6 years ago Admin.php 6 years ago Ajax.php 6 years ago Assets.php 6 years ago Course.php 6 years ago Course_Settings_Tabs.php 6 years ago Course_Widget.php 6 years ago Dashboard.php 6 years ago Email.php 6 years ago FormHandler.php 6 years ago Frontend.php 6 years ago Gutenberg.php 6 years ago Instructor.php 6 years ago Instructors_List.php 6 years ago Lesson.php 6 years ago Options.php 6 years ago Post_types.php 6 years ago Q_and_A.php 6 years ago Question_Answers_List.php 6 years ago Quiz.php 6 years ago Quiz_Attempts_List.php 6 years ago RestAPI.php 6 years ago Rewrite_Rules.php 6 years ago Shortcode.php 6 years ago Student.php 6 years ago Students_List.php 6 years ago Taxonomies.php 6 years ago Template.php 6 years ago Theme_Compatibility.php 6 years ago Tools.php 6 years ago Tutor.php 6 years ago TutorEDD.php 6 years ago Tutor_Base.php 6 years ago Tutor_List_Table.php 6 years ago Tutor_Setup.php 6 years ago Upgrader.php 6 years ago User.php 6 years ago Utils.php 6 years ago Video_Stream.php 6 years ago Withdraw.php 6 years ago Withdraw_Requests_List.php 6 years ago WooCommerce.php 6 years ago
Utils.php
5379 lines
1 <?php
2 namespace TUTOR;
3
4 if ( ! defined( 'ABSPATH' ) )
5 exit;
6
7
8 class Utils {
9 /**
10 * @param null $key
11 * @param bool $default
12 *
13 * @return array|bool|mixed
14 *
15 * Get option data
16 *
17 * @since v.1.0.0
18 */
19 public function get_option($key = null, $default = false){
20 $option = (array) maybe_unserialize(get_option('tutor_option'));
21
22 if (empty($option) || ! is_array($option)){
23 return $default;
24 }
25 if ( ! $key){
26 return $option;
27 }
28 if (array_key_exists($key, $option)){
29 return apply_filters($key, $option[$key]);
30 }
31 //Access array value via dot notation, such as option->get('value.subvalue')
32 if (strpos($key, '.')){
33 $option_key_array = explode('.', $key);
34
35 $new_option = $option;
36 foreach ($option_key_array as $dotKey){
37 if (isset($new_option[$dotKey])){
38 $new_option = $new_option[$dotKey];
39 }else{
40 return $default;
41 }
42 }
43 return apply_filters($key, $new_option);
44 }
45
46 return $default;
47 }
48
49 /**
50 * @param null $key
51 * @param bool $value
52 *
53 * Update Option
54 *
55 * @since v.1.0.0
56 */
57
58 public function update_option($key = null, $value = false){
59 $option = (array) maybe_unserialize(get_option('tutor_option'));
60 $option[$key] = $value;
61 update_option('tutor_option', $option);
62 }
63
64 /**
65 * @param null $key
66 * @param array $array
67 *
68 * @return array|bool|mixed
69 *
70 * get array value by dot notation
71 *
72 * @since v.1.0.0
73 *
74 * @update v.1.4.1 (Added default parameter)
75 */
76
77 public function avalue_dot($key = null, $array = array(), $default = false){
78 $array = (array) $array;
79 if ( ! $key || ! count($array) ){
80 return $default;
81 }
82 $option_key_array = explode('.', $key);
83
84 $value = $array;
85
86 foreach ($option_key_array as $dotKey){
87 if (isset($value[$dotKey])){
88 $value = $value[$dotKey];
89 }else{
90 return $default;
91 }
92 }
93 return $value;
94 }
95
96 /**
97 * @param null $key
98 * @param array $array
99 *
100 * @return array|bool|mixed
101 *
102 * alias of avalue_dot method of utils
103 *
104 * Get array value by key and recursive array value by dot notation key
105 *
106 * ex: tutor_utils()->array_get('key.child_key', $array);
107 *
108 * @since v.1.3.3
109 */
110 public function array_get($key = null, $array = array(), $default = false){
111 return $this->avalue_dot($key, $array, $default);
112 }
113
114 /**
115 * @return array
116 *
117 * Get all pages
118 *
119 * @since v.1.0.0
120 */
121 public function get_pages(){
122 $pages = array();
123 $wp_pages = get_pages();
124 if (is_array($wp_pages) && count($wp_pages)){
125 foreach ($wp_pages as $page){
126 $pages[$page->ID] = $page->post_title;
127 }
128 }
129 return $pages;
130 }
131
132 /**
133 * @return string
134 *
135 * Get course archive URL
136 *
137 * @since v.1.0.0
138 */
139 public function course_archive_page_url(){
140 $course_post_type = tutor()->course_post_type;
141 $course_page_url = trailingslashit(home_url()).$course_post_type;
142
143 $course_archive_page = $this->get_option('course_archive_page');
144 if ($course_archive_page && $course_archive_page !== '-1'){
145 $course_page_url = get_permalink($course_archive_page);
146 }
147 return trailingslashit($course_page_url);
148 }
149
150 /**
151 * @param int $student_id
152 *
153 * @return string
154 *
155 * Get student URL
156 *
157 * @since v.1.0.0
158 */
159
160 public function profile_url($student_id = 0){
161 $site_url = trailingslashit(home_url()).'profile/';
162 $user_name = '';
163
164 $student_id = $this->get_user_id($student_id);
165 if ($student_id){
166 global $wpdb;
167 $user = $wpdb->get_row("SELECT user_nicename from {$wpdb->users} WHERE ID = {$student_id} ");
168 if ($user){
169 $user_name = $user->user_nicename;
170 }
171 }else{
172 $user_name = 'user_name';
173 }
174
175 return $site_url.$user_name;
176 }
177
178 /**
179 * @param string $user_nicename
180 *
181 * @return array|null|object
182 *
183 * Get user by user login
184 *
185 * @since v.1.0.0
186 */
187 public function get_user_by_login($user_nicename = ''){
188 global $wpdb;
189 $user_nicename = sanitize_text_field($user_nicename);
190 $user = $wpdb->get_row("SELECT * from {$wpdb->users} WHERE user_nicename = '{$user_nicename}'");
191 return $user;
192 }
193
194 /**
195 * @return bool
196 *
197 * Check if WooCommerce Activated
198 *
199 * @since v.1.0.0
200 * @updated @1.5.9
201 */
202
203 public function has_wc(){
204 return class_exists('WooCommerce');
205 }
206
207 /**
208 * @return bool
209 *
210 * determine if EDD plugin activated
211 *
212 * @since v.1.0.0
213 */
214 public function has_edd(){
215 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
216 //$depends = array('easy-digital-downloads/easy-digital-downloads.php', 'tutor-edd/tutor-edd.php');
217 $depends = array('easy-digital-downloads/easy-digital-downloads.php');
218 $has = count(array_intersect($depends, $activated_plugins)) == count($depends);
219
220 return $has;
221 }
222
223 /**
224 * @return bool
225 *
226 * Determine if PMPro is activated
227 *
228 * @since v.1.3.6
229 */
230 public function has_pmpro(){
231 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
232 $depends = array('paid-memberships-pro/paid-memberships-pro.php');
233 return count(array_intersect($depends, $activated_plugins)) == count($depends);
234 }
235
236 public function has_wcs(){
237 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
238 $depends = array('woocommerce-subscriptions/woocommerce-subscriptions.php');
239 return count(array_intersect($depends, $activated_plugins)) == count($depends);
240 }
241
242
243 /**
244 * @return bool
245 *
246 * checking if BuddyPress exists and activated;
247 *
248 * @since v.1.4.8
249 */
250 public function has_bp(){
251 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
252 $depends = array('buddypress/bp-loader.php');
253 return count(array_intersect($depends, $activated_plugins)) == count($depends);
254 }
255
256 /**
257 * @return mixed
258 *
259 * @since v.1.0.0
260 */
261 public function languages(){
262 $language_codes = array(
263 'en' => 'English' ,
264 'aa' => 'Afar' ,
265 'ab' => 'Abkhazian' ,
266 'af' => 'Afrikaans' ,
267 'am' => 'Amharic' ,
268 'ar' => 'Arabic' ,
269 'as' => 'Assamese' ,
270 'ay' => 'Aymara' ,
271 'az' => 'Azerbaijani' ,
272 'ba' => 'Bashkir' ,
273 'be' => 'Byelorussian' ,
274 'bg' => 'Bulgarian' ,
275 'bh' => 'Bihari' ,
276 'bi' => 'Bislama' ,
277 'bn' => 'Bengali/Bangla' ,
278 'bo' => 'Tibetan' ,
279 'br' => 'Breton' ,
280 'ca' => 'Catalan' ,
281 'co' => 'Corsican' ,
282 'cs' => 'Czech' ,
283 'cy' => 'Welsh' ,
284 'da' => 'Danish' ,
285 'de' => 'German' ,
286 'dz' => 'Bhutani' ,
287 'el' => 'Greek' ,
288 'eo' => 'Esperanto' ,
289 'es' => 'Spanish' ,
290 'et' => 'Estonian' ,
291 'eu' => 'Basque' ,
292 'fa' => 'Persian' ,
293 'fi' => 'Finnish' ,
294 'fj' => 'Fiji' ,
295 'fo' => 'Faeroese' ,
296 'fr' => 'French' ,
297 'fy' => 'Frisian' ,
298 'ga' => 'Irish' ,
299 'gd' => 'Scots/Gaelic' ,
300 'gl' => 'Galician' ,
301 'gn' => 'Guarani' ,
302 'gu' => 'Gujarati' ,
303 'ha' => 'Hausa' ,
304 'hi' => 'Hindi' ,
305 'hr' => 'Croatian' ,
306 'hu' => 'Hungarian' ,
307 'hy' => 'Armenian' ,
308 'ia' => 'Interlingua' ,
309 'ie' => 'Interlingue' ,
310 'ik' => 'Inupiak' ,
311 'in' => 'Indonesian' ,
312 'is' => 'Icelandic' ,
313 'it' => 'Italian' ,
314 'iw' => 'Hebrew' ,
315 'ja' => 'Japanese' ,
316 'ji' => 'Yiddish' ,
317 'jw' => 'Javanese' ,
318 'ka' => 'Georgian' ,
319 'kk' => 'Kazakh' ,
320 'kl' => 'Greenlandic' ,
321 'km' => 'Cambodian' ,
322 'kn' => 'Kannada' ,
323 'ko' => 'Korean' ,
324 'ks' => 'Kashmiri' ,
325 'ku' => 'Kurdish' ,
326 'ky' => 'Kirghiz' ,
327 'la' => 'Latin' ,
328 'ln' => 'Lingala' ,
329 'lo' => 'Laothian' ,
330 'lt' => 'Lithuanian' ,
331 'lv' => 'Latvian/Lettish' ,
332 'mg' => 'Malagasy' ,
333 'mi' => 'Maori' ,
334 'mk' => 'Macedonian' ,
335 'ml' => 'Malayalam' ,
336 'mn' => 'Mongolian' ,
337 'mo' => 'Moldavian' ,
338 'mr' => 'Marathi' ,
339 'ms' => 'Malay' ,
340 'mt' => 'Maltese' ,
341 'my' => 'Burmese' ,
342 'na' => 'Nauru' ,
343 'ne' => 'Nepali' ,
344 'nl' => 'Dutch' ,
345 'no' => 'Norwegian' ,
346 'oc' => 'Occitan' ,
347 'om' => '(Afan)/Oromoor/Oriya' ,
348 'pa' => 'Punjabi' ,
349 'pl' => 'Polish' ,
350 'ps' => 'Pashto/Pushto' ,
351 'pt' => 'Portuguese' ,
352 'qu' => 'Quechua' ,
353 'rm' => 'Rhaeto-Romance' ,
354 'rn' => 'Kirundi' ,
355 'ro' => 'Romanian' ,
356 'ru' => 'Russian' ,
357 'rw' => 'Kinyarwanda' ,
358 'sa' => 'Sanskrit' ,
359 'sd' => 'Sindhi' ,
360 'sg' => 'Sangro' ,
361 'sh' => 'Serbo-Croatian' ,
362 'si' => 'Singhalese' ,
363 'sk' => 'Slovak' ,
364 'sl' => 'Slovenian' ,
365 'sm' => 'Samoan' ,
366 'sn' => 'Shona' ,
367 'so' => 'Somali' ,
368 'sq' => 'Albanian' ,
369 'sr' => 'Serbian' ,
370 'ss' => 'Siswati' ,
371 'st' => 'Sesotho' ,
372 'su' => 'Sundanese' ,
373 'sv' => 'Swedish' ,
374 'sw' => 'Swahili' ,
375 'ta' => 'Tamil' ,
376 'te' => 'Tegulu' ,
377 'tg' => 'Tajik' ,
378 'th' => 'Thai' ,
379 'ti' => 'Tigrinya' ,
380 'tk' => 'Turkmen' ,
381 'tl' => 'Tagalog' ,
382 'tn' => 'Setswana' ,
383 'to' => 'Tonga' ,
384 'tr' => 'Turkish' ,
385 'ts' => 'Tsonga' ,
386 'tt' => 'Tatar' ,
387 'tw' => 'Twi' ,
388 'uk' => 'Ukrainian' ,
389 'ur' => 'Urdu' ,
390 'uz' => 'Uzbek' ,
391 'vi' => 'Vietnamese' ,
392 'vo' => 'Volapuk' ,
393 'wo' => 'Wolof' ,
394 'xh' => 'Xhosa' ,
395 'yo' => 'Yoruba' ,
396 'zh' => 'Chinese' ,
397 'zu' => 'Zulu' ,
398 );
399
400 return apply_filters('tutor/utils/languages', $language_codes);
401 }
402
403
404 /**
405 * @param string $value
406 *
407 * Check raw data
408 *
409 * @since v.1.0.0
410 */
411 public function print_view($value = ''){
412 echo '<pre>';
413 print_r($value);
414 echo '</pre>';
415 }
416
417 /**
418 * @param array $excludes
419 *
420 * @return array|null|object
421 *
422 * Get courses
423 *
424 * @since v.1.0.0
425 */
426
427 public function get_courses($excludes = array()){
428 global $wpdb;
429
430
431 $excludes = (array) $excludes;
432 $exclude_query = '';
433 if (count($excludes)){
434 $exclude_query = implode("','", $excludes);
435 }
436
437 $course_post_type = tutor()->course_post_type;
438 $query = $wpdb->get_results("SELECT ID, post_author, post_title, post_name,post_status, menu_order
439 from {$wpdb->posts} WHERE post_status = 'publish'
440 AND ID NOT IN('$exclude_query')
441 AND post_type = '{$course_post_type}' ");
442 return $query;
443 }
444
445 /**
446 * @param int $instructor_id
447 *
448 * @return array|null|object
449 *
450 * Get courses for instructors
451 *
452 * @since v.1.0.0
453 */
454 public function get_courses_for_instructors($instructor_id = 0){
455 global $wpdb;
456
457 $instructor_id = $this->get_user_id($instructor_id);
458
459 $course_post_type = tutor()->course_post_type;
460 $query = $wpdb->get_results("SELECT ID, post_author, post_title, post_name,post_status, menu_order
461 from {$wpdb->posts}
462 WHERE post_author = {$instructor_id}
463 AND post_status IN ('publish', 'pending')
464 AND post_type = '{$course_post_type}' ");
465 return $query;
466 }
467
468 /**
469 * @param $instructor_id
470 *
471 * @return null|string
472 *
473 * Get course count by instructor
474 *
475 * @since v.1.0.0
476 */
477
478 public function get_course_count_by_instructor($instructor_id){
479 global $wpdb;
480
481 $course_post_type = tutor()->course_post_type;
482 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts}
483 INNER JOIN {$wpdb->usermeta} ON user_id = {$instructor_id} AND meta_key = '_tutor_instructor_course_id' AND meta_value = ID
484 WHERE post_status = 'publish'
485 AND post_type = '{$course_post_type}' ; ");
486
487 return $count;
488 }
489
490 /**
491 * @param $instructor_id
492 *
493 * @return array|null|object
494 *
495 * Get courses by a instructor
496 *
497 * @since v.1.0.0
498 */
499 public function get_courses_by_instructor($instructor_id = 0, $post_status = array('publish')){
500 global $wpdb;
501
502 $instructor_id = $this->get_user_id($instructor_id);
503 $course_post_type = tutor()->course_post_type;
504
505 if ($post_status === 'any'){
506 $where_post_status = "";
507 }else{
508 $post_status = (array) $post_status;
509 $statuses = "'".implode("','", $post_status)."'";
510 $where_post_status = "AND $wpdb->posts.post_status IN({$statuses}) ";
511 }
512
513 //AND $wpdb->posts.post_date < NOW()
514 $querystr = "
515 SELECT $wpdb->posts.*
516 FROM $wpdb->posts
517 INNER JOIN {$wpdb->usermeta} ON $wpdb->usermeta.user_id = {$instructor_id} AND $wpdb->usermeta.meta_key = '_tutor_instructor_course_id' AND $wpdb->usermeta.meta_value = $wpdb->posts.ID
518
519 WHERE 1 = 1 {$where_post_status}
520 AND $wpdb->posts.post_type = '{$course_post_type}'
521
522 ORDER BY $wpdb->posts.post_date DESC";
523
524 $pageposts = $wpdb->get_results($querystr, OBJECT);
525 return $pageposts;
526 }
527
528 /**
529 * @return mixed
530 *
531 * Get archive page course count
532 *
533 * @since v.1.0.0
534 */
535 public function get_archive_page_course_count(){
536 global $wp_query;
537 return $wp_query->post_count;
538 }
539
540 /**
541 * @return null|string
542 *
543 * Get course count
544 *
545 * @since v.1.0.0
546 */
547 public function get_course_count(){
548 global $wpdb;
549
550 $course_post_type = tutor()->course_post_type;
551 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = '{$course_post_type}'; ");
552 return $count;
553 }
554
555 /**
556 * @return null|string
557 *
558 * Get lesson count
559 *
560 * @since v.1.0.0
561 */
562 public function get_lesson_count(){
563 global $wpdb;
564
565 $lesson_post_type = tutor()->lesson_post_type;
566 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = '{$lesson_post_type}'; ");
567 return $count;
568 }
569
570 /**
571 * @param int $course_id
572 * @param int $limit
573 *
574 * @return \WP_Query
575 *
576 * Get lesson
577 *
578 * @since v.1.0.0
579 */
580 public function get_lesson($course_id = 0, $limit = 10){
581 $course_id = $this->get_post_id($course_id);
582
583 $lesson_post_type = tutor()->lesson_post_type;
584 $args = array(
585 'post_status' => 'publish',
586 'post_type' => $lesson_post_type,
587 'posts_per_page' => $limit,
588 'meta_query' => array(
589 array(
590 'key' => '_tutor_course_id_for_lesson',
591 'value' => $course_id,
592 'compare' => '=',
593 ),
594 ),
595 );
596 $query = new \WP_Query($args);
597
598 return $query;
599 }
600
601 /**
602 * @param int $course_id
603 *
604 * @return int
605 *
606 * Get total lesson count by a course
607 *
608 * @since v.1.0.0
609 */
610 public function get_lesson_count_by_course($course_id = 0){
611 $course_id = $this->get_post_id($course_id);
612 global $wpdb;
613
614 $lesson_post_type = tutor()->lesson_post_type;
615
616 $course_id = $this->get_post_id($course_id);
617 $topicIDS = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'topics' AND post_parent = {$course_id} ");
618
619 $lesson_count = 0;
620 if ($this->count($topicIDS)){
621 $inIDS = implode(",", $topicIDS);
622 $lesson_count = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_parent IN({$inIDS}) AND post_type = '{$lesson_post_type}' ");
623 }
624
625 return (int) $lesson_count;
626 }
627
628 /**
629 * @param int $course_id
630 * @param int $user_id
631 *
632 * @return int
633 *
634 * Get completed lesson total number by a course
635 *
636 * @since v.1.0.0
637 */
638 public function get_completed_lesson_count_by_course($course_id = 0, $user_id = 0){
639 $course_id = $this->get_post_id($course_id);
640 $user_id = $this->get_user_id($user_id);
641 global $wpdb;
642
643 $completed_lesson_ids = $wpdb->get_col("select post_id from {$wpdb->postmeta} where meta_key = '_tutor_course_id_for_lesson' AND meta_value = {$course_id} ");
644
645 $count = 0;
646 if (is_array($completed_lesson_ids) && count($completed_lesson_ids)){
647 $completed_lesson_meta_ids = array();
648 foreach ($completed_lesson_ids as $lesson_id){
649 $completed_lesson_meta_ids[] = '_tutor_completed_lesson_id_'.$lesson_id;
650 }
651 $in_ids = implode("','", $completed_lesson_meta_ids);
652
653 $count = (int) $wpdb->get_var("select count(umeta_id) from {$wpdb->usermeta} WHERE user_id = '{$user_id}' AND meta_key in('{$in_ids}') ");
654 }
655
656 return $count;
657 }
658
659 /**
660 * @param int $course_id
661 * @param int $user_id
662 *
663 * @return float|int
664 *
665 * @since v.1.0.0
666 */
667 public function get_course_completed_percent($course_id = 0, $user_id = 0){
668 $course_id = $this->get_post_id($course_id);
669 $user_id = $this->get_user_id($user_id);
670
671 $total_lesson = $this->get_lesson_count_by_course($course_id);
672 $completed_lesson = $this->get_completed_lesson_count_by_course($course_id, $user_id);
673
674 if ($total_lesson > 0 && $completed_lesson > 0){
675 return number_format(($completed_lesson * 100) / $total_lesson);
676 }
677
678 return 0;
679 }
680
681 /**
682 * @param int $course_id
683 *
684 * @return \WP_Query
685 *
686 * Get all topics by given course ID
687 *
688 * @since v.1.0.0
689 */
690 public function get_topics($course_id = 0){
691 $course_id = $this->get_post_id($course_id);
692
693 $args = array(
694 'post_type' => 'topics',
695 'post_parent' => $course_id,
696 'orderby' => 'menu_order',
697 'order' => 'ASC',
698 'posts_per_page' => -1,
699 );
700
701 $query = new \WP_Query($args);
702 return $query;
703 }
704
705 /**
706 * @param $course_ID
707 *
708 * @return int
709 *
710 * Get next topic order id
711 *
712 * @since v.1.0.0
713 */
714 public function get_next_topic_order_id($course_ID){
715 global $wpdb;
716
717 $last_order = (int) $wpdb->get_var("SELECT MAX(menu_order) FROM {$wpdb->posts} WHERE post_parent = {$course_ID} AND post_type = 'topics';");
718 return $last_order + 1;
719 }
720
721 /**
722 * @param $topic_ID
723 *
724 * @return int
725 *
726 * Get next course content order id
727 *
728 * @since v.1.0.0
729 */
730 public function get_next_course_content_order_id($topic_ID){
731 global $wpdb;
732
733 $last_order = (int) $wpdb->get_var("SELECT MAX(menu_order) FROM {$wpdb->posts} WHERE post_parent = {$topic_ID};");
734 return $last_order + 1;
735 }
736
737 /**
738 * @param int $topics_id
739 * @param int $limit
740 *
741 * @return \WP_Query
742 *
743 * Get lesson by topic
744 *
745 * @since v.1.0.0
746 */
747 public function get_lessons_by_topic($topics_id = 0, $limit = 10){
748 $topics_id = $this->get_post_id($topics_id);
749
750 $lesson_post_type = tutor()->lesson_post_type;
751 $args = array(
752 'post_type' => $lesson_post_type,
753 'post_parent' => $topics_id,
754 'posts_per_page' => $limit,
755 'orderby' => 'menu_order',
756 'order' => 'ASC',
757 );
758
759 $query = new \WP_Query($args);
760
761 return $query;
762 }
763
764 /**
765 * @param int $topics_id
766 * @param int $limit
767 *
768 * @return \WP_Query
769 *
770 * Get course content by topic
771 *
772 * @since v.1.0.0
773 */
774 public function get_course_contents_by_topic($topics_id = 0, $limit = 10){
775 $topics_id = $this->get_post_id($topics_id);
776
777 $lesson_post_type = tutor()->lesson_post_type;
778 $args = array(
779 'post_type' => apply_filters('tutor_course_contents_post_types', array($lesson_post_type, 'tutor_quiz')),
780 'post_parent' => $topics_id,
781 'posts_per_page' => $limit,
782 'orderby' => 'menu_order',
783 'order' => 'ASC',
784 );
785
786 $query = new \WP_Query($args);
787
788 return $query;
789 }
790
791 /**
792 * @param string $request_method
793 *
794 * Check actions nonce
795 *
796 * @since v.1.0.0
797 */
798 public function checking_nonce($request_method = 'post'){
799 if ($request_method === 'post'){
800 if (!isset($_POST[tutor()->nonce]) || !wp_verify_nonce($_POST[tutor()->nonce], tutor()->nonce_action)) {
801 exit('Nonce does not matched');
802 }
803 }else{
804 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
805 exit('Nonce does not matched');
806 }
807 }
808 }
809
810 /**
811 * @param int $course_id
812 *
813 * @return bool
814 *
815 * @since v.1.0.0
816 */
817 public function is_course_purchasable($course_id = 0){
818 $course_id = $this->get_post_id($course_id);
819
820 $price_type = $this->price_type($course_id);
821 if ($price_type === 'free'){
822 $is_paid = apply_filters('is_course_paid', false, $course_id);
823 if ( ! $is_paid){
824 return false;
825 }
826 }
827 return apply_filters('is_course_purchasable', false, $course_id);
828 }
829
830 /**
831 * @param int $course_id
832 *
833 * @return null|string
834 *
835 * get course price in digits format if any
836 *
837 * @since v.1.0.0
838 */
839
840 public function get_course_price($course_id = 0){
841 $course_id = $this->get_post_id($course_id);
842
843 $price = null;
844
845 if ($this->is_course_purchasable()) {
846 $monetize_by = $this->get_option('monetize_by');
847
848 if ($this->has_wc() && $monetize_by === 'wc'){
849 $product_id = tutor_utils()->get_course_product_id($course_id);
850 $product = wc_get_product( $product_id );
851
852 if ( $product ) {
853 $price = $product->get_price();
854 }
855 }else{
856 $price = apply_filters('get_tutor_course_price', null, $course_id);
857 }
858 }
859
860 return $price;
861 }
862
863 /**
864 * @param int $course_id
865 *
866 * @return object
867 *
868 * Get raw course price and sale price of a course
869 * It could help you to calculate something
870 * Such as Calculate discount by regular price and sale price
871 *
872 * @since v.1.3.1
873 */
874 public function get_raw_course_price($course_id = 0){
875 $course_id = $this->get_post_id($course_id);
876
877 $prices = array(
878 'regular_price' => 0,
879 'sale_price' => 0,
880 );
881
882 $monetize_by = $this->get_option('monetize_by');
883
884 //if ($this->is_course_purchasable($course_id)){
885 $product_id = $this->get_course_product_id($course_id);
886 if ($product_id) {
887 if ( $monetize_by === 'wc' && $this->has_wc() ) {
888 $prices['regular_price'] = get_post_meta( $product_id, '_regular_price', true );
889 $prices['sale_price'] = get_post_meta( $product_id, '_sale_price', true );
890 } elseif ( $monetize_by === 'edd' && $this->has_edd() ) {
891 $prices['regular_price'] = get_post_meta( $product_id, 'edd_price', true );
892 $prices['sale_price'] = get_post_meta( $product_id, 'edd_price', true );
893 }
894 }
895 //}
896
897 return (object) $prices;
898 }
899
900 /**
901 * @param int $course_id
902 *
903 * @return mixed
904 *
905 * Get the course price type
906 *
907 * @since v.1.3.5
908 */
909
910 public function price_type($course_id = 0){
911 $course_id = $this->get_post_id($course_id);
912
913 $price_type = get_post_meta($course_id, '_tutor_course_price_type', true);
914 return $price_type;
915 }
916
917 /**
918 * @param int $course_id
919 *
920 * @return array|bool|null|object
921 *
922 * Check if current user has been enrolled or not
923 *
924 * @since v.1.0.0
925 */
926
927 public function is_enrolled($course_id = 0, $user_id = 0){
928 $course_id = $this->get_post_id($course_id);
929 $user_id = $this->get_user_id($user_id);
930
931 if (is_user_logged_in()) {
932 global $wpdb;
933
934 do_action('tutor_is_enrolled_before', $course_id, $user_id);
935
936 $getEnrolledInfo = $wpdb->get_row( "select ID, post_author, post_date,post_date_gmt,post_title from {$wpdb->posts} WHERE post_type = 'tutor_enrolled' AND post_parent = {$course_id} AND post_author = {$user_id} AND post_status = 'completed'; " );
937
938 if ( $getEnrolledInfo ) {
939 return apply_filters('tutor_is_enrolled', $getEnrolledInfo, $course_id, $user_id);
940 }
941 }
942 return false;
943 }
944
945 /**
946 * @param int $course_id
947 * @param int $user_id
948 *
949 * @return array|bool|null|object|void
950 *
951 * Has any enrolled for a user in a course
952 *
953 * @since v.1.0.0
954 */
955 public function has_any_enrolled($course_id = 0, $user_id = 0){
956 $course_id = $this->get_post_id($course_id);
957 $user_id = $this->get_user_id($user_id);
958
959 if (is_user_logged_in()) {
960 global $wpdb;
961
962 $getEnrolledInfo = $wpdb->get_row( "select ID, post_author, post_date,post_date_gmt,post_title from {$wpdb->posts} WHERE post_type = 'tutor_enrolled' AND post_parent = {$course_id} AND post_author = {$user_id}; " );
963
964 if ( $getEnrolledInfo ) {
965 return $getEnrolledInfo;
966 }
967 }
968 return false;
969 }
970
971 /**
972 * @param int $lesson_id
973 * @param int $user_id
974 *
975 * @return array|bool|null|object
976 *
977 * Get the course Enrolled confirmation by lesson ID
978 *
979 * @since v.1.0.0
980 */
981
982 public function is_course_enrolled_by_lesson($lesson_id = 0, $user_id = 0){
983 $lesson_id = $this->get_post_id($lesson_id);
984 $user_id = $this->get_user_id($user_id);
985 $course_id = $this->get_course_id_by_lesson($lesson_id);
986
987 return $this->is_enrolled($course_id);
988 }
989
990 /**
991 * @param int $lesson_id
992 *
993 * @return bool|mixed
994 *
995 * Get the course ID by Lesson
996 *
997 * @since v.1.0.0
998 *
999 * @updated v.1.4.8
1000 * Added Legacy Supports
1001 */
1002
1003 public function get_course_id_by_lesson($lesson_id = 0){
1004 $lesson_id = $this->get_post_id($lesson_id);
1005 $course_id = get_post_meta($lesson_id, '_tutor_course_id_for_lesson', true);
1006
1007 if ( ! $course_id) {
1008 $course_id = $this->get_course_id_by_content($lesson_id);
1009 }
1010 if ( ! $course_id){
1011 $course_id = 0;
1012 }
1013
1014 return $course_id;
1015 }
1016
1017 /**
1018 * @param int $course_id
1019 *
1020 * @return bool|false|string
1021 *
1022 * Get first lesson of a course
1023 *
1024 * @since v.1.0.0
1025 */
1026 public function get_course_first_lesson($course_id = 0){
1027 $course_id = $this->get_post_id($course_id);
1028 global $wpdb;
1029
1030 $user_id = get_current_user_id();
1031
1032 $lessons = $wpdb->get_results("SELECT items.ID FROM {$wpdb->posts} topic
1033 INNER JOIN {$wpdb->posts} items ON topic.ID = items.post_parent
1034 WHERE topic.post_parent = {$course_id} AND items.post_status = 'publish' order by topic.menu_order ASC, items.menu_order ASC;");
1035
1036 $first_lesson = false;
1037
1038 if (tutils()->count($lessons)){
1039 if (! empty($lessons[0])){
1040 $first_lesson = $lessons[0];
1041 }
1042
1043 foreach ($lessons as $lesson){
1044 $is_complete = get_user_meta($user_id, "_tutor_completed_lesson_id_{$lesson->ID}", true);
1045 if ( ! $is_complete){
1046 $first_lesson = $lesson;
1047 break;
1048 }
1049 }
1050
1051 if (! empty($first_lesson->ID)){
1052 return get_permalink($first_lesson->ID);
1053 }
1054 }
1055
1056 return false;
1057 }
1058
1059 /**
1060 *
1061 * Get course sub pages in course dashboard
1062 *
1063 * @since v.1.0.0
1064 */
1065 public function course_sub_pages(){
1066 $nav_items = array(
1067 'overview' => __('Overview', 'tutor'),
1068 'questions' => __('Q&A', 'tutor'),
1069 'announcements' => __('Announcements', 'tutor'),
1070 );
1071 return apply_filters('tutor_course/single/enrolled/nav_items', $nav_items);
1072 }
1073
1074 /**
1075 * @param int $post_id
1076 *
1077 * @return bool|array
1078 *
1079 * @since v.1.0.0
1080 */
1081 public function get_video($post_id = 0){
1082 $post_id = $this->get_post_id($post_id);
1083 $attachments = get_post_meta($post_id, '_video', true);
1084 if ($attachments) {
1085 $attachments = maybe_unserialize($attachments);
1086 }
1087 return $attachments;
1088 }
1089
1090 /**
1091 * @param int $post_id
1092 * @param array $video_data
1093 *
1094 * @return bool
1095 *
1096 * Update the video Info
1097 */
1098 public function update_video($post_id = 0, $video_data = array()){
1099 $post_id = $this->get_post_id($post_id);
1100
1101 if (is_array($video_data) && count($video_data)){
1102 update_post_meta($post_id, '_video', $video_data);
1103 }
1104 }
1105
1106 /**
1107 * @param int $post_id
1108 *
1109 * @return bool|mixed
1110 *
1111 * @since v.1.0.0
1112 */
1113 public function get_attachments($post_id = 0){
1114 $post_id = $this->get_post_id($post_id);
1115 $attachments_arr = array();
1116 $attachments = maybe_unserialize(get_post_meta($post_id, '_tutor_attachments', true));
1117
1118 $font_icons = apply_filters('tutor_file_types_icon', array(
1119 'archive',
1120 'audio',
1121 'code',
1122 'default',
1123 'document',
1124 'interactive',
1125 'spreadsheet',
1126 'text',
1127 'video',
1128 'image',
1129 ));
1130
1131 if ( is_array($attachments) && count($attachments)) {
1132 foreach ( $attachments as $attachment ) {
1133 $url = wp_get_attachment_url( $attachment );
1134 $file_type = wp_check_filetype( $url );
1135 $ext = $file_type['ext'];
1136 $title = get_the_title($attachment);
1137
1138 $file_path = get_attached_file( $attachment );
1139 $size_bytes = file_exists($file_path) ? filesize( $file_path ) : 0;
1140 $size = size_format( $size_bytes, 2 );
1141 $type = wp_ext2type( $ext );
1142
1143 $icon = 'default';
1144 if ( $type && in_array( $type, $font_icons ) ) {
1145 $icon = $type;
1146 }
1147
1148 $data = array(
1149 'post_id' => $post_id,
1150 'id' => $attachment,
1151 'url' => $url,
1152 'name' => $title . '.' . $ext,
1153 'title' => $title,
1154 'ext' => $ext,
1155 'size' => $size,
1156 'size_bytes' => $size_bytes,
1157 'icon' => $icon,
1158 );
1159
1160 $attachments_arr[] = (object) apply_filters( 'tutor/posts/attachments', $data );
1161 }
1162 }
1163
1164 return $attachments_arr;
1165 }
1166
1167
1168 /**
1169 * @param $seconds
1170 *
1171 * @return string
1172 *
1173 * return seconds to formatted playtime
1174 *
1175 * @since v.1.0.0
1176 */
1177 public function playtime_string($seconds) {
1178 $sign = (($seconds < 0) ? '-' : '');
1179 $seconds = round(abs($seconds));
1180 $H = (int) floor( $seconds / 3600);
1181 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
1182 $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
1183 return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
1184 }
1185
1186 /**
1187 * @param $seconds
1188 *
1189 * @return array
1190 *
1191 * Get the playtime in array
1192 *
1193 * @since v.1.0.0
1194 */
1195 public function playtime_array($seconds){
1196 $run_time_format = array(
1197 'hours' => '00',
1198 'minutes' => '00',
1199 'seconds' => '00',
1200 );
1201
1202 if ($seconds <= 0 ){
1203 return $run_time_format;
1204 }
1205
1206 $playTimeString = $this->playtime_string($seconds);
1207 $timeInArray = explode(':', $playTimeString);
1208
1209 $run_time_size = count($timeInArray);
1210 if ($run_time_size === 3){
1211 $run_time_format['hours'] = $timeInArray[0];
1212 $run_time_format['minutes'] = $timeInArray[1];
1213 $run_time_format['seconds'] = $timeInArray[2];
1214 }elseif($run_time_size === 2){
1215 $run_time_format['minutes'] = $timeInArray[0];
1216 $run_time_format['seconds'] = $timeInArray[1];
1217 }
1218
1219 return $run_time_format;
1220 }
1221
1222 /**
1223 * @param $seconds
1224 *
1225 * @return string
1226 *
1227 * Convert seconds to human readable time
1228 *
1229 * @since v.1.0.0
1230 */
1231 public function seconds_to_time_context($seconds) {
1232 $sign = (($seconds < 0) ? '-' : '');
1233 $seconds = round(abs($seconds));
1234 $H = (int) floor( $seconds / 3600);
1235 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
1236 $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
1237
1238 return $sign.($H ? $H.'h ' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).'m '.str_pad($S, 2, 0, STR_PAD_LEFT).'s';
1239 }
1240
1241 /**
1242 * @param int $lesson_id
1243 *
1244 * @return bool|object
1245 *
1246 * @since v.1.0.0
1247 */
1248
1249 public function get_video_info($lesson_id = 0){
1250 $lesson_id = $this->get_post_id($lesson_id);
1251 $video = $this->get_video($lesson_id);
1252
1253 if ( ! $video){
1254 return false;
1255 }
1256
1257 $info = array(
1258 'playtime' => '00:00',
1259 );
1260
1261 $types = apply_filters('tutor_video_types', array("mp4"=>"video/mp4", "webm"=>"video/webm", "ogg"=>"video/ogg"));
1262
1263 $videoSource = $this->avalue_dot('source', $video);
1264
1265 if ($videoSource === 'html5'){
1266 $sourceVideoID = $this->avalue_dot('source_video_id', $video);
1267 $video_info = get_post_meta($sourceVideoID, '_wp_attachment_metadata', true);
1268
1269 if ( $video_info && in_array($this->array_get('mime_type', $video_info), $types) ) {
1270 $path = get_attached_file( $sourceVideoID );
1271 $info['playtime'] = $video_info['length_formatted'];
1272 $info['path'] = $path;
1273 $info['url'] = wp_get_attachment_url( $sourceVideoID );
1274 $info['ext'] = strtolower( pathinfo( $path, PATHINFO_EXTENSION ) );
1275 $info['type'] = $types[ $info['ext'] ];
1276 }
1277 }
1278
1279 if ($videoSource !== 'html5'){
1280 $video = maybe_unserialize(get_post_meta($lesson_id, '_video', true));
1281
1282 $runtimeHours = tutor_utils()->avalue_dot('runtime.hours', $video);
1283 $runtimeMinutes = tutor_utils()->avalue_dot('runtime.minutes', $video);
1284 $runtimeSeconds = tutor_utils()->avalue_dot('runtime.seconds', $video);
1285
1286 $runtimeHours = $runtimeHours ? $runtimeHours : '00';
1287 $runtimeMinutes = $runtimeMinutes ? $runtimeMinutes : '00';
1288 $runtimeSeconds = $runtimeSeconds ? $runtimeSeconds : '00';
1289
1290 $info['playtime'] = "$runtimeHours:$runtimeMinutes:$runtimeSeconds";
1291 }
1292
1293 $info = array_merge($info, $video);
1294
1295 return (object) $info;
1296 }
1297
1298 /**
1299 * @param int $post_id
1300 *
1301 * @return bool
1302 *
1303 * Ensure if attached video is self hosted or not
1304 *
1305 * @since v.1.0.0
1306 */
1307 public function is_html5_video($post_id = 0){
1308 $post_id = $this->get_post_id($post_id);
1309
1310 $video = $this->get_video($post_id);
1311 if ( ! $video){
1312 return false;
1313 }
1314 $videoSource = $this->avalue_dot('source', $video);
1315 return $videoSource === 'html5';
1316 }
1317
1318 /**
1319 *
1320 * return lesson type icon
1321 *
1322 * @param int $lesson_id
1323 * @param bool $html
1324 * @param bool $echo
1325 *
1326 * @return string
1327 *
1328 * @since v.1.0.0
1329 */
1330
1331 public function get_lesson_type_icon($lesson_id = 0, $html = false, $echo = false){
1332 $post_id = $this->get_post_id($lesson_id);
1333 $video = tutor_utils()->get_video_info($post_id);
1334
1335 $play_time = false;
1336 if ($video){
1337 $play_time = $video->playtime;
1338 }
1339
1340 $tutor_lesson_type_icon = $play_time ? 'youtube' : 'document';
1341
1342 if ($html){
1343 $tutor_lesson_type_icon = "<i class='tutor-icon-$tutor_lesson_type_icon'></i> ";
1344 }
1345
1346 if ($tutor_lesson_type_icon){
1347 echo $tutor_lesson_type_icon;
1348 }
1349
1350 return $tutor_lesson_type_icon;
1351 }
1352
1353 /**
1354 * @param int $lesson_id
1355 * @param int $user_id
1356 *
1357 * @return bool|mixed
1358 *
1359 * @since v.1.0.0
1360 */
1361
1362 public function is_completed_lesson($lesson_id = 0, $user_id = 0){
1363 $lesson_id = $this->get_post_id($lesson_id);
1364 $user_id = $this->get_user_id($user_id);
1365
1366 $is_completed = get_user_meta($user_id, '_tutor_completed_lesson_id_'.$lesson_id, true);
1367
1368 if ($is_completed){
1369 return $is_completed;
1370 }
1371
1372 return false;
1373 }
1374
1375 /**
1376 * @param int $course_id
1377 * @param int $user_id
1378 *
1379 * @return array|bool|null|object
1380 *
1381 * Determine if a course completed
1382 *
1383 * @since v.1.0.0
1384 *
1385 * @updated v.1.4.9
1386 */
1387
1388 public function is_completed_course($course_id = 0, $user_id = 0){
1389 if ( ! is_user_logged_in()){
1390 return apply_filters('is_completed_course', false, $course_id, $user_id);
1391 }
1392
1393 global $wpdb;
1394 $course_id = $this->get_post_id($course_id);
1395 $user_id = $this->get_user_id($user_id);
1396
1397 $is_completed = $wpdb->get_row("SELECT comment_ID,
1398 comment_post_ID as course_id,
1399 comment_author as completed_user_id,
1400 comment_date as completion_date,
1401 comment_content as completed_hash
1402 from {$wpdb->comments}
1403 WHERE comment_agent = 'TutorLMSPlugin'
1404 AND comment_type = 'course_completed'
1405 AND comment_post_ID = {$course_id}
1406 AND user_id = {$user_id} ;");
1407
1408 if ($is_completed){
1409 return apply_filters('is_completed_course', $is_completed, $course_id, $user_id);
1410 }
1411
1412 return apply_filters('is_completed_course', false, $course_id, $user_id);
1413 }
1414
1415 /**
1416 * @param array $input
1417 *
1418 * @return array
1419 *
1420 * Sanitize input array
1421 *
1422 * @since v.1.0.0
1423 */
1424 public function sanitize_array($input = array()){
1425 $array = array();
1426
1427 if (is_array($input) && count($input)){
1428 foreach ($input as $key => $value){
1429 if (is_array($value)){
1430 $array[$key] = $this->sanitize_array($value);
1431 }else{
1432 $key = sanitize_text_field($key);
1433 $value = sanitize_text_field($value);
1434 $array[$key] = $value;
1435 }
1436 }
1437 }
1438
1439 return $array;
1440 }
1441
1442 /**
1443 * @param int $post_id
1444 *
1445 * @return array|bool
1446 *
1447 * Determine if has any video in single
1448 *
1449 * @since v.1.0.0
1450 */
1451
1452 public function has_video_in_single($post_id = 0){
1453 if (is_single()) {
1454 $post_id = $this->get_post_id($post_id);
1455
1456 $video = $this->get_video( $post_id );
1457 if ( $video && $this->array_get('source', $video) !== '-1' ) {
1458 return $video;
1459 }
1460 }
1461 return false;
1462 }
1463
1464 /**
1465 * @param int $start
1466 * @param int $limit
1467 * @param string $search_term
1468 * @param int $course_id
1469 *
1470 * @return array|null|object
1471 *
1472 *
1473 * Get the enrolled students for all courses.
1474 *
1475 * Pass course id in 4th parameter to get students course wise.
1476 *
1477 * @since v.1.0.0
1478 */
1479 public function get_students($start = 0, $limit = 10, $search_term = ''){
1480 $meta_key = '_is_tutor_student';
1481
1482 global $wpdb;
1483
1484 if ($search_term){
1485 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
1486 }
1487
1488 $students = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS {$wpdb->users}.* FROM {$wpdb->users}
1489 INNER JOIN {$wpdb->usermeta}
1490 ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id )
1491 WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) {$search_term}
1492 ORDER BY {$wpdb->usermeta}.meta_value DESC
1493 LIMIT {$start}, {$limit} ");
1494
1495 return $students;
1496 }
1497
1498 /**
1499 * @return int
1500 *
1501 * @since v.1.0.0
1502 *
1503 * get the total students
1504 * pass course id to get course wise total students
1505 *
1506 * @since v.1.0.0
1507 */
1508 public function get_total_students($search_term = ''){
1509 $meta_key = '_is_tutor_student';
1510
1511 global $wpdb;
1512
1513 if ($search_term){
1514 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
1515 }
1516
1517 $count = $wpdb->get_var("SELECT COUNT({$wpdb->users}.ID) FROM {$wpdb->users} INNER JOIN {$wpdb->usermeta} ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id ) WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) $search_term ");
1518
1519 return (int) $count;
1520 }
1521
1522 /**
1523 * @param int $user_id
1524 *
1525 * @return array
1526 *
1527 * Get complete courses ids by user
1528 *
1529 * @since v.1.0.0
1530 */
1531 public function get_completed_courses_ids_by_user($user_id = 0){
1532 global $wpdb;
1533
1534 $user_id = $this->get_user_id($user_id);
1535
1536 $course_ids = (array) $wpdb->get_col("SELECT comment_post_ID as course_id
1537 from {$wpdb->comments}
1538 WHERE comment_agent = 'TutorLMSPlugin'
1539 AND comment_type = 'course_completed'
1540 AND user_id = {$user_id} ;");
1541
1542 return $course_ids;
1543 }
1544
1545 /**
1546 * @param int $user_id
1547 *
1548 * @return bool|\WP_Query
1549 *
1550 * Return courses by user_id
1551 *
1552 * @since v.1.0.0
1553 */
1554 public function get_courses_by_user($user_id = 0){
1555 $user_id = $this->get_user_id($user_id);
1556 $course_ids = $this->get_completed_courses_ids_by_user($user_id);
1557
1558 if (count($course_ids)){
1559 $course_post_type = tutor()->course_post_type;
1560 $course_args = array(
1561 'post_type' => $course_post_type,
1562 'post_status' => 'publish',
1563 'post__in' => $course_ids,
1564 );
1565
1566 return new \WP_Query($course_args);
1567 }
1568
1569 return false;
1570 }
1571
1572 /**
1573 * @param int $user_id
1574 *
1575 * @return bool|\WP_Query
1576 *
1577 * Get the active course by user
1578 *
1579 * @since v.1.0.0
1580 */
1581
1582 public function get_active_courses_by_user($user_id = 0){
1583 $user_id = $this->get_user_id($user_id);
1584
1585 $course_ids = $this->get_completed_courses_ids_by_user($user_id);
1586 $enrolled_course_ids = $this->get_enrolled_courses_ids_by_user($user_id);
1587 $active_courses = array_diff($enrolled_course_ids, $course_ids);
1588
1589 if (count($active_courses)){
1590 $course_post_type = tutor()->course_post_type;
1591 $course_args = array(
1592 'post_type' => $course_post_type,
1593 'post_status' => 'publish',
1594 'post__in' => $active_courses,
1595 );
1596
1597 return new \WP_Query($course_args);
1598 }
1599
1600 return false;
1601 }
1602
1603 /**
1604 * @param int $user_id
1605 *
1606 * @return array
1607 *
1608 * Get enrolled course ids by a user
1609 *
1610 * @since v.1.0.0
1611 */
1612
1613 public function get_enrolled_courses_ids_by_user($user_id = 0){
1614 global $wpdb;
1615 $user_id = $this->get_user_id($user_id);
1616 $course_ids = $wpdb->get_col("select post_parent from {$wpdb->posts} WHERE post_type = 'tutor_enrolled' AND post_author = {$user_id} AND post_status = 'completed'; ");
1617
1618 return $course_ids;
1619 }
1620
1621 /**
1622 * @param int $course_id
1623 *
1624 * @return int
1625 *
1626 * Get the total enrolled users at course
1627 */
1628 public function count_enrolled_users_by_course($course_id = 0){
1629 global $wpdb;
1630 $course_id = $this->get_post_id($course_id);
1631
1632 $course_ids = $wpdb->get_var("select COUNT(ID) from {$wpdb->posts} WHERE post_type = 'tutor_enrolled' AND post_parent = {$course_id} AND post_status = 'completed'; ");
1633
1634 return (int) $course_ids;
1635 }
1636
1637 /**
1638 * @param int $user_id
1639 *
1640 * @return bool|\WP_Query
1641 *
1642 * Get the enrolled courses by user
1643 */
1644 public function get_enrolled_courses_by_user($user_id = 0){
1645 global $wpdb;
1646
1647 $user_id = $this->get_user_id($user_id);
1648 $course_ids = $this->get_enrolled_courses_ids_by_user($user_id);
1649
1650 if (count($course_ids)){
1651 $course_post_type = tutor()->course_post_type;
1652 $course_args = array(
1653 'post_type' => $course_post_type,
1654 'post_status' => 'publish',
1655 'post__in' => $course_ids,
1656 );
1657 return new \WP_Query($course_args);
1658 }
1659 return false;
1660 }
1661
1662
1663 /**
1664 * @param int $post_id
1665 *
1666 * @return string
1667 *
1668 * Get the video streaming URL by post/lesson/course ID
1669 */
1670 public function get_video_stream_url($post_id = 0){
1671 $post_id = $this->get_post_id($post_id);
1672 $post = get_post($post_id);
1673
1674 if ($post->post_type === tutor()->lesson_post_type ){
1675 $video_url = trailingslashit(home_url()).'video-url/'.$post->post_name;
1676 }else{
1677 $video_info = tutor_utils()->get_video_info($post_id);
1678 $video_url = $video_info->url;
1679 }
1680
1681 return $video_url;
1682 }
1683
1684 /**
1685 * @param int $lesson_id
1686 * @param int $user_id
1687 *
1688 * @return array|bool|mixed
1689 *
1690 * Get student lesson reading current info
1691 *
1692 * @since v.1.0.0
1693 */
1694 public function get_lesson_reading_info_full($lesson_id = 0, $user_id = 0){
1695 $lesson_id = $this->get_post_id($lesson_id);
1696 $user_id = $this->get_user_id($user_id);
1697
1698 $lesson_info = (array) maybe_unserialize(get_user_meta($user_id, '_lesson_reading_info', true));
1699 return $this->avalue_dot($lesson_id, $lesson_info);
1700 }
1701
1702 /**
1703 * @param int $post_id
1704 *
1705 * @return bool|false|int
1706 *
1707 * Get current post id or given post id
1708 *
1709 * @since v.1.0.0
1710 */
1711 public function get_post_id($post_id = 0){
1712 if ( ! $post_id){
1713 $post_id = get_the_ID();
1714 if ( ! $post_id){
1715 return false;
1716 }
1717 }
1718
1719 return $post_id;
1720 }
1721
1722 /**
1723 * @param int $user_id
1724 *
1725 * @return bool|int
1726 *
1727 * Get current user or given user ID
1728 *
1729 * @since v.1.0.0
1730 */
1731 public function get_user_id($user_id = 0){
1732 if ( ! $user_id){
1733 $user_id = get_current_user_id();
1734 if ( ! $user_id){
1735 return false;
1736 }
1737 }
1738
1739 return $user_id;
1740 }
1741
1742 /**
1743 * @param int $lesson_id
1744 * @param int $user_id
1745 * @param string $key
1746 *
1747 * @return array|bool|mixed
1748 *
1749 * Get lesson reading info by key
1750 *
1751 * @since v.1.0.0
1752 */
1753
1754 public function get_lesson_reading_info($lesson_id = 0, $user_id = 0, $key = ''){
1755 $lesson_id = $this->get_post_id($lesson_id);
1756 $user_id = $this->get_user_id($user_id);
1757
1758 $lesson_info = $this->get_lesson_reading_info_full($lesson_id, $user_id);
1759
1760 return $this->avalue_dot($key, $lesson_info);
1761 }
1762
1763 /**
1764 * @param int $lesson_id
1765 * @param int $user_id
1766 * @param array $data
1767 *
1768 * @return bool
1769 *
1770 * Update student lesson reading info
1771 *
1772 * @since v.1.0.0
1773 */
1774 public function update_lesson_reading_info($lesson_id = 0, $user_id = 0, $key = '', $value = ''){
1775 $lesson_id = $this->get_post_id($lesson_id);
1776 $user_id = $this->get_user_id($user_id);
1777
1778 if ($key && $value){
1779 $lesson_info = (array) maybe_unserialize(get_user_meta($user_id, '_lesson_reading_info', true));
1780 $lesson_info[$lesson_id][$key] = $value;
1781 update_user_meta($user_id, '_lesson_reading_info', $lesson_info);
1782 }
1783 }
1784
1785 /**
1786 * @param string $url
1787 *
1788 * @return bool
1789 *
1790 * Get the Youtube Video ID from URL
1791 *
1792 * @since v.1.0.0
1793 */
1794 public function get_youtube_video_id($url = ''){
1795 if (!$url){
1796 return false;
1797 }
1798 preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match);
1799
1800 if (isset($match[1])) {
1801 $youtube_id = $match[1];
1802 return $youtube_id;
1803 }
1804
1805 return false;
1806 }
1807
1808 /**
1809 * @param string $url
1810 *
1811 * @return bool
1812 *
1813 * Get the vimeo video id from URL
1814 *
1815 * @since v.1.0.0
1816 */
1817 public function get_vimeo_video_id($url = ''){
1818 if (preg_match('%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)(?:[?]?.*)$%im', $url, $match)) {
1819 if (isset($match[3])){
1820 return $match[3];
1821 }
1822 }
1823 return false;
1824 }
1825
1826 /**
1827 * @param int $post_id
1828 *
1829 * Mark lesson complete
1830 *
1831 * @since v.1.0.0
1832 */
1833 public function mark_lesson_complete($post_id = 0, $user_id = 0){
1834 $post_id = $this->get_post_id($post_id);
1835 $user_id = $this->get_user_id($user_id);
1836
1837 do_action('tutor_mark_lesson_complete_before', $post_id, $user_id);
1838 update_user_meta($user_id, '_tutor_completed_lesson_id_'.$post_id, tutor_time());
1839 do_action('tutor_mark_lesson_complete_after', $post_id, $user_id);
1840 }
1841
1842 /**
1843 *
1844 * @param int $course_id
1845 * @param int $order_id
1846 * @param int $user_id
1847 *
1848 * Saving enroll information to posts table
1849 * post_author = enrolled_student_id (wp_users id)
1850 * post_parent = enrolled course id
1851 *
1852 * @type: call when need
1853 * @return bool;
1854 *
1855 * @since v.1.0.0
1856 * @updated v.1.4.3
1857 *
1858 * @return bool
1859 */
1860
1861 public function do_enroll($course_id = 0, $order_id = 0, $user_id = 0){
1862 if ( ! $course_id){
1863 return false;
1864 }
1865
1866 do_action('tutor_before_enroll', $course_id);
1867 $user_id = $this->get_user_id($user_id);
1868 $title = __('Course Enrolled', 'tutor')." &ndash; ".date(get_option('date_format')) .' @ '.date(get_option('time_format') ) ;
1869
1870 $enrolment_status = 'completed';
1871
1872 if ($this->is_course_purchasable($course_id)) {
1873 /**
1874 * We need to verify this enrollment, we will change the status later after payment confirmation
1875 */
1876 $enrolment_status = 'pending';
1877 }
1878
1879 $enroll_data = apply_filters('tutor_enroll_data',
1880 array(
1881 'post_type' => 'tutor_enrolled',
1882 'post_title' => $title,
1883 'post_status' => $enrolment_status,
1884 'post_author' => $user_id,
1885 'post_parent' => $course_id,
1886 )
1887 );
1888
1889 // Insert the post into the database
1890 $isEnrolled = wp_insert_post( $enroll_data );
1891 if ($isEnrolled) {
1892 do_action('tutor_after_enroll', $course_id, $isEnrolled);
1893
1894 //Mark Current User as Students with user meta data
1895 update_user_meta( $user_id, '_is_tutor_student', tutor_time() );
1896
1897 if ($order_id) {
1898 //Mark order for course and user
1899 $product_id = $this->get_course_product_id($course_id);
1900 update_post_meta( $isEnrolled, '_tutor_enrolled_by_order_id', $order_id );
1901 update_post_meta( $isEnrolled, '_tutor_enrolled_by_product_id', $product_id );
1902 update_post_meta( $order_id, '_is_tutor_order_for_course', tutor_time() );
1903 update_post_meta( $order_id, '_tutor_order_for_course_id_'.$course_id, $isEnrolled );
1904 }
1905 return true;
1906 }
1907
1908 return false;
1909 }
1910
1911
1912 /**
1913 * @param int $course_id
1914 * @param int $user_id
1915 * @param string $cancel_status
1916 */
1917 public function cancel_course_enrol($course_id = 0, $user_id = 0, $cancel_status = 'canceled'){
1918 $course_id = $this->get_post_id($course_id);
1919 $user_id = $this->get_user_id($user_id);
1920
1921 $enrolled = $this->is_enrolled($course_id, $user_id);
1922
1923 if ($enrolled){
1924 global $wpdb;
1925
1926 if ($cancel_status === 'delete'){
1927 $wpdb->delete($wpdb->posts, array('post_type' => 'tutor_enrolled', 'post_author' => $user_id, 'post_parent' => $course_id));
1928
1929 //Delete Related Meta Data
1930 delete_post_meta($enrolled->ID, '_tutor_enrolled_by_product_id');
1931 $order_id = get_post_meta($enrolled->ID, '_tutor_enrolled_by_order_id', true);
1932 if ($order_id){
1933 delete_post_meta($enrolled->ID, '_tutor_enrolled_by_order_id');
1934 delete_post_meta($order_id, '_is_tutor_order_for_course');
1935 delete_post_meta($order_id, '_tutor_order_for_course_id_'.$course_id);
1936 }
1937 }else{
1938 $wpdb->update($wpdb->posts, array('post_status' => $cancel_status), array('post_type' => 'tutor_enrolled', 'post_author' => $user_id, 'post_parent' => $course_id) );
1939 }
1940 }
1941 }
1942
1943 /**
1944 * @param $order_id
1945 *
1946 * Complete course enrollment and do some task
1947 *
1948 * @since v.1.0.0
1949 */
1950 public function complete_course_enroll($order_id){
1951 if ( ! tutor_utils()->is_tutor_order($order_id)){
1952 return;
1953 }
1954
1955 global $wpdb;
1956
1957 $enrolled_ids_with_course = $this->get_course_enrolled_ids_by_order_id($order_id);
1958 if ($enrolled_ids_with_course){
1959 $enrolled_ids = wp_list_pluck($enrolled_ids_with_course, 'enrolled_id');
1960
1961 if (is_array($enrolled_ids) && count($enrolled_ids)){
1962 foreach ($enrolled_ids as $enrolled_id){
1963 $wpdb->update( $wpdb->posts, array( 'post_status' => 'completed' ), array( 'ID' => $enrolled_id ) );
1964 }
1965 }
1966 }
1967 }
1968
1969 /**
1970 * @param $order_id
1971 *
1972 * @return array|bool
1973 *
1974 * @since v.1.0.0
1975 */
1976 public function get_course_enrolled_ids_by_order_id($order_id){
1977 global $wpdb;
1978 //Getting all of courses ids within this order
1979
1980 $courses_ids = $wpdb->get_results("SELECT * FROM {$wpdb->postmeta} WHERE post_id = {$order_id} AND meta_key LIKE '_tutor_order_for_course_id_%' ");
1981
1982 if (is_array($courses_ids) && count($courses_ids)){
1983 $course_enrolled_by_order = array();
1984 foreach ($courses_ids as $courses_id){
1985 $course_id = str_replace('_tutor_order_for_course_id_', '',$courses_id->meta_key);
1986 //array(order_id => array('course_id' => $course_id, 'enrolled_id' => enrolled_id))
1987 $course_enrolled_by_order[] = array('course_id' => $course_id, 'enrolled_id' => $courses_id->meta_value, 'order_id' => $courses_id->post_id );
1988 }
1989 return $course_enrolled_by_order;
1990 }
1991 return false;
1992 }
1993
1994 /**
1995 * Get wc product in efficient query
1996 *
1997 * @since v.1.0.0
1998 */
1999
2000 /**
2001 * @return array|null|object
2002 *
2003 * WooCommerce specific utils
2004 */
2005 public function get_wc_products_db(){
2006 global $wpdb;
2007 $query = $wpdb->get_results("SELECT ID, post_title from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'product' ");
2008
2009 return $query;
2010 }
2011
2012 /**
2013 * @return array|null|object
2014 *
2015 * Get EDD Products
2016 */
2017 public function get_edd_products(){
2018 global $wpdb;
2019 $query = $wpdb->get_results("SELECT ID, post_title from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'download' ");
2020
2021 return $query;
2022 }
2023
2024 /**
2025 * @param int $course_id
2026 *
2027 * @return int
2028 *
2029 * Get course productID
2030 *
2031 * @since v.1.0.0
2032 */
2033 public function get_course_product_id($course_id = 0){
2034 $course_id = $this->get_post_id($course_id);
2035 $product_id = (int) get_post_meta($course_id, '_tutor_course_product_id', true);
2036
2037 return $product_id;
2038 }
2039
2040 /**
2041 * @param int $product_id
2042 *
2043 * @return array|null|object|void
2044 *
2045 * Get Product belongs with course
2046 *
2047 * @since v.1.0.0
2048 */
2049
2050 public function product_belongs_with_course($product_id = 0){
2051 global $wpdb;
2052
2053 $query = $wpdb->get_row("select * from {$wpdb->postmeta} WHERE meta_key='_tutor_course_product_id' AND meta_value = {$product_id} limit 1 ");
2054 return $query;
2055 }
2056
2057 /**
2058 * #End WooCommerce specific utils
2059 *
2060 * @since v.1.0.0
2061 */
2062
2063 public function get_enrolled_statuses(){
2064 return apply_filters(
2065 'tutor_get_enrolled_statuses',
2066 array (
2067 'pending',
2068 'processing',
2069 'on-hold',
2070 'completed',
2071 'cancelled',
2072 'refunded',
2073 'failed',
2074 )
2075 );
2076 }
2077
2078 /**
2079 * @param $order_id
2080 *
2081 * @return mixed
2082 *
2083 * determine is this a tutor order
2084 *
2085 * @since v.1.0.0
2086 */
2087 public function is_tutor_order($order_id){
2088 return get_post_meta($order_id, '_is_tutor_order_for_course', true);
2089 }
2090
2091 /**
2092 * @return mixed
2093 *
2094 * @deprecated
2095 */
2096 public function tutor_student_dashboard_pages(){
2097 _deprecated_function(__METHOD__, '1.1.2', 'tutor_dashboard_pages');
2098 return $this->tutor_dashboard_pages();
2099 }
2100
2101 /**
2102 * @return mixed
2103 *
2104 * Tutor Dashboard Pages, supporting for the URL rewriting
2105 *
2106 * @since v.1.0.0
2107 */
2108
2109 public function tutor_dashboard_pages(){
2110 $nav_items = apply_filters('tutor_dashboard/nav_items', array(
2111 'index' => __('Dashboard', 'tutor'),
2112 'my-profile' => __('My Profile', 'tutor'),
2113 'create-course' => array('title' => __('Create Course', 'tutor'), 'show_ui' => false, 'auth_cap' => tutor()->instructor_role),
2114 'enrolled-courses' => __('Enrolled Courses', 'tutor'),
2115 'wishlist' => __('Wishlist', 'tutor'),
2116 'reviews' => __('Reviews', 'tutor'),
2117 'my-quiz-attempts' => __('My Quiz Attempts', 'tutor'),
2118
2119 'my-courses' => array('title' => __('My Courses', 'tutor'), 'auth_cap' => tutor()->instructor_role),
2120 'earning' => array('title' => __('Earnings', 'tutor'), 'auth_cap' => tutor()->instructor_role),
2121 'withdraw' => array('title' => __('Withdrawal', 'tutor'), 'auth_cap' => tutor()->instructor_role),
2122 'quiz-attempts' => array('title' => __('Quiz Attempts', 'tutor'), 'auth_cap' => tutor()->instructor_role),
2123
2124 'purchase_history' => __('Purchase History', 'tutor'),
2125 ));
2126
2127 $disable = get_tutor_option('disable_course_review');
2128 if ($disable && isset($nav_items['reviews'])){
2129 unset($nav_items['reviews']);
2130 }
2131
2132 $new_navs = array(
2133 'settings' => __('Settings', 'tutor'),
2134 'logout' => __('Logout', 'tutor'),
2135 );
2136 $all_nav_items = array_merge($nav_items, $new_navs);
2137
2138 return apply_filters('tutor_dashboard/nav_items_all', $all_nav_items);
2139 }
2140
2141 public function tutor_dashboard_permalinks(){
2142 $dashboard_pages = $this->tutor_dashboard_pages();
2143
2144 $dashboard_permalinks = apply_filters('tutor_dashboard/permalinks', array(
2145 'retrieve-password' => array('title' => __('Retrieve Password', 'tutor'), 'login_require' => false),
2146 ));
2147
2148 $dashboard_pages = array_merge($dashboard_pages, $dashboard_permalinks);
2149
2150 return $dashboard_pages;
2151 }
2152
2153 /**
2154 * @return mixed
2155 *
2156 * Tutor Dashboard UI nav, only for using in the nav, it's handling user permission based
2157 * Dashboard nav items
2158 *
2159 * @since v.1.3.4
2160 */
2161 public function tutor_dashboard_nav_ui_items(){
2162 $nav_items = $this->tutor_dashboard_pages();
2163
2164 foreach ($nav_items as $key => $nav_item){
2165 if (is_array($nav_item)){
2166
2167 if ( isset($nav_item['show_ui']) && ! tutor_utils()->array_get('show_ui', $nav_item)){
2168 unset($nav_items[$key]);
2169 }
2170 if ( isset($nav_item['auth_cap'] ) && ! current_user_can($nav_item['auth_cap']) ){
2171 unset($nav_items[$key]);
2172 }
2173 }
2174 }
2175
2176 return apply_filters('tutor_dashboard/nav_ui_items', $nav_items);
2177 }
2178
2179 /**
2180 * @param string $page_key
2181 * @param int $page_id
2182 *
2183 * @return string
2184 *
2185 * Get tutor dashboard page single URL
2186 *
2187 * @since v.1.0.0
2188 */
2189 public function get_tutor_dashboard_page_permalink($page_key = '', $page_id = 0){
2190 if ($page_key === 'index'){
2191 $page_key = '';
2192 }
2193 $page_id = $this->get_post_id($page_id);
2194 return trailingslashit(get_permalink($page_id)).$page_key;
2195 }
2196
2197 /**
2198 * @param string $input
2199 *
2200 * @return array|bool|mixed|string
2201 *
2202 * Get old input
2203 *
2204 * @since v.1.0.0
2205 * @updated v.1.4.2
2206 */
2207 public function input_old($input = '', $old_data = null){
2208 if ( ! $old_data){
2209 $old_data = $_REQUEST;
2210 }
2211 $value = $this->avalue_dot($input, $old_data);
2212 if ($value){
2213 return $value;
2214 }
2215 return '';
2216 }
2217
2218 /**
2219 * @param int $user_id
2220 *
2221 * @return mixed
2222 *
2223 * Determine if is instructor or not
2224 *
2225 * @since v.1.0.0
2226 */
2227 public function is_instructor($user_id = 0){
2228 $user_id = $this->get_user_id($user_id);
2229 return get_user_meta($user_id, '_is_tutor_instructor', true);
2230 }
2231
2232 /**
2233 * @param int $user_id
2234 * @param bool $status_name
2235 *
2236 * @return bool|mixed
2237 *
2238 * Instructor status
2239 *
2240 * @since v.1.0.0
2241 */
2242 public function instructor_status($user_id = 0, $status_name = true){
2243 $user_id = $this->get_user_id($user_id);
2244
2245 $instructor_status = apply_filters('tutor_instructor_statuses', array(
2246 'pending' => __('Pending', 'tutor'),
2247 'approved' => __('Approved', 'tutor'),
2248 'blocked' => __('Blocked', 'tutor'),
2249 ));
2250
2251 $status = get_user_meta($user_id, '_tutor_instructor_status', true);
2252
2253 if (isset($instructor_status[$status])){
2254 if ( ! $status_name){
2255 return $status;
2256 }
2257 return $instructor_status[$status];
2258 }
2259 return false;
2260 }
2261
2262 /**
2263 * @param string $search_term
2264 *
2265 * @return int
2266 *
2267 * Get total number of instructors
2268 *
2269 * @since v.1.0.0
2270 */
2271
2272 public function get_total_instructors($search_term = ''){
2273 $meta_key = '_is_tutor_instructor';
2274
2275 global $wpdb;
2276
2277 if ($search_term){
2278 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
2279 }
2280
2281 $count = $wpdb->get_var("SELECT COUNT({$wpdb->users}.ID) FROM {$wpdb->users} INNER JOIN {$wpdb->usermeta} ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id ) WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) $search_term ");
2282
2283 return (int) $count;
2284 }
2285
2286 /**
2287 * @param int $start
2288 * @param int $limit
2289 * @param string $search_term
2290 *
2291 * @return array|null|object
2292 *
2293 * Get all instructors
2294 *
2295 * @since v.1.0.0
2296 */
2297 public function get_instructors($start = 0, $limit = 10, $search_term = ''){
2298 $meta_key = '_is_tutor_instructor';
2299 global $wpdb;
2300
2301 if ($search_term){
2302 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
2303 }
2304
2305 $instructors = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS {$wpdb->users}.* FROM {$wpdb->users}
2306 INNER JOIN {$wpdb->usermeta}
2307 ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id )
2308 WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) {$search_term}
2309 ORDER BY {$wpdb->usermeta}.meta_value DESC
2310 LIMIT {$start}, {$limit} ");
2311
2312 return $instructors;
2313 }
2314
2315 /**
2316 * @param int $course_id
2317 *
2318 * @return array|bool|null|object
2319 *
2320 * Get all instructors by course
2321 *
2322 * @since v.1.0.0
2323 */
2324 public function get_instructors_by_course($course_id = 0){
2325 global $wpdb;
2326 $course_id = $this->get_post_id($course_id);
2327
2328 $instructors = $wpdb->get_results("select ID, display_name,
2329 get_course.meta_value as taught_course_id,
2330 tutor_job_title.meta_value as tutor_profile_job_title,
2331 tutor_bio.meta_value as tutor_profile_bio,
2332 tutor_photo.meta_value as tutor_profile_photo
2333 from {$wpdb->users}
2334 INNER JOIN {$wpdb->usermeta} get_course ON ID = get_course.user_id AND get_course.meta_key = '_tutor_instructor_course_id' AND get_course.meta_value = {$course_id}
2335 LEFT JOIN {$wpdb->usermeta} tutor_job_title ON ID = tutor_job_title.user_id AND tutor_job_title.meta_key = '_tutor_profile_job_title'
2336 LEFT JOIN {$wpdb->usermeta} tutor_bio ON ID = tutor_bio.user_id AND tutor_bio.meta_key = '_tutor_profile_bio'
2337 LEFT JOIN {$wpdb->usermeta} tutor_photo ON ID = tutor_photo.user_id AND tutor_photo.meta_key = '_tutor_profile_photo'
2338 ");
2339
2340 if (is_array($instructors) && count($instructors)){
2341 return $instructors;
2342 }
2343
2344 return false;
2345 }
2346
2347 /**
2348 * @param $instructor_id
2349 *
2350 * Get total Students by instructor
2351 * 1 enrollment = 1 student, so total enrolled for a equivalent total students (Tricks)
2352 *
2353 * @return int
2354 *
2355 * @since v.1.0.0
2356 */
2357
2358 public function get_total_students_by_instructor($instructor_id){
2359 global $wpdb;
2360
2361 $course_post_type = tutor()->course_post_type;
2362 $count = $wpdb->get_var("SELECT COUNT(courses.ID) from {$wpdb->posts} courses
2363
2364 INNER JOIN {$wpdb->posts} enrolled ON courses.ID = enrolled.post_parent AND enrolled.post_type = 'tutor_enrolled'
2365 WHERE courses.post_status = 'publish'
2366 AND courses.post_type = '{$course_post_type}'
2367 AND courses.post_author = {$instructor_id} ; ");
2368 return (int) $count;
2369 }
2370
2371 /**
2372 * @param float $input
2373 *
2374 * @return float|string
2375 *
2376 * Get rating format from value
2377 *
2378 * @since v.1.0.0
2379 */
2380 public function get_rating_value($input = 0.00){
2381
2382 if ( $input > 0){
2383 $input = number_format($input, 2);
2384 $int_value = (int) $input;
2385 $fraction = $input - $int_value;
2386
2387 if ($fraction == 0){
2388 $fraction = 0.00;
2389 }elseif($fraction > 0.5){
2390 $fraction = 1;
2391 }else{
2392 $fraction = 0.5;
2393 }
2394
2395 return number_format( ($int_value + $fraction), 2);
2396 }
2397 return 0.00;
2398 }
2399
2400 /**
2401 * @param float $current_rating
2402 * @param bool $echo
2403 *
2404 * @return string
2405 *
2406 * Generate star rating based in given rating value
2407 *
2408 * @since v.1.0.0
2409 */
2410 public function star_rating_generator($current_rating = 0.00, $echo = true){
2411 $output = '<div class="tutor-star-rating-group">';
2412
2413 for ($i = 1; $i <=5 ; $i++){
2414 $intRating = (int) $current_rating;
2415
2416 if ($intRating >= $i){
2417 $output.= '<i class="tutor-icon-star-full" data-rating-value="'.$i.'"></i>';
2418 } else{
2419 if ( ($current_rating - $i) == -0.5){
2420 $output.= '<i class="tutor-icon-star-half" data-rating-value="'.$i.'"></i>';
2421 }else{
2422 $output.= '<i class="tutor-icon-star-line" data-rating-value="'.$i.'"></i>';
2423 }
2424 }
2425 }
2426
2427 $output .= "<div class='tutor-rating-gen-input'><input type='hidden' name='tutor_rating_gen_input' value='{$current_rating}' /> </div>";
2428
2429 $output .= "</div>";
2430
2431 if ($echo){
2432 echo $output;
2433 }
2434 return $output;
2435 }
2436
2437 /**
2438 * @param null $name
2439 *
2440 * @return string
2441 *
2442 * Generate text to avatar
2443 *
2444 * @since v.1.0.0
2445 */
2446 public function get_tutor_avatar($user_id = null, $size = 'thumbnail'){
2447 global $wpdb;
2448
2449 if ( ! $user_id){
2450 return '';
2451 }
2452
2453 $user = $this->get_tutor_user($user_id);
2454 if ($user->tutor_profile_photo){
2455 return '<img src="'.wp_get_attachment_image_url($user->tutor_profile_photo, $size).'" class="tutor-image-avatar" alt="" /> ';
2456 }
2457
2458 $name = $user->display_name;
2459 $arr = explode(' ', trim($name));
2460
2461 if (count($arr) > 1){
2462 $first_char = substr($arr[0], 0, 1) ;
2463 $second_char = substr($arr[1], 0, 1) ;
2464 }else{
2465 $first_char = substr($arr[0], 0, 1) ;
2466 $second_char = substr($arr[0], 1, 1) ;
2467 }
2468
2469 $initial_avatar = strtoupper($first_char.$second_char);
2470
2471 $bg_color = '#'.substr(md5($initial_avatar), 0, 6);
2472 $initial_avatar = "<span class='tutor-text-avatar' style='background-color: {$bg_color}; color: #fff8e5'>{$initial_avatar}</span>";
2473
2474 return $initial_avatar;
2475 }
2476
2477 /**
2478 * @param $user_id
2479 *
2480 * @return array|null|object|void
2481 *
2482 * Get tutor user
2483 *
2484 * @since v.1.0.0
2485 */
2486
2487 public function get_tutor_user($user_id){
2488 global $wpdb;
2489
2490 $user = $wpdb->get_row("select ID, display_name,
2491 tutor_job_title.meta_value as tutor_profile_job_title,
2492 tutor_bio.meta_value as tutor_profile_bio,
2493 tutor_photo.meta_value as tutor_profile_photo
2494
2495 from {$wpdb->users}
2496 LEFT JOIN {$wpdb->usermeta} tutor_job_title ON ID = tutor_job_title.user_id AND tutor_job_title.meta_key = '_tutor_profile_job_title'
2497 LEFT JOIN {$wpdb->usermeta} tutor_bio ON ID = tutor_bio.user_id AND tutor_bio.meta_key = '_tutor_profile_bio'
2498 LEFT JOIN {$wpdb->usermeta} tutor_photo ON ID = tutor_photo.user_id AND tutor_photo.meta_key = '_tutor_profile_photo'
2499
2500 WHERE ID = {$user_id} ");
2501 return $user;
2502 }
2503
2504 /**
2505 * @param int $course_id
2506 * @param int $offset
2507 * @param int $limit
2508 *
2509 * @return array|null|object
2510 *
2511 * get course reviews
2512 *
2513 * @since v.1.0.0
2514 */
2515 public function get_course_reviews($course_id = 0, $offset = 0, $limit = 150){
2516 $course_id = $this->get_post_id($course_id);
2517 global $wpdb;
2518
2519 $reviews = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2520 {$wpdb->comments}.comment_post_ID,
2521 {$wpdb->comments}.comment_author,
2522 {$wpdb->comments}.comment_author_email,
2523 {$wpdb->comments}.comment_date,
2524 {$wpdb->comments}.comment_content,
2525 {$wpdb->comments}.user_id,
2526 {$wpdb->commentmeta}.meta_value as rating,
2527 {$wpdb->users}.display_name
2528
2529 from {$wpdb->comments}
2530 INNER JOIN {$wpdb->commentmeta}
2531 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2532 LEFT JOIN {$wpdb->users}
2533 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2534 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2535 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2536 );
2537
2538 return $reviews;
2539 }
2540
2541 /**
2542 * @param int $course_id
2543 *
2544 * @return object
2545 *
2546 * Get course rating
2547 *
2548 * @since v.1.0.0
2549 */
2550 public function get_course_rating($course_id = 0){
2551 $course_id = $this->get_post_id($course_id);
2552
2553 $ratings = array(
2554 'rating_count' => 0,
2555 'rating_sum' => 0,
2556 'rating_avg' => 0.00,
2557 'count_by_value' => array(5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0)
2558 );
2559
2560 global $wpdb;
2561
2562 $rating = $wpdb->get_row("select COUNT(meta_value) as rating_count, SUM(meta_value) as rating_sum
2563 from {$wpdb->comments}
2564 INNER JOIN {$wpdb->commentmeta}
2565 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2566 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2567 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2568 AND meta_key = 'tutor_rating' ;"
2569 );
2570
2571 if ($rating->rating_count){
2572 $avg_rating = number_format(($rating->rating_sum / $rating->rating_count), 2);
2573
2574 /**
2575 * Get individual Rating by integer
2576 */
2577 $five_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2578 from {$wpdb->comments}
2579 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2580 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2581 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2582 AND meta_key = 'tutor_rating' AND meta_value = 5 ;"
2583 );
2584 $four_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2585 from {$wpdb->comments}
2586 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2587 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2588 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2589 AND meta_key = 'tutor_rating' AND meta_value = 4 ;"
2590 );
2591 $three_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2592 from {$wpdb->comments}
2593 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2594 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2595 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2596 AND meta_key = 'tutor_rating' AND meta_value = 3 ;"
2597 );
2598 $two_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2599 from {$wpdb->comments}
2600 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2601 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2602 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2603 AND meta_key = 'tutor_rating' AND meta_value = 2 ;"
2604 );
2605 $one_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2606 from {$wpdb->comments}
2607 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2608 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2609 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2610 AND meta_key = 'tutor_rating' AND meta_value = 1 ;"
2611 );
2612
2613 $ratings = array(
2614 'rating_count' => $rating->rating_count,
2615 'rating_sum' => $rating->rating_sum,
2616 'rating_avg' => $avg_rating,
2617 'count_by_value' => array(5 => $five_stars_count, 4 => $four_stars_count, 3 => $three_stars_count, 2 => $two_stars_count, 1 => $one_stars_count)
2618 );
2619
2620 }
2621
2622 return (object) $ratings;
2623 }
2624
2625 /**
2626 * @param int $user_id
2627 * @param int $offset
2628 * @param int $limit
2629 *
2630 * @return array|null|object
2631 *
2632 * Get reviews by a user
2633 *
2634 * @since v.1.0.0
2635 */
2636 public function get_reviews_by_user($user_id = 0, $offset = 0, $limit = 150){
2637 $user_id = $this->get_user_id($user_id);
2638 global $wpdb;
2639
2640 $reviews = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2641 {$wpdb->comments}.comment_post_ID,
2642 {$wpdb->comments}.comment_author,
2643 {$wpdb->comments}.comment_author_email,
2644 {$wpdb->comments}.comment_date,
2645 {$wpdb->comments}.comment_content,
2646 {$wpdb->comments}.user_id,
2647 {$wpdb->commentmeta}.meta_value as rating,
2648 {$wpdb->users}.display_name
2649
2650 from {$wpdb->comments}
2651 INNER JOIN {$wpdb->commentmeta}
2652 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2653 INNER JOIN {$wpdb->users}
2654 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2655 WHERE {$wpdb->comments}.user_id = {$user_id}
2656 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2657 );
2658
2659 return $reviews;
2660 }
2661
2662 /**
2663 * @param int $user_id
2664 * @param int $offset
2665 * @param int $limit
2666 *
2667 * @return array|null|object
2668 *
2669 * Get reviews by instructor
2670 *
2671 * @since v.1.4.0
2672 */
2673
2674 public function get_reviews_by_instructor($instructor_id = 0, $offset = 0, $limit = 150){
2675 $instructor_id = $this->get_user_id($instructor_id);
2676 global $wpdb;
2677
2678 $results = array(
2679 'count' => 0,
2680 'results' => false,
2681 );
2682
2683 $cours_ids = (array) $this->get_assigned_courses_ids_by_instructors($instructor_id);
2684
2685 if ($this->count($cours_ids)){
2686 $implode_ids = implode( ',', $cours_ids );
2687
2688 //Count
2689 $results['count'] = $wpdb->get_var("select COUNT({$wpdb->comments}.comment_ID)
2690 from {$wpdb->comments}
2691 INNER JOIN {$wpdb->commentmeta}
2692 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2693 INNER JOIN {$wpdb->users}
2694 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2695 WHERE {$wpdb->comments}.comment_post_ID IN({$implode_ids})
2696 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating';" );
2697
2698 //Results
2699 $results['results'] = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2700 {$wpdb->comments}.comment_post_ID,
2701 {$wpdb->comments}.comment_author,
2702 {$wpdb->comments}.comment_author_email,
2703 {$wpdb->comments}.comment_date,
2704 {$wpdb->comments}.comment_content,
2705 {$wpdb->comments}.user_id,
2706 {$wpdb->commentmeta}.meta_value as rating,
2707 {$wpdb->users}.display_name
2708
2709 from {$wpdb->comments}
2710 INNER JOIN {$wpdb->commentmeta}
2711 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2712 INNER JOIN {$wpdb->users}
2713 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2714 WHERE {$wpdb->comments}.comment_post_ID IN({$implode_ids})
2715 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;" );
2716 }
2717
2718 return (object) $results;
2719 }
2720
2721 /**
2722 * @param $instructor_id
2723 *
2724 * @return object
2725 *
2726 * Get instructors rating
2727 *
2728 * @since v.1.0.0
2729 */
2730 public function get_instructor_ratings($instructor_id){
2731 global $wpdb;
2732
2733 $ratings = array(
2734 'rating_count' => 0,
2735 'rating_sum' => 0,
2736 'rating_avg' => 0.00,
2737 );
2738
2739 $rating = $wpdb->get_row("SELECT COUNT(rating.meta_value) as rating_count, SUM(rating.meta_value) as rating_sum
2740 FROM {$wpdb->usermeta} courses
2741 INNER JOIN {$wpdb->comments} reviews ON courses.meta_value = reviews.comment_post_ID AND reviews.comment_type = 'tutor_course_rating'
2742 INNER JOIN {$wpdb->commentmeta} rating ON reviews.comment_ID = rating.comment_id AND rating.meta_key = 'tutor_rating'
2743 WHERE courses.user_id = {$instructor_id} AND courses.meta_key = '_tutor_instructor_course_id'");
2744
2745 if ($rating->rating_count){
2746 $avg_rating = number_format(($rating->rating_sum / $rating->rating_count), 2);
2747
2748 $ratings = array(
2749 'rating_count' => $rating->rating_count,
2750 'rating_sum' => $rating->rating_sum,
2751 'rating_avg' => $avg_rating,
2752 );
2753 }
2754
2755 return (object) $ratings;
2756 }
2757
2758 /**
2759 * @param int $course_id
2760 * @param int $user_id
2761 *
2762 * @return object
2763 *
2764 * Get course rating by user
2765 *
2766 * @since v.1.0.0
2767 */
2768 public function get_course_rating_by_user($course_id = 0, $user_id = 0){
2769 $course_id = $this->get_post_id($course_id);
2770 $user_id = $this->get_user_id($user_id);
2771
2772 $ratings = array(
2773 'rating' => 0,
2774 'review' => '',
2775 );
2776
2777 global $wpdb;
2778
2779 $rating = $wpdb->get_row("select meta_value as rating, comment_content as review from {$wpdb->comments}
2780 INNER JOIN {$wpdb->commentmeta}
2781 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2782 WHERE {$wpdb->comments}.comment_post_ID = {$course_id} AND user_id = {$user_id}
2783 AND meta_key = 'tutor_rating' ;"
2784 );
2785
2786 if ($rating){
2787 $rating_format = number_format($rating->rating, 2);
2788
2789 $ratings = array(
2790 'rating' => $rating_format,
2791 'review' => $rating->review,
2792 );
2793 }
2794 return (object) $ratings;
2795 }
2796
2797 /**
2798 * @param int $user_id
2799 *
2800 * @return null|string
2801 *
2802 * @since v.1.0.0
2803 */
2804 public function count_reviews_wrote_by_user($user_id = 0){
2805 global $wpdb;
2806 $user_id = $this->get_user_id($user_id);
2807
2808 $count_reviews = $wpdb->get_var("SELECT COUNT(comment_ID) from {$wpdb->comments} WHERE user_id = {$user_id} AND comment_type = 'tutor_course_rating' ");
2809 return $count_reviews;
2810 }
2811
2812 /**
2813 * @param $size
2814 *
2815 * @return bool|int|string
2816 *
2817 * This function transforms the php.ini notation for numbers (like '2M') to an integer.
2818 *
2819 * @since v.1.0.0
2820 */
2821
2822 function let_to_num( $size ) {
2823 $l = substr( $size, -1 );
2824 $ret = substr( $size, 0, -1 );
2825 $byte = 1024;
2826
2827 switch ( strtoupper( $l ) ) {
2828 case 'P':
2829 $ret *= 1024;
2830 // No break.
2831 case 'T':
2832 $ret *= 1024;
2833 // No break.
2834 case 'G':
2835 $ret *= 1024;
2836 // No break.
2837 case 'M':
2838 $ret *= 1024;
2839 // No break.
2840 case 'K':
2841 $ret *= 1024;
2842 // No break.
2843 }
2844 return $ret;
2845 }
2846
2847 /**
2848 * @return array
2849 *
2850 * Get Database version
2851 *
2852 * @since v.1.0.0
2853 */
2854 function get_db_version() {
2855 global $wpdb;
2856
2857 if ( empty( $wpdb->is_mysql ) ) {
2858 return array(
2859 'string' => '',
2860 'number' => '',
2861 );
2862 }
2863
2864 if ( $wpdb->use_mysqli ) {
2865 $server_info = mysqli_get_server_info( $wpdb->dbh ); // @codingStandardsIgnoreLine.
2866 } else {
2867 $server_info = mysql_get_server_info( $wpdb->dbh ); // @codingStandardsIgnoreLine.
2868 }
2869
2870 return array(
2871 'string' => $server_info,
2872 'number' => preg_replace( '/([^\d.]+).*/', '', $server_info ),
2873 );
2874 }
2875
2876 public function help_tip($tip = ''){
2877 return '<span class="tutor-help-tip" data-tip="' . $tip . '"></span>';
2878 }
2879
2880 /**
2881 * @param int $course_id
2882 * @param int $user_id
2883 * @param int $offset
2884 * @param int $limit
2885 *
2886 * @return array|null|object
2887 *
2888 * Get top question
2889 *
2890 * @since v.1.0.0
2891 */
2892 public function get_top_question($course_id = 0, $user_id = 0, $offset = 0, $limit = 20){
2893 $course_id = $this->get_post_id($course_id);
2894 $user_id = $this->get_user_id($user_id);
2895
2896 global $wpdb;
2897
2898 $questions = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2899 {$wpdb->comments}.comment_post_ID,
2900 {$wpdb->comments}.comment_author,
2901 {$wpdb->comments}.comment_date,
2902 {$wpdb->comments}.comment_content,
2903 {$wpdb->comments}.user_id,
2904 {$wpdb->commentmeta}.meta_value as question_title,
2905 {$wpdb->users}.display_name
2906
2907 from {$wpdb->comments}
2908 INNER JOIN {$wpdb->commentmeta}
2909 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2910 INNER JOIN {$wpdb->users}
2911 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2912 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2913 AND {$wpdb->comments}.user_id = {$user_id}
2914 AND {$wpdb->comments}.comment_type = 'tutor_q_and_a'
2915 AND meta_key = 'tutor_question_title' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2916 );
2917
2918 return $questions;
2919 }
2920
2921 /**
2922 * @param string $search_term
2923 *
2924 * @return int
2925 *
2926 * Get total number of Q&A questions
2927 *
2928 * @since v.1.0.0
2929 */
2930 public function get_total_qa_question($search_term = ''){
2931 global $wpdb;
2932
2933 if ($search_term){
2934 $search_term = " AND {$wpdb->commentmeta}.meta_value LIKE '%{$search_term}%' ";
2935 }
2936
2937 $user_id = get_current_user_id();
2938 $course_type = tutor()->course_post_type;
2939
2940 $in_question_id_query = '';
2941 /**
2942 * Get only assinged courses questions if current user is a
2943 */
2944 if ( ! current_user_can('administrator') && current_user_can(tutor()->instructor_role)) {
2945 $get_course_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_author = {$user_id} AND post_type = '{$course_type}' AND post_status = 'publish' " );
2946 $get_assigned_courses_ids = $wpdb->get_col( "SELECT meta_value from {$wpdb->usermeta} WHERE meta_key = '_tutor_instructor_course_id' AND user_id = {$user_id} " );
2947 $my_course_ids = array_unique( array_merge( $get_course_ids, $get_assigned_courses_ids ) );
2948
2949 if ( $this->count( $my_course_ids ) ) {
2950 $implode_ids = implode( ',', $my_course_ids );
2951 $in_question_id_query = " AND {$wpdb->comments}.comment_post_ID IN($implode_ids) ";
2952 }
2953 }
2954
2955 $count = $wpdb->get_var("SELECT COUNT({$wpdb->comments}.comment_ID) FROM {$wpdb->comments}
2956 INNER JOIN {$wpdb->commentmeta}
2957 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2958 WHERE comment_type = 'tutor_q_and_a' AND comment_parent = 0 {$in_question_id_query} {$search_term} ");
2959
2960 return (int) $count;
2961 }
2962
2963 /**
2964 * @param int $start
2965 * @param int $limit
2966 * @param string $search_term
2967 *
2968 * @return array|null|object
2969 *
2970 *
2971 * Get question and answer query
2972 *
2973 * @since v.1.0.0
2974 */
2975 public function get_qa_questions($start = 0, $limit = 10, $search_term = '') {
2976 global $wpdb;
2977
2978 if ($search_term){
2979 $search_term = " AND {$wpdb->commentmeta}.meta_value LIKE '%{$search_term}%' ";
2980 }
2981
2982 $user_id = get_current_user_id();
2983 $course_type = tutor()->course_post_type;
2984
2985 $in_question_id_query = '';
2986 /**
2987 * Get only assinged courses questions if current user is a
2988 */
2989 if ( ! current_user_can('administrator') && current_user_can(tutor()->instructor_role)) {
2990 $get_course_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_author = {$user_id} AND post_type = '{$course_type}' AND post_status = 'publish' " );
2991 $get_assigned_courses_ids = $wpdb->get_col( "SELECT meta_value from {$wpdb->usermeta} WHERE meta_key = '_tutor_instructor_course_id' AND user_id = {$user_id} " );
2992 $my_course_ids = array_unique( array_merge( $get_course_ids, $get_assigned_courses_ids ) );
2993
2994 if ( $this->count( $my_course_ids ) ) {
2995 $implode_ids = implode( ',', $my_course_ids );
2996 $in_question_id_query = " AND {$wpdb->comments}.comment_post_ID IN($implode_ids) ";
2997 }
2998 }
2999
3000 $query = $wpdb->get_results("SELECT
3001 {$wpdb->comments}.comment_ID,
3002 {$wpdb->comments}.comment_post_ID,
3003 {$wpdb->comments}.comment_author,
3004 {$wpdb->comments}.comment_date,
3005 {$wpdb->comments}.comment_content,
3006 {$wpdb->comments}.user_id,
3007 {$wpdb->commentmeta}.meta_value as question_title,
3008 {$wpdb->users}.display_name,
3009 {$wpdb->posts}.post_title,
3010
3011 (SELECT COUNT(answers_t.comment_ID) FROM {$wpdb->comments} answers_t
3012 WHERE answers_t.comment_parent = {$wpdb->comments}.comment_ID ) as answer_count
3013
3014 FROM {$wpdb->comments}
3015
3016 INNER JOIN {$wpdb->commentmeta}
3017 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
3018
3019 INNER JOIN {$wpdb->posts}
3020 ON {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID
3021
3022 INNER JOIN {$wpdb->users}
3023 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
3024
3025 WHERE {$wpdb->comments}.comment_type = 'tutor_q_and_a' AND {$wpdb->comments}.comment_parent = 0 {$search_term}
3026 {$in_question_id_query}
3027 ORDER BY {$wpdb->comments}.comment_ID DESC
3028 LIMIT {$start},{$limit}; ");
3029
3030 return $query;
3031 }
3032
3033 /**
3034 * @param $question_id
3035 *
3036 * @return array|null|object|void
3037 *
3038 * Get question for Q&A
3039 *
3040 * @since v.1.0.0
3041 */
3042 public function get_qa_question($question_id){
3043 global $wpdb;
3044 $query = $wpdb->get_row("SELECT
3045 {$wpdb->comments}.comment_ID,
3046 {$wpdb->comments}.comment_post_ID,
3047 {$wpdb->comments}.comment_author,
3048 {$wpdb->comments}.comment_date,
3049 {$wpdb->comments}.comment_content,
3050 {$wpdb->comments}.user_id,
3051 {$wpdb->commentmeta}.meta_value as question_title,
3052 {$wpdb->users}.display_name,
3053 {$wpdb->posts}.post_title
3054
3055 FROM {$wpdb->comments}
3056 INNER JOIN {$wpdb->commentmeta}
3057 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
3058
3059 INNER JOIN {$wpdb->posts}
3060 ON {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID
3061
3062 INNER JOIN {$wpdb->users}
3063 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
3064 WHERE comment_type = 'tutor_q_and_a' AND {$wpdb->comments}.comment_ID = {$question_id}");
3065
3066 return $query;
3067 }
3068
3069 /**
3070 * @param $question_id
3071 *
3072 * @return array|null|object
3073 *
3074 * Get question and asnwer by question
3075 */
3076 public function get_qa_answer_by_question($question_id){
3077 global $wpdb;
3078 $query = $wpdb->get_results("SELECT
3079 {$wpdb->comments}.comment_ID,
3080 {$wpdb->comments}.comment_post_ID,
3081 {$wpdb->comments}.comment_author,
3082 {$wpdb->comments}.comment_date,
3083 {$wpdb->comments}.comment_content,
3084 {$wpdb->comments}.comment_parent,
3085 {$wpdb->comments}.user_id,
3086 {$wpdb->users}.display_name
3087
3088 FROM {$wpdb->comments}
3089
3090 INNER JOIN {$wpdb->users}
3091 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
3092 WHERE comment_type = 'tutor_q_and_a'
3093 AND {$wpdb->comments}.comment_parent = {$question_id} ORDER BY {$wpdb->comments}.comment_ID ASC ");
3094
3095 return $query;
3096 }
3097
3098 public function unanswered_question_count(){
3099 global $wpdb;
3100
3101 $count = $wpdb->get_var("select COUNT({$wpdb->comments}.comment_ID)
3102 from {$wpdb->comments}
3103 WHERE {$wpdb->comments}.comment_type = 'tutor_q_and_a'
3104 AND {$wpdb->comments}.comment_approved = 'waiting_for_answer'
3105 AND {$wpdb->comments}.comment_parent = 0;");
3106 return (int) $count;
3107 }
3108
3109 /**
3110 * @param int $course_id
3111 *
3112 * @return array|null|object
3113 *
3114 * Return all of announcements for a course
3115 *
3116 * @since v.1.0.0
3117 */
3118 public function get_announcements($course_id = 0){
3119 $course_id = $this->get_post_id($course_id);
3120 global $wpdb;
3121
3122 $query = $wpdb->get_results("select {$wpdb->posts}.ID, post_author, post_date, post_content, post_title, display_name
3123 from {$wpdb->posts}
3124 INNER JOIN {$wpdb->users} ON post_author = {$wpdb->users}.ID
3125 WHERE post_type = 'tutor_announcements'
3126 AND post_parent = {$course_id} ORDER BY {$wpdb->posts}.ID DESC;");
3127 return $query;
3128 }
3129
3130 /**
3131 * @param string $content
3132 *
3133 * @return mixed
3134 *
3135 * Announcement content
3136 *
3137 * @since v.1.0.0
3138 */
3139
3140 public function announcement_content($content = ''){
3141 $search = array('{user_display_name}');
3142
3143 $user_display_name = 'User';
3144 if (is_user_logged_in()){
3145 $user = wp_get_current_user();
3146 $user_display_name = $user->display_name;
3147 }
3148 $replace = array($user_display_name);
3149
3150 return str_replace($search, $replace, $content);
3151 }
3152
3153 /**
3154 * @param int $post_id
3155 * @param string $option_key
3156 * @param bool $default
3157 *
3158 * @return array|bool|mixed
3159 *
3160 * Get the quiz option from meta
3161 */
3162 public function get_quiz_option($post_id = 0, $option_key = '', $default = false){
3163 $post_id = $this->get_post_id($post_id);
3164 $get_option_meta = maybe_unserialize(get_post_meta($post_id, 'tutor_quiz_option', true));
3165
3166 if ( ! $option_key && ! empty($get_option_meta)) {
3167 return $get_option_meta;
3168 }
3169
3170 $value = $this->avalue_dot( $option_key, $get_option_meta );
3171 if ( $value > 0 || $value !== false ) {
3172 return $value;
3173 }
3174 return $default;
3175 }
3176
3177
3178 /**
3179 * @param int $quiz_id
3180 *
3181 * @return array|bool|null|object
3182 *
3183 * Get the questions by quiz ID
3184 */
3185 public function get_questions_by_quiz($quiz_id = 0){
3186 $quiz_id = $this->get_post_id($quiz_id);
3187 global $wpdb;
3188
3189 $questions = $wpdb->get_results("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} ORDER BY question_order ASC ");
3190
3191 if (is_array($questions) && count($questions)){
3192 return $questions;
3193 }
3194 return false;
3195 }
3196
3197 /**
3198 * @param int $question_id
3199 *
3200 * @return array|bool|object|void|null
3201 *
3202 * Get Quiz question by question id
3203 */
3204 public function get_quiz_question_by_id($question_id = 0){
3205 global $wpdb;
3206
3207 if ($question_id){
3208 $question = $wpdb->get_row("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE question_id = {$question_id} LIMIT 0,1 ;");
3209 return $question;
3210 }
3211
3212 return false;
3213 }
3214
3215 /**
3216 * @param null $type
3217 *
3218 * @return array|mixed
3219 *
3220 * Get all question types
3221 *
3222 * @since v.1.0.0
3223 */
3224
3225 public function get_question_types($type = null){
3226 $types = array(
3227 'true_false' => array('name' => __('True/False', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-yes-no"></i>', 'is_pro' => false),
3228 'single_choice' => array('name' => __('Single Choice', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-mark"></i>', 'is_pro' => false),
3229 'multiple_choice' => array('name' => __('Multiple Choice', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-multiple-choice"></i>', 'is_pro' => false),
3230 'open_ended' => array('name' => __('Open Ended/Essay', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-open-ended"></i>', 'is_pro' => false),
3231 'fill_in_the_blank' => array('name' => __('Fill In The Blanks', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-fill-gaps"></i>', 'is_pro' => false),
3232 'short_answer' => array('name' => __('Short Answer', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-short-ans"></i>', 'is_pro' => true),
3233 'matching' => array('name' => __('Matching', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-matching"></i>', 'is_pro' => true),
3234 'image_matching' => array('name' => __('Image Matching', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-image-matching"></i>', 'is_pro' => true),
3235 'image_answering' => array('name' => __('Image Answering', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-image-ans"></i>', 'is_pro' => true),
3236 'ordering' => array('name' => __('Ordering', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-ordering"></i>', 'is_pro' => true),
3237 );
3238
3239 if (isset($types[$type])){
3240 return $types[$type];
3241 }
3242 return $types;
3243 }
3244
3245 public function get_quiz_answer_options_by_question($question_id){
3246 global $wpdb;
3247
3248 $answer_options = $wpdb->get_results("select
3249 {$wpdb->comments}.comment_ID,
3250 {$wpdb->comments}.comment_post_ID,
3251 {$wpdb->comments}.comment_content
3252
3253 FROM {$wpdb->comments}
3254 WHERE {$wpdb->comments}.comment_post_ID = {$question_id}
3255 AND {$wpdb->comments}.comment_type = 'quiz_answer_option'
3256 ORDER BY {$wpdb->comments}.comment_karma ASC ;");
3257
3258 if (is_array($answer_options) && count($answer_options)){
3259 return $answer_options;
3260 }
3261 return false;
3262 }
3263
3264 /**
3265 * @param $quiz_id
3266 *
3267 * @return int
3268 *
3269 * Get the next question order ID
3270 *
3271 * @since v.1.0.0
3272 */
3273
3274 public function quiz_next_question_order_id($quiz_id){
3275 global $wpdb;
3276
3277 $last_order = (int) $wpdb->get_var("SELECT MAX(question_order) FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} ;");
3278 return $last_order + 1;
3279 }
3280
3281 /**
3282 * @param $quiz_id
3283 *
3284 * @return int
3285 *
3286 * new design quiz question
3287 * @since v.1.0.0
3288 */
3289 public function quiz_next_question_id(){
3290 global $wpdb;
3291
3292 $last_order = (int) $wpdb->get_var("SELECT MAX(question_id) FROM {$wpdb->prefix}tutor_quiz_questions;");
3293 return $last_order + 1;
3294 }
3295
3296 public function get_quiz_id_by_question($question_id){
3297 global $wpdb;
3298
3299 $quiz_id = $wpdb->get_var("SELECT quiz_id FROM {$wpdb->tutor_quiz_questions} WHERE question_id = {$question_id} ;");
3300 return $quiz_id;
3301 }
3302
3303 /**
3304 * @param int $post_id
3305 *
3306 * @return array|bool|null|object
3307 *
3308 * @since v.1.0.0
3309 */
3310 public function get_attached_quiz($post_id = 0){
3311 global $wpdb;
3312
3313 $post_id = $this->get_post_id($post_id);
3314
3315 $questions = $wpdb->get_results("SELECT ID, post_content, post_title, post_parent from {$wpdb->posts} WHERE post_type = 'tutor_quiz' AND post_status = 'publish' AND post_parent = {$post_id}");
3316
3317 if (is_array($questions) && count($questions)){
3318 return $questions;
3319 }
3320 return false;
3321 }
3322
3323 /**
3324 * @param $quiz_id
3325 *
3326 * @return array|bool|null|object|void
3327 *
3328 * Get course by quiz
3329 *
3330 * @since v.1.0.0
3331 */
3332
3333 public function get_course_by_quiz($quiz_id){
3334 global $wpdb;
3335
3336 $quiz_id = $this->get_post_id($quiz_id);
3337 $post = get_post($quiz_id);
3338
3339 if ($post) {
3340 $course_post_type = tutor()->course_post_type;
3341 $course = $wpdb->get_row( "select ID, post_name, post_type, post_parent from {$wpdb->posts} where ID = {$post->post_parent} " );
3342 if ($course) {
3343 if ( $course->post_type !== $course_post_type ) {
3344 $course = $wpdb->get_row( "select ID, post_name, post_type, post_parent from {$wpdb->posts} where ID = {$course->post_parent} " );
3345 }
3346 return $course;
3347 }
3348 }
3349
3350 return false;
3351 }
3352
3353 /**
3354 * @param $quiz_id
3355 *
3356 * @return int
3357 *
3358 * @since v.1.0.0
3359 */
3360 public function total_questions_for_student_by_quiz($quiz_id){
3361 $quiz_id = $this->get_post_id($quiz_id);
3362 global $wpdb;
3363
3364
3365 $max_questions_count = (int) tutor_utils()->get_quiz_option(get_the_ID(), 'max_questions_for_answer');
3366 $total_question = (int) $wpdb->get_var("select count(question_id) from {$wpdb->tutor_quiz_questions} where quiz_id = {$quiz_id}");
3367
3368 return min($max_questions_count, $total_question);
3369 }
3370
3371 /**
3372 * @param int $quiz_id
3373 *
3374 * @return array|null|object|void
3375 *
3376 * Determine if there is any started quiz exists
3377 *
3378 * @since v.1.0.0
3379 */
3380
3381 public function is_started_quiz($quiz_id = 0){
3382 global $wpdb;
3383
3384 $quiz_id = $this->get_post_id($quiz_id);
3385 $user_id = get_current_user_id();
3386
3387 $is_started = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE user_id = {$user_id} AND quiz_id = {$quiz_id} AND attempt_status = 'attempt_started' ");
3388
3389 return $is_started;
3390 }
3391
3392 /**
3393 * @param $quiz_id
3394 *
3395 * Method for get the total amount of question for a quiz
3396 * Student will answer this amount of question, one quiz have many question
3397 * but student will answer a specific amount of questions
3398 *
3399 * @return int
3400 *
3401 * @since v.1.0.0
3402 */
3403
3404 public function max_questions_for_take_quiz($quiz_id){
3405 $quiz_id = $this->get_post_id($quiz_id);
3406 global $wpdb;
3407
3408 $max_questions = (int) $wpdb->get_var("select count(question_id) from {$wpdb->prefix}tutor_quiz_questions where quiz_id = {$quiz_id} ");
3409 $max_mentioned = (int) $this->get_quiz_option($quiz_id, 'max_questions_for_answer', 10);
3410
3411 if ($max_mentioned < $max_questions ){
3412 return $max_mentioned;
3413 }
3414
3415 return $max_questions;
3416 }
3417
3418 /**
3419 * @param int $attempt_id
3420 *
3421 * @return array|bool|null|object|void
3422 *
3423 * Get single quiz attempt
3424 *
3425 * @since v.1.0.0
3426 */
3427 public function get_attempt($attempt_id = 0){
3428 global $wpdb;
3429 if ( ! $attempt_id){
3430 return false;
3431 }
3432 $attempt = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE attempt_id = {$attempt_id} ");
3433 return $attempt;
3434 }
3435
3436 /**
3437 * @param $attempt_info
3438 *
3439 * @return mixed
3440 *
3441 * Get unserialize attempt info
3442 *
3443 * @since v.1.0.0
3444 */
3445
3446 public function quiz_attempt_info($attempt_info){
3447 return maybe_unserialize($attempt_info);
3448 }
3449
3450 /**
3451 * @param $quiz_attempt_id
3452 * @param array $attempt_info
3453 *
3454 * @return bool|int
3455 *
3456 * Update attempt for various action
3457 *
3458 * @since v.1.0.0
3459 */
3460 public function quiz_update_attempt_info($quiz_attempt_id, $attempt_info = array()){
3461 $answers = tutor_utils()->avalue_dot('answers', $attempt_info);
3462 $total_marks = array_sum(wp_list_pluck($answers, 'question_mark'));
3463 $earned_marks = tutor_utils()->avalue_dot('marks_earned', $attempt_info);
3464 $earned_mark_percent = $earned_marks > 0 ? ( number_format(($earned_marks * 100) / $total_marks)) : 0;
3465 update_comment_meta($quiz_attempt_id, 'earned_mark_percent', $earned_mark_percent);
3466
3467 return update_comment_meta($quiz_attempt_id,'quiz_attempt_info', $attempt_info);
3468 }
3469
3470 /**
3471 * @param int $quiz_id
3472 *
3473 * @return array|null|object
3474 *
3475 * Get random question by quiz id
3476 *
3477 * @since v.1.0.0
3478 */
3479
3480 public function get_random_question_by_quiz($quiz_id = 0){
3481 global $wpdb;
3482
3483 $quiz_id = $this->get_post_id($quiz_id);
3484 $is_attempt = $this->is_started_quiz($quiz_id);
3485
3486 $tempSql = " AND question_type = 'matching' ";
3487 $questions = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} {$tempSql} ORDER BY RAND() LIMIT 0,1 ");
3488
3489 return $questions;
3490 }
3491
3492 /**
3493 * @param int $quiz_id
3494 *
3495 * @return array|null|object
3496 *
3497 * Get random questions by quiz
3498 */
3499 public function get_random_questions_by_quiz($quiz_id = 0){
3500 global $wpdb;
3501
3502 $quiz_id = $this->get_post_id($quiz_id);
3503 $attempt = $this->is_started_quiz($quiz_id);
3504 $total_questions = (int) $attempt->total_questions;
3505 if ( ! $attempt){
3506 return false;
3507 }
3508
3509 $questions_order = tutor_utils()->get_quiz_option(get_the_ID(), 'questions_order', 'rand');
3510
3511 $order_by = "";
3512 if ($questions_order === 'rand'){
3513 $order_by = "ORDER BY RAND()";
3514 }elseif ($questions_order === 'asc'){
3515 $order_by = "ORDER BY question_id ASC";
3516 }elseif ($questions_order === 'desc'){
3517 $order_by = "ORDER BY question_id DESC";
3518 }elseif ($questions_order === 'sorting'){
3519 $order_by = "ORDER BY question_order ASC";
3520 }
3521
3522 $limit = '';
3523 if ($total_questions){
3524 $limit = "LIMIT {$total_questions} ";
3525 }
3526
3527 $questions = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} {$order_by} {$limit} ");
3528
3529 return $questions;
3530 }
3531
3532 /**
3533 * @param $question_id
3534 * @param bool $rand
3535 *
3536 * @return array|bool|null|object
3537 *
3538 * Get answers list by quiz question
3539 *
3540 * @since v.1.0.0
3541 */
3542 public function get_answers_by_quiz_question($question_id, $rand = false){
3543 global $wpdb;
3544
3545 $question = $wpdb->get_row("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE question_id = {$question_id} ;");
3546 if ( ! $question){
3547 return false;
3548 }
3549
3550 $order = " answer_order ASC ";
3551 if ($question->question_type === 'ordering'){
3552 $order = " RAND() ";
3553 }
3554
3555 if ($rand){
3556 $order = " RAND() ";
3557 }
3558
3559 $answers = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question_id} AND belongs_question_type = '{$question->question_type}' order by {$order} ");
3560 return $answers;
3561 }
3562
3563 /**
3564 * @param int $quiz_id
3565 * @param int $user_id
3566 *
3567 * @return array|bool|null|object
3568 *
3569 * Get all of the attempts by an user of a quiz
3570 *
3571 * @since v.1.0.0
3572 */
3573
3574 public function quiz_attempts($quiz_id = 0, $user_id = 0){
3575 global $wpdb;
3576
3577 $quiz_id = $this->get_post_id($quiz_id);
3578 $user_id = $this->get_user_id($user_id);
3579
3580 $attempts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} ");
3581
3582 if (is_array($attempts) && count($attempts)){
3583 return $attempts;
3584 }
3585
3586 return false;
3587 }
3588
3589 /**
3590 * @param int $quiz_id
3591 * @param int $user_id
3592 *
3593 * @return array|bool|null|object
3594 *
3595 * Get all ended attempts by an user of a quiz
3596 *
3597 * @since v.1.4.1
3598 */
3599 public function quiz_ended_attempts($quiz_id = 0, $user_id = 0){
3600 global $wpdb;
3601
3602 $quiz_id = $this->get_post_id($quiz_id);
3603 $user_id = $this->get_user_id($user_id);
3604
3605 $attempts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} AND attempt_status != 'attempt_started' ");
3606
3607 if (is_array($attempts) && count($attempts)){
3608 return $attempts;
3609 }
3610
3611 return false;
3612 }
3613
3614
3615 /**
3616 * @param int $user_id
3617 *
3618 * @return array|bool|null|object
3619 *
3620 * Get attempts by an user
3621 *
3622 * @since v.1.0.0
3623 */
3624 public function get_all_quiz_attempts_by_user($user_id = 0){
3625 global $wpdb;
3626
3627 $user_id = $this->get_user_id($user_id);
3628 $attempts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE user_id = {$user_id} ORDER BY attempt_id DESC ");
3629
3630 if (is_array($attempts) && count($attempts)){
3631 return $attempts;
3632 }
3633
3634 return false;
3635 }
3636
3637 /**
3638 * @param string $search_term
3639 *
3640 * @return int
3641 *
3642 * Total number of quiz attempts
3643 *
3644 * @since v.1.0.0
3645 */
3646
3647 public function get_total_quiz_attempts($search_term = ''){
3648 global $wpdb;
3649
3650 if ($search_term){
3651 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3652 }
3653
3654 $count = $wpdb->get_var("SELECT COUNT(attempt_id)
3655 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3656 INNER JOIN {$wpdb->posts} quiz
3657 ON quiz_attempts.quiz_id = quiz.ID
3658 INNER JOIN {$wpdb->users}
3659 ON quiz_attempts.user_id = {$wpdb->users}.ID
3660 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term} ");
3661 return (int) $count;
3662 }
3663
3664 /**
3665 * @param int $start
3666 * @param int $limit
3667 * @param string $search_term
3668 *
3669 * @return array|null|object
3670 *
3671 *
3672 * Get the all quiz attempts
3673 *
3674 * @since v.1.0.0
3675 */
3676 public function get_quiz_attempts($start = 0, $limit = 10, $search_term = '') {
3677 global $wpdb;
3678
3679 if ($search_term){
3680 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3681 }
3682
3683 $query = $wpdb->get_results("SELECT *
3684 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3685 INNER JOIN {$wpdb->posts} quiz
3686 ON quiz_attempts.quiz_id = quiz.ID
3687 INNER JOIN {$wpdb->users}
3688 ON quiz_attempts.user_id = {$wpdb->users}.ID
3689 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term}
3690 ORDER BY quiz_attempts.attempt_id DESC
3691 LIMIT {$start},{$limit}; ");
3692 return $query;
3693 }
3694
3695 public function get_quiz_attempts_by_course_ids($start = 0, $limit = 10, $course_ids = array(), $search_term = '') {
3696 global $wpdb;
3697
3698 if ($search_term){
3699 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3700 }
3701
3702 $course_ids_in = implode(',', $course_ids);
3703 $sql = " AND quiz_attempts.course_id IN({$course_ids_in}) ";
3704 $search_term = $sql.$search_term;
3705
3706 $query = $wpdb->get_results("SELECT *
3707 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3708 INNER JOIN {$wpdb->posts} quiz
3709 ON quiz_attempts.quiz_id = quiz.ID
3710 INNER JOIN {$wpdb->users}
3711 ON quiz_attempts.user_id = {$wpdb->users}.ID
3712 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term}
3713 ORDER BY quiz_attempts.attempt_id DESC
3714 LIMIT {$start},{$limit}; ");
3715 return $query;
3716 }
3717
3718 public function get_total_quiz_attempts_by_course_ids($course_ids = array(), $search_term = ''){
3719 global $wpdb;
3720
3721 if ($search_term){
3722 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3723 }
3724
3725 $course_ids_in = implode(',', $course_ids);
3726 $sql = " AND quiz_attempts.course_id IN({$course_ids_in}) ";
3727 $search_term = $sql.$search_term;
3728
3729 $count = $wpdb->get_var("SELECT COUNT(attempt_id)
3730 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3731 INNER JOIN {$wpdb->posts} quiz
3732 ON quiz_attempts.quiz_id = quiz.ID
3733 INNER JOIN {$wpdb->users}
3734 ON quiz_attempts.user_id = {$wpdb->users}.ID
3735 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term} ");
3736 return (int) $count;
3737 }
3738
3739 /**
3740 * @param $attempt_id
3741 *
3742 * @return array|null|object
3743 *
3744 * Get quiz answers by attempt id
3745 *
3746 * @since v.1.0.0
3747 */
3748 public function get_quiz_answers_by_attempt_id($attempt_id){
3749 global $wpdb;
3750
3751 $results = $wpdb->get_results("SELECT answers.*, question.question_title, question.question_type
3752 FROM {$wpdb->prefix}tutor_quiz_attempt_answers answers
3753 LEFT JOIN {$wpdb->prefix}tutor_quiz_questions question ON answers.question_id = question.question_id
3754 WHERE answers.quiz_attempt_id = {$attempt_id} ORDER BY attempt_answer_id ASC ;");
3755
3756 return $results;
3757 }
3758
3759 /**
3760 * @param $answer_id
3761 *
3762 * @return array|null|object
3763 *
3764 * Get single answer by answer_id
3765 *
3766 * @since v.1.0.0
3767 */
3768 public function get_answer_by_id($answer_id){
3769 global $wpdb;
3770
3771 if (is_array($answer_id)){
3772 $in_ids = implode(",", $answer_id);
3773 $sql = "answer.answer_id IN({$in_ids})";
3774 }else{
3775 $sql = "answer.answer_id = {$answer_id}";
3776 }
3777
3778 $answer = $wpdb->get_results("SELECT answer.*, question.question_title, question.question_type
3779 FROM {$wpdb->prefix}tutor_quiz_question_answers answer
3780 LEFT JOIN {$wpdb->prefix}tutor_quiz_questions question ON answer.belongs_question_id = question.question_id
3781 WHERE 1=1 AND {$sql} ");
3782
3783 return $answer;
3784 }
3785
3786 /**
3787 * @param $ids
3788 *
3789 * @return array|bool|null|object
3790 *
3791 * Get quiz answers by ids
3792 *
3793 * @since v.1.0.0
3794 */
3795
3796 public function get_quiz_answers_by_ids($ids){
3797 $ids = (array) $ids;
3798
3799 if (!count($ids)){
3800 return false;
3801 }
3802
3803 $in_ids = implode(",", $ids);
3804
3805 global $wpdb;
3806 $query = $wpdb->get_results("SELECT
3807 comment_ID,
3808 comment_content
3809 FROM {$wpdb->comments}
3810 WHERE comment_type = 'quiz_answer_option' AND comment_ID IN({$in_ids}) ");
3811
3812 if (is_array($query) && count($query)){
3813 return $query;
3814 }
3815
3816 return false;
3817 }
3818
3819 /**
3820 * @param null $level
3821 *
3822 * @return mixed
3823 *
3824 * Get the users / students / course levels
3825 *
3826 * @since v.1.0.0
3827 */
3828
3829 public function course_levels($level = null){
3830 $levels = apply_filters('tutor_course_level', array(
3831 'all_levels' => __('All Levels', 'tutor'),
3832 'beginner' => __('Beginner', 'tutor'),
3833 'intermediate' => __('Intermediate', 'tutor'),
3834 'expert' => __('Expert', 'tutor'),
3835 ));
3836
3837 if ($level){
3838 if (isset($levels[$level])){
3839 return $levels[$level];
3840 }else{
3841 return '';
3842 }
3843 }
3844
3845 return $levels;
3846 }
3847
3848 /**
3849 * @return mixed|void
3850 *
3851 * Get user permalink for dashboard
3852 *
3853 * @since v.1.0.0
3854 */
3855 public function user_profile_permalinks(){
3856 $permalinks = array(
3857 'courses_taken' => __('Courses Taken', 'tutor'),
3858 );
3859
3860 $show_enrolled_course = tutor_utils()->get_option('show_courses_completed_by_student');
3861 $enable_show_reviews_wrote = tutor_utils()->get_option('students_own_review_show_at_profile');
3862
3863 if ($show_enrolled_course){
3864 $permalinks['enrolled_course'] = __('Enrolled Course', 'tutor');
3865 }
3866 if ($enable_show_reviews_wrote){
3867 $permalinks['reviews_wrote'] = __('Reviews Written', 'tutor');
3868 }
3869
3870
3871 return apply_filters('tutor_public_profile/permalinks', $permalinks);
3872 }
3873
3874 /**
3875 * @return bool|false|string
3876 *
3877 * Student registration form
3878 *
3879 * @since v.1.0.0
3880 */
3881 public function student_register_url(){
3882 $student_register_page = (int) $this->get_option('student_register_page');
3883
3884 if ($student_register_page){
3885 return get_the_permalink($student_register_page);
3886 }
3887 return false;
3888 }
3889 /**
3890 * @return bool|false|string
3891 *
3892 * Instructor registration form
3893 *
3894 * @since v.1.2.13
3895 */
3896 public function instructor_register_url(){
3897 $instructor_register_page = (int) $this->get_option('instructor_register_page');
3898
3899 if ($instructor_register_page){
3900 return get_the_permalink($instructor_register_page);
3901 }
3902 return false;
3903 }
3904
3905 /**
3906 * @return false|string
3907 *
3908 * Get frontend dashboard URL
3909 */
3910 public function tutor_dashboard_url($sub_url = ''){
3911 $page_id = (int) tutor_utils()->get_option('tutor_dashboard_page_id');
3912 $page_id = apply_filters('tutor_dashboard_page_id', $page_id);
3913 return trailingslashit(get_the_permalink($page_id)).$sub_url;
3914 }
3915
3916 /**
3917 * Get the tutor dashboard page ID
3918 *
3919 * @return int
3920 *
3921 */
3922 public function dashboard_page_id(){
3923 $page_id = (int) tutor_utils()->get_option('tutor_dashboard_page_id');
3924 $page_id = apply_filters('tutor_dashboard_page_id', $page_id);
3925 return $page_id;
3926 }
3927
3928 /**
3929 * @param int $course_id
3930 * @param int $user_id
3931 *
3932 * @return bool
3933 *
3934 * is_wishlisted();
3935 *
3936 * @since v.1.0.0
3937 */
3938 public function is_wishlisted($course_id = 0, $user_id = 0){
3939 $course_id = $this->get_post_id($course_id);
3940 $user_id = $this->get_user_id($user_id);
3941 if ( ! $user_id){
3942 return false;
3943 }
3944
3945 global $wpdb;
3946 $if_added_to_list = (bool) $wpdb->get_row("select * from {$wpdb->usermeta} WHERE user_id = {$user_id} AND meta_key = '_tutor_course_wishlist' AND meta_value = {$course_id} ;");
3947
3948 return $if_added_to_list;
3949 }
3950
3951 /**
3952 * @param int $user_id
3953 *
3954 * @return array|null|object
3955 *
3956 * Get the wish lists by an user
3957 *
3958 * @since v.1.0.0
3959 */
3960 public function get_wishlist($user_id = 0){
3961 $user_id = $this->get_user_id($user_id);
3962 $course_post_type = tutor()->course_post_type;
3963
3964 global $wpdb;
3965
3966 $query = "SELECT $wpdb->posts.*
3967 FROM $wpdb->posts
3968 LEFT JOIN $wpdb->usermeta ON ($wpdb->posts.ID = $wpdb->usermeta.meta_value)
3969 WHERE post_type = '{$course_post_type}' AND post_status = 'publish' AND $wpdb->usermeta.meta_key = '_tutor_course_wishlist'
3970 AND $wpdb->usermeta.user_id = {$user_id}
3971 ORDER BY $wpdb->usermeta.umeta_id DESC ";
3972 $pageposts = $wpdb->get_results($query, OBJECT);
3973 return $pageposts;
3974 }
3975
3976 /**
3977 * @param int $limit
3978 *
3979 * @return array|null|object
3980 *
3981 * Getting popular courses
3982 *
3983 * @since v.1.0.0
3984 */
3985 public function most_popular_courses($limit = 10){
3986 global $wpdb;
3987
3988 $courses = $wpdb->get_results("
3989 SELECT COUNT(enrolled.ID) as total_enrolled,
3990 enrolled.post_parent as course_id,
3991 course.*
3992 from {$wpdb->posts} enrolled
3993 INNER JOIN {$wpdb->posts} course ON enrolled.post_parent = course.ID
3994 WHERE enrolled.post_type = 'tutor_enrolled' AND enrolled.post_status = 'completed'
3995
3996 GROUP BY course_id
3997 ORDER BY total_enrolled DESC LIMIT 0,{$limit} ;");
3998
3999 return $courses;
4000 }
4001
4002 /**
4003 * @param int $limit
4004 *
4005 * @return array|bool|null|object
4006 *
4007 * Get most rated courses lists
4008 *
4009 * @since v.1.0.0
4010 */
4011 public function most_rated_courses($limit = 10){
4012 global $wpdb;
4013
4014 $result = $wpdb->get_results("
4015 SELECT COUNT(comment_ID) AS total_rating,
4016 comment_ID,
4017 comment_post_ID,
4018 course.*
4019 FROM {$wpdb->comments}
4020 INNER JOIN {$wpdb->posts} course ON comment_post_ID = course.ID
4021 WHERE {$wpdb->comments}.comment_type = 'tutor_course_rating' AND {$wpdb->comments}.comment_approved = 'approved'
4022 GROUP BY comment_post_ID ORDER BY total_rating DESC LIMIT 0,{$limit}
4023 ;");
4024
4025 if (is_array($result) && count($result)){
4026 return $result;
4027 }
4028 return false;
4029 }
4030
4031 /**
4032 * @param null $addon_field
4033 *
4034 * @return bool
4035 *
4036 * Get Addon config
4037 *
4038 * @since v.1.0.0
4039 */
4040 public function get_addon_config($addon_field = null){
4041 if ( ! $addon_field){
4042 return false;
4043 }
4044
4045 $addonsConfig = maybe_unserialize(get_option('tutor_addons_config'));
4046
4047 if (isset($addonsConfig[$addon_field])){
4048 return $addonsConfig[$addon_field];
4049 }
4050
4051 return false;
4052 }
4053
4054 /**
4055 * @return array|false|string
4056 *
4057 * Get the IP from visitor
4058 *
4059 * @since v.1.0.0
4060 */
4061 function get_ip() {
4062 $ipaddress = '';
4063 if (getenv('HTTP_CLIENT_IP'))
4064 $ipaddress = getenv('HTTP_CLIENT_IP');
4065 else if(getenv('HTTP_X_FORWARDED_FOR'))
4066 $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
4067 else if(getenv('HTTP_X_FORWARDED'))
4068 $ipaddress = getenv('HTTP_X_FORWARDED');
4069 else if(getenv('HTTP_FORWARDED_FOR'))
4070 $ipaddress = getenv('HTTP_FORWARDED_FOR');
4071 else if(getenv('HTTP_FORWARDED'))
4072 $ipaddress = getenv('HTTP_FORWARDED');
4073 else if(getenv('REMOTE_ADDR'))
4074 $ipaddress = getenv('REMOTE_ADDR');
4075 else
4076 $ipaddress = 'UNKNOWN';
4077 return $ipaddress;
4078 }
4079
4080 /**
4081 * @return array $array
4082 *
4083 * Get the social icons
4084 *
4085 * @since v.1.0.4
4086 */
4087
4088 public function tutor_social_share_icons(){
4089 $icons = array(
4090 'facebook' => array('share_class' => 's_facebook', 'icon_html' => '<i class="tutor-icon-facebook"></i>' ),
4091 'twitter' => array('share_class' => 's_twitter', 'icon_html' => '<i class="tutor-icon-twitter"></i>' ),
4092 'linkedin' => array('share_class' => 's_linkedin', 'icon_html' => '<i class="tutor-icon-linkedin"></i>' ),
4093 'tumblr' => array('share_class' => 's_tumblr', 'icon_html' => '<i class="tutor-icon-tumblr"></i>' ),
4094 );
4095
4096 return apply_filters('tutor_social_share_icons', $icons);
4097 }
4098
4099 /**
4100 * @return array $array
4101 *
4102 * Get the user social icons
4103 *
4104 * @since v.1.3.7
4105 */
4106
4107 public function tutor_user_social_icons(){
4108 $icons = array(
4109 '_tutor_profile_website' => array(
4110 'label' => __('Website URL', 'tutor'),
4111 'placeholder' => 'https://example.com/',
4112 'icon_classes' => 'tutor-icon-earth'
4113 ),
4114 '_tutor_profile_github' => array(
4115 'label' => __('Github URL', 'tutor'),
4116 'placeholder' => 'https://github.com/username',
4117 'icon_classes' => 'tutor-icon-github-logo'
4118 ),
4119 '_tutor_profile_facebook' => array(
4120 'label' => __('Facebook URL', 'tutor'),
4121 'placeholder' => 'https://facebook.com/username',
4122 'icon_classes' => 'tutor-icon-facebook'
4123 ),
4124 '_tutor_profile_twitter' => array(
4125 'label' => __('Twitter URL', 'tutor'),
4126 'placeholder' => 'https://twitter.com/username',
4127 'icon_classes' => 'tutor-icon-twitter'
4128 ),
4129 '_tutor_profile_linkedin' => array(
4130 'label' => __('Linkedin URL', 'tutor'),
4131 'placeholder' => 'https://linkedin.com/username',
4132 'icon_classes' => 'tutor-icon-linkedin'
4133 ),
4134 );
4135
4136 return apply_filters('tutor_user_social_icons', $icons);
4137 }
4138
4139 /**
4140 * @param array $array
4141 *
4142 * @return bool
4143 *
4144 * count method with check is_array
4145 *
4146 * @since v.1.0.4
4147 */
4148 public function count($array = array()){
4149 if (is_array($array) && count($array)){
4150 return count($array);
4151 }
4152 return false;
4153 }
4154
4155 /**
4156 * @return array
4157 *
4158 * get all screen ids
4159 *
4160 * @since v.1.1.2
4161 */
4162 public function tutor_get_screen_ids(){
4163 $screen_ids = array(
4164 "edit-course",
4165 "course",
4166 "edit-course-category",
4167 "edit-course-tag",
4168 "tutor-lms_page_tutor-students",
4169 "tutor-lms_page_tutor-instructors",
4170 "tutor-lms_page_question_answer",
4171 "tutor-lms_page_tutor_quiz_attempts",
4172 "tutor-lms_page_tutor-addons",
4173 "tutor-lms_page_tutor-status",
4174 "tutor-lms_page_tutor_report",
4175 "tutor-lms_page_tutor_settings",
4176 "tutor-lms_page_tutor_emails",
4177 );
4178
4179 return apply_filters('tutor_get_screen_ids', $screen_ids);
4180 }
4181
4182
4183 /**
4184 * @return mixed
4185 *
4186 * get earning transaction completed status
4187 *
4188 * @since v.1.1.2
4189 */
4190 public function get_earnings_completed_statuses(){
4191 return apply_filters(
4192 'tutor_get_earnings_completed_statuses',
4193 array (
4194 'wc-completed',
4195 'completed',
4196 'complete',
4197 )
4198 );
4199 }
4200
4201 /**
4202 * @param int $user_id
4203 * @param array $date_filter
4204 *
4205 * @return array|null|object
4206 *
4207 * Get all time earning sum for an instructor with all commission
4208 *
4209 * @since v.1.1.2
4210 */
4211
4212 public function get_earning_sum($user_id = 0, $date_filter = array()){
4213 global $wpdb;
4214
4215 $user_id = $this->get_user_id($user_id);
4216 $date_query = '';
4217 if ($this->count($date_filter)){
4218 extract($date_filter);
4219
4220 if ( ! empty($dataFor)){
4221 if ($dataFor === 'yearly'){
4222 if (empty($year)){
4223 $year = date('Y');
4224 }
4225 $date_query = "AND YEAR(created_at) = {$year} ";
4226 }
4227 }else{
4228 $date_query = " AND (created_at BETWEEN '{$start_date}' AND '{$end_date}') ";
4229 }
4230 }
4231
4232 $complete_status = tutor_utils()->get_earnings_completed_statuses();
4233 $complete_status = "'".implode("','", $complete_status)."'";
4234
4235 $earning_sum = $wpdb->get_row("SELECT SUM(course_price_total) as course_price_total,
4236 SUM(course_price_grand_total) as course_price_grand_total,
4237 SUM(instructor_amount) as instructor_amount,
4238 (SELECT SUM(amount) FROM {$wpdb->prefix}tutor_withdraws WHERE user_id = {$user_id} AND status != 'rejected' ) as
4239 withdraws_amount,
4240 SUM(admin_amount) as admin_amount,
4241 SUM(deduct_fees_amount) as deduct_fees_amount
4242 FROM {$wpdb->prefix}tutor_earnings
4243 WHERE user_id = {$user_id} AND order_status IN({$complete_status}) {$date_query} ");
4244
4245 //TODO: need to check
4246 // (SUM(instructor_amount) - (SELECT withdraws_amount) ) as balance,
4247
4248
4249 if ( $earning_sum->course_price_total){
4250 $earning_sum->balance = $earning_sum->instructor_amount - $earning_sum->withdraws_amount;
4251 }else{
4252
4253 $earning_sum = (object) array(
4254 'course_price_total' => 0,
4255 'course_price_grand_total' => 0,
4256 'instructor_amount' => 0,
4257 'withdraws_amount' => 0,
4258 'balance' => 0,
4259 'admin_amount' => 0,
4260 'deduct_fees_amount' => 0,
4261 );
4262 }
4263
4264 return $earning_sum;
4265 }
4266
4267 /**
4268 * @param int $user_id
4269 * @param array $date_filter
4270 *
4271 * @return array|null|object
4272 *
4273 * Get earning statements
4274 *
4275 * @since v.1.1.2
4276 */
4277 public function get_earning_statements($user_id = 0, $filter_data = array()){
4278 global $wpdb;
4279
4280 $user_sql = "";
4281 if ($user_id){
4282 $user_sql = " AND user_id='{$user_id}' ";
4283 }
4284
4285 $date_query = '';
4286 $query_by_status = '';
4287 $pagination_query = '';
4288
4289 /**
4290 * Query by Date Filter
4291 */
4292 if ($this->count($filter_data)){
4293 extract($filter_data);
4294
4295 if ( ! empty($dataFor)){
4296 if ($dataFor === 'yearly'){
4297 if (empty($year)){
4298 $year = date('Y');
4299 }
4300 $date_query = "AND YEAR(created_at) = {$year} ";
4301 }
4302 }else{
4303 $date_query = " AND (created_at BETWEEN '{$start_date}' AND '{$end_date}') ";
4304 }
4305
4306 /**
4307 * Query by order status related to this earning transaction
4308 */
4309 if ( ! empty($statuses)) {
4310 if ( $this->count( $statuses ) ) {
4311 $status = "'" . implode( "','", $statuses ) . "'";
4312 $query_by_status = "AND order_status IN({$status})";
4313 } elseif ( $statuses === 'completed' ) {
4314
4315 $get_earnings_completed_statuses = $this->get_earnings_completed_statuses();
4316 if ( $this->count( $get_earnings_completed_statuses ) ) {
4317 $status = "'" . implode( "','", $get_earnings_completed_statuses ) . "'";
4318 $query_by_status = "AND order_status IN({$status})";
4319 }
4320 }
4321 }
4322
4323 if ( ! empty($per_page)){
4324 $offset = (int) ! empty($offset) ? $offset : 0;
4325
4326 $pagination_query = " LIMIT {$offset}, {$per_page} ";
4327
4328 }
4329
4330
4331 }
4332
4333 $query = $wpdb->get_results("SELECT earning_tbl.*, course.post_title as course_title
4334 FROM {$wpdb->prefix}tutor_earnings earning_tbl
4335 LEFT JOIN {$wpdb->posts} course ON earning_tbl.course_id = course.ID
4336 WHERE 1=1 {$user_sql} {$date_query} {$query_by_status} ORDER BY created_at DESC {$pagination_query} ");
4337
4338
4339 $query_count = (int) $wpdb->get_var("SELECT COUNT(earning_tbl.earning_id)
4340 FROM {$wpdb->prefix}tutor_earnings earning_tbl
4341 WHERE 1=1 {$user_sql} {$date_query} {$query_by_status} ORDER BY created_at DESC ");
4342
4343 return (object) array(
4344 'count' => $query_count,
4345 'results' => $query,
4346 );
4347 }
4348
4349 /**
4350 * @param int $price
4351 *
4352 * @return int|string
4353 *
4354 * Get the price format
4355 *
4356 * @since v.1.1.2
4357 */
4358
4359 public function tutor_price($price = 0){
4360 if (function_exists('wc_price')){
4361 return wc_price($price);
4362 }elseif (function_exists('edd_currency_filter')){
4363 return edd_currency_filter(edd_format_amount($price));
4364 }else{
4365 return number_format_i18n($price);
4366 }
4367 }
4368
4369 /**
4370 * @return mixed
4371 *
4372 * Get currency symbol from activated plugin, WC,EDD
4373 *
4374 * @since v.1.3.4
4375 */
4376
4377 public function currency_symbol(){
4378 $enable_tutor_edd = tutor_utils()->get_option('enable_tutor_edd');
4379 $monetize_by = $this->get_option('monetize_by');
4380
4381 $symbol = '&#36;';
4382 if ($enable_tutor_edd && function_exists('edd_currency_symbol')){
4383 $symbol = edd_currency_symbol();
4384 }
4385
4386 if ($monetize_by === 'wc' && function_exists('get_woocommerce_currency_symbol') ){
4387 $symbol = get_woocommerce_currency_symbol();
4388 }
4389
4390 return apply_filters('get_tutor_currency_symbol', $symbol);
4391 }
4392
4393 /**
4394 * @param int $user_id
4395 *
4396 * @return bool|mixed
4397 *
4398 * Get withdraw method for a specific
4399 */
4400 public function get_user_withdraw_method($user_id = 0){
4401 $user_id = $this->get_user_id($user_id);
4402
4403 $account = get_user_meta($user_id, '_tutor_withdraw_method_data', true);
4404 if ($account){
4405 return maybe_unserialize($account);
4406 }
4407
4408 return false;
4409 }
4410
4411 /**
4412 * @param int $user_id
4413 * @param array $filter
4414 *
4415 * get withdrawal history
4416 *
4417 * @return object
4418 */
4419 public function get_withdrawals_history($user_id = 0, $filter = array()){
4420 global $wpdb;
4421
4422 $filter = (array) $filter;
4423 extract($filter);
4424
4425 $query_by_status_sql = "";
4426 $query_by_user_sql = "";
4427 $query_by_pagination = "";
4428
4429 if ( ! empty($status)){
4430 $status = (array) $status;
4431 $status = "'".implode("','", $status)."'";
4432
4433 $query_by_status_sql = " AND status IN({$status}) ";
4434 }
4435
4436 if ( ! empty($per_page)){
4437 if ( empty($start))
4438 $start = 0;
4439
4440 $query_by_pagination = " LIMIT {$start}, {$per_page} ";
4441 }
4442
4443 if ($user_id){
4444 $query_by_user_sql = " AND user_id = {$user_id} ";
4445 }
4446
4447
4448 $count = (int) $wpdb->get_var("SELECT COUNT(withdraw_id) FROM {$wpdb->prefix}tutor_withdraws WHERE 1=1 {$query_by_user_sql} {$query_by_status_sql} ");
4449
4450 $results = $wpdb->get_results("SELECT withdraw_tbl.*,
4451 user_tbl.display_name as user_name,
4452 user_tbl.user_email
4453 FROM {$wpdb->prefix}tutor_withdraws withdraw_tbl
4454 INNER JOIN {$wpdb->users} user_tbl ON withdraw_tbl.user_id = user_tbl.ID
4455 WHERE 1=1
4456 {$query_by_user_sql}
4457 {$query_by_status_sql} ORDER BY
4458 created_at DESC {$query_by_pagination} ");
4459
4460 $withdraw_history = array(
4461 'count' => 0,
4462 'results' => null,
4463 );
4464
4465 if ($count){
4466 $withdraw_history['count'] = $count;
4467 }
4468
4469 if (tutor_utils()->count($results)){
4470 $withdraw_history['results'] = $results;
4471 }
4472 return (object) $withdraw_history;
4473
4474 }
4475
4476 /**
4477 * @param int $instructor_id
4478 *
4479 * Add Instructor role to any user by user iD
4480 */
4481 public function add_instructor_role($instructor_id = 0){
4482 if ( ! $instructor_id){
4483 return;
4484 }
4485 do_action('tutor_before_approved_instructor', $instructor_id);
4486
4487 update_user_meta($instructor_id, '_tutor_instructor_status', 'approved');
4488 update_user_meta($instructor_id, '_tutor_instructor_approved', tutor_time());
4489
4490 $instructor = new \WP_User($instructor_id);
4491 $instructor->add_role(tutor()->instructor_role);
4492
4493 do_action('tutor_after_approved_instructor', $instructor_id);
4494 }
4495
4496 /**
4497 * @param int $instructor_id
4498 *
4499 * Remove instructor role by instructor id
4500 */
4501 public function remove_instructor_role($instructor_id = 0){
4502 if ( ! $instructor_id){
4503 return;
4504 }
4505
4506 do_action('tutor_before_blocked_instructor', $instructor_id);
4507 update_user_meta($instructor_id, '_tutor_instructor_status', 'blocked');
4508
4509 $instructor = new \WP_User($instructor_id);
4510 $instructor->remove_role(tutor()->instructor_role);
4511 do_action('tutor_after_blocked_instructor', $instructor_id);
4512 }
4513
4514 /**
4515 * @param string $msg
4516 * @param string $name
4517 *
4518 * Set Flash Message to view in next action / route
4519 */
4520 public function set_flash_msg($msg = '', $name = 'success'){
4521 global $wp_filesystem;
4522 if ( ! $wp_filesystem ) {
4523 require_once( ABSPATH . 'wp-admin/includes/file.php' );
4524 }
4525
4526 $filename = "tutor_flash_msg_{$name}.txt";
4527 $upload_dir = wp_upload_dir();
4528 $dir = trailingslashit($upload_dir['basedir']) . 'tutor/';
4529
4530 WP_Filesystem( false, $upload_dir['basedir'], true );
4531
4532 if( ! $wp_filesystem->is_dir( $dir ) ) {
4533 $wp_filesystem->mkdir( $dir );
4534 }
4535 $wp_filesystem->put_contents( $dir . $filename, $msg );
4536 }
4537
4538 /**
4539 * @param null $name
4540 *
4541 * @return mixed|string|void
4542 *
4543 * Get Flash Message
4544 */
4545 public function get_flash_msg($name = null){
4546 if ( ! $name){
4547 return '';
4548 }
4549
4550 $upload_dir = wp_get_upload_dir();
4551 $upload_dir = trailingslashit($upload_dir['basedir']);
4552 $msg_name = 'tutor_flash_msg_'.$name;
4553
4554 $msg = '';
4555 $flash_msg_file_name = $upload_dir."tutor/{$msg_name}.txt";
4556 if (file_exists($flash_msg_file_name)){
4557 $msg = file_get_contents($flash_msg_file_name);
4558 unlink($flash_msg_file_name);
4559 }
4560
4561 return apply_filters('tutor_get_flash_msg', $msg, $name);
4562 }
4563
4564 /**
4565 * @param int $user_id
4566 *
4567 * @return array|null|object
4568 *
4569 * Get purchase history by customer id
4570 */
4571
4572 public function get_orders_by_user_id($user_id = 0){
4573 global $wpdb;
4574
4575 $user_id = $this->get_user_id();
4576
4577 $query = $wpdb->get_results("SELECT {$wpdb->posts}.* FROM {$wpdb->posts}
4578 INNER JOIN {$wpdb->postmeta} customer ON ID = customer.post_id AND customer.meta_key = '_customer_user'
4579 INNER JOIN {$wpdb->postmeta} tutor_order ON ID = tutor_order.post_id AND tutor_order.meta_key = '_is_tutor_order_for_course'
4580 WHERE post_type = 'shop_order' AND customer.meta_value = {$user_id}
4581 ORDER BY {$wpdb->posts}.ID DESC");
4582 return $query;
4583 }
4584
4585 /**
4586 * @param null $status
4587 *
4588 * @return string
4589 *
4590 * Get status contact formatted for order
4591 *
4592 * @since v.1.3.1
4593 */
4594 public function order_status_context($status = null){
4595 $status = str_replace('wc-', '', $status);
4596 $status_name = ucwords(str_replace('-', ' ', $status));
4597
4598 return "<span class='label-order-status label-status-{$status}'>$status_name</span>";
4599 }
4600
4601 public function get_course_id_by_assignment($assignment_id = 0){
4602 $assignment_id = $this->get_post_id($assignment_id);
4603 return get_post_meta($assignment_id, '_tutor_course_id_for_assignments', true);
4604 }
4605
4606 /**
4607 * @param int $assignment_id
4608 * @param string $option_key
4609 * @param bool $default
4610 *
4611 * @return array|bool|mixed
4612 *
4613 * Get assignment options
4614 *
4615 * @since v.1.3.3
4616 */
4617 public function get_assignment_option($assignment_id = 0, $option_key = '', $default = false){
4618 $assignment_id = $this->get_post_id($assignment_id);
4619 $get_option_meta = maybe_unserialize(get_post_meta($assignment_id, 'assignment_option', true));
4620
4621 if ( ! $option_key && ! empty($get_option_meta)) {
4622 return $get_option_meta;
4623 }
4624
4625 $value = $this->avalue_dot( $option_key, $get_option_meta );
4626 if ( $value ) {
4627 return $value;
4628 }
4629 return $default;
4630 }
4631
4632 /**
4633 * @param int $assignment_id
4634 * @param int $user_id
4635 *
4636 * @return int
4637 *
4638 * Is running any assignment submitting
4639 *
4640 * @since v.1.3.3
4641 */
4642 public function is_assignment_submitting($assignment_id = 0, $user_id = 0){
4643 global $wpdb;
4644
4645 $assignment_id = $this->get_post_id($assignment_id);
4646 $user_id = $this->get_user_id($user_id);
4647
4648 $is_running_submit = (int) $wpdb->get_var("SELECT comment_ID FROM {$wpdb->comments}
4649 WHERE comment_type = 'tutor_assignment'
4650 AND comment_approved = 'submitting'
4651 AND user_id = {$user_id}
4652 AND comment_post_ID = {$assignment_id} ");
4653
4654 return $is_running_submit;
4655 }
4656
4657 /**
4658 * @param int $assignment_id
4659 * @param int $user_id
4660 *
4661 * @return array|null|object
4662 *
4663 * Determine if any assignment submitted by user to a assignment
4664 *
4665 * @since v.1.3.3
4666 */
4667
4668 public function is_assignment_submitted($assignment_id = 0, $user_id = 0){
4669 global $wpdb;
4670
4671 $assignment_id = $this->get_post_id($assignment_id);
4672 $user_id = $this->get_user_id($user_id);
4673
4674 $has_submitted = $wpdb->get_row("SELECT * FROM {$wpdb->comments} WHERE comment_type = 'tutor_assignment' AND comment_approved = 'submitted' AND user_id = {$user_id} AND comment_post_ID = {$assignment_id} ");
4675
4676 return $has_submitted;
4677 }
4678
4679 public function get_assignment_submit_info($assignment_submitted_id = 0){
4680 global $wpdb;
4681
4682 $assignment_submitted_id = $this->get_post_id($assignment_submitted_id);
4683 $submitted_info = $wpdb->get_row("SELECT * FROM {$wpdb->comments} WHERE comment_ID = {$assignment_submitted_id} AND comment_type = 'tutor_assignment' AND comment_approved = 'submitted' ");
4684
4685 return $submitted_info;
4686 }
4687
4688 public function get_total_assignments(){
4689 global $wpdb;
4690
4691 $count = $wpdb->get_var("SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_type = 'tutor_assignment' AND comment_approved = 'submitted' ");
4692
4693 return (int) $count;
4694 }
4695
4696 public function get_assignments(){
4697 global $wpdb;
4698
4699 $results = $wpdb->get_results("SELECT * FROM {$wpdb->comments} WHERE comment_type = 'tutor_assignment' AND comment_approved = 'submitted' ");
4700
4701 return $results;
4702 }
4703
4704 /**
4705 * @param int $user_id
4706 *
4707 * @return array
4708 *
4709 * Get all courses id assigned or owned by an instructors
4710 *
4711 * @since v.1.3.3
4712 */
4713 public function get_assigned_courses_ids_by_instructors($user_id = 0){
4714 global $wpdb;
4715 $user_id = $this->get_user_id($user_id);
4716
4717 $course_post_type = tutor()->course_post_type;
4718 $get_assigned_courses_ids = $wpdb->get_col("SELECT meta_value from {$wpdb->usermeta} WHERE meta_key = '_tutor_instructor_course_id' AND user_id = {$user_id} GROUP BY meta_value ; ");
4719
4720 /*
4721 $author_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} where post_type = '{$course_post_type}' AND post_author = {$user_id}");
4722 $final_course_ids = array_merge($get_assigned_courses_ids, $author_ids);
4723 $final_course_ids = array_unique($final_course_ids);
4724 */
4725
4726 return $get_assigned_courses_ids;
4727 }
4728
4729 /**
4730 * @param int $parent
4731 *
4732 * @return array
4733 *
4734 * Get course categories in array with child
4735 *
4736 * @since v.1.3.4
4737 */
4738
4739 public function get_course_categories($parent = 0 ){
4740 $args = apply_filters('tutor_get_course_categories_args', array(
4741 'taxonomy' => 'course-category',
4742 'hide_empty' => false,
4743 'parent' => $parent,
4744 ));
4745
4746 $terms = get_terms($args);
4747
4748 $children = array();
4749 foreach ( $terms as $term ){
4750 $term->children = $this->get_course_categories( $term->term_id );
4751 $children[ $term->term_id ] = $term;
4752 }
4753
4754 return $children;
4755 }
4756
4757 /**
4758 * @param int $parent_id
4759 *
4760 * @return array|int|\WP_Error
4761 *
4762 * Get course categories terms in raw array
4763 *
4764 * @since v.1.3.5
4765 */
4766 public function get_course_categories_term($parent_id = 0){
4767 $args = apply_filters('tutor_get_course_categories_terms_args', array(
4768 'taxonomy' => 'course-category',
4769 'parent' => $parent_id,
4770 'hide_empty' => false,
4771 ));
4772
4773 $terms = get_terms($args);
4774
4775 return $terms;
4776 }
4777
4778 /**
4779 * @return mixed
4780 *
4781 * Get back url from the request
4782 * @since v.1.3.4
4783 */
4784 public function referer(){
4785 $url = $this->array_get('_wp_http_referer', $_REQUEST);
4786 return apply_filters('tutor_referer_url', $url);
4787 }
4788
4789 /**
4790 * @param int $course_id
4791 *
4792 * @return false|string
4793 *
4794 * Get the frontend dashboard course edit page
4795 *
4796 * @since v.1.3.4
4797 */
4798 public function course_edit_link($course_id = 0){
4799 $course_id = $this->get_post_id($course_id);
4800
4801 $url = admin_url("post.php?post={$course_id}&action=edit");
4802 if (tutor()->has_pro){
4803 $url = $this->tutor_dashboard_url("create-course/?course_ID=".$course_id);
4804 }
4805
4806 return $url;
4807 }
4808
4809 public function get_assignments_by_instructor($instructor_id = 0, $filter_data = array()){
4810 global $wpdb;
4811
4812 $instructor_id = $this->get_user_id($instructor_id);
4813 $course_ids = tutor_utils()->get_assigned_courses_ids_by_instructors($instructor_id);
4814
4815 //$new_course_ids = tutils()->get_courses_by_instructor();
4816
4817 //die($this->print_view($course_ids));
4818
4819 $in_course_ids = implode("','", $course_ids);
4820
4821 $count = (int) $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->postmeta} post_meta
4822 INNER JOIN {$wpdb->posts} assignment ON post_meta.post_id = assignment.ID AND post_meta.meta_key = '_tutor_course_id_for_assignments'
4823 where post_type = 'tutor_assignments' AND post_meta.meta_value IN('$in_course_ids') ORDER BY ID DESC ");
4824
4825 $pagination_query = '';
4826 if ($this->count($filter_data)) {
4827 extract( $filter_data );
4828
4829 if ( ! empty( $per_page ) ) {
4830 $offset = (int) ! empty( $offset ) ? $offset : 0;
4831 $pagination_query = " LIMIT {$offset}, {$per_page} ";
4832 }
4833 }
4834
4835 $query = $wpdb->get_results("SELECT * FROM {$wpdb->postmeta} post_meta
4836 INNER JOIN {$wpdb->posts} assignment ON post_meta.post_id = assignment.ID AND post_meta.meta_key = '_tutor_course_id_for_assignments'
4837 where post_type = 'tutor_assignments' AND post_meta.meta_value IN('$in_course_ids') ORDER BY ID DESC {$pagination_query} ");
4838
4839 return (object) array('count' => $count, 'results' => $query);
4840 }
4841
4842 /**
4843 * @param int $course_id
4844 *
4845 * @return bool|object
4846 *
4847 * Get assignments by course id
4848 */
4849 public function get_assignments_by_course($course_id = 0){
4850 if ( ! $course_id){
4851 return false;
4852 }
4853 global $wpdb;
4854
4855 $count = (int) $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->postmeta} post_meta
4856 INNER JOIN {$wpdb->posts} assignment ON post_meta.post_id = assignment.ID AND post_meta.meta_key = '_tutor_course_id_for_assignments'
4857 where post_type = 'tutor_assignments' AND post_meta.meta_value = {$course_id} ORDER BY ID DESC ");
4858
4859 $query = $wpdb->get_results("SELECT * FROM {$wpdb->postmeta} post_meta
4860 INNER JOIN {$wpdb->posts} assignment ON post_meta.post_id = assignment.ID AND post_meta.meta_key = '_tutor_course_id_for_assignments'
4861 where post_type = 'tutor_assignments' AND post_meta.meta_value = {$course_id} ORDER BY ID DESC");
4862
4863 return (object) array('count' => $count, 'results' => $query);
4864 }
4865
4866 /**
4867 * @return bool
4868 *
4869 * Determine if script debug
4870 *
4871 * @since v.1.3.4
4872 */
4873 public function is_script_debug(){
4874 return ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG );
4875 }
4876
4877 /**
4878 * Check lesson edit access by instructor
4879 *
4880 * @since v.1.4.0
4881 */
4882
4883 public function has_lesson_edit_access($lesson_id = 0, $instructor_id = 0){
4884 $lesson_id = $this->get_post_id($lesson_id);
4885 $instructor_id = $this->get_user_id($instructor_id);
4886
4887 if (user_can($instructor_id, tutor()->instructor_role)){
4888 $permitted_course_ids = tutils()->get_assigned_courses_ids_by_instructors();
4889 $course_id = tutils()->get_course_id_by_lesson($lesson_id);
4890
4891 if (in_array($course_id, $permitted_course_ids)){
4892 return true;
4893 }
4894 }
4895
4896 return false;
4897 }
4898
4899
4900 /**
4901 * Get total Enrolments
4902 * @since v.1.4.0
4903 */
4904
4905 public function get_total_enrolments($search_term = ''){
4906 global $wpdb;
4907
4908 $search_sql = '';
4909 if ($search_term){
4910 $search_sql = " AND ( enrol.ID = '{$search_term}' OR student.display_name LIKE '%{$search_term}%' OR student.user_email LIKE '%{$search_term}%' OR course.post_title LIKE '%{$search_term}%' ) ";
4911 }
4912
4913 $count = $wpdb->get_var("SELECT COUNT(enrol.ID)
4914 FROM {$wpdb->posts} enrol
4915 INNER JOIN {$wpdb->posts} course ON enrol.post_parent = course.ID
4916 INNER JOIN {$wpdb->users} student ON enrol.post_author = student.ID
4917 WHERE enrol.post_type = 'tutor_enrolled' {$search_sql} ");
4918 return (int) $count;
4919 }
4920
4921 public function get_enrolments($start = 0, $limit = 10, $search_term = ''){
4922 global $wpdb;
4923
4924 $search_sql = '';
4925 if ($search_term){
4926 $search_sql = " AND ( enrol.ID = '{$search_term}' OR student.display_name LIKE '%{$search_term}%' OR student.user_email LIKE '%{$search_term}%' OR course.post_title LIKE '%{$search_term}%' ) ";
4927 }
4928
4929 $enrolments = $wpdb->get_results("SELECT
4930 enrol.ID as enrol_id,
4931 enrol.post_author as student_id,
4932 enrol.post_date as enrol_date,
4933 enrol.post_title as enrol_title,
4934 enrol.post_status as status,
4935 enrol.post_parent as course_id,
4936
4937 course.post_title as course_title,
4938
4939 student.user_nicename,
4940 student.user_email,
4941 student.display_name
4942
4943 FROM {$wpdb->posts} enrol
4944
4945 INNER JOIN {$wpdb->posts} course ON enrol.post_parent = course.ID
4946 INNER JOIN {$wpdb->users} student ON enrol.post_author = student.ID
4947
4948 WHERE enrol.post_type = 'tutor_enrolled' {$search_sql}
4949 ORDER BY enrol_id DESC
4950 LIMIT {$start}, {$limit} ");
4951
4952 return $enrolments;
4953 }
4954
4955 /**
4956 * @param int $post_id
4957 *
4958 * @return false|string
4959 *
4960 * @since v.1.4.0
4961 */
4962
4963 public function get_current_url($post_id = 0){
4964 $page_id = $this->get_post_id($post_id);
4965
4966 if ($page_id){
4967 return get_the_permalink($page_id);
4968 }else{
4969 global $wp;
4970 $current_url = home_url( $wp->request );
4971
4972 return $current_url;
4973 }
4974 }
4975
4976
4977 /**
4978 * @param int $rating_id
4979 *
4980 * @return object
4981 *
4982 * Get rating by rating id|comment_ID
4983 *
4984 * @since v.1.4.0
4985 */
4986
4987 public function get_rating_by_id($rating_id = 0){
4988 $ratings = array(
4989 'rating' => 0,
4990 'review' => '',
4991 );
4992
4993 global $wpdb;
4994
4995 $rating = $wpdb->get_row("select meta_value as rating, comment_content as review from {$wpdb->comments}
4996 INNER JOIN {$wpdb->commentmeta}
4997 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
4998 WHERE {$wpdb->comments}.comment_ID = {$rating_id} ;"
4999 );
5000
5001 if ($rating){
5002 $rating_format = number_format($rating->rating, 2);
5003
5004 $ratings = array(
5005 'rating' => $rating_format,
5006 'review' => $rating->review,
5007 );
5008 }
5009 return (object) $ratings;
5010 }
5011
5012 /**
5013 * @param int $course_id
5014 * @param null $key
5015 * @param bool $default
5016 *
5017 * @return array|bool|mixed
5018 *
5019 * Get course settings by course ID
5020 */
5021 public function get_course_settings($course_id = 0, $key = null, $default = false){
5022 $course_id = $this->get_post_id($course_id);
5023 $settings_meta = get_post_meta($course_id, '_tutor_course_settings', true);
5024 $settings = (array) maybe_unserialize($settings_meta);
5025
5026 return $this->array_get($key, $settings, $default);
5027 }
5028
5029 /**
5030 * @param int $lesson_id
5031 * @param null $key
5032 * @param bool $default
5033 *
5034 * @return array|bool|mixed
5035 *
5036 * Get Lesson content drip settings
5037 *
5038 * @since v.1.4.0
5039 */
5040 public function get_item_content_drip_settings($lesson_id = 0, $key = null, $default = false){
5041 $lesson_id = $this->get_post_id($lesson_id);
5042 $settings_meta = get_post_meta($lesson_id, '_content_drip_settings', true);
5043 $settings = (array) maybe_unserialize($settings_meta);
5044
5045 return $this->array_get($key, $settings, $default);
5046 }
5047
5048
5049 /**
5050 * @param null $post
5051 *
5052 * @return bool
5053 *
5054 * Get previous ID
5055 */
5056 public function get_course_previous_content_id($post = null){
5057 $current_item = get_post($post);
5058 $course_id = $this->get_course_id_by_content($current_item);
5059
5060 $topics = tutor_utils()->get_topics($course_id);
5061
5062 $contents = array();
5063 if ($topics->have_posts()) {
5064 while ( $topics->have_posts() ) {
5065 $topics->the_post();
5066 $topic_id = get_the_ID();
5067 $lessons = tutor_utils()->get_course_contents_by_topic($topic_id, -1);
5068 if ($lessons->have_posts()) {
5069 while ( $lessons->have_posts() ) {
5070 $lessons->the_post();
5071 global $post;
5072 $contents[] = $post;
5073 }
5074 }
5075
5076 }
5077 }
5078
5079 if (tutils()->count($contents)){
5080 foreach ($contents as $key => $content){
5081 if ($current_item->ID == $content->ID){
5082 if ( ! empty($contents[$key-1]->ID)){
5083 return $contents[$key-1]->ID;
5084 }
5085 }
5086 }
5087 }
5088
5089 /*
5090
5091 if ($post->menu_order > 0){
5092
5093 $contents = $wpdb->get_results("SELECT items.* FROM {$wpdb->posts} topic
5094 INNER JOIN {$wpdb->posts} items ON topic.ID = items.post_parent
5095 WHERE topic.post_parent = {$course_id} AND items.post_status = 'publish' order by topic.menu_order ASC, items.menu_order ASC;");
5096
5097
5098
5099 if (tutils()->count($contents)){
5100 foreach ($contents as $key => $content){
5101 if ($post->ID == $content->ID){
5102 if ( ! empty($contents[$key-1]->ID)){
5103 //return $contents[$key-1]->ID;
5104 }
5105 }
5106 }
5107 }
5108
5109 die(print_r($contents));
5110
5111 }else{
5112 $previous = $wpdb->get_row("SELECT items.* FROM {$wpdb->posts} topic
5113 INNER JOIN {$wpdb->posts} items ON topic.ID = items.post_parent
5114 WHERE topic.post_parent = {$course_id}
5115 AND items.post_status = 'publish'
5116 AND items.ID < {$post->ID} ORDER BY ID DESC LIMIT 1; ");
5117
5118 if ( ! empty($previous->ID)){
5119 return $previous->ID;
5120 }
5121 }*/
5122
5123 return false;
5124 }
5125
5126 /**
5127 * @param null $post
5128 *
5129 * @return int
5130 *
5131 * Get Course iD by any course content
5132 */
5133 public function get_course_id_by_content($post = null){
5134 global $wpdb;
5135 $post = get_post($post);
5136 $course_id = $wpdb->get_var("SELECT post_parent FROM {$wpdb->posts} WHERE ID = {$post->post_parent} AND post_type = 'topics'");
5137
5138 return (int) $course_id;
5139 }
5140
5141 /**
5142 * @param int $course_id
5143 *
5144 * @return array|null|object
5145 *
5146 * Get Course contents by Course ID
5147 *
5148 * @since v.1.4.1
5149 */
5150 public function get_course_contents_by_id($course_id = 0){
5151 global $wpdb;
5152
5153 $course_id = $this->get_post_id($course_id);
5154
5155 $contents = $wpdb->get_results("SELECT items.* FROM {$wpdb->posts} topic
5156 INNER JOIN {$wpdb->posts} items ON topic.ID = items.post_parent
5157 WHERE topic.post_parent = {$course_id} AND items.post_status = 'publish' order by topic.menu_order ASC, items.menu_order ASC;");
5158
5159 return $contents;
5160 }
5161
5162 /**
5163 * @param string $grade_for
5164 *
5165 * @return array|null|object
5166 *
5167 * Get Gradebooks lists by type
5168 *
5169 * @since v.1.4.2
5170 */
5171 public function get_gradebooks(){
5172 global $wpdb;
5173 $results = $wpdb->get_results("SELECT * FROM {$wpdb->tutor_gradebooks} ORDER BY grade_point DESC ");
5174 return $results;
5175 }
5176
5177
5178 /**
5179 * @param int $quiz_id
5180 * @param int $user_id
5181 *
5182 * @return array|bool|null|object
5183 *
5184 * Get Attempt row by grade method settings
5185 *
5186 * @since v.1.4.2
5187 */
5188 public function get_quiz_attempt($quiz_id = 0, $user_id = 0){
5189 global $wpdb;
5190
5191 $quiz_id = $this->get_post_id($quiz_id);
5192 $user_id = $this->get_user_id($user_id);
5193
5194 $attempt = false;
5195
5196 $quiz_grade_method = get_tutor_option('quiz_grade_method', 'highest_grade');
5197
5198 if ($quiz_grade_method === 'highest_grade'){
5199
5200 $attempt = $wpdb->get_row("SELECT *
5201 FROM {$wpdb->tutor_quiz_attempts} WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} AND attempt_status != 'attempt_started'
5202 ORDER BY earned_marks DESC LIMIT 1; ");
5203
5204 }elseif ($quiz_grade_method === 'average_grade'){
5205
5206 $attempt = $wpdb->get_row("SELECT {$wpdb->tutor_quiz_attempts}.*,
5207 COUNT(attempt_id) as attempt_count,
5208 AVG(total_marks) as total_marks,
5209 AVG(earned_marks) as earned_marks
5210 FROM {$wpdb->tutor_quiz_attempts} WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} AND attempt_status != 'attempt_started' ");
5211
5212 }elseif ($quiz_grade_method === 'first_attempt'){
5213
5214 $attempt = $wpdb->get_row("SELECT *
5215 FROM {$wpdb->tutor_quiz_attempts} WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} AND attempt_status != 'attempt_started'
5216 ORDER BY attempt_id ASC LIMIT 1; ");
5217
5218 }elseif ($quiz_grade_method === 'last_attempt'){
5219
5220 $attempt = $wpdb->get_row("SELECT *
5221 FROM {$wpdb->tutor_quiz_attempts} WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} AND attempt_status != 'attempt_started'
5222 ORDER BY attempt_id DESC LIMIT 1; ");
5223
5224 }
5225
5226 return $attempt;
5227 }
5228
5229 /**
5230 * @param int $course_id
5231 * @param int $user_id
5232 *
5233 * @return string
5234 *
5235 * Print Course Status Context
5236 *
5237 * @since v.1.4.2
5238 */
5239 public function course_progress_status_context($course_id = 0, $user_id = 0){
5240 $course_id = $this->get_post_id($course_id);
5241 $user_id = $this->get_user_id($user_id);
5242
5243 $is_completed = tutils()->is_completed_course($course_id, $user_id);
5244 $html = '';
5245 if ($is_completed){
5246 $html = '<span class="course-completion-status course-completed"><i class="tutor-icon-mark"></i> '.__('Completed', 'tutor-pro').' </span>';
5247 }else{
5248 $is_in_progress = tutor_utils()->get_completed_lesson_count_by_course($course_id, $user_id);
5249 if($is_in_progress){
5250 $html = '<span class="course-completion-status course-inprogress"><i class="tutor-icon-refresh-button-1"></i> '.__('In Progress', 'tutor-pro').' </span>';
5251 }else{
5252 $html = '<span class="course-completion-status course-not-taken"><i class="tutor-icon-spinner"></i> '.__('Not Taken', 'tutor-pro').' </span>';
5253 }
5254 }
5255 return $html;
5256 }
5257
5258 /**
5259 * @param $user
5260 * @param $new_pass
5261 *
5262 * Reset Password
5263 *
5264 * @since v.1.4.3
5265 */
5266 public function reset_password( $user, $new_pass ) {
5267 do_action( 'password_reset', $user, $new_pass );
5268
5269 wp_set_password( $new_pass, $user->ID );
5270
5271 $rp_cookie = 'wp-resetpass-' . COOKIEHASH;
5272 $rp_path = isset( $_SERVER['REQUEST_URI'] ) ? current( explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) : ''; // WPCS: input var ok, sanitization ok.
5273
5274 setcookie( $rp_cookie, ' ', tutor_time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
5275 wp_password_change_notification( $user );
5276 }
5277
5278 /**
5279 * @return array
5280 *
5281 * Get tutor pages, required to show dashboard, and others forms
5282 *
5283 * @since v.1.4.3
5284 */
5285 public function tutor_pages(){
5286 $pages = apply_filters('tutor_pages', array(
5287 'tutor_dashboard_page_id' => __('Dashboard Page', 'tutor'),
5288 'instructor_register_page' => __('Instructor Registration Page', 'tutor'),
5289 'student_register_page' => __('Student Registration Page', 'tutor'),
5290 ));
5291
5292 $new_pages = array();
5293 foreach ($pages as $key => $page){
5294 $page_id = (int) get_tutor_option($key);
5295
5296 $wp_page_name = '';
5297 $wp_page = get_post($page_id);
5298 $page_exists = (bool) $wp_page;
5299 $page_visible = false;
5300
5301 if ($wp_page){
5302 $wp_page_name = $wp_page->post_title;
5303 $page_visible = $wp_page->post_status === 'publish';
5304 }
5305
5306 $new_pages[] = array(
5307 'option_key' => $key,
5308 'page_name' => $page,
5309 'wp_page_name' => $wp_page_name,
5310 'page_id' => $page_id,
5311 'page_exists' => $page_exists,
5312 'page_visible' => $page_visible,
5313 );
5314
5315 }
5316
5317 return $new_pages;
5318 }
5319
5320 /**
5321 * @param int $course_id
5322 *
5323 * @return array|null|object
5324 *
5325 * Get Course prev next lession contents by content ID
5326 *
5327 * @since v.1.4.9
5328 */
5329 public function get_course_prev_next_contents_by_id($content_id = 0){
5330
5331 $course_id = $this->get_course_id_by_content($content_id);
5332 $course_contents = $this->get_course_contents_by_id($course_id);
5333 $previous_id = 0;
5334 $next_id = 0;
5335 if ($this->count($course_contents)){
5336 $ids = wp_list_pluck($course_contents, 'ID');
5337
5338 $i=0;
5339 foreach ($ids as $key => $id){
5340 $previous_i = $key - 1;
5341 $next_i = $key + 1;
5342
5343 if ($id == $content_id){
5344 if (isset($ids[$previous_i])){
5345 $previous_id = $ids[$previous_i];
5346 }
5347 if (isset($ids[$next_i])){
5348 $next_id = $ids[$next_i];
5349 }
5350 }
5351 $i++;
5352 }
5353 }
5354
5355 return (object) ['previous_id'=>$previous_id, 'next_id'=>$next_id];
5356 }
5357
5358
5359 /**
5360 * Get a subset of the items from the given array.
5361 *
5362 * @param array $array
5363 * @param array|string $keys
5364 *
5365 * @return array|bool
5366 *
5367 * @since v.1.5.2
5368 */
5369
5370 public function array_only($array = array(), $keys = null){
5371 if ( ! $this->count($array) || ! $keys){
5372 return false;
5373 }
5374
5375 return array_intersect_key($array, array_flip((array) $keys));
5376 }
5377
5378
5379 }