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