PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.3.1
Tutor LMS – eLearning and online course solution v1.3.1
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 7 years ago Admin.php 7 years ago Ajax.php 7 years ago Assets.php 7 years ago Course.php 7 years ago Course_Widget.php 7 years ago Gutenberg.php 7 years ago Instructor.php 7 years ago Instructors_List.php 7 years ago Lesson.php 7 years ago Options.php 7 years ago Post_types.php 7 years ago Q_and_A.php 7 years ago Question.php 7 years ago Question_Answers_List.php 7 years ago Quiz.php 7 years ago Quiz_Attempts_List.php 7 years ago Rewrite_Rules.php 7 years ago Shortcode.php 7 years ago Student.php 7 years ago Students_List.php 7 years ago Taxonomies.php 7 years ago Template.php 7 years ago Theme_Compatibility.php 7 years ago Tools.php 7 years ago Tutor.php 7 years ago TutorEDD.php 7 years ago Tutor_Base.php 7 years ago Tutor_List_Table.php 7 years ago User.php 7 years ago Utils.php 7 years ago Video_Stream.php 7 years ago Withdraw.php 7 years ago Withdraw_Requests_List.php 7 years ago WooCommerce.php 7 years ago
Utils.php
4265 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 */
75
76 public function avalue_dot($key = null, $array = array()){
77 $array = (array) $array;
78 if ( ! $key || ! count($array) ){
79 return false;
80 }
81 $option_key_array = explode('.', $key);
82
83 $value = $array;
84
85 foreach ($option_key_array as $dotKey){
86 if (isset($value[$dotKey])){
87 $value = $value[$dotKey];
88 }else{
89 return false;
90 }
91 }
92 return $value;
93 }
94
95 /**
96 * @return array
97 *
98 * Get all pages
99 *
100 * @since v.1.0.0
101 */
102 public function get_pages(){
103 $pages = array();
104 $wp_pages = get_pages();
105 if (is_array($wp_pages) && count($wp_pages)){
106 foreach ($wp_pages as $page){
107 $pages[$page->ID] = $page->post_title;
108 }
109 }
110 return $pages;
111 }
112
113 /**
114 * @return string
115 *
116 * Get course archive URL
117 *
118 * @since v.1.0.0
119 */
120 public function course_archive_page_url(){
121 $course_post_type = tutor()->course_post_type;
122 $course_page_url = trailingslashit(home_url()).$course_post_type;
123
124 $course_archive_page = $this->get_option('course_archive_page');
125 if ($course_archive_page && $course_archive_page !== '-1'){
126 $course_page_url = get_permalink($course_archive_page);
127 }
128 return trailingslashit($course_page_url);
129 }
130
131 /**
132 * @param int $student_id
133 *
134 * @return string
135 *
136 * Get student URL
137 *
138 * @since v.1.0.0
139 */
140
141 public function profile_url($student_id = 0){
142 $site_url = trailingslashit(home_url()).'profile/';
143 $user_name = '';
144
145 $student_id = $this->get_user_id($student_id);
146 if ($student_id){
147 global $wpdb;
148 $user = $wpdb->get_row("SELECT user_login from {$wpdb->users} WHERE ID = {$student_id} ");
149 if ($user){
150 $user_name = $user->user_login;
151 }
152 }else{
153 $user_name = 'user_name';
154 }
155
156 return $site_url.$user_name;
157 }
158
159 /**
160 * @param string $user_login
161 *
162 * @return array|null|object
163 *
164 * Get user by user login
165 *
166 * @since v.1.0.0
167 */
168 public function get_user_by_login($user_login = ''){
169 global $wpdb;
170 $user_login = sanitize_text_field($user_login);
171 $user = $wpdb->get_row("SELECT * from {$wpdb->users} WHERE user_login = '{$user_login}'");
172 return $user;
173 }
174
175 /**
176 * @return bool
177 *
178 * Check if WooCommerce Activated
179 *
180 * @since v.1.0.0
181 */
182
183 public function has_wc(){
184 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
185 //$depends = array('woocommerce/woocommerce.php', 'tutor-woocommerce/tutor-woocommerce.php');
186 $depends = array('woocommerce/woocommerce.php');
187 $has = count(array_intersect($depends, $activated_plugins)) == count($depends);
188
189 return $has;
190 }
191
192 /**
193 * @return bool
194 *
195 * determine if EDD plugin activated
196 *
197 * @since v.1.0.0
198 */
199 public function has_edd(){
200 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ));
201 //$depends = array('easy-digital-downloads/easy-digital-downloads.php', 'tutor-edd/tutor-edd.php');
202 $depends = array('easy-digital-downloads/easy-digital-downloads.php');
203 $has = count(array_intersect($depends, $activated_plugins)) == count($depends);
204
205 return $has;
206 }
207
208 /**
209 * @return mixed
210 *
211 * @since v.1.0.0
212 */
213 public function languages(){
214 $language_codes = array(
215 'en' => 'English' ,
216 'aa' => 'Afar' ,
217 'ab' => 'Abkhazian' ,
218 'af' => 'Afrikaans' ,
219 'am' => 'Amharic' ,
220 'ar' => 'Arabic' ,
221 'as' => 'Assamese' ,
222 'ay' => 'Aymara' ,
223 'az' => 'Azerbaijani' ,
224 'ba' => 'Bashkir' ,
225 'be' => 'Byelorussian' ,
226 'bg' => 'Bulgarian' ,
227 'bh' => 'Bihari' ,
228 'bi' => 'Bislama' ,
229 'bn' => 'Bengali/Bangla' ,
230 'bo' => 'Tibetan' ,
231 'br' => 'Breton' ,
232 'ca' => 'Catalan' ,
233 'co' => 'Corsican' ,
234 'cs' => 'Czech' ,
235 'cy' => 'Welsh' ,
236 'da' => 'Danish' ,
237 'de' => 'German' ,
238 'dz' => 'Bhutani' ,
239 'el' => 'Greek' ,
240 'eo' => 'Esperanto' ,
241 'es' => 'Spanish' ,
242 'et' => 'Estonian' ,
243 'eu' => 'Basque' ,
244 'fa' => 'Persian' ,
245 'fi' => 'Finnish' ,
246 'fj' => 'Fiji' ,
247 'fo' => 'Faeroese' ,
248 'fr' => 'French' ,
249 'fy' => 'Frisian' ,
250 'ga' => 'Irish' ,
251 'gd' => 'Scots/Gaelic' ,
252 'gl' => 'Galician' ,
253 'gn' => 'Guarani' ,
254 'gu' => 'Gujarati' ,
255 'ha' => 'Hausa' ,
256 'hi' => 'Hindi' ,
257 'hr' => 'Croatian' ,
258 'hu' => 'Hungarian' ,
259 'hy' => 'Armenian' ,
260 'ia' => 'Interlingua' ,
261 'ie' => 'Interlingue' ,
262 'ik' => 'Inupiak' ,
263 'in' => 'Indonesian' ,
264 'is' => 'Icelandic' ,
265 'it' => 'Italian' ,
266 'iw' => 'Hebrew' ,
267 'ja' => 'Japanese' ,
268 'ji' => 'Yiddish' ,
269 'jw' => 'Javanese' ,
270 'ka' => 'Georgian' ,
271 'kk' => 'Kazakh' ,
272 'kl' => 'Greenlandic' ,
273 'km' => 'Cambodian' ,
274 'kn' => 'Kannada' ,
275 'ko' => 'Korean' ,
276 'ks' => 'Kashmiri' ,
277 'ku' => 'Kurdish' ,
278 'ky' => 'Kirghiz' ,
279 'la' => 'Latin' ,
280 'ln' => 'Lingala' ,
281 'lo' => 'Laothian' ,
282 'lt' => 'Lithuanian' ,
283 'lv' => 'Latvian/Lettish' ,
284 'mg' => 'Malagasy' ,
285 'mi' => 'Maori' ,
286 'mk' => 'Macedonian' ,
287 'ml' => 'Malayalam' ,
288 'mn' => 'Mongolian' ,
289 'mo' => 'Moldavian' ,
290 'mr' => 'Marathi' ,
291 'ms' => 'Malay' ,
292 'mt' => 'Maltese' ,
293 'my' => 'Burmese' ,
294 'na' => 'Nauru' ,
295 'ne' => 'Nepali' ,
296 'nl' => 'Dutch' ,
297 'no' => 'Norwegian' ,
298 'oc' => 'Occitan' ,
299 'om' => '(Afan)/Oromoor/Oriya' ,
300 'pa' => 'Punjabi' ,
301 'pl' => 'Polish' ,
302 'ps' => 'Pashto/Pushto' ,
303 'pt' => 'Portuguese' ,
304 'qu' => 'Quechua' ,
305 'rm' => 'Rhaeto-Romance' ,
306 'rn' => 'Kirundi' ,
307 'ro' => 'Romanian' ,
308 'ru' => 'Russian' ,
309 'rw' => 'Kinyarwanda' ,
310 'sa' => 'Sanskrit' ,
311 'sd' => 'Sindhi' ,
312 'sg' => 'Sangro' ,
313 'sh' => 'Serbo-Croatian' ,
314 'si' => 'Singhalese' ,
315 'sk' => 'Slovak' ,
316 'sl' => 'Slovenian' ,
317 'sm' => 'Samoan' ,
318 'sn' => 'Shona' ,
319 'so' => 'Somali' ,
320 'sq' => 'Albanian' ,
321 'sr' => 'Serbian' ,
322 'ss' => 'Siswati' ,
323 'st' => 'Sesotho' ,
324 'su' => 'Sundanese' ,
325 'sv' => 'Swedish' ,
326 'sw' => 'Swahili' ,
327 'ta' => 'Tamil' ,
328 'te' => 'Tegulu' ,
329 'tg' => 'Tajik' ,
330 'th' => 'Thai' ,
331 'ti' => 'Tigrinya' ,
332 'tk' => 'Turkmen' ,
333 'tl' => 'Tagalog' ,
334 'tn' => 'Setswana' ,
335 'to' => 'Tonga' ,
336 'tr' => 'Turkish' ,
337 'ts' => 'Tsonga' ,
338 'tt' => 'Tatar' ,
339 'tw' => 'Twi' ,
340 'uk' => 'Ukrainian' ,
341 'ur' => 'Urdu' ,
342 'uz' => 'Uzbek' ,
343 'vi' => 'Vietnamese' ,
344 'vo' => 'Volapuk' ,
345 'wo' => 'Wolof' ,
346 'xh' => 'Xhosa' ,
347 'yo' => 'Yoruba' ,
348 'zh' => 'Chinese' ,
349 'zu' => 'Zulu' ,
350 );
351
352 return apply_filters('tutor/utils/languages', $language_codes);
353 }
354
355
356 /**
357 * @param string $value
358 *
359 * Check raw data
360 *
361 * @since v.1.0.0
362 */
363 public function print_view($value = ''){
364 echo '<pre>';
365 print_r($value);
366 echo '</pre>';
367 }
368
369 /**
370 * @param array $excludes
371 *
372 * @return array|null|object
373 *
374 * Get courses
375 *
376 * @since v.1.0.0
377 */
378
379 public function get_courses($excludes = array()){
380 global $wpdb;
381
382
383 $excludes = (array) $excludes;
384 $exclude_query = '';
385 if (count($excludes)){
386 $exclude_query = implode("','", $excludes);
387 }
388
389 $course_post_type = tutor()->course_post_type;
390 $query = $wpdb->get_results("SELECT ID, post_author, post_title, post_name,post_status, menu_order
391 from {$wpdb->posts} WHERE post_status = 'publish'
392 AND ID NOT IN('$exclude_query')
393 AND post_type = '{$course_post_type}' ");
394 return $query;
395 }
396
397 /**
398 * @param int $instructor_id
399 *
400 * @return array|null|object
401 *
402 * Get courses for instructors
403 *
404 * @since v.1.0.0
405 */
406 public function get_courses_for_instructors($instructor_id = 0){
407 global $wpdb;
408
409 $instructor_id = $this->get_user_id($instructor_id);
410
411 $course_post_type = tutor()->course_post_type;
412 $query = $wpdb->get_results("SELECT ID, post_author, post_title, post_name,post_status, menu_order
413 from {$wpdb->posts}
414 WHERE post_author = {$instructor_id}
415 AND post_status IN ('publish', 'pending')
416 AND post_type = '{$course_post_type}' ");
417 return $query;
418 }
419
420 /**
421 * @param $instructor_id
422 *
423 * @return null|string
424 *
425 * Get course count by instructor
426 *
427 * @since v.1.0.0
428 */
429
430 public function get_course_count_by_instructor($instructor_id){
431 global $wpdb;
432
433 $course_post_type = tutor()->course_post_type;
434 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts}
435 INNER JOIN {$wpdb->usermeta} ON user_id = {$instructor_id} AND meta_key = '_tutor_instructor_course_id' AND meta_value = ID
436 WHERE post_status = 'publish'
437 AND post_type = '{$course_post_type}' ; ");
438
439 return $count;
440 }
441
442 /**
443 * @param $instructor_id
444 *
445 * @return array|null|object
446 *
447 * Get courses by a instructor
448 *
449 * @since v.1.0.0
450 */
451 public function get_courses_by_instructor($instructor_id = 0, $post_status = array('publish')){
452 global $wpdb;
453
454 $instructor_id = $this->get_user_id($instructor_id);
455 $course_post_type = tutor()->course_post_type;
456
457
458 if ($post_status === 'any'){
459 $where_post_status = "";
460 }else{
461 $post_status = (array) $post_status;
462 $statuses = "'".implode("','", $post_status)."'";
463 $where_post_status = "AND $wpdb->posts.post_status IN({$statuses}) ";
464 }
465
466 $querystr = "
467 SELECT $wpdb->posts.*
468 FROM $wpdb->posts
469 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
470
471 WHERE 1 = 1 {$where_post_status}
472 AND $wpdb->posts.post_type = '{$course_post_type}'
473 AND $wpdb->posts.post_date < NOW()
474 ORDER BY $wpdb->posts.post_date DESC";
475
476 $pageposts = $wpdb->get_results($querystr, OBJECT);
477 return $pageposts;
478 }
479
480 /**
481 * @return mixed
482 *
483 * Get archive page course count
484 *
485 * @since v.1.0.0
486 */
487 public function get_archive_page_course_count(){
488 global $wp_query;
489 return $wp_query->post_count;
490 }
491
492 /**
493 * @return null|string
494 *
495 * Get course count
496 *
497 * @since v.1.0.0
498 */
499 public function get_course_count(){
500 global $wpdb;
501
502 $course_post_type = tutor()->course_post_type;
503 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = '{$course_post_type}'; ");
504 return $count;
505 }
506
507 /**
508 * @return null|string
509 *
510 * Get lesson count
511 *
512 * @since v.1.0.0
513 */
514 public function get_lesson_count(){
515 global $wpdb;
516
517 $lesson_post_type = tutor()->lesson_post_type;
518 $count = $wpdb->get_var("SELECT COUNT(ID) from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = '{$lesson_post_type}'; ");
519 return $count;
520 }
521
522 /**
523 * @param int $course_id
524 * @param int $limit
525 *
526 * @return \WP_Query
527 *
528 * Get lesson
529 *
530 * @since v.1.0.0
531 */
532 public function get_lesson($course_id = 0, $limit = 10){
533 $course_id = $this->get_post_id($course_id);
534
535 $lesson_post_type = tutor()->lesson_post_type;
536 $args = array(
537 'post_status' => 'publish',
538 'post_type' => $lesson_post_type,
539 'posts_per_page' => $limit,
540 'meta_query' => array(
541 array(
542 'key' => '_tutor_course_id_for_lesson',
543 'value' => $course_id,
544 'compare' => '=',
545 ),
546 ),
547 );
548 $query = new \WP_Query($args);
549
550 return $query;
551 }
552
553 /**
554 * @param int $course_id
555 *
556 * @return int
557 *
558 * Get total lesson count by a course
559 *
560 * @since v.1.0.0
561 */
562 public function get_lesson_count_by_course($course_id = 0){
563 $course_id = $this->get_post_id($course_id);
564 global $wpdb;
565
566 $count_lesson = $wpdb->get_var("select count(meta_id) from {$wpdb->postmeta} where meta_key = '_tutor_course_id_for_lesson' AND meta_value = {$course_id} ");
567
568 return (int) $count_lesson;
569 }
570
571 /**
572 * @param int $course_id
573 * @param int $user_id
574 *
575 * @return int
576 *
577 * Get completed lesson total number by a course
578 *
579 * @since v.1.0.0
580 */
581 public function get_completed_lesson_count_by_course($course_id = 0, $user_id = 0){
582 $course_id = $this->get_post_id($course_id);
583 $user_id = $this->get_user_id($user_id);
584 global $wpdb;
585
586 $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} ");
587
588 $count = 0;
589 if (is_array($completed_lesson_ids) && count($completed_lesson_ids)){
590 $completed_lesson_meta_ids = array();
591 foreach ($completed_lesson_ids as $lesson_id){
592 $completed_lesson_meta_ids[] = '_tutor_completed_lesson_id_'.$lesson_id;
593 }
594 $in_ids = implode("','", $completed_lesson_meta_ids);
595
596 $count = (int) $wpdb->get_var("select count(umeta_id) from {$wpdb->usermeta} WHERE user_id = '{$user_id}' AND meta_key in('{$in_ids}') ");
597 }
598
599 return $count;
600 }
601
602 /**
603 * @param int $course_id
604 * @param int $user_id
605 *
606 * @return float|int
607 *
608 * @since v.1.0.0
609 */
610 public function get_course_completed_percent($course_id = 0, $user_id = 0){
611 $course_id = $this->get_post_id($course_id);
612 $user_id = $this->get_user_id($user_id);
613
614 $total_lesson = $this->get_lesson_count_by_course($course_id);
615 $completed_lesson = $this->get_completed_lesson_count_by_course($course_id, $user_id);
616
617 if ($total_lesson > 0 && $completed_lesson > 0){
618 return number_format(($completed_lesson * 100) / $total_lesson);
619 }
620
621 return 0;
622 }
623
624 /**
625 * @param int $course_id
626 *
627 * @return \WP_Query
628 *
629 * Get all topics by given course ID
630 *
631 * @since v.1.0.0
632 */
633 public function get_topics($course_id = 0){
634 $course_id = $this->get_post_id($course_id);
635
636 $args = array(
637 'post_type' => 'topics',
638 'post_parent' => $course_id,
639 'orderby' => 'menu_order',
640 'order' => 'ASC',
641 'posts_per_page' => -1,
642 );
643
644 $query = new \WP_Query($args);
645 return $query;
646 }
647
648 /**
649 * @param $course_ID
650 *
651 * @return int
652 *
653 * Get next topic order id
654 *
655 * @since v.1.0.0
656 */
657 public function get_next_topic_order_id($course_ID){
658 global $wpdb;
659
660 $last_order = (int) $wpdb->get_var("SELECT MAX(menu_order) FROM {$wpdb->posts} WHERE post_parent = {$course_ID} AND post_type = 'topics';");
661 return $last_order + 1;
662 }
663
664 /**
665 * @param $topic_ID
666 *
667 * @return int
668 *
669 * Get next course content order id
670 *
671 * @since v.1.0.0
672 */
673 public function get_next_course_content_order_id($topic_ID){
674 global $wpdb;
675
676 $last_order = (int) $wpdb->get_var("SELECT MAX(menu_order) FROM {$wpdb->posts} WHERE post_parent = {$topic_ID};");
677 return $last_order + 1;
678 }
679
680 /**
681 * @param int $topics_id
682 * @param int $limit
683 *
684 * @return \WP_Query
685 *
686 * Get lesson by topic
687 *
688 * @since v.1.0.0
689 */
690 public function get_lessons_by_topic($topics_id = 0, $limit = 10){
691 $topics_id = $this->get_post_id($topics_id);
692
693 $lesson_post_type = tutor()->lesson_post_type;
694 $args = array(
695 'post_type' => $lesson_post_type,
696 'post_parent' => $topics_id,
697 'posts_per_page' => $limit,
698 'orderby' => 'menu_order',
699 'order' => 'ASC',
700 );
701
702 $query = new \WP_Query($args);
703
704 return $query;
705 }
706
707 /**
708 * @param int $topics_id
709 * @param int $limit
710 *
711 * @return \WP_Query
712 *
713 * Get course content by topic
714 *
715 * @since v.1.0.0
716 */
717 public function get_course_contents_by_topic($topics_id = 0, $limit = 10){
718 $topics_id = $this->get_post_id($topics_id);
719
720 $lesson_post_type = tutor()->lesson_post_type;
721 $args = array(
722 'post_type' => array($lesson_post_type, 'tutor_quiz'),
723 'post_parent' => $topics_id,
724 'posts_per_page' => $limit,
725 'orderby' => 'menu_order',
726 'order' => 'ASC',
727 );
728
729 $query = new \WP_Query($args);
730
731 return $query;
732 }
733
734 /**
735 * @param string $request_method
736 *
737 * Check actions nonce
738 *
739 * @since v.1.0.0
740 */
741 public function checking_nonce($request_method = 'post'){
742 if ($request_method === 'post'){
743 if (!isset($_POST[tutor()->nonce]) || !wp_verify_nonce($_POST[tutor()->nonce], tutor()->nonce_action)) {
744 exit();
745 }
746 }else{
747 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
748 exit();
749 }
750 }
751 }
752
753 /**
754 * @param int $course_id
755 *
756 * @return bool
757 *
758 * @since v.1.0.0
759 */
760 public function is_course_purchasable($course_id = 0){
761 return apply_filters('is_course_purchasable', false, $course_id);
762 }
763
764 /**
765 * @param int $course_id
766 *
767 * @return null|string
768 *
769 * get course price in digits format if any
770 *
771 * @since v.1.0.0
772 */
773
774 public function get_course_price($course_id = 0){
775 $course_id = $this->get_post_id($course_id);
776
777 $price = null;
778
779 if ($this->is_course_purchasable()) {
780 if ($this->has_wc()){
781 $product_id = tutor_utils()->get_course_product_id($course_id);
782 $product = wc_get_product( $product_id );
783
784 if ( $product ) {
785 $price = $product->get_price();
786 }
787 }else{
788 $price = apply_filters('get_tutor_course_price', null, $course_id);
789 }
790
791 }
792
793 return $price;
794 }
795
796 /**
797 * @param int $course_id
798 *
799 * @return object
800 *
801 * Get raw course price and sale price of a course
802 * It could help you to calculate something
803 * Such as Calculate discount by regular price and sale price
804 *
805 * @since v.1.3.1
806 */
807 public function get_raw_course_price($course_id = 0){
808 $course_id = $this->get_post_id($course_id);
809
810 $prices = array(
811 'regular_price' => 0,
812 'sale_price' => 0,
813 );
814
815 if ($this->is_course_purchasable($course_id)){
816 if ($this->get_option('enable_course_sell_by_woocommerce') && $this->has_wc()){
817 $prices['regular_price']= get_post_meta($course_id, '_regular_price', true);
818 $prices['sale_price']= get_post_meta($course_id, '_sale_price', true);
819 }elseif ($this->get_option('enable_tutor_edd') && $this->has_edd() ){
820 $prices['regular_price']= get_post_meta($course_id, 'edd_price', true);
821 $prices['sale_price']= get_post_meta($course_id, 'edd_price', true);
822 }
823 }
824
825 return (object) $prices;
826 }
827
828 /**
829 * @param int $course_id
830 *
831 * @return array|bool|null|object
832 *
833 * Check if current user has been enrolled or not
834 *
835 * @since v.1.0.0
836 */
837
838 public function is_enrolled($course_id = 0, $user_id = 0){
839 $course_id = $this->get_post_id($course_id);
840 $user_id = $this->get_user_id($user_id);
841
842 if (is_user_logged_in()) {
843 global $wpdb;
844
845 $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'; " );
846
847 if ( $getEnrolledInfo ) {
848 return $getEnrolledInfo;
849 }
850 }
851 return false;
852 }
853
854 /**
855 * @param int $course_id
856 * @param int $user_id
857 *
858 * @return array|bool|null|object|void
859 *
860 * Has any enrolled for a user in a course
861 *
862 * @since v.1.0.0
863 */
864 public function has_any_enrolled($course_id = 0, $user_id = 0){
865 $course_id = $this->get_post_id($course_id);
866 $user_id = $this->get_user_id($user_id);
867
868 if (is_user_logged_in()) {
869 global $wpdb;
870
871 $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}; " );
872
873 if ( $getEnrolledInfo ) {
874 return $getEnrolledInfo;
875 }
876 }
877 return false;
878 }
879
880 /**
881 * @param int $lesson_id
882 * @param int $user_id
883 *
884 * @return array|bool|null|object
885 *
886 * Get the course Enrolled confirmation by lesson ID
887 *
888 * @since v.1.0.0
889 */
890
891 public function is_course_enrolled_by_lesson($lesson_id = 0, $user_id = 0){
892 $lesson_id = $this->get_post_id($lesson_id);
893 $user_id = $this->get_user_id($user_id);
894
895 return $this->is_enrolled($this->get_course_id_by_lesson($lesson_id));
896 }
897
898 /**
899 * @param int $lesson_id
900 *
901 * @return bool|mixed
902 *
903 * Get the course ID by Lesson
904 *
905 * @since v.1.0.0
906 */
907 public function get_course_id_by_lesson($lesson_id = 0){
908 $lesson_id = $this->get_post_id($lesson_id);
909 return get_post_meta($lesson_id, '_tutor_course_id_for_lesson', true);
910 }
911
912 /**
913 * @param int $course_id
914 *
915 * @return bool|false|string
916 *
917 * Get first lesson of a course
918 *
919 * @since v.1.0.0
920 */
921 public function get_course_first_lesson($course_id = 0){
922 $course_id = $this->get_post_id($course_id);
923 global $wpdb;
924
925 $lesson_id = $wpdb->get_var("
926 SELECT post_id as lesson_id
927 FROM $wpdb->postmeta
928 INNER JOIN {$wpdb->posts} ON post_id = {$wpdb->posts}.ID
929 WHERE meta_key = '_tutor_course_id_for_lesson' AND meta_value = {$course_id}
930
931 ORDER BY menu_order ASC LIMIT 1
932 ");
933
934 /*
935 $lesson_id = $wpdb->get_var(" select main_posts.ID from {$wpdb->posts} main_posts
936 WHERE post_parent =
937 (SELECT sub_posts.ID FROM {$wpdb->posts} sub_posts
938 WHERE post_type = 'topics' AND
939 sub_posts.post_parent = {$course_id} ORDER BY sub_posts.menu_order ASC LIMIT 1 )
940 ORDER BY main_posts.menu_order ASC LIMIT 1 ;");
941 */
942
943 if ($lesson_id){
944 return get_permalink($lesson_id);
945 }
946 return false;
947 }
948
949 /**
950 *
951 * Get course sub pages in course dashboard
952 *
953 * @since v.1.0.0
954 */
955 public function course_sub_pages(){
956 $nav_items = array(
957 'overview' => __('Overview', 'tutor'),
958 );
959
960 $enable_q_and_a_on_course = tutor_utils()->get_option('enable_q_and_a_on_course');
961 if ($enable_q_and_a_on_course){
962 $nav_items['questions'] = __('Q&A', 'tutor');
963 }
964 $nav_items['announcements'] = __('Announcements', 'tutor');
965
966 return apply_filters('tutor_course/single/enrolled/nav_items', $nav_items);
967 }
968
969 /**
970 * @param int $post_id
971 *
972 * @return bool|array
973 *
974 * @since v.1.0.0
975 */
976 public function get_video($post_id = 0){
977 $post_id = $this->get_post_id($post_id);
978 $attachments = get_post_meta($post_id, '_video', true);
979 if ($attachments) {
980 $attachments = maybe_unserialize($attachments);
981 }
982 return $attachments;
983 }
984
985 /**
986 * @param int $post_id
987 * @param array $video_data
988 *
989 * @return bool
990 *
991 * Update the video Info
992 */
993 public function update_video($post_id = 0, $video_data = array()){
994 $post_id = $this->get_post_id($post_id);
995
996 if (is_array($video_data) && count($video_data)){
997 update_post_meta($post_id, '_video', $video_data);
998 }
999 }
1000
1001 /**
1002 * @param int $post_id
1003 *
1004 * @return bool|mixed
1005 *
1006 * @since v.1.0.0
1007 */
1008 public function get_attachments($post_id = 0){
1009 $post_id = $this->get_post_id($post_id);
1010 $attachments_arr = array();
1011 $attachments = maybe_unserialize(get_post_meta($post_id, '_tutor_attachments', true));
1012
1013 $font_icons = apply_filters('tutor_file_types_icon', array(
1014 'archive',
1015 'audio',
1016 'code',
1017 'default',
1018 'document',
1019 'interactive',
1020 'spreadsheet',
1021 'text',
1022 'video',
1023 'image',
1024 ));
1025
1026 if ( is_array($attachments) && count($attachments)) {
1027 foreach ( $attachments as $attachment ) {
1028 $url = wp_get_attachment_url( $attachment );
1029 $file_type = wp_check_filetype( $url );
1030 $ext = $file_type['ext'];
1031 $title = get_the_title($attachment);
1032
1033 $file_path = get_attached_file( $attachment );
1034 $size_bytes = file_exists($file_path) ? filesize( $file_path ) : 0;
1035 $size = size_format( $size_bytes, 2 );
1036 $type = wp_ext2type( $ext );
1037
1038 $icon = 'default';
1039 if ( $type && in_array( $type, $font_icons ) ) {
1040 $icon = $type;
1041 }
1042
1043 $data = array(
1044 'post_id' => $post_id,
1045 'id' => $attachment,
1046 'url' => $url,
1047 'name' => $title . '.' . $ext,
1048 'title' => $title,
1049 'ext' => $ext,
1050 'size' => $size,
1051 'size_bytes' => $size_bytes,
1052 'icon' => $icon,
1053 );
1054
1055 $attachments_arr[] = (object) apply_filters( 'tutor/posts/attachments', $data );
1056 }
1057 }
1058
1059 return $attachments_arr;
1060 }
1061
1062
1063 /**
1064 * @param $seconds
1065 *
1066 * @return string
1067 *
1068 * return seconds to formatted playtime
1069 *
1070 * @since v.1.0.0
1071 */
1072 public function playtime_string($seconds) {
1073 $sign = (($seconds < 0) ? '-' : '');
1074 $seconds = round(abs($seconds));
1075 $H = (int) floor( $seconds / 3600);
1076 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
1077 $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
1078 return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
1079 }
1080
1081 /**
1082 * @param $seconds
1083 *
1084 * @return array
1085 *
1086 * Get the playtime in array
1087 *
1088 * @since v.1.0.0
1089 */
1090 public function playtime_array($seconds){
1091 $run_time_format = array(
1092 'hours' => '00',
1093 'minutes' => '00',
1094 'seconds' => '00',
1095 );
1096
1097 if ($seconds <= 0 ){
1098 return $run_time_format;
1099 }
1100
1101 $playTimeString = $this->playtime_string($seconds);
1102 $timeInArray = explode(':', $playTimeString);
1103
1104 $run_time_size = count($timeInArray);
1105 if ($run_time_size === 3){
1106 $run_time_format['hours'] = $timeInArray[0];
1107 $run_time_format['minutes'] = $timeInArray[1];
1108 $run_time_format['seconds'] = $timeInArray[2];
1109 }elseif($run_time_size === 2){
1110 $run_time_format['minutes'] = $timeInArray[0];
1111 $run_time_format['seconds'] = $timeInArray[1];
1112 }
1113
1114 return $run_time_format;
1115 }
1116
1117 /**
1118 * @param $seconds
1119 *
1120 * @return string
1121 *
1122 * Convert seconds to human readable time
1123 *
1124 * @since v.1.0.0
1125 */
1126 public function seconds_to_time_context($seconds) {
1127 $sign = (($seconds < 0) ? '-' : '');
1128 $seconds = round(abs($seconds));
1129 $H = (int) floor( $seconds / 3600);
1130 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
1131 $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
1132
1133 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';
1134 }
1135
1136 /**
1137 * @param int $lesson_id
1138 *
1139 * @return bool|object
1140 *
1141 * @since v.1.0.0
1142 */
1143
1144 public function get_video_info($lesson_id = 0){
1145 $lesson_id = $this->get_post_id($lesson_id);
1146 $video = $this->get_video($lesson_id);
1147
1148 if ( ! $video){
1149 return false;
1150 }
1151
1152 $info = array(
1153 'playtime' => '00:00',
1154 );
1155
1156 $types = apply_filters('tutor_video_types', array("mp4"=>"video/mp4", "webm"=>"video/webm", "ogg"=>"video/ogg"));
1157
1158 $videoSource = $this->avalue_dot('source', $video);
1159 if ($videoSource === 'html5'){
1160 $sourceVideoID = $this->avalue_dot('source_video_id', $video);
1161 $video_info = get_post_meta($sourceVideoID, '_wp_attachment_metadata', true);
1162
1163 if ($video_info){
1164 $path = get_attached_file($sourceVideoID);
1165 $info['playtime'] = $video_info['length_formatted'];
1166 $info['path'] = $path;
1167 $info['url'] = wp_get_attachment_url($sourceVideoID);
1168 $info['ext'] = strtolower(pathinfo($path, PATHINFO_EXTENSION));
1169 $info['type'] = $types[$info['ext']];
1170 }
1171 }
1172
1173 if ($videoSource !== 'html5'){
1174 $video = maybe_unserialize(get_post_meta($lesson_id, '_video', true));
1175
1176 $runtimeHours = tutor_utils()->avalue_dot('runtime.hours', $video);
1177 $runtimeMinutes = tutor_utils()->avalue_dot('runtime.minutes', $video);
1178 $runtimeSeconds = tutor_utils()->avalue_dot('runtime.seconds', $video);
1179
1180 $runtimeHours = $runtimeHours ? $runtimeHours : '00';
1181 $runtimeMinutes = $runtimeMinutes ? $runtimeMinutes : '00';
1182 $runtimeSeconds = $runtimeSeconds ? $runtimeSeconds : '00';
1183
1184 $info['playtime'] = "$runtimeHours:$runtimeMinutes:$runtimeSeconds";
1185 }
1186
1187 $info = array_merge($info, $video);
1188
1189 return (object) $info;
1190 }
1191
1192 /**
1193 * @param int $post_id
1194 *
1195 * @return bool
1196 *
1197 * Ensure if attached video is self hosted or not
1198 *
1199 * @since v.1.0.0
1200 */
1201 public function is_html5_video($post_id = 0){
1202 $post_id = $this->get_post_id($post_id);
1203
1204 $video = $this->get_video($post_id);
1205 if ( ! $video){
1206 return false;
1207 }
1208 $videoSource = $this->avalue_dot('source', $video);
1209 return $videoSource === 'html5';
1210 }
1211
1212 /**
1213 *
1214 * return lesson type icon
1215 *
1216 * @param int $lesson_id
1217 * @param bool $html
1218 * @param bool $echo
1219 *
1220 * @return string
1221 *
1222 * @since v.1.0.0
1223 */
1224
1225 public function get_lesson_type_icon($lesson_id = 0, $html = false, $echo = false){
1226 $post_id = $this->get_post_id($lesson_id);
1227 $video = tutor_utils()->get_video_info($post_id);
1228
1229 $play_time = false;
1230 if ($video){
1231 $play_time = $video->playtime;
1232 }
1233
1234 $tutor_lesson_type_icon = $play_time ? 'youtube' : 'document';
1235
1236 if ($html){
1237 $tutor_lesson_type_icon = "<i class='tutor-icon-$tutor_lesson_type_icon'></i> ";
1238 }
1239
1240 if ($tutor_lesson_type_icon){
1241 echo $tutor_lesson_type_icon;
1242 }
1243
1244 return $tutor_lesson_type_icon;
1245 }
1246
1247 /**
1248 * @param int $lesson_id
1249 * @param int $user_id
1250 *
1251 * @return bool|mixed
1252 *
1253 * @since v.1.0.0
1254 */
1255
1256 public function is_completed_lesson($lesson_id = 0, $user_id = 0){
1257 $lesson_id = $this->get_post_id($lesson_id);
1258 $user_id = $this->get_user_id($user_id);
1259
1260 $is_completed = get_user_meta($user_id, '_tutor_completed_lesson_id_'.$lesson_id, true);
1261
1262 if ($is_completed){
1263 return $is_completed;
1264 }
1265
1266 return false;
1267 }
1268
1269 /**
1270 * @param int $course_id
1271 * @param int $user_id
1272 *
1273 * @return array|bool|null|object|void
1274 *
1275 * Determine if a course completed
1276 *
1277 * @since v.1.0.0
1278 */
1279
1280 public function is_completed_course($course_id = 0, $user_id = 0){
1281 if ( ! is_user_logged_in()){
1282 return false;
1283 }
1284
1285 global $wpdb;
1286 $course_id = $this->get_post_id($course_id);
1287 $user_id = $this->get_user_id($user_id);
1288
1289 $is_completed = $wpdb->get_row("SELECT comment_ID,
1290 comment_post_ID as course_id,
1291 comment_author as completed_user_id,
1292 comment_date as completion_date,
1293 comment_content as completed_hash
1294 from {$wpdb->comments}
1295 WHERE comment_agent = 'TutorLMSPlugin'
1296 AND comment_type = 'course_completed'
1297 AND comment_post_ID = {$course_id}
1298 AND user_id = {$user_id} ;");
1299
1300 if ($is_completed){
1301 return $is_completed;
1302 }
1303
1304 return false;
1305 }
1306
1307 /**
1308 * @param array $input
1309 *
1310 * @return array
1311 *
1312 * Sanitize input array
1313 *
1314 * @since v.1.0.0
1315 */
1316 public function sanitize_array($input = array()){
1317 $array = array();
1318
1319 if (is_array($input) && count($input)){
1320 foreach ($input as $key => $value){
1321 if (is_array($value)){
1322 $array[$key] = $this->sanitize_array($value);
1323 }else{
1324 $key = sanitize_text_field($key);
1325 $value = sanitize_text_field($value);
1326 $array[$key] = $value;
1327 }
1328 }
1329 }
1330
1331 return $array;
1332 }
1333
1334 /**
1335 * @param int $post_id
1336 *
1337 * @return array|bool
1338 *
1339 * Determine if has any video in single
1340 *
1341 * @since v.1.0.0
1342 */
1343
1344 public function has_video_in_single($post_id = 0){
1345 if (is_single()) {
1346 $post_id = $this->get_post_id($post_id);
1347
1348 $video = $this->get_video( $post_id );
1349 if ( $video ) {
1350 return $video;
1351 }
1352 }
1353 return false;
1354
1355 }
1356
1357 /**
1358 * @param int $start
1359 * @param int $limit
1360 * @param string $search_term
1361 * @param int $course_id
1362 *
1363 * @return array|null|object
1364 *
1365 *
1366 * Get the enrolled students for all courses.
1367 *
1368 * Pass course id in 4th parameter to get students course wise.
1369 *
1370 * @since v.1.0.0
1371 */
1372 public function get_students($start = 0, $limit = 10, $search_term = ''){
1373 $meta_key = '_is_tutor_student';
1374
1375 global $wpdb;
1376
1377 if ($search_term){
1378 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
1379 }
1380
1381 $students = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS {$wpdb->users}.* FROM {$wpdb->users}
1382 INNER JOIN {$wpdb->usermeta}
1383 ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id )
1384 WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) {$search_term}
1385 ORDER BY {$wpdb->usermeta}.meta_value DESC
1386 LIMIT {$start}, {$limit} ");
1387
1388 return $students;
1389 }
1390
1391 /**
1392 * @return int
1393 *
1394 * @since v.1.0.0
1395 *
1396 * get the total students
1397 * pass course id to get course wise total students
1398 *
1399 * @since v.1.0.0
1400 */
1401 public function get_total_students($search_term = ''){
1402 $meta_key = '_is_tutor_student';
1403
1404 global $wpdb;
1405
1406 if ($search_term){
1407 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
1408 }
1409
1410 $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 ");
1411
1412 return (int) $count;
1413 }
1414
1415 /**
1416 * @param int $user_id
1417 *
1418 * @return array
1419 *
1420 * Get complete courses ids by user
1421 *
1422 * @since v.1.0.0
1423 */
1424 public function get_completed_courses_ids_by_user($user_id = 0){
1425 global $wpdb;
1426
1427 $user_id = $this->get_user_id($user_id);
1428
1429 $course_ids = (array) $wpdb->get_col("SELECT comment_post_ID as course_id
1430 from {$wpdb->comments}
1431 WHERE comment_agent = 'TutorLMSPlugin'
1432 AND comment_type = 'course_completed'
1433 AND user_id = {$user_id} ;");
1434
1435 return $course_ids;
1436 }
1437
1438 /**
1439 * @param int $user_id
1440 *
1441 * @return bool|\WP_Query
1442 *
1443 * Return courses by user_id
1444 *
1445 * @since v.1.0.0
1446 */
1447 public function get_courses_by_user($user_id = 0){
1448 $user_id = $this->get_user_id($user_id);
1449 $course_ids = $this->get_completed_courses_ids_by_user($user_id);
1450
1451 if (count($course_ids)){
1452 $course_post_type = tutor()->course_post_type;
1453 $course_args = array(
1454 'post_type' => $course_post_type,
1455 'post_status' => 'publish',
1456 'post__in' => $course_ids,
1457 );
1458
1459 return new \WP_Query($course_args);
1460 }
1461
1462 return false;
1463 }
1464
1465 /**
1466 * @param int $user_id
1467 *
1468 * @return bool|\WP_Query
1469 *
1470 * Get the active course by user
1471 *
1472 * @since v.1.0.0
1473 */
1474
1475 public function get_active_courses_by_user($user_id = 0){
1476 $user_id = $this->get_user_id($user_id);
1477
1478 $course_ids = $this->get_completed_courses_ids_by_user($user_id);
1479 $enrolled_course_ids = $this->get_enrolled_courses_ids_by_user($user_id);
1480 $active_courses = array_diff($enrolled_course_ids, $course_ids);
1481
1482 if (count($active_courses)){
1483 $course_post_type = tutor()->course_post_type;
1484 $course_args = array(
1485 'post_type' => $course_post_type,
1486 'post_status' => 'publish',
1487 'post__in' => $active_courses,
1488 );
1489
1490 return new \WP_Query($course_args);
1491 }
1492
1493 return false;
1494 }
1495
1496 /**
1497 * @param int $user_id
1498 *
1499 * @return array
1500 *
1501 * Get enrolled course ids by a user
1502 *
1503 * @since v.1.0.0
1504 */
1505
1506 public function get_enrolled_courses_ids_by_user($user_id = 0){
1507 global $wpdb;
1508 $user_id = $this->get_user_id($user_id);
1509 $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'; ");
1510
1511 return $course_ids;
1512 }
1513
1514 /**
1515 * @param int $course_id
1516 *
1517 * @return int
1518 *
1519 * Get the total enrolled users at course
1520 */
1521 public function count_enrolled_users_by_course($course_id = 0){
1522 global $wpdb;
1523 $course_id = $this->get_post_id($course_id);
1524
1525 $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'; ");
1526
1527 return (int) $course_ids;
1528 }
1529
1530 /**
1531 * @param int $user_id
1532 *
1533 * @return bool|\WP_Query
1534 *
1535 * Get the enrolled courses by user
1536 */
1537 public function get_enrolled_courses_by_user($user_id = 0){
1538 global $wpdb;
1539
1540 $user_id = $this->get_user_id($user_id);
1541 $course_ids = $this->get_enrolled_courses_ids_by_user($user_id);
1542
1543 if (count($course_ids)){
1544 $course_post_type = tutor()->course_post_type;
1545 $course_args = array(
1546 'post_type' => $course_post_type,
1547 'post_status' => 'publish',
1548 'post__in' => $course_ids,
1549 );
1550 return new \WP_Query($course_args);
1551 }
1552 return false;
1553 }
1554
1555
1556 /**
1557 * @param int $post_id
1558 *
1559 * @return string
1560 *
1561 * Get the video streaming URL by post/lesson/course ID
1562 */
1563 public function get_video_stream_url($post_id = 0){
1564 $post_id = $this->get_post_id($post_id);
1565 $post = get_post($post_id);
1566
1567 if ($post->post_type === tutor()->lesson_post_type ){
1568 $video_url = trailingslashit(home_url()).'video-url/'.$post->post_name;
1569 }else{
1570 $video_info = tutor_utils()->get_video_info($post_id);
1571 $video_url = $video_info->url;
1572 }
1573
1574 return $video_url;
1575 }
1576
1577 /**
1578 * @param int $lesson_id
1579 * @param int $user_id
1580 *
1581 * @return array|bool|mixed
1582 *
1583 * Get student lesson reading current info
1584 *
1585 * @since v.1.0.0
1586 */
1587 public function get_lesson_reading_info_full($lesson_id = 0, $user_id = 0){
1588 $lesson_id = $this->get_post_id($lesson_id);
1589 $user_id = $this->get_user_id($user_id);
1590
1591 $lesson_info = (array) maybe_unserialize(get_user_meta($user_id, '_lesson_reading_info', true));
1592 return $this->avalue_dot($lesson_id, $lesson_info);
1593 }
1594
1595 /**
1596 * @param int $post_id
1597 *
1598 * @return bool|false|int
1599 *
1600 * Get current post id or given post id
1601 *
1602 * @since v.1.0.0
1603 */
1604 public function get_post_id($post_id = 0){
1605 if ( ! $post_id){
1606 $post_id = get_the_ID();
1607 if ( ! $post_id){
1608 return false;
1609 }
1610 }
1611
1612 return $post_id;
1613 }
1614
1615 /**
1616 * @param int $user_id
1617 *
1618 * @return bool|int
1619 *
1620 * Get current user or given user ID
1621 *
1622 * @since v.1.0.0
1623 */
1624 public function get_user_id($user_id = 0){
1625 if ( ! $user_id){
1626 $user_id = get_current_user_id();
1627 if ( ! $user_id){
1628 return false;
1629 }
1630 }
1631
1632 return $user_id;
1633 }
1634
1635 /**
1636 * @param int $lesson_id
1637 * @param int $user_id
1638 * @param string $key
1639 *
1640 * @return array|bool|mixed
1641 *
1642 * Get lesson reading info by key
1643 *
1644 * @since v.1.0.0
1645 */
1646
1647 public function get_lesson_reading_info($lesson_id = 0, $user_id = 0, $key = ''){
1648 $lesson_id = $this->get_post_id($lesson_id);
1649 $user_id = $this->get_user_id($user_id);
1650
1651 $lesson_info = $this->get_lesson_reading_info_full($lesson_id, $user_id);
1652
1653 return $this->avalue_dot($key, $lesson_info);
1654 }
1655
1656 /**
1657 * @param int $lesson_id
1658 * @param int $user_id
1659 * @param array $data
1660 *
1661 * @return bool
1662 *
1663 * Update student lesson reading info
1664 *
1665 * @since v.1.0.0
1666 */
1667 public function update_lesson_reading_info($lesson_id = 0, $user_id = 0, $key = '', $value = ''){
1668 $lesson_id = $this->get_post_id($lesson_id);
1669 $user_id = $this->get_user_id($user_id);
1670
1671 if ($key && $value){
1672 $lesson_info = (array) maybe_unserialize(get_user_meta($user_id, '_lesson_reading_info', true));
1673 $lesson_info[$lesson_id][$key] = $value;
1674 update_user_meta($user_id, '_lesson_reading_info', $lesson_info);
1675 }
1676 }
1677
1678 /**
1679 * @param string $url
1680 *
1681 * @return bool
1682 *
1683 * Get the Youtube Video ID from URL
1684 *
1685 * @since v.1.0.0
1686 */
1687 public function get_youtube_video_id($url = ''){
1688 if (!$url){
1689 return false;
1690 }
1691 preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match);
1692
1693 if (isset($match[1])) {
1694 $youtube_id = $match[1];
1695 return $youtube_id;
1696 }
1697
1698 return false;
1699 }
1700
1701 /**
1702 * @param string $url
1703 *
1704 * @return bool
1705 *
1706 * Get the vimeo video id from URL
1707 *
1708 * @since v.1.0.0
1709 */
1710 public function get_vimeo_video_id($url = ''){
1711 if (preg_match('%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)(?:[?]?.*)$%im', $url, $match)) {
1712 if (isset($match[3])){
1713 return $match[3];
1714 }
1715 }
1716 return false;
1717 }
1718
1719 /**
1720 * @param int $post_id
1721 *
1722 * Mark lesson complete
1723 *
1724 * @since v.1.0.0
1725 */
1726 public function mark_lesson_complete($post_id = 0, $user_id = 0){
1727 $post_id = $this->get_post_id($post_id);
1728 $user_id = $this->get_user_id($user_id);
1729
1730 do_action('tutor_mark_lesson_complete_before', $post_id, $user_id);
1731 update_user_meta($user_id, '_tutor_completed_lesson_id_'.$post_id, time());
1732 do_action('tutor_mark_lesson_complete_after', $post_id, $user_id);
1733
1734 }
1735
1736 /**
1737 * Saving enroll information to posts table
1738 * post_author = enrolled_student_id (wp_users id)
1739 * post_parent = enrolled course id
1740 *
1741 * @type: call when need
1742 * @return bool;
1743 *
1744 * @since v.1.0.0
1745 */
1746 public function do_enroll($course_id = 0, $order_id = 0){
1747 if ( ! $course_id){
1748 return false;
1749 }
1750
1751 do_action('tutor_before_enroll', $course_id);
1752 $user_id = get_current_user_id();
1753 $title = __('Course Enrolled', 'tutor')." &ndash; ".date_i18n(get_option('date_format')) .' @ '.date_i18n(get_option('time_format') ) ;
1754
1755 $enrolment_status = 'completed';
1756
1757 if ($this->is_course_purchasable($course_id)) {
1758 /**
1759 * We need to verify this enrollment, we will change the status later after payment confirmation
1760 */
1761 $enrolment_status = 'pending';
1762 }
1763
1764 $enroll_data = apply_filters('tutor_enroll_data',
1765 array(
1766 'post_type' => 'tutor_enrolled',
1767 'post_title' => $title,
1768 'post_status' => $enrolment_status,
1769 'post_author' => $user_id,
1770 'post_parent' => $course_id,
1771 )
1772 );
1773
1774 // Insert the post into the database
1775 $isEnrolled = wp_insert_post( $enroll_data );
1776 if ($isEnrolled) {
1777 do_action('tutor_after_enroll', $course_id, $isEnrolled);
1778
1779 //Mark Current User as Students with user meta data
1780 update_user_meta( $user_id, '_is_tutor_student', time() );
1781
1782 if ($order_id) {
1783 //Mark order for course and user
1784 $product_id = $this->get_course_product_id($course_id);
1785 update_post_meta( $isEnrolled, '_tutor_enrolled_by_order_id', $order_id );
1786 update_post_meta( $isEnrolled, '_tutor_enrolled_by_product_id', $product_id );
1787 update_post_meta( $order_id, '_is_tutor_order_for_course', time() );
1788 update_post_meta( $order_id, '_tutor_order_for_course_id_'.$course_id, $isEnrolled );
1789 }
1790 return true;
1791 }
1792
1793 return false;
1794 }
1795
1796 /**
1797 * @param $order_id
1798 *
1799 * Complete course enrollment and do some task
1800 *
1801 * @since v.1.0.0
1802 */
1803 public function complete_course_enroll($order_id){
1804 if ( ! tutor_utils()->is_tutor_order($order_id)){
1805 return;
1806 }
1807
1808 global $wpdb;
1809
1810 $enrolled_ids_with_course = $this->get_course_enrolled_ids_by_order_id($order_id);
1811 if ($enrolled_ids_with_course){
1812 $enrolled_ids = wp_list_pluck($enrolled_ids_with_course, 'enrolled_id');
1813
1814 if (is_array($enrolled_ids) && count($enrolled_ids)){
1815 foreach ($enrolled_ids as $enrolled_id){
1816 $wpdb->update( $wpdb->posts, array( 'post_status' => 'completed' ), array( 'ID' => $enrolled_id ) );
1817 }
1818 }
1819 }
1820 }
1821
1822 /**
1823 * @param $order_id
1824 *
1825 * @return array|bool
1826 *
1827 * @since v.1.0.0
1828 */
1829 public function get_course_enrolled_ids_by_order_id($order_id){
1830 global $wpdb;
1831 //Getting all of courses ids within this order
1832
1833 $courses_ids = $wpdb->get_results("SELECT * FROM {$wpdb->postmeta} WHERE post_id = {$order_id} AND meta_key LIKE '_tutor_order_for_course_id_%' ");
1834
1835 if (is_array($courses_ids) && count($courses_ids)){
1836 $course_enrolled_by_order = array();
1837 foreach ($courses_ids as $courses_id){
1838 $course_id = str_replace('_tutor_order_for_course_id_', '',$courses_id->meta_key);
1839 //array(order_id => array('course_id' => $course_id, 'enrolled_id' => enrolled_id))
1840 $course_enrolled_by_order[] = array('course_id' => $course_id, 'enrolled_id' => $courses_id->meta_value, 'order_id' => $courses_id->post_id );
1841 }
1842 return $course_enrolled_by_order;
1843 }
1844 return false;
1845 }
1846
1847 /**
1848 * Get wc product in efficient query
1849 *
1850 * @since v.1.0.0
1851 */
1852
1853 /**
1854 * @return array|null|object
1855 *
1856 * WooCommerce specific utils
1857 */
1858 public function get_wc_products_db(){
1859 global $wpdb;
1860 $query = $wpdb->get_results("SELECT ID, post_title from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'product' ");
1861
1862 return $query;
1863 }
1864
1865 /**
1866 * @return array|null|object
1867 *
1868 * Get EDD Products
1869 */
1870 public function get_edd_products(){
1871 global $wpdb;
1872 $query = $wpdb->get_results("SELECT ID, post_title from {$wpdb->posts} WHERE post_status = 'publish' AND post_type = 'download' ");
1873
1874 return $query;
1875 }
1876
1877 /**
1878 * @param int $course_id
1879 *
1880 * @return int
1881 *
1882 * Get course productID
1883 *
1884 * @since v.1.0.0
1885 */
1886 public function get_course_product_id($course_id = 0){
1887 $course_id = $this->get_post_id($course_id);
1888 return (int) get_post_meta($course_id, '_tutor_course_product_id', true);
1889 }
1890
1891 /**
1892 * @param int $product_id
1893 *
1894 * @return array|null|object|void
1895 *
1896 * Get Product belongs with course
1897 *
1898 * @since v.1.0.0
1899 */
1900
1901 public function product_belongs_with_course($product_id = 0){
1902 global $wpdb;
1903
1904 $query = $wpdb->get_row("select * from {$wpdb->postmeta} WHERE meta_key='_tutor_course_product_id' AND meta_value = {$product_id} limit 1 ");
1905 return $query;
1906 }
1907
1908 /**
1909 * #End WooCommerce specific utils
1910 *
1911 * @since v.1.0.0
1912 */
1913
1914 public function get_enrolled_statuses(){
1915 return apply_filters(
1916 'tutor_get_enrolled_statuses',
1917 array (
1918 'pending',
1919 'processing',
1920 'on-hold',
1921 'completed',
1922 'cancelled',
1923 'refunded',
1924 'failed',
1925 )
1926 );
1927 }
1928
1929 /**
1930 * @param $order_id
1931 *
1932 * @return mixed
1933 *
1934 * determine is this a tutor order
1935 *
1936 * @since v.1.0.0
1937 */
1938 public function is_tutor_order($order_id){
1939 return get_post_meta($order_id, '_is_tutor_order_for_course', true);
1940 }
1941
1942 /**
1943 * @return mixed
1944 *
1945 * @deprecated
1946 */
1947 public function tutor_student_dashboard_pages(){
1948 _deprecated_function(__METHOD__, '1.1.2', 'tutor_dashboard_pages');
1949 return $this->tutor_dashboard_pages();
1950 }
1951
1952 /**
1953 * @return mixed
1954 *
1955 * Tutor Dashboard Pages
1956 *
1957 * @since v.1.0.0
1958 */
1959
1960 public function tutor_dashboard_pages(){
1961 $nav_items = array(
1962 'index' => __('Dashboard', 'tutor'),
1963 'my-profile' => __('My Profile', 'tutor'),
1964 'enrolled-courses' => __('Enrolled Courses', 'tutor'),
1965 'wishlist' => __('Wishlist', 'tutor'),
1966 'reviews' => __('Reviews', 'tutor'),
1967
1968 //'purchase-history' => __('Purchase History', 'tutor'),
1969 //'messages' => __('Messages', 'tutor'),
1970 );
1971
1972 if (current_user_can(tutor()->instructor_role)) {
1973 $instructor_items = array(
1974 'my-courses' => __('My Courses', 'tutor'),
1975 'quiz-attempts' => __('Quiz Attempts', 'tutor'),
1976 'earning' => __('Earning', 'tutor'),
1977 'withdraw' => __('Withdraw', 'tutor'),
1978 );
1979
1980 $nav_items = array_merge($nav_items, $instructor_items);
1981 }
1982
1983 $nav_items['purchase_history'] = __('Purchase History', 'tutor');
1984 $nav_items['settings'] = __('Settings', 'tutor');
1985 $nav_items['logout'] = __('Logout', 'tutor');
1986
1987 return apply_filters('tutor_dashboard/nav_items', $nav_items);
1988 }
1989
1990 /**
1991 * @param string $page_key
1992 * @param int $page_id
1993 *
1994 * @return string
1995 *
1996 * Get tutor dashboard page single URL
1997 *
1998 * @since v.1.0.0
1999 */
2000 public function get_tutor_dashboard_page_permalink($page_key = '', $page_id = 0){
2001 if ($page_key === 'index'){
2002 $page_key = '';
2003 }
2004 $page_id = $this->get_post_id($page_id);
2005 return trailingslashit(get_permalink($page_id)).$page_key;
2006 }
2007
2008 /**
2009 * @param string $input
2010 *
2011 * @return array|bool|mixed|string
2012 *
2013 * Get old input
2014 *
2015 * @since v.1.0.0
2016 */
2017 public function input_old($input = ''){
2018 $value = $this->avalue_dot($input, $_REQUEST);
2019 if ($value){
2020 return $value;
2021 }
2022 return '';
2023 }
2024
2025 /**
2026 * @param int $user_id
2027 *
2028 * @return mixed
2029 *
2030 * Determine if is instructor or not
2031 *
2032 * @since v.1.0.0
2033 */
2034 public function is_instructor($user_id = 0){
2035 $user_id = $this->get_user_id($user_id);
2036 return get_user_meta($user_id, '_is_tutor_instructor', true);
2037 }
2038
2039 /**
2040 * @param int $user_id
2041 * @param bool $status_name
2042 *
2043 * @return bool|mixed
2044 *
2045 * Instructor status
2046 *
2047 * @since v.1.0.0
2048 */
2049 public function instructor_status($user_id = 0, $status_name = true){
2050 $user_id = $this->get_user_id($user_id);
2051
2052 $instructor_status = apply_filters('tutor_instructor_statuses', array(
2053 'pending' => __('Pending', 'tutor'),
2054 'approved' => __('Approved', 'tutor'),
2055 'blocked' => __('Blocked', 'tutor'),
2056 ));
2057
2058 $status = get_user_meta($user_id, '_tutor_instructor_status', true);
2059
2060 if (isset($instructor_status[$status])){
2061 if ( ! $status_name){
2062 return $status;
2063 }
2064 return $instructor_status[$status];
2065 }
2066 return false;
2067 }
2068
2069 /**
2070 * @param string $search_term
2071 *
2072 * @return int
2073 *
2074 * Get total number of instructors
2075 *
2076 * @since v.1.0.0
2077 */
2078
2079 public function get_total_instructors($search_term = ''){
2080 $meta_key = '_is_tutor_instructor';
2081
2082 global $wpdb;
2083
2084 if ($search_term){
2085 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
2086 }
2087
2088 $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 ");
2089
2090 return (int) $count;
2091 }
2092
2093 /**
2094 * @param int $start
2095 * @param int $limit
2096 * @param string $search_term
2097 *
2098 * @return array|null|object
2099 *
2100 * Get all instructors
2101 *
2102 * @since v.1.0.0
2103 */
2104 public function get_instructors($start = 0, $limit = 10, $search_term = ''){
2105 $meta_key = '_is_tutor_instructor';
2106 global $wpdb;
2107
2108 if ($search_term){
2109 $search_term = " AND ( {$wpdb->users}.display_name LIKE '%{$search_term}%' OR {$wpdb->users}.user_email LIKE '%{$search_term}%' ) ";
2110 }
2111
2112 $instructors = $wpdb->get_results("SELECT SQL_CALC_FOUND_ROWS {$wpdb->users}.* FROM {$wpdb->users}
2113 INNER JOIN {$wpdb->usermeta}
2114 ON ( {$wpdb->users}.ID = {$wpdb->usermeta}.user_id )
2115 WHERE 1=1 AND ( {$wpdb->usermeta}.meta_key = '{$meta_key}' ) {$search_term}
2116 ORDER BY {$wpdb->usermeta}.meta_value DESC
2117 LIMIT {$start}, {$limit} ");
2118
2119 return $instructors;
2120 }
2121
2122 /**
2123 * @param int $course_id
2124 *
2125 * @return array|bool|null|object
2126 *
2127 * Get all instructors by course
2128 *
2129 * @since v.1.0.0
2130 */
2131 public function get_instructors_by_course($course_id = 0){
2132 global $wpdb;
2133 $course_id = $this->get_post_id($course_id);
2134
2135 $instructors = $wpdb->get_results("select ID, display_name,
2136 get_course.meta_value as taught_course_id,
2137 tutor_job_title.meta_value as tutor_profile_job_title,
2138 tutor_bio.meta_value as tutor_profile_bio,
2139 tutor_photo.meta_value as tutor_profile_photo
2140 from {$wpdb->users}
2141 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}
2142 LEFT JOIN {$wpdb->usermeta} tutor_job_title ON ID = tutor_job_title.user_id AND tutor_job_title.meta_key = '_tutor_profile_job_title'
2143 LEFT JOIN {$wpdb->usermeta} tutor_bio ON ID = tutor_bio.user_id AND tutor_bio.meta_key = '_tutor_profile_bio'
2144 LEFT JOIN {$wpdb->usermeta} tutor_photo ON ID = tutor_photo.user_id AND tutor_photo.meta_key = '_tutor_profile_photo'
2145 ");
2146
2147 if (is_array($instructors) && count($instructors)){
2148 return $instructors;
2149 }
2150
2151 return false;
2152 }
2153
2154 /**
2155 * @param $instructor_id
2156 *
2157 * Get total Students by instructor
2158 * 1 enrollment = 1 student, so total enrolled for a equivalent total students (Tricks)
2159 *
2160 * @return int
2161 *
2162 * @since v.1.0.0
2163 */
2164
2165 public function get_total_students_by_instructor($instructor_id){
2166 global $wpdb;
2167
2168 $course_post_type = tutor()->course_post_type;
2169 $count = $wpdb->get_var("SELECT COUNT(courses.ID) from {$wpdb->posts} courses
2170
2171 INNER JOIN {$wpdb->posts} enrolled ON courses.ID = enrolled.post_parent AND enrolled.post_type = 'tutor_enrolled'
2172 WHERE courses.post_status = 'publish'
2173 AND courses.post_type = '{$course_post_type}'
2174 AND courses.post_author = {$instructor_id} ; ");
2175 return (int) $count;
2176 }
2177
2178 /**
2179 * @param float $input
2180 *
2181 * @return float|string
2182 *
2183 * Get rating format from value
2184 *
2185 * @since v.1.0.0
2186 */
2187 public function get_rating_value($input = 0.00){
2188
2189 if ( $input > 0){
2190 $input = number_format($input, 2);
2191 $int_value = (int) $input;
2192 $fraction = $input - $int_value;
2193
2194 if ($fraction == 0){
2195 $fraction = 0.00;
2196 }elseif($fraction > 0.5){
2197 $fraction = 1;
2198 }else{
2199 $fraction = 0.5;
2200 }
2201
2202 return number_format( ($int_value + $fraction), 2);
2203 }
2204 return 0.00;
2205 }
2206
2207 /**
2208 * @param float $current_rating
2209 * @param bool $echo
2210 *
2211 * @return string
2212 *
2213 * Generate star rating based in given rating value
2214 *
2215 * @since v.1.0.0
2216 */
2217 public function star_rating_generator($current_rating = 0.00, $echo = true){
2218 $output = '<div class="tutor-star-rating-group">';
2219
2220 for ($i = 1; $i <=5 ; $i++){
2221 $intRating = (int) $current_rating;
2222
2223 if ($intRating >= $i){
2224 $output.= '<i class="tutor-icon-star-full" data-rating-value="'.$i.'"></i>';
2225 } else{
2226 if ( ($current_rating - $i) == -0.5){
2227 $output.= '<i class="tutor-icon-star-half" data-rating-value="'.$i.'"></i>';
2228 }else{
2229 $output.= '<i class="tutor-icon-star-line" data-rating-value="'.$i.'"></i>';
2230 }
2231 }
2232 }
2233
2234 $output .= "<div class='tutor-rating-gen-input'><input type='hidden' name='tutor_rating_gen_input' value='{$current_rating}' /> </div>";
2235
2236 $output .= "</div>";
2237
2238 if ($echo){
2239 echo $output;
2240 }
2241 return $output;
2242 }
2243
2244 /**
2245 * @param null $name
2246 *
2247 * @return string
2248 *
2249 * Generate text to avatar
2250 *
2251 * @since v.1.0.0
2252 */
2253 public function get_tutor_avatar($user_id = null, $size = 'thumbnail'){
2254 global $wpdb;
2255
2256 if ( ! $user_id){
2257 return '';
2258 }
2259
2260 $user = $this->get_tutor_user($user_id);
2261 if ($user->tutor_profile_photo){
2262 return '<img src="'.wp_get_attachment_image_url($user->tutor_profile_photo, $size).'" class="tutor-image-avatar" alt="" /> ';
2263 }
2264
2265 $name = $user->display_name;
2266 $arr = explode(' ', trim($name));
2267
2268 if (count($arr) > 1){
2269 $first_char = substr($arr[0], 0, 1) ;
2270 $second_char = substr($arr[1], 0, 1) ;
2271 }else{
2272 $first_char = substr($arr[0], 0, 1) ;
2273 $second_char = substr($arr[0], 1, 1) ;
2274 }
2275
2276 $initial_avatar = strtoupper($first_char.$second_char);
2277
2278 $bg_color = '#'.substr(md5($initial_avatar), 0, 6);
2279 $initial_avatar = "<span class='tutor-text-avatar' style='background-color: {$bg_color}; color: #fff8e5'>{$initial_avatar}</span>";
2280
2281 return $initial_avatar;
2282 }
2283
2284 /**
2285 * @param $user_id
2286 *
2287 * @return array|null|object|void
2288 *
2289 * Get tutor user
2290 *
2291 * @since v.1.0.0
2292 */
2293
2294 public function get_tutor_user($user_id){
2295 global $wpdb;
2296
2297 $user = $wpdb->get_row("select ID, display_name,
2298 tutor_job_title.meta_value as tutor_profile_job_title,
2299 tutor_bio.meta_value as tutor_profile_bio,
2300 tutor_photo.meta_value as tutor_profile_photo
2301
2302 from {$wpdb->users}
2303 LEFT JOIN {$wpdb->usermeta} tutor_job_title ON ID = tutor_job_title.user_id AND tutor_job_title.meta_key = '_tutor_profile_job_title'
2304 LEFT JOIN {$wpdb->usermeta} tutor_bio ON ID = tutor_bio.user_id AND tutor_bio.meta_key = '_tutor_profile_bio'
2305 LEFT JOIN {$wpdb->usermeta} tutor_photo ON ID = tutor_photo.user_id AND tutor_photo.meta_key = '_tutor_profile_photo'
2306
2307 WHERE ID = {$user_id} ");
2308 return $user;
2309 }
2310
2311 /**
2312 * @param int $course_id
2313 * @param int $offset
2314 * @param int $limit
2315 *
2316 * @return array|null|object
2317 *
2318 * get course reviews
2319 *
2320 * @since v.1.0.0
2321 */
2322 public function get_course_reviews($course_id = 0, $offset = 0, $limit = 150){
2323 $course_id = $this->get_post_id($course_id);
2324 global $wpdb;
2325
2326 $reviews = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2327 {$wpdb->comments}.comment_post_ID,
2328 {$wpdb->comments}.comment_author,
2329 {$wpdb->comments}.comment_author_email,
2330 {$wpdb->comments}.comment_date,
2331 {$wpdb->comments}.comment_content,
2332 {$wpdb->comments}.user_id,
2333 {$wpdb->commentmeta}.meta_value as rating,
2334 {$wpdb->users}.display_name
2335
2336 from {$wpdb->comments}
2337 INNER JOIN {$wpdb->commentmeta}
2338 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2339 INNER JOIN {$wpdb->users}
2340 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2341 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2342 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2343 );
2344
2345 return $reviews;
2346 }
2347
2348 /**
2349 * @param int $course_id
2350 *
2351 * @return object
2352 *
2353 * Get course rating
2354 *
2355 * @since v.1.0.0
2356 */
2357 public function get_course_rating($course_id = 0){
2358 $course_id = $this->get_post_id($course_id);
2359
2360 $ratings = array(
2361 'rating_count' => 0,
2362 'rating_sum' => 0,
2363 'rating_avg' => 0.00,
2364 'count_by_value' => array(5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0)
2365 );
2366
2367 global $wpdb;
2368
2369 $rating = $wpdb->get_row("select COUNT(meta_value) as rating_count, SUM(meta_value) as rating_sum
2370 from {$wpdb->comments}
2371 INNER JOIN {$wpdb->commentmeta}
2372 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2373 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2374 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2375 AND meta_key = 'tutor_rating' ;"
2376 );
2377
2378 if ($rating->rating_count){
2379 $avg_rating = number_format(($rating->rating_sum / $rating->rating_count), 2);
2380
2381 /**
2382 * Get individual Rating by integer
2383 */
2384 $five_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2385 from {$wpdb->comments}
2386 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2387 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2388 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2389 AND meta_key = 'tutor_rating' AND meta_value = 5 ;"
2390 );
2391 $four_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2392 from {$wpdb->comments}
2393 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2394 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2395 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2396 AND meta_key = 'tutor_rating' AND meta_value = 4 ;"
2397 );
2398 $three_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2399 from {$wpdb->comments}
2400 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2401 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2402 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2403 AND meta_key = 'tutor_rating' AND meta_value = 3 ;"
2404 );
2405 $two_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2406 from {$wpdb->comments}
2407 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2408 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2409 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2410 AND meta_key = 'tutor_rating' AND meta_value = 2 ;"
2411 );
2412 $one_stars_count = $wpdb->get_var("select COUNT(meta_value) as rating_count
2413 from {$wpdb->comments}
2414 INNER JOIN {$wpdb->commentmeta} ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2415 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2416 AND {$wpdb->comments}.comment_type = 'tutor_course_rating'
2417 AND meta_key = 'tutor_rating' AND meta_value = 1 ;"
2418 );
2419
2420 $ratings = array(
2421 'rating_count' => $rating->rating_count,
2422 'rating_sum' => $rating->rating_sum,
2423 'rating_avg' => $avg_rating,
2424 'count_by_value' => array(5 => $five_stars_count, 4 => $four_stars_count, 3 => $three_stars_count, 2 => $two_stars_count, 1 => $one_stars_count)
2425 );
2426
2427 }
2428
2429 return (object) $ratings;
2430 }
2431
2432 /**
2433 * @param int $user_id
2434 * @param int $offset
2435 * @param int $limit
2436 *
2437 * @return array|null|object
2438 *
2439 * Get reviews by a user
2440 *
2441 * @since v.1.0.0
2442 */
2443 public function get_reviews_by_user($user_id = 0, $offset = 0, $limit = 150){
2444 $user_id = $this->get_user_id($user_id);
2445 global $wpdb;
2446
2447 $reviews = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2448 {$wpdb->comments}.comment_post_ID,
2449 {$wpdb->comments}.comment_author,
2450 {$wpdb->comments}.comment_author_email,
2451 {$wpdb->comments}.comment_date,
2452 {$wpdb->comments}.comment_content,
2453 {$wpdb->comments}.user_id,
2454 {$wpdb->commentmeta}.meta_value as rating,
2455 {$wpdb->users}.display_name
2456
2457 from {$wpdb->comments}
2458 INNER JOIN {$wpdb->commentmeta}
2459 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2460 INNER JOIN {$wpdb->users}
2461 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2462 WHERE {$wpdb->comments}.user_id = {$user_id}
2463 AND comment_type = 'tutor_course_rating' AND meta_key = 'tutor_rating' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2464 );
2465
2466 return $reviews;
2467 }
2468
2469 /**
2470 * @param $instructor_id
2471 *
2472 * @return object
2473 *
2474 * Get instructors rating
2475 *
2476 * @since v.1.0.0
2477 */
2478 public function get_instructor_ratings($instructor_id){
2479 global $wpdb;
2480
2481 $ratings = array(
2482 'rating_count' => 0,
2483 'rating_sum' => 0,
2484 'rating_avg' => 0.00,
2485 );
2486
2487 $rating = $wpdb->get_row("SELECT COUNT(rating.meta_value) as rating_count, SUM(rating.meta_value) as rating_sum
2488 FROM {$wpdb->usermeta} courses
2489 INNER JOIN {$wpdb->comments} reviews ON courses.meta_value = reviews.comment_post_ID AND reviews.comment_type = 'tutor_course_rating'
2490 INNER JOIN {$wpdb->commentmeta} rating ON reviews.comment_ID = rating.comment_id AND rating.meta_key = 'tutor_rating'
2491 WHERE courses.user_id = {$instructor_id} AND courses.meta_key = '_tutor_instructor_course_id'");
2492
2493 if ($rating->rating_count){
2494 $avg_rating = number_format(($rating->rating_sum / $rating->rating_count), 2);
2495
2496 $ratings = array(
2497 'rating_count' => $rating->rating_count,
2498 'rating_sum' => $rating->rating_sum,
2499 'rating_avg' => $avg_rating,
2500 );
2501 }
2502
2503 return (object) $ratings;
2504 }
2505
2506 /**
2507 * @param int $course_id
2508 * @param int $user_id
2509 *
2510 * @return object
2511 *
2512 * Get course rating by user
2513 *
2514 * @since v.1.0.0
2515 */
2516 public function get_course_rating_by_user($course_id = 0, $user_id = 0){
2517 $course_id = $this->get_post_id($course_id);
2518 $user_id = $this->get_user_id($user_id);
2519
2520 $ratings = array(
2521 'rating' => 0,
2522 'review' => '',
2523 );
2524
2525 global $wpdb;
2526
2527 $rating = $wpdb->get_row("select meta_value as rating, comment_content as review from {$wpdb->comments}
2528 INNER JOIN {$wpdb->commentmeta}
2529 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2530 WHERE {$wpdb->comments}.comment_post_ID = {$course_id} AND user_id = {$user_id}
2531 AND meta_key = 'tutor_rating' ;"
2532 );
2533
2534 if ($rating){
2535 $rating_format = number_format($rating->rating, 2);
2536
2537 $ratings = array(
2538 'rating' => $rating_format,
2539 'review' => $rating->review,
2540 );
2541 }
2542 return (object) $ratings;
2543 }
2544
2545 /**
2546 * @param int $user_id
2547 *
2548 * @return null|string
2549 *
2550 * @since v.1.0.0
2551 */
2552 public function count_reviews_wrote_by_user($user_id = 0){
2553 global $wpdb;
2554 $user_id = $this->get_user_id($user_id);
2555
2556 $count_reviews = $wpdb->get_var("SELECT COUNT(comment_ID) from {$wpdb->comments} WHERE user_id = {$user_id} AND comment_type = 'tutor_course_rating' ");
2557 return $count_reviews;
2558 }
2559
2560 /**
2561 * @param $size
2562 *
2563 * @return bool|int|string
2564 *
2565 * This function transforms the php.ini notation for numbers (like '2M') to an integer.
2566 *
2567 * @since v.1.0.0
2568 */
2569
2570 function let_to_num( $size ) {
2571 $l = substr( $size, -1 );
2572 $ret = substr( $size, 0, -1 );
2573 $byte = 1024;
2574
2575 switch ( strtoupper( $l ) ) {
2576 case 'P':
2577 $ret *= 1024;
2578 // No break.
2579 case 'T':
2580 $ret *= 1024;
2581 // No break.
2582 case 'G':
2583 $ret *= 1024;
2584 // No break.
2585 case 'M':
2586 $ret *= 1024;
2587 // No break.
2588 case 'K':
2589 $ret *= 1024;
2590 // No break.
2591 }
2592 return $ret;
2593 }
2594
2595 /**
2596 * @return array
2597 *
2598 * Get Database version
2599 *
2600 * @since v.1.0.0
2601 */
2602 function get_db_version() {
2603 global $wpdb;
2604
2605 if ( empty( $wpdb->is_mysql ) ) {
2606 return array(
2607 'string' => '',
2608 'number' => '',
2609 );
2610 }
2611
2612 if ( $wpdb->use_mysqli ) {
2613 $server_info = mysqli_get_server_info( $wpdb->dbh ); // @codingStandardsIgnoreLine.
2614 } else {
2615 $server_info = mysql_get_server_info( $wpdb->dbh ); // @codingStandardsIgnoreLine.
2616 }
2617
2618 return array(
2619 'string' => $server_info,
2620 'number' => preg_replace( '/([^\d.]+).*/', '', $server_info ),
2621 );
2622 }
2623
2624 public function help_tip($tip = ''){
2625 return '<span class="tutor-help-tip" data-tip="' . $tip . '"></span>';
2626 }
2627
2628 /**
2629 * @param int $course_id
2630 * @param int $user_id
2631 * @param int $offset
2632 * @param int $limit
2633 *
2634 * @return array|null|object
2635 *
2636 * Get top question
2637 *
2638 * @since v.1.0.0
2639 */
2640 public function get_top_question($course_id = 0, $user_id = 0, $offset = 0, $limit = 20){
2641 $course_id = $this->get_post_id($course_id);
2642 $user_id = $this->get_user_id($user_id);
2643
2644 global $wpdb;
2645
2646 $questions = $wpdb->get_results("select {$wpdb->comments}.comment_ID,
2647 {$wpdb->comments}.comment_post_ID,
2648 {$wpdb->comments}.comment_author,
2649 {$wpdb->comments}.comment_date,
2650 {$wpdb->comments}.comment_content,
2651 {$wpdb->comments}.user_id,
2652 {$wpdb->commentmeta}.meta_value as question_title,
2653 {$wpdb->users}.display_name
2654
2655 from {$wpdb->comments}
2656 INNER JOIN {$wpdb->commentmeta}
2657 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2658 INNER JOIN {$wpdb->users}
2659 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2660 WHERE {$wpdb->comments}.comment_post_ID = {$course_id}
2661 AND {$wpdb->comments}.user_id = {$user_id}
2662 AND {$wpdb->comments}.comment_type = 'tutor_q_and_a'
2663 AND meta_key = 'tutor_question_title' ORDER BY comment_ID DESC LIMIT {$offset},{$limit} ;"
2664 );
2665
2666 return $questions;
2667 }
2668
2669 /**
2670 * @param string $search_term
2671 *
2672 * @return int
2673 *
2674 * Get total number of Q&A questions
2675 *
2676 * @since v.1.0.0
2677 */
2678 public function get_total_qa_question($search_term = ''){
2679 global $wpdb;
2680
2681 if ($search_term){
2682 $search_term = " AND {$wpdb->commentmeta}.meta_value LIKE '%{$search_term}%' ";
2683 }
2684
2685 $user_id = get_current_user_id();
2686 $course_type = tutor()->course_post_type;
2687
2688 $in_question_id_query = '';
2689 /**
2690 * Get only assinged courses questions if current user is a
2691 */
2692 if ( ! current_user_can('administrator') && current_user_can(tutor()->instructor_role)) {
2693 $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' " );
2694 $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} " );
2695 $my_course_ids = array_unique( array_merge( $get_course_ids, $get_assigned_courses_ids ) );
2696
2697 if ( $this->count( $my_course_ids ) ) {
2698 $implode_ids = implode( ',', $my_course_ids );
2699 $in_question_id_query = " AND {$wpdb->comments}.comment_post_ID IN($implode_ids) ";
2700 }
2701 }
2702
2703 $count = $wpdb->get_var("SELECT COUNT({$wpdb->comments}.comment_ID) FROM {$wpdb->comments}
2704 INNER JOIN {$wpdb->commentmeta}
2705 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2706 WHERE comment_type = 'tutor_q_and_a' AND comment_parent = 0 {$in_question_id_query} {$search_term} ");
2707
2708 return (int) $count;
2709 }
2710
2711 /**
2712 * @param int $start
2713 * @param int $limit
2714 * @param string $search_term
2715 *
2716 * @return array|null|object
2717 *
2718 *
2719 * Get question and answer query
2720 *
2721 * @since v.1.0.0
2722 */
2723 public function get_qa_questions($start = 0, $limit = 10, $search_term = '') {
2724 global $wpdb;
2725
2726 if ($search_term){
2727 $search_term = " AND {$wpdb->commentmeta}.meta_value LIKE '%{$search_term}%' ";
2728 }
2729
2730 $user_id = get_current_user_id();
2731 $course_type = tutor()->course_post_type;
2732
2733 $in_question_id_query = '';
2734 /**
2735 * Get only assinged courses questions if current user is a
2736 */
2737 if ( ! current_user_can('administrator') && current_user_can(tutor()->instructor_role)) {
2738 $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' " );
2739 $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} " );
2740 $my_course_ids = array_unique( array_merge( $get_course_ids, $get_assigned_courses_ids ) );
2741
2742 if ( $this->count( $my_course_ids ) ) {
2743 $implode_ids = implode( ',', $my_course_ids );
2744 $in_question_id_query = " AND {$wpdb->comments}.comment_post_ID IN($implode_ids) ";
2745 }
2746 }
2747
2748 $query = $wpdb->get_results("SELECT
2749 {$wpdb->comments}.comment_ID,
2750 {$wpdb->comments}.comment_post_ID,
2751 {$wpdb->comments}.comment_author,
2752 {$wpdb->comments}.comment_date,
2753 {$wpdb->comments}.comment_content,
2754 {$wpdb->comments}.user_id,
2755 {$wpdb->commentmeta}.meta_value as question_title,
2756 {$wpdb->users}.display_name,
2757 {$wpdb->posts}.post_title,
2758
2759 (SELECT COUNT(answers_t.comment_ID) FROM {$wpdb->comments} answers_t
2760 WHERE answers_t.comment_parent = {$wpdb->comments}.comment_ID ) as answer_count
2761
2762 FROM {$wpdb->comments}
2763
2764 INNER JOIN {$wpdb->commentmeta}
2765 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2766
2767 INNER JOIN {$wpdb->posts}
2768 ON {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID
2769
2770 INNER JOIN {$wpdb->users}
2771 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2772
2773 WHERE {$wpdb->comments}.comment_type = 'tutor_q_and_a' AND {$wpdb->comments}.comment_parent = 0 {$search_term}
2774 {$in_question_id_query}
2775 ORDER BY {$wpdb->comments}.comment_ID DESC
2776 LIMIT {$start},{$limit}; ");
2777
2778 return $query;
2779 }
2780
2781 /**
2782 * @param $question_id
2783 *
2784 * @return array|null|object|void
2785 *
2786 * Get question for Q&A
2787 *
2788 * @since v.1.0.0
2789 */
2790 public function get_qa_question($question_id){
2791 global $wpdb;
2792 $query = $wpdb->get_row("SELECT
2793 {$wpdb->comments}.comment_ID,
2794 {$wpdb->comments}.comment_post_ID,
2795 {$wpdb->comments}.comment_author,
2796 {$wpdb->comments}.comment_date,
2797 {$wpdb->comments}.comment_content,
2798 {$wpdb->comments}.user_id,
2799 {$wpdb->commentmeta}.meta_value as question_title,
2800 {$wpdb->users}.display_name,
2801 {$wpdb->posts}.post_title
2802
2803 FROM {$wpdb->comments}
2804 INNER JOIN {$wpdb->commentmeta}
2805 ON {$wpdb->comments}.comment_ID = {$wpdb->commentmeta}.comment_id
2806
2807 INNER JOIN {$wpdb->posts}
2808 ON {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID
2809
2810 INNER JOIN {$wpdb->users}
2811 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2812 WHERE comment_type = 'tutor_q_and_a' AND {$wpdb->comments}.comment_ID = {$question_id}");
2813
2814 return $query;
2815 }
2816
2817 /**
2818 * @param $question_id
2819 *
2820 * @return array|null|object
2821 *
2822 * Get question and asnwer by question
2823 */
2824 public function get_qa_answer_by_question($question_id){
2825 global $wpdb;
2826 $query = $wpdb->get_results("SELECT
2827 {$wpdb->comments}.comment_ID,
2828 {$wpdb->comments}.comment_post_ID,
2829 {$wpdb->comments}.comment_author,
2830 {$wpdb->comments}.comment_date,
2831 {$wpdb->comments}.comment_content,
2832 {$wpdb->comments}.comment_parent,
2833 {$wpdb->comments}.user_id,
2834 {$wpdb->users}.display_name
2835
2836 FROM {$wpdb->comments}
2837
2838 INNER JOIN {$wpdb->users}
2839 ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
2840 WHERE comment_type = 'tutor_q_and_a'
2841 AND {$wpdb->comments}.comment_parent = {$question_id} ORDER BY {$wpdb->comments}.comment_ID ASC ");
2842
2843 return $query;
2844 }
2845
2846 public function unanswered_question_count(){
2847 global $wpdb;
2848
2849 $count = $wpdb->get_var("select COUNT({$wpdb->comments}.comment_ID)
2850 from {$wpdb->comments}
2851 WHERE {$wpdb->comments}.comment_type = 'tutor_q_and_a'
2852 AND {$wpdb->comments}.comment_approved = 'waiting_for_answer'
2853 AND {$wpdb->comments}.comment_parent = 0;");
2854 return (int) $count;
2855 }
2856
2857 /**
2858 * @param int $course_id
2859 *
2860 * @return array|null|object
2861 *
2862 * Return all of announcements for a course
2863 *
2864 * @since v.1.0.0
2865 */
2866 public function get_announcements($course_id = 0){
2867 $course_id = $this->get_post_id($course_id);
2868 global $wpdb;
2869
2870 $query = $wpdb->get_results("select {$wpdb->posts}.ID, post_author, post_date, post_content, post_title, display_name
2871 from {$wpdb->posts}
2872 INNER JOIN {$wpdb->users} ON post_author = {$wpdb->users}.ID
2873 WHERE post_type = 'tutor_announcements'
2874 AND post_parent = {$course_id} ORDER BY {$wpdb->posts}.ID DESC;");
2875 return $query;
2876 }
2877
2878 /**
2879 * @param string $content
2880 *
2881 * @return mixed
2882 *
2883 * Announcement content
2884 *
2885 * @since v.1.0.0
2886 */
2887
2888 public function announcement_content($content = ''){
2889 $search = array('{user_display_name}');
2890
2891 $user_display_name = 'User';
2892 if (is_user_logged_in()){
2893 $user = wp_get_current_user();
2894 $user_display_name = $user->display_name;
2895 }
2896 $replace = array($user_display_name);
2897
2898 return str_replace($search, $replace, $content);
2899 }
2900
2901 /**
2902 * @param int $post_id
2903 * @param string $option_key
2904 * @param bool $default
2905 *
2906 * @return array|bool|mixed
2907 *
2908 * Get the quiz option from meta
2909 */
2910 public function get_quiz_option($post_id = 0, $option_key = '', $default = false){
2911 $post_id = $this->get_post_id($post_id);
2912 $get_option_meta = maybe_unserialize(get_post_meta($post_id, 'tutor_quiz_option', true));
2913
2914 if ( ! $option_key && ! empty($get_option_meta)) {
2915 return $get_option_meta;
2916 }
2917
2918 $value = $this->avalue_dot( $option_key, $get_option_meta );
2919 if ( $value ) {
2920 return $value;
2921 }
2922 return $default;
2923 }
2924
2925
2926 /**
2927 * @param int $quiz_id
2928 *
2929 * @return array|bool|null|object
2930 *
2931 * Get the questions by quiz ID
2932 */
2933 public function get_questions_by_quiz($quiz_id = 0){
2934 $quiz_id = $this->get_post_id($quiz_id);
2935 global $wpdb;
2936
2937 //$questions = $wpdb->get_results("SELECT ID, post_content, post_title, post_parent from {$wpdb->posts} WHERE post_type = 'tutor_question'
2938 // AND post_parent = {$quiz_id} ORDER BY menu_order ASC ");
2939
2940 $questions = $wpdb->get_results("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} ORDER BY question_order ASC ");
2941
2942 if (is_array($questions) && count($questions)){
2943 return $questions;
2944 }
2945 return false;
2946 }
2947
2948 /**
2949 * @param int $question_id
2950 *
2951 * @return array|bool|object|void|null
2952 *
2953 * Get Quiz question by question id
2954 */
2955 public function get_quiz_question_by_id($question_id = 0){
2956 global $wpdb;
2957
2958 if ($question_id){
2959 $question = $wpdb->get_row("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE question_id = {$question_id} LIMIT 0,1 ;");
2960 return $question;
2961 }
2962
2963 return false;
2964 }
2965
2966 /**
2967 * @param null $type
2968 *
2969 * @return array|mixed
2970 *
2971 * Get all question types
2972 *
2973 * @since v.1.0.0
2974 */
2975
2976 public function get_question_types($type = null){
2977 $types = array(
2978 'true_false' => array('name' => __('True/False', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-yes-no"></i>', 'is_pro' => false),
2979 'single_choice' => array('name' => __('Single Choice', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-mark"></i>', 'is_pro' => false),
2980 'multiple_choice' => array('name' => __('Multiple Choice', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-multiple-choice"></i>', 'is_pro' => false),
2981 'open_ended' => array('name' => __('Open Ended/Essay', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-open-ended"></i>', 'is_pro' => false),
2982 'fill_in_the_blank' => array('name' => __('Fill In The Blank', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-fill-gaps"></i>', 'is_pro' => false),
2983 'short_answer' => array('name' => __('Short Answer', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-short-ans"></i>', 'is_pro' => true),
2984 'matching' => array('name' => __('Matching', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-matching"></i>', 'is_pro' => true),
2985 'image_matching' => array('name' => __('Image Matching', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-image-matching"></i>', 'is_pro' => true),
2986 'image_answering' => array('name' => __('Image Answering', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-image-ans"></i>', 'is_pro' => true),
2987 'ordering' => array('name' => __('Ordering', 'tutor'), 'icon' => '<i class="tutor-icon-block tutor-icon-ordering"></i>', 'is_pro' => true),
2988 );
2989
2990 if (isset($types[$type])){
2991 return $types[$type];
2992 }
2993 return $types;
2994 }
2995
2996 public function get_quiz_answer_options_by_question($question_id){
2997 global $wpdb;
2998
2999 $answer_options = $wpdb->get_results("select
3000 {$wpdb->comments}.comment_ID,
3001 {$wpdb->comments}.comment_post_ID,
3002 {$wpdb->comments}.comment_content
3003
3004 FROM {$wpdb->comments}
3005 WHERE {$wpdb->comments}.comment_post_ID = {$question_id}
3006 AND {$wpdb->comments}.comment_type = 'quiz_answer_option'
3007 ORDER BY {$wpdb->comments}.comment_karma ASC ;");
3008
3009 if (is_array($answer_options) && count($answer_options)){
3010 return $answer_options;
3011 }
3012 return false;
3013 }
3014
3015 /**
3016 * @param $quiz_id
3017 *
3018 * @return int
3019 *
3020 * Get the next question order ID
3021 *
3022 * @since v.1.0.0
3023 */
3024
3025 public function quiz_next_question_order_id($quiz_id){
3026 global $wpdb;
3027
3028 //$last_order = (int) $wpdb->get_var("SELECT MAX(menu_order) FROM {$wpdb->posts} WHERE post_parent = {$quiz_id} AND post_type =
3029 // 'tutor_question';");
3030
3031 $last_order = (int) $wpdb->get_var("SELECT MAX(question_order) FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} ;");
3032 return $last_order + 1;
3033 }
3034
3035 /**
3036 * @param $quiz_id
3037 *
3038 * @return int
3039 *
3040 * new design quiz question
3041 * @since v.1.0.0
3042 */
3043 public function quiz_next_question_id(){
3044 global $wpdb;
3045
3046 $last_order = (int) $wpdb->get_var("SELECT MAX(question_id) FROM {$wpdb->prefix}tutor_quiz_questions;");
3047 return $last_order + 1;
3048 }
3049
3050 public function get_quiz_id_by_question($question_id){
3051 global $wpdb;
3052
3053 $quiz_id = $wpdb->get_var("SELECT post_parent FROM {$wpdb->posts} WHERE ID = {$question_id} AND post_type = 'tutor_question' ;");
3054 return $quiz_id;
3055 }
3056
3057 /**
3058 * @param array $config
3059 *
3060 * @return array|bool|null|object
3061 *
3062 * It was used in previous quiz algorithm
3063 *
3064 * @deprecated
3065 *
3066 * @since v.1.0.0
3067 */
3068 public function get_unattached_quiz($config = array()){
3069 global $wpdb;
3070
3071 $default_attr = array(
3072 'search_term' => '',
3073 'start' => '0',
3074 'limit' => '10',
3075 'order' => 'DESC',
3076 'order_by' => 'ID',
3077 );
3078 $attr = array_merge($default_attr, $config);
3079 extract($attr);
3080
3081 $search_query = '';
3082 if (! empty($search_term)){
3083 $search_query = "AND post_title LIKE '%{$search_term}%'";
3084 }
3085
3086 $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 = 0 {$search_query} ORDER BY {$order_by} {$order} LIMIT {$start},{$limit} ");
3087
3088 if (is_array($questions) && count($questions)){
3089 return $questions;
3090 }
3091 return false;
3092 }
3093
3094 /**
3095 * @param int $post_id
3096 *
3097 * @return array|bool|null|object
3098 *
3099 * @since v.1.0.0
3100 */
3101 public function get_attached_quiz($post_id = 0){
3102 global $wpdb;
3103
3104 $post_id = $this->get_post_id($post_id);
3105
3106 $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}");
3107
3108 if (is_array($questions) && count($questions)){
3109 return $questions;
3110 }
3111 return false;
3112 }
3113
3114 /**
3115 * @param $quiz_id
3116 *
3117 * @return array|bool|null|object|void
3118 *
3119 * Get course by quiz
3120 *
3121 * @since v.1.0.0
3122 */
3123
3124 public function get_course_by_quiz($quiz_id){
3125 global $wpdb;
3126
3127 $quiz_id = $this->get_post_id($quiz_id);
3128 $post = get_post($quiz_id);
3129
3130 if ($post) {
3131 $course_post_type = tutor()->course_post_type;
3132 $course = $wpdb->get_row( "select ID, post_name, post_type, post_parent from {$wpdb->posts} where ID = {$post->post_parent} " );
3133
3134 if ($course) {
3135 //Checking if this topic
3136 if ( $course->post_type !== $course_post_type ) {
3137 $course = $wpdb->get_row( "select ID, post_name, post_type, post_parent from {$wpdb->posts} where ID = {$course->post_parent} " );
3138 }
3139 //Checking if this lesson
3140 if ( $course->post_type !== $course_post_type ) {
3141 $course = $wpdb->get_row( "select ID, post_name, post_type, post_parent from {$wpdb->posts} where ID = {$course->post_parent} " );
3142 }
3143
3144 return $course;
3145 }
3146 }
3147
3148 return false;
3149 }
3150
3151 /**
3152 * @param $quiz_id
3153 *
3154 * @return int
3155 *
3156 * @since v.1.0.0
3157 */
3158 public function total_questions_for_student_by_quiz($quiz_id){
3159 $quiz_id = $this->get_post_id($quiz_id);
3160 global $wpdb;
3161
3162 $total_question = (int) $wpdb->get_var("select count(ID) from {$wpdb->posts} where post_parent = {$quiz_id} AND post_type = 'tutor_question' ");
3163
3164 return $total_question;
3165 }
3166
3167 /**
3168 * @param int $quiz_id
3169 *
3170 * @return array|null|object|void
3171 *
3172 * Determine if there is any started quiz exists
3173 *
3174 * @since v.1.0.0
3175 */
3176
3177 public function is_started_quiz($quiz_id = 0){
3178 global $wpdb;
3179
3180 $quiz_id = $this->get_post_id($quiz_id);
3181 $user_id = get_current_user_id();
3182
3183 $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' ");
3184
3185 return $is_started;
3186 }
3187
3188 /**
3189 * @param $quiz_id
3190 *
3191 * Method for get the total amount of question for a quiz
3192 * Student will answer this amount of question, one quiz have many question
3193 * but student will answer a specific amount of questions
3194 *
3195 * @return int
3196 *
3197 * @since v.1.0.0
3198 */
3199
3200 public function max_questions_for_take_quiz($quiz_id){
3201 $quiz_id = $this->get_post_id($quiz_id);
3202 global $wpdb;
3203
3204 $max_questions = (int) $wpdb->get_var("select count(question_id) from {$wpdb->prefix}tutor_quiz_questions where quiz_id = {$quiz_id} ");
3205 $max_mentioned = (int) $this->get_quiz_option($quiz_id, 'max_questions_for_answer', 10);
3206
3207 if ($max_mentioned < $max_questions ){
3208 return $max_mentioned;
3209 }
3210
3211 return $max_questions;
3212 }
3213
3214 /**
3215 * @param int $attempt_id
3216 *
3217 * @return array|bool|null|object|void
3218 *
3219 * Get single quiz attempt
3220 *
3221 * @since v.1.0.0
3222 */
3223 public function get_attempt($attempt_id = 0){
3224 global $wpdb;
3225 if ( ! $attempt_id){
3226 return false;
3227 }
3228 $attempt = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE attempt_id = {$attempt_id} ");
3229 return $attempt;
3230 }
3231
3232 /**
3233 * @param $attempt_info
3234 *
3235 * @return mixed
3236 *
3237 * Get unserialize attempt info
3238 *
3239 * @since v.1.0.0
3240 */
3241
3242 public function quiz_attempt_info($attempt_info){
3243 return maybe_unserialize($attempt_info);
3244 }
3245
3246 /**
3247 * @param $quiz_attempt_id
3248 * @param array $attempt_info
3249 *
3250 * @return bool|int
3251 *
3252 * Update attempt for various action
3253 *
3254 * @since v.1.0.0
3255 */
3256 public function quiz_update_attempt_info($quiz_attempt_id, $attempt_info = array()){
3257 $answers = tutor_utils()->avalue_dot('answers', $attempt_info);
3258 $total_marks = array_sum(wp_list_pluck($answers, 'question_mark'));
3259 $earned_marks = tutor_utils()->avalue_dot('marks_earned', $attempt_info);
3260 $earned_mark_percent = $earned_marks > 0 ? ( number_format(($earned_marks * 100) / $total_marks)) : 0;
3261 update_comment_meta($quiz_attempt_id, 'earned_mark_percent', $earned_mark_percent);
3262
3263 return update_comment_meta($quiz_attempt_id,'quiz_attempt_info', $attempt_info);
3264 }
3265
3266 /**
3267 * @param int $quiz_id
3268 *
3269 * @return array|null|object
3270 *
3271 * Get random question by quiz id
3272 *
3273 * @since v.1.0.0
3274 */
3275
3276 public function get_random_question_by_quiz($quiz_id = 0){
3277 global $wpdb;
3278
3279 $quiz_id = $this->get_post_id($quiz_id);
3280 $is_attempt = $this->is_started_quiz($quiz_id);
3281
3282 $tempSql = " AND question_type = 'matching' ";
3283 $questions = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} {$tempSql} ORDER BY RAND() LIMIT 0,1 ");
3284
3285 return $questions;
3286 }
3287
3288 /**
3289 * @param int $quiz_id
3290 *
3291 * @return array|null|object
3292 *
3293 * Get random questions by quiz
3294 */
3295 public function get_random_questions_by_quiz($quiz_id = 0){
3296 global $wpdb;
3297
3298 $quiz_id = $this->get_post_id($quiz_id);
3299 $attempt = $this->is_started_quiz($quiz_id);
3300 if ( ! $attempt){
3301 return false;
3302 }
3303
3304 $questions = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = {$quiz_id} ORDER BY RAND() LIMIT {$attempt->total_questions} ");
3305
3306 return $questions;
3307 }
3308
3309 /**
3310 * @param $question_id
3311 * @param bool $rand
3312 *
3313 * @return array|bool|null|object
3314 *
3315 * Get answers list by quiz question
3316 *
3317 * @since v.1.0.0
3318 */
3319 public function get_answers_by_quiz_question($question_id, $rand = false){
3320 global $wpdb;
3321
3322
3323 $question = $wpdb->get_row("SELECT * from {$wpdb->prefix}tutor_quiz_questions WHERE question_id = {$question_id} ;");
3324 if ( ! $question){
3325 return false;
3326 }
3327
3328 $order = " answer_order ASC ";
3329 if ($question->question_type === 'ordering'){
3330 $order = " RAND() ";
3331 }
3332
3333 if ($rand){
3334 $order = " RAND() ";
3335 }
3336
3337 $answers = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id = {$question_id} AND belongs_question_type =
3338 '{$question->question_type}' order by {$order} ");
3339 return $answers;
3340 }
3341
3342 /**
3343 * @param int $quiz_id
3344 * @param int $user_id
3345 *
3346 * @return array|bool|null|object
3347 *
3348 * Get all of the attempts by an user of a quiz
3349 *
3350 * @since v.1.0.0
3351 */
3352
3353 public function quiz_attempts($quiz_id = 0, $user_id = 0){
3354 global $wpdb;
3355
3356 $quiz_id = $this->get_post_id($quiz_id);
3357 $user_id = $this->get_user_id($user_id);
3358
3359 $attempts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE quiz_id = {$quiz_id} AND user_id = {$user_id} ");
3360
3361 if (is_array($attempts) && count($attempts)){
3362 return $attempts;
3363 }
3364
3365 return false;
3366 }
3367
3368
3369 public function get_all_quiz_attempts_by_user($user_id = 0){
3370 global $wpdb;
3371
3372 $user_id = $this->get_user_id($user_id);
3373
3374 $attempts = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}tutor_quiz_attempts WHERE user_id = {$user_id} ");
3375
3376 if (is_array($attempts) && count($attempts)){
3377 return $attempts;
3378 }
3379
3380 return false;
3381 }
3382
3383 /**
3384 * @param string $search_term
3385 *
3386 * @return int
3387 *
3388 * Total number of quiz attempts
3389 *
3390 * @since v.1.0.0
3391 */
3392
3393 public function get_total_quiz_attempts($search_term = ''){
3394 global $wpdb;
3395
3396 if ($search_term){
3397 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3398 }
3399
3400 $count = $wpdb->get_var("SELECT COUNT(attempt_id)
3401 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3402 INNER JOIN {$wpdb->posts} quiz
3403 ON quiz_attempts.quiz_id = quiz.ID
3404 INNER JOIN {$wpdb->users}
3405 ON quiz_attempts.user_id = {$wpdb->users}.ID
3406 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term} ");
3407 return (int) $count;
3408 }
3409
3410 /**
3411 * @param int $start
3412 * @param int $limit
3413 * @param string $search_term
3414 *
3415 * @return array|null|object
3416 *
3417 *
3418 * Get the all quiz attempts
3419 *
3420 * @since v.1.0.0
3421 */
3422 public function get_quiz_attempts($start = 0, $limit = 10, $search_term = '') {
3423 global $wpdb;
3424
3425 if ($search_term){
3426 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3427 }
3428
3429 $query = $wpdb->get_results("SELECT *
3430 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3431 INNER JOIN {$wpdb->posts} quiz
3432 ON quiz_attempts.quiz_id = quiz.ID
3433 INNER JOIN {$wpdb->users}
3434 ON quiz_attempts.user_id = {$wpdb->users}.ID
3435 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term}
3436 ORDER BY quiz_attempts.attempt_id DESC
3437 LIMIT {$start},{$limit}; ");
3438 return $query;
3439 }
3440
3441 public function get_quiz_attempts_by_course_ids($start = 0, $limit = 10, $course_ids = array(), $search_term = '') {
3442 global $wpdb;
3443
3444 if ($search_term){
3445 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3446 }
3447
3448 $course_ids_in = implode($course_ids, ',');
3449 $sql = " AND quiz_attempts.course_id IN({$course_ids_in}) ";
3450 $search_term = $sql.$search_term;
3451
3452 $query = $wpdb->get_results("SELECT *
3453 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3454 INNER JOIN {$wpdb->posts} quiz
3455 ON quiz_attempts.quiz_id = quiz.ID
3456 INNER JOIN {$wpdb->users}
3457 ON quiz_attempts.user_id = {$wpdb->users}.ID
3458 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term}
3459 ORDER BY quiz_attempts.attempt_id DESC
3460 LIMIT {$start},{$limit}; ");
3461 return $query;
3462 }
3463
3464 public function get_total_quiz_attempts_by_course_ids($course_ids = array(), $search_term = ''){
3465 global $wpdb;
3466
3467 if ($search_term){
3468 $search_term = " AND ( user_email like '%{$search_term}%' OR display_name like '%{$search_term}%' OR post_title like '%{$search_term}%' ) ";
3469 }
3470
3471 $course_ids_in = implode($course_ids, ',');
3472 $sql = " AND quiz_attempts.course_id IN({$course_ids_in}) ";
3473 $search_term = $sql.$search_term;
3474
3475 $count = $wpdb->get_var("SELECT COUNT(attempt_id)
3476 FROM {$wpdb->prefix}tutor_quiz_attempts quiz_attempts
3477 INNER JOIN {$wpdb->posts} quiz
3478 ON quiz_attempts.quiz_id = quiz.ID
3479 INNER JOIN {$wpdb->users}
3480 ON quiz_attempts.user_id = {$wpdb->users}.ID
3481 WHERE 1=1 AND quiz_attempts.attempt_ended_at <= NOW() {$search_term} ");
3482 return (int) $count;
3483 }
3484
3485 /**
3486 * @param $attempt_id
3487 *
3488 * @return array|null|object
3489 *
3490 * Get quiz answers by attempt id
3491 *
3492 * @since v.1.0.0
3493 */
3494 public function get_quiz_answers_by_attempt_id($attempt_id){
3495 global $wpdb;
3496
3497 $results = $wpdb->get_results("SELECT answers.*, question.question_title, question.question_type
3498 FROM {$wpdb->prefix}tutor_quiz_attempt_answers answers
3499 LEFT JOIN {$wpdb->prefix}tutor_quiz_questions question ON answers.question_id = question.question_id
3500 WHERE answers.quiz_attempt_id = {$attempt_id} ");
3501
3502 return $results;
3503 }
3504
3505 /**
3506 * @param $answer_id
3507 *
3508 * @return array|null|object
3509 *
3510 * Get single answer by answer_id
3511 *
3512 * @since v.1.0.0
3513 */
3514 public function get_answer_by_id($answer_id){
3515 global $wpdb;
3516
3517 if (is_array($answer_id)){
3518 $in_ids = implode(",", $answer_id);
3519 $sql = "answer.answer_id IN({$in_ids})";
3520 }else{
3521 $sql = "answer.answer_id = {$answer_id}";
3522 }
3523
3524 $answer = $wpdb->get_results("SELECT answer.*, question.question_title, question.question_type
3525 FROM {$wpdb->prefix}tutor_quiz_question_answers answer
3526 LEFT JOIN {$wpdb->prefix}tutor_quiz_questions question ON answer.belongs_question_id = question.question_id
3527 WHERE 1=1 AND {$sql} ");
3528
3529 return $answer;
3530 }
3531
3532 /**
3533 * @param $ids
3534 *
3535 * @return array|bool|null|object
3536 *
3537 * Get quiz answers by ids
3538 *
3539 * @since v.1.0.0
3540 */
3541
3542 public function get_quiz_answers_by_ids($ids){
3543 $ids = (array) $ids;
3544
3545 if (!count($ids)){
3546 return false;
3547 }
3548
3549 $in_ids = implode(",", $ids);
3550
3551 global $wpdb;
3552 $query = $wpdb->get_results("SELECT
3553 comment_ID,
3554 comment_content
3555 FROM {$wpdb->comments}
3556 WHERE comment_type = 'quiz_answer_option' AND comment_ID IN({$in_ids}) ");
3557
3558 if (is_array($query) && count($query)){
3559 return $query;
3560 }
3561
3562 return false;
3563 }
3564
3565 /**
3566 * @param null $level
3567 *
3568 * @return mixed
3569 *
3570 * Get the users / students / course levels
3571 *
3572 * @since v.1.0.0
3573 */
3574
3575 public function course_levels($level = null){
3576 $levels = apply_filters('tutor_course_level', array(
3577 'all_levels' => __('All Levels', 'tutor'),
3578 'beginner' => __('Beginner', 'tutor'),
3579 'intermediate' => __('Intermediate', 'tutor'),
3580 'expert' => __('Expert', 'tutor'),
3581 ));
3582
3583 if ($level){
3584 if (isset($levels[$level])){
3585 return $levels[$level];
3586 }else{
3587 return '';
3588 }
3589 }
3590
3591 return $levels;
3592 }
3593
3594 /**
3595 * @return mixed|void
3596 *
3597 * Get user permalink for dashboard
3598 *
3599 * @since v.1.0.0
3600 */
3601 public function user_profile_permalinks(){
3602 $permalinks = array(
3603 'courses_taken' => __('Courses Taken', 'tutor'),
3604 );
3605
3606 $show_enrolled_course = tutor_utils()->get_option('show_courses_completed_by_student');
3607 $enable_show_reviews_wrote = tutor_utils()->get_option('students_own_review_show_at_profile');
3608
3609 if ($show_enrolled_course){
3610 $permalinks['enrolled_course'] = __('Enrolled Course', 'tutor');
3611 }
3612 if ($enable_show_reviews_wrote){
3613 $permalinks['reviews_wrote'] = __('Reviews Written', 'tutor');
3614 }
3615
3616
3617 return apply_filters('tutor_public_profile/permalinks', $permalinks);
3618 }
3619
3620 /**
3621 * @return bool|false|string
3622 *
3623 * Student registration form
3624 *
3625 * @since v.1.0.0
3626 */
3627 public function student_register_url(){
3628 $student_register_page = (int) $this->get_option('student_register_page');
3629
3630 if ($student_register_page){
3631 return get_the_permalink($student_register_page);
3632 }
3633 return false;
3634 }
3635 /**
3636 * @return bool|false|string
3637 *
3638 * Instructor registration form
3639 *
3640 * @since v.1.2.13
3641 */
3642 public function instructor_register_url(){
3643 $instructor_register_page = (int) $this->get_option('instructor_register_page');
3644
3645 if ($instructor_register_page){
3646 return get_the_permalink($instructor_register_page);
3647 }
3648 return false;
3649 }
3650
3651 /**
3652 * @return false|string
3653 *
3654 * Get frontend dashboard URL
3655 */
3656 public function tutor_dashboard_url(){
3657 $page_id = (int) tutor_utils()->get_option('tutor_dashboard_page_id');
3658 $page_id = apply_filters('tutor_dashboard_url', $page_id);
3659 return get_the_permalink($page_id);
3660 }
3661
3662 /**
3663 * @param int $course_id
3664 * @param int $user_id
3665 *
3666 * @return bool
3667 *
3668 * is_wishlisted();
3669 *
3670 * @since v.1.0.0
3671 */
3672 public function is_wishlisted($course_id = 0, $user_id = 0){
3673 $course_id = $this->get_post_id($course_id);
3674 $user_id = $this->get_user_id($user_id);
3675 if ( ! $user_id){
3676 return false;
3677 }
3678
3679 global $wpdb;
3680 $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} ;");
3681
3682 return $if_added_to_list;
3683 }
3684
3685 /**
3686 * @param int $user_id
3687 *
3688 * @return array|null|object
3689 *
3690 * Get the wish lists by an user
3691 *
3692 * @since v.1.0.0
3693 */
3694 public function get_wishlist($user_id = 0){
3695 $user_id = $this->get_user_id($user_id);
3696 global $wpdb;
3697
3698 $query = "SELECT $wpdb->posts.*
3699 FROM $wpdb->posts
3700 LEFT JOIN $wpdb->usermeta ON ($wpdb->posts.ID = $wpdb->usermeta.meta_value)
3701 WHERE $wpdb->usermeta.meta_key = '_tutor_course_wishlist'
3702 AND $wpdb->usermeta.user_id = {$user_id}
3703 ORDER BY $wpdb->usermeta.umeta_id DESC ";
3704 $pageposts = $wpdb->get_results($query, OBJECT);
3705 return $pageposts;
3706 }
3707
3708 /**
3709 * @param int $limit
3710 *
3711 * @return array|null|object
3712 *
3713 * Getting popular courses
3714 *
3715 * @since v.1.0.0
3716 */
3717 public function most_popular_courses($limit = 10){
3718 global $wpdb;
3719
3720 $courses = $wpdb->get_results("
3721 SELECT COUNT(enrolled.ID) as total_enrolled,
3722 enrolled.post_parent as course_id,
3723 course.*
3724 from {$wpdb->posts} enrolled
3725 INNER JOIN {$wpdb->posts} course ON enrolled.post_parent = course.ID
3726 WHERE enrolled.post_type = 'tutor_enrolled' AND enrolled.post_status = 'completed'
3727
3728 GROUP BY course_id
3729 ORDER BY total_enrolled DESC LIMIT 0,{$limit} ;");
3730
3731 return $courses;
3732 }
3733
3734 /**
3735 * @param int $limit
3736 *
3737 * @return array|bool|null|object
3738 *
3739 * Get most rated courses lists
3740 *
3741 * @since v.1.0.0
3742 */
3743 public function most_rated_courses($limit = 10){
3744 global $wpdb;
3745
3746 $result = $wpdb->get_results("
3747 SELECT COUNT(comment_ID) AS total_rating,
3748 comment_ID,
3749 comment_post_ID,
3750 course.*
3751 FROM {$wpdb->comments}
3752 INNER JOIN {$wpdb->posts} course ON comment_post_ID = course.ID
3753 WHERE {$wpdb->comments}.comment_type = 'tutor_course_rating' AND {$wpdb->comments}.comment_approved = 'approved'
3754 GROUP BY comment_post_ID ORDER BY total_rating DESC LIMIT 0,{$limit}
3755 ;");
3756
3757 if (is_array($result) && count($result)){
3758 return $result;
3759 }
3760 return false;
3761 }
3762
3763 /**
3764 * @param null $addon_field
3765 *
3766 * @return bool
3767 *
3768 * Get Addon config
3769 *
3770 * @since v.1.0.0
3771 */
3772 public function get_addon_config($addon_field = null){
3773 if ( ! $addon_field){
3774 return false;
3775 }
3776
3777 $addonsConfig = maybe_unserialize(get_option('tutor_addons_config'));
3778
3779 if (isset($addonsConfig[$addon_field])){
3780 return $addonsConfig[$addon_field];
3781 }
3782
3783 return false;
3784 }
3785
3786 /**
3787 * @return array|false|string
3788 *
3789 * Get the IP from visitor
3790 *
3791 * @since v.1.0.0
3792 */
3793 function get_ip() {
3794 $ipaddress = '';
3795 if (getenv('HTTP_CLIENT_IP'))
3796 $ipaddress = getenv('HTTP_CLIENT_IP');
3797 else if(getenv('HTTP_X_FORWARDED_FOR'))
3798 $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
3799 else if(getenv('HTTP_X_FORWARDED'))
3800 $ipaddress = getenv('HTTP_X_FORWARDED');
3801 else if(getenv('HTTP_FORWARDED_FOR'))
3802 $ipaddress = getenv('HTTP_FORWARDED_FOR');
3803 else if(getenv('HTTP_FORWARDED'))
3804 $ipaddress = getenv('HTTP_FORWARDED');
3805 else if(getenv('REMOTE_ADDR'))
3806 $ipaddress = getenv('REMOTE_ADDR');
3807 else
3808 $ipaddress = 'UNKNOWN';
3809 return $ipaddress;
3810 }
3811
3812 /**
3813 * @return mixed|void
3814 *
3815 * Get the social icons
3816 *
3817 * @since v.1.0.4
3818 */
3819
3820 public function tutor_social_share_icons(){
3821 $icons = array(
3822 'facebook' => array('share_class' => 's_facebook', 'icon_html' => '<i class="tutor-icon-facebook"></i>' ),
3823 'twitter' => array('share_class' => 's_twitter', 'icon_html' => '<i class="tutor-icon-twitter"></i>' ),
3824 'linkedin' => array('share_class' => 's_linkedin', 'icon_html' => '<i class="tutor-icon-linkdin"></i>' ),
3825 'tumblr' => array('share_class' => 's_tumblr', 'icon_html' => '<i class="tutor-icon-tumblr"></i>' ),
3826 );
3827
3828 return apply_filters('tutor_social_share_icons', $icons);
3829 }
3830
3831 /**
3832 * @param array $array
3833 *
3834 * @return bool
3835 *
3836 * count method with check is_array
3837 *
3838 * @since v.1.0.4
3839 */
3840 public function count($array = array()){
3841 return is_array($array) && count($array);
3842 }
3843
3844 /**
3845 * @return array
3846 *
3847 * get all screen ids
3848 *
3849 * @since v.1.1.2
3850 */
3851 public function tutor_get_screen_ids(){
3852 $screen_ids = array(
3853 "edit-course",
3854 "course",
3855 "edit-course-category",
3856 "edit-course-tag",
3857 "tutor-lms_page_tutor-students",
3858 "tutor-lms_page_tutor-instructors",
3859 "tutor-lms_page_question_answer",
3860 "tutor-lms_page_tutor_quiz_attempts",
3861 "tutor-lms_page_tutor-addons",
3862 "tutor-lms_page_tutor-status",
3863 "tutor-lms_page_tutor_report",
3864 "tutor-lms_page_tutor_settings",
3865 "tutor-lms_page_tutor_emails",
3866 );
3867
3868 return apply_filters('tutor_get_screen_ids', $screen_ids);
3869 }
3870
3871
3872 /**
3873 * @return mixed
3874 *
3875 * get earning transaction completed status
3876 *
3877 * @since v.1.1.2
3878 */
3879 public function get_earnings_completed_statuses(){
3880 return apply_filters(
3881 'tutor_get_earnings_completed_statuses',
3882 array (
3883 'wc-completed',
3884 'completed',
3885 'complete',
3886 )
3887 );
3888 }
3889
3890 /**
3891 * @param int $user_id
3892 * @param array $date_filter
3893 *
3894 * @return array|null|object
3895 *
3896 * Get all time earning sum for an instructor with all commission
3897 *
3898 * @since v.1.1.2
3899 */
3900
3901 public function get_earning_sum($user_id = 0, $date_filter = array()){
3902 global $wpdb;
3903
3904 $user_id = $this->get_user_id($user_id);
3905 $date_query = '';
3906 if ($this->count($date_filter)){
3907 extract($date_filter);
3908
3909 if ( ! empty($dataFor)){
3910 if ($dataFor === 'yearly'){
3911 if (empty($year)){
3912 $year = date('Y');
3913 }
3914 $date_query = "AND YEAR(created_at) = {$year} ";
3915 }
3916 }else{
3917 $date_query = " AND (created_at BETWEEN '{$start_date}' AND '{$end_date}') ";
3918 }
3919 }
3920
3921 $complete_status = tutor_utils()->get_earnings_completed_statuses();
3922 $complete_status = "'".implode("','", $complete_status)."'";
3923
3924 $earning_sum = $wpdb->get_row("SELECT SUM(course_price_total) as course_price_total,
3925 SUM(course_price_grand_total) as course_price_grand_total,
3926 SUM(instructor_amount) as instructor_amount,
3927 (SELECT SUM(amount) FROM {$wpdb->prefix}tutor_withdraws WHERE user_id = {$user_id} AND status != 'rejected' ) as
3928 withdraws_amount,
3929 SUM(admin_amount) as admin_amount,
3930 SUM(deduct_fees_amount) as deduct_fees_amount
3931 FROM {$wpdb->prefix}tutor_earnings
3932 WHERE user_id = {$user_id} AND order_status IN({$complete_status}) {$date_query} ");
3933
3934 //TODO: need to check
3935 // (SUM(instructor_amount) - (SELECT withdraws_amount) ) as balance,
3936
3937
3938 if ( $earning_sum->course_price_total){
3939 $earning_sum->balance = $earning_sum->instructor_amount - $earning_sum->withdraws_amount;
3940 }else{
3941
3942 $earning_sum = (object) array(
3943 'course_price_total' => 0,
3944 'course_price_grand_total' => 0,
3945 'instructor_amount' => 0,
3946 'withdraws_amount' => 0,
3947 'balance' => 0,
3948 'admin_amount' => 0,
3949 'deduct_fees_amount' => 0,
3950 );
3951 }
3952
3953 return $earning_sum;
3954 }
3955
3956 /**
3957 * @param int $user_id
3958 * @param array $date_filter
3959 *
3960 * @return array|null|object
3961 *
3962 * Get earning statements
3963 *
3964 * @since v.1.1.2
3965 */
3966 public function get_earning_statements($user_id = 0, $filter_data = array()){
3967 global $wpdb;
3968
3969 $user_sql = "";
3970 if ($user_id){
3971 $user_sql = " AND user_id='{$user_id}' ";
3972 }
3973
3974 $date_query = '';
3975 $query_by_status = '';
3976 $pagination_query = '';
3977
3978 /**
3979 * Query by Date Filter
3980 */
3981 if ($this->count($filter_data)){
3982 extract($filter_data);
3983
3984 if ( ! empty($dataFor)){
3985 if ($dataFor === 'yearly'){
3986 if (empty($year)){
3987 $year = date('Y');
3988 }
3989 $date_query = "AND YEAR(created_at) = {$year} ";
3990 }
3991 }else{
3992 $date_query = " AND (created_at BETWEEN '{$start_date}' AND '{$end_date}') ";
3993 }
3994
3995 /**
3996 * Query by order status related to this earning transaction
3997 */
3998 if ( ! empty($statuses)) {
3999 if ( $this->count( $statuses ) ) {
4000 $status = "'" . implode( "','", $statuses ) . "'";
4001 $query_by_status = "AND order_status IN({$status})";
4002 } elseif ( $statuses === 'completed' ) {
4003
4004 $get_earnings_completed_statuses = $this->get_earnings_completed_statuses();
4005 if ( $this->count( $get_earnings_completed_statuses ) ) {
4006 $status = "'" . implode( "','", $get_earnings_completed_statuses ) . "'";
4007 $query_by_status = "AND order_status IN({$status})";
4008 }
4009 }
4010 }
4011
4012 if ( ! empty($per_page)){
4013 $offset = (int) ! empty($offset) ? $offset : 0;
4014
4015 $pagination_query = " LIMIT {$offset}, {$per_page} ";
4016
4017 }
4018
4019
4020 }
4021
4022 $query = $wpdb->get_results("SELECT earning_tbl.*, course.post_title as course_title
4023 FROM {$wpdb->prefix}tutor_earnings earning_tbl
4024 LEFT JOIN {$wpdb->posts} course ON earning_tbl.course_id = course.ID
4025 WHERE 1=1 {$user_sql} {$date_query} {$query_by_status} ORDER BY created_at DESC {$pagination_query} ");
4026
4027
4028 $query_count = (int) $wpdb->get_var("SELECT COUNT(earning_tbl.earning_id)
4029 FROM {$wpdb->prefix}tutor_earnings earning_tbl
4030 WHERE 1=1 {$user_sql} {$date_query} {$query_by_status} ORDER BY created_at DESC ");
4031
4032 return (object) array(
4033 'count' => $query_count,
4034 'results' => $query,
4035 );
4036 }
4037
4038 /**
4039 * @param int $price
4040 *
4041 * @return int|string
4042 *
4043 * Get the price format
4044 *
4045 * @since v.1.1.2
4046 */
4047
4048 public function tutor_price($price = 0){
4049 if (function_exists('wc_price')){
4050 return wc_price($price);
4051 }elseif (function_exists('edd_currency_filter')){
4052 return edd_currency_filter(edd_format_amount($price));
4053 }else{
4054 return number_format_i18n($price);
4055 }
4056 }
4057
4058 /**
4059 * @param int $user_id
4060 *
4061 * @return bool|mixed
4062 *
4063 * Get withdraw method for a specific
4064 */
4065 public function get_user_withdraw_method($user_id = 0){
4066 $user_id = $this->get_user_id($user_id);
4067
4068 $account = get_user_meta($user_id, '_tutor_withdraw_method_data', true);
4069 if ($account){
4070 return maybe_unserialize($account);
4071 }
4072
4073 return false;
4074 }
4075
4076 /**
4077 * @param int $user_id
4078 * @param array $filter
4079 *
4080 * get withdrawal history
4081 *
4082 * @return object
4083 */
4084 public function get_withdrawals_history($user_id = 0, $filter = array()){
4085 global $wpdb;
4086
4087 $filter = (array) $filter;
4088 extract($filter);
4089
4090 $query_by_status_sql = "";
4091 $query_by_user_sql = "";
4092 $query_by_pagination = "";
4093
4094 if ( ! empty($status)){
4095 $status = (array) $status;
4096 $status = "'".implode("','", $status)."'";
4097
4098 $query_by_status_sql = " AND status IN({$status}) ";
4099 }
4100
4101 if ( ! empty($per_page)){
4102 if ( empty($start))
4103 $start = 0;
4104
4105 $query_by_pagination = " LIMIT {$start}, {$per_page} ";
4106 }
4107
4108 if ($user_id){
4109 $query_by_user_sql = " AND user_id = {$user_id} ";
4110 }
4111
4112
4113 $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} ");
4114
4115 $results = $wpdb->get_results("SELECT withdraw_tbl.*,
4116 user_tbl.display_name as user_name,
4117 user_tbl.user_email
4118 FROM {$wpdb->prefix}tutor_withdraws withdraw_tbl
4119 INNER JOIN {$wpdb->users} user_tbl ON withdraw_tbl.user_id = user_tbl.ID
4120 WHERE 1=1
4121 {$query_by_user_sql}
4122 {$query_by_status_sql} ORDER BY
4123 created_at DESC {$query_by_pagination} ");
4124
4125 $withdraw_history = array(
4126 'count' => 0,
4127 'results' => null,
4128 );
4129
4130 if ($count){
4131 $withdraw_history['count'] = $count;
4132 }
4133
4134 if (tutor_utils()->count($results)){
4135 $withdraw_history['results'] = $results;
4136 }
4137 return (object) $withdraw_history;
4138
4139 }
4140
4141 /**
4142 * @param int $instructor_id
4143 *
4144 * Add Instructor role to any user by user iD
4145 */
4146 public function add_instructor_role($instructor_id = 0){
4147 if ( ! $instructor_id){
4148 return;
4149 }
4150 do_action('tutor_before_approved_instructor', $instructor_id);
4151
4152 update_user_meta($instructor_id, '_tutor_instructor_status', 'approved');
4153 update_user_meta($instructor_id, '_tutor_instructor_approved', time());
4154
4155 $instructor = new \WP_User($instructor_id);
4156 $instructor->add_role(tutor()->instructor_role);
4157
4158 do_action('tutor_after_approved_instructor', $instructor_id);
4159 }
4160
4161 /**
4162 * @param int $instructor_id
4163 *
4164 * Remove instructor role by instructor id
4165 */
4166 public function remove_instructor_role($instructor_id = 0){
4167 if ( ! $instructor_id){
4168 return;
4169 }
4170
4171 do_action('tutor_before_blocked_instructor', $instructor_id);
4172 update_user_meta($instructor_id, '_tutor_instructor_status', 'blocked');
4173
4174 $instructor = new \WP_User($instructor_id);
4175 $instructor->remove_role(tutor()->instructor_role);
4176 do_action('tutor_after_blocked_instructor', $instructor_id);
4177 }
4178
4179 /**
4180 * @param string $msg
4181 * @param string $name
4182 *
4183 * Set Flash Message to view in next action / route
4184 */
4185 public function set_flash_msg($msg = '', $name = 'success'){
4186 global $wp_filesystem;
4187 if ( ! $wp_filesystem ) {
4188 require_once( ABSPATH . 'wp-admin/includes/file.php' );
4189 }
4190
4191 $filename = "tutor_flash_msg_{$name}.txt";
4192 $upload_dir = wp_upload_dir();
4193 $dir = trailingslashit($upload_dir['basedir']) . 'tutor/';
4194
4195 WP_Filesystem( false, $upload_dir['basedir'], true );
4196
4197 if( ! $wp_filesystem->is_dir( $dir ) ) {
4198 $wp_filesystem->mkdir( $dir );
4199 }
4200 $wp_filesystem->put_contents( $dir . $filename, $msg );
4201 }
4202
4203 /**
4204 * @param null $name
4205 *
4206 * @return mixed|string|void
4207 *
4208 * Get Flash Message
4209 */
4210 public function get_flash_msg($name = null){
4211 if ( ! $name){
4212 return '';
4213 }
4214
4215 $upload_dir = wp_get_upload_dir();
4216 $upload_dir = trailingslashit($upload_dir['basedir']);
4217 $msg_name = 'tutor_flash_msg_'.$name;
4218
4219 $msg = '';
4220 $flash_msg_file_name = $upload_dir."tutor/{$msg_name}.txt";
4221 if (file_exists($flash_msg_file_name)){
4222 $msg = file_get_contents($flash_msg_file_name);
4223 unlink($flash_msg_file_name);
4224 }
4225
4226 return apply_filters('tutor_get_flash_msg', $msg, $name);
4227 }
4228
4229 /**
4230 * @param int $user_id
4231 *
4232 * @return array|null|object
4233 *
4234 * Get purchase history by customer id
4235 */
4236
4237 public function get_orders_by_user_id($user_id = 0){
4238 global $wpdb;
4239
4240 $user_id = $this->get_user_id();
4241
4242 $query = $wpdb->get_results("SELECT {$wpdb->posts}.* FROM {$wpdb->posts}
4243 INNER JOIN {$wpdb->postmeta} customer ON ID = customer.post_id AND customer.meta_key = '_customer_user'
4244 INNER JOIN {$wpdb->postmeta} tutor_order ON ID = tutor_order.post_id AND tutor_order.meta_key = '_is_tutor_order_for_course'
4245 where post_type = 'shop_order' AND customer.meta_value = {$user_id} ");
4246 return $query;
4247 }
4248
4249 /**
4250 * @param null $status
4251 *
4252 * @return string
4253 *
4254 * Get status contact formatted for order
4255 *
4256 * @since v.1.3.1
4257 */
4258 public function order_status_context($status = null){
4259 $status = str_replace('wc-', '', $status);
4260 $status_name = ucwords(str_replace('-', ' ', $status));
4261
4262 return "<span class='label-order-status label-status-{$status}'>$status_name</span>";
4263 }
4264
4265 }