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