/wp-content/plugins/learnpress/inc/quiz/lp-quiz-functions.php

https://gitlab.com/gregtyka/lfmawordpress · PHP · 341 lines · 224 code · 34 blank · 83 comment · 61 complexity · 256e587f016780569fb00c3bb42331a6 MD5 · raw file

  1. <?php
  2. /**
  3. * Common functions to manipulate with the quiz
  4. */
  5. if ( !defined( 'ABSPATH' ) ) {
  6. exit; // Exit if accessed directly
  7. }
  8. /**
  9. * Get all questions of a quiz
  10. *
  11. * @author TuNN
  12. *
  13. * @param int $quiz_id The ID of a quiz to get all questions
  14. * @param boolean $only_ids return an array of questions with IDs only or as post objects
  15. *
  16. * @return array|null
  17. */
  18. function learn_press_get_quiz_questions( $quiz_id = null, $only_ids = true ) {
  19. if ( !$quiz_id ) {
  20. $quiz_id = get_the_ID();
  21. }
  22. return ( $quiz = LP_Quiz::get_quiz( $quiz_id ) ) ? $quiz->get_questions() : false;
  23. }
  24. function learn_press_question_class( $question = null, $args = array() /*, $classes = null, $user_id = null, $context = null*/ ) {
  25. $args = wp_parse_args(
  26. $args,
  27. array(
  28. 'user' => LP()->user,
  29. 'quiz' => LP()->quiz,
  30. 'classes' => ''
  31. )
  32. );
  33. $quiz = $args['quiz'];
  34. $user = $args['user'];
  35. $classes = $args['classes'];
  36. if ( !$question ) {
  37. $question = LP_Question_Factory::get_question( get_the_ID() );
  38. } elseif ( is_numeric( $question ) ) {
  39. $question = LP_Question_Factory::get_question( $question );
  40. }
  41. if ( $question ) {
  42. if ( is_string( $classes ) ) {
  43. $classes = explode( ' ', $classes );
  44. }
  45. settype( $classes, 'array' );
  46. $classes = array_merge( $classes, array( "learn-press-question-wrap", "question-type-{$question->type}", "question-{$question->id}" ) );
  47. $status = $user->get_quiz_status( $quiz->id );
  48. if ( $status == 'completed' ) {
  49. $user_id = learn_press_get_current_user_id();
  50. $user = learn_press_get_user( $user_id );
  51. $answer_data = $user->get_answer_results( $question->id, $quiz->id );
  52. $classes[] = 'question-results';
  53. if ( $user->is_answered_question( $question->id, $quiz->id ) ) {
  54. if ( $answer_data['correct'] ) {
  55. $classes[] = 'correct';
  56. } else {
  57. $classes[] = 'incorrect';
  58. }
  59. } else {
  60. $classes[] = 'skipped';
  61. }
  62. } else if ( $status == 'started' && $question->id == learn_press_get_request( 'question' ) ) {
  63. $classes[] = 'current';
  64. }
  65. $classes = apply_filters( 'learn_press_question_class', $classes, $question, $quiz );
  66. $classes = array_unique( $classes );
  67. $classes = array_filter( $classes );
  68. echo "class=\"" . join( ' ', $classes ) . "\"";
  69. }
  70. }
  71. function learn_press_get_user_quiz_meta( $quiz_user_id, $meta_key, $single = true ) {
  72. return get_metadata( 'learnpress_user_quiz', $quiz_user_id, $meta_key, $single );
  73. }
  74. function learn_press_add_user_quiz_meta( $quiz_user_id, $meta_key, $meta_value, $prev_value = '' ) {
  75. return add_metadata( 'learnpress_user_quiz', $quiz_user_id, $meta_key, $meta_value, $prev_value );
  76. }
  77. function learn_press_update_user_quiz_meta( $quiz_user_id, $meta_key, $meta_value, $prev_value = '' ) {
  78. return update_metadata( 'learnpress_user_quiz', $quiz_user_id, $meta_key, $meta_value, $prev_value );
  79. }
  80. /**
  81. * @param int
  82. * @param int - since 0.9.5
  83. *
  84. * @return bool|int
  85. */
  86. function learn_press_get_current_question( $quiz_id = null, $user_id = 0 ) {
  87. if ( $user_id ) {
  88. $user = learn_press_get_user( $user_id );
  89. } else {
  90. $user = LP()->user;
  91. }
  92. return $user->get_current_question( $quiz_id );
  93. }
  94. /**
  95. * Check to see if user not passed the ID of quiz try to get it from global
  96. * Only works in single quiz page
  97. *
  98. * @param $id
  99. *
  100. * @return mixed
  101. */
  102. function learn_press_get_quiz_id( $id ) {
  103. if ( !$id ) {
  104. global $quiz;
  105. $id = $quiz->id;
  106. }
  107. return $id;
  108. }
  109. /**
  110. * Check if user has completed a quiz or not
  111. *
  112. * @author TuNN
  113. *
  114. * @param int $user_id The ID of user need to check
  115. * @param int $quiz_id The ID of quiz need to check
  116. *
  117. * @return boolean
  118. */
  119. function learn_press_user_has_completed_quiz( $user_id = null, $quiz_id = null ) {
  120. //_deprecated_function( __FUNCTION__, '1.0', 'LP_User() -> has_completed_quiz' );
  121. if ( $user = learn_press_get_user( $user_id ) ) {
  122. return $user->has_completed_quiz( $quiz_id );
  123. }
  124. return false;
  125. }
  126. /**
  127. * get the time remaining of a quiz has started by an user
  128. *
  129. * @param null $user_id
  130. * @param null $quiz_id
  131. *
  132. * @return int
  133. */
  134. function learn_press_get_quiz_time_remaining( $user_id = null, $quiz_id = null ) {
  135. global $quiz;
  136. if ( !$user_id ) $user_id = get_current_user_id();
  137. $quiz_id = $quiz_id ? $quiz_id : ( $quiz ? $quiz->id : 0 );
  138. if ( !$quiz_id ) return 0;
  139. $meta = get_user_meta( $user_id, '_lpr_quiz_start_time', true );
  140. $quiz_duration = get_post_meta( $quiz_id, '_lpr_duration', true );
  141. $time_remaining = $quiz_duration * 60;
  142. $quiz_start_time = !empty( $meta[$quiz_id] ) ? $meta[$quiz_id] : 0;
  143. $quiz_start_time = apply_filters( 'learn_press_user_quiz_start_time', $quiz_start_time, $quiz_id, $user_id );
  144. if ( $quiz_duration && learn_press_user_has_started_quiz( $user_id, $quiz_id ) ) {
  145. $quiz_duration *= 60;
  146. $now = current_time( 'timestamp' );
  147. if ( $now < $quiz_start_time + $quiz_duration ) {
  148. $time_remaining = $quiz_start_time + $quiz_duration - $now;
  149. } else {
  150. $time_remaining = 0;
  151. }
  152. }
  153. return apply_filters( 'learn_press_get_quiz_time_remaining', $time_remaining, $user_id, $quiz_id );
  154. }
  155. /*
  156. * Get question url in a quiz for user
  157. *
  158. * @param int the ID of a quiz
  159. * @param int the ID of question - default is current question of quiz user is doing
  160. * @param int the ID of user - default is current user
  161. *
  162. * @return string
  163. */
  164. function learn_press_get_user_question_url( $quiz_id, $current_question_id = 0, $user_id = 0 ) {
  165. if ( !$current_question_id ) {
  166. $current_question_id = learn_press_get_current_question( $quiz_id, $user_id );
  167. }
  168. $permalink = get_the_permalink( $quiz_id );
  169. if ( $current_question_id && get_post_type( $current_question_id ) == 'lp_question' ) {
  170. $question_name = get_post_field( 'post_name', $current_question_id );
  171. if ( '' != get_option( 'permalink_structure' ) ) {
  172. $permalink .= $question_name;
  173. } else {
  174. $permalink = add_query_arg( 'question', $question_name, $permalink );
  175. }
  176. }
  177. $permalink = trailingslashit( $permalink );
  178. return apply_filters( 'learn_press_quiz_question_url', $permalink, $quiz_id, $current_question_id, $user_id );
  179. }
  180. /**
  181. * Check if user has started a quiz or not
  182. *
  183. * @param int $user_id
  184. * @param int $quiz_id
  185. *
  186. * @return boolean
  187. */
  188. function learn_press_user_has_started_quiz( $user_id = null, $quiz_id = null ) {
  189. $user = $user_id ? learn_press_get_user( $user_id ) : LP()->user;
  190. return $user ? $user->has( 'started-quiz', $quiz_id ) : false;
  191. }
  192. /**
  193. * Get current status of a quiz for user
  194. * Status:
  195. * - null => User does not start quiz
  196. * - Started => User has started quiz
  197. * - Completed => User has finished quiz
  198. *
  199. * @param $quiz_id
  200. * @param bool|false $user_id
  201. *
  202. * @return string
  203. */
  204. function learn_press_get_user_quiz_status( $quiz_id, $user_id = false ) {
  205. $user = $user_id ? learn_press_get_user( $user_id ) : LP()->user;
  206. return $user ? $user->get_quiz_status( $quiz_id ) : '';
  207. }
  208. /**
  209. * Redirect to question if user access to a quiz that user has started
  210. *
  211. * @param string
  212. *
  213. * @return string
  214. */
  215. function learn_press_redirect_to_question( $template ) {
  216. global $post_type;
  217. if ( is_single() && $post_type == LP()->quiz_post_type ) {
  218. $user = learn_press_get_current_user();
  219. $quiz_id = get_the_ID();
  220. $quiz_status = $user->get_quiz_status( $quiz_id );
  221. if ( $quiz_status == 'started' && learn_press_get_quiz_time_remaining( $user->id, $quiz_id ) == 0 && get_post_meta( $quiz_id, '_lpr_duration', true ) ) {
  222. $user->finish_quiz( $quiz_id );
  223. $quiz_status = 'completed';
  224. }
  225. $redirect = null;
  226. if ( learn_press_get_request( 'question' ) && $quiz_status == '' ) {
  227. $redirect = get_the_permalink( $quiz_id );
  228. } elseif ( $quiz_status == 'started' ) {
  229. if ( learn_press_get_request( 'question' ) ) {
  230. } else {
  231. $redirect = learn_press_get_user_question_url( $quiz_id );
  232. }
  233. } elseif ( $quiz_status == 'completed' && learn_press_get_request( 'question' ) ) {
  234. $redirect = get_the_permalink( $quiz_id );
  235. }
  236. if ( $redirect && !learn_press_is_current_url( $redirect ) ) {
  237. wp_redirect( $redirect );
  238. exit();
  239. }
  240. }
  241. return $template;
  242. }
  243. //add_action( 'template_redirect', 'learn_press_redirect_to_question' );
  244. function learn_press_get_quizzes( $user_id = 0, &$args = array() ) {
  245. if ( !$user_id ) {
  246. $user_id = learn_press_get_current_user_id();
  247. }
  248. if ( !$user_id ) {
  249. return;
  250. }
  251. $user = learn_press_get_user( $user_id );
  252. return $user->get_quizzes( $args );
  253. }
  254. function learn_press_output_question_nonce( $question ) {
  255. printf( '<input type="hidden" name="update-question-nonce" value="%s" />', wp_create_nonce( 'current-question-nonce-' . $question->id ) );
  256. }
  257. add_action( 'learn_press_after_question_wrap', 'learn_press_output_question_nonce' );
  258. function learn_press_add_question_type_support( $types, $supports ) {
  259. if ( empty( $GLOBALS['learn_press_question_type_support'] ) ) {
  260. $GLOBALS['learn_press_question_type_support'] = array();
  261. }
  262. $_supports = $GLOBALS['learn_press_question_type_support'];
  263. settype( $types, 'array' );
  264. settype( $supports, 'array' );
  265. $types = array_filter( $types );
  266. $supports = array_filter( $supports );
  267. if ( $types ) foreach ( $types as $type ) {
  268. if ( !$type ) {
  269. continue;
  270. }
  271. if ( empty( $_supports[$type] ) ) {
  272. $_supports[$type] = array();
  273. }
  274. if ( $supports ) foreach ( $supports as $s ) {
  275. $_supports[$type][] = $s;
  276. }
  277. $_supports[$type] = array_filter( $_supports[$type] );
  278. }
  279. $GLOBALS['learn_press_question_type_support'] = $_supports;
  280. }
  281. function learn_press_get_question_type_support( $type = '' ) {
  282. $supports = !empty( $GLOBALS['learn_press_question_type_support'] ) ? $GLOBALS['learn_press_question_type_support'] : array();
  283. return $type && !empty( $supports[$type] ) ? $supports[$type] : $supports;
  284. }
  285. function learn_press_question_type_support( $type, $features ) {
  286. settype( $features, 'array' );
  287. $features = array_filter( $features );
  288. $supports = learn_press_get_question_type_support( $type );
  289. $has_support = true;
  290. if ( $features ) {
  291. foreach ( $features as $feature ) {
  292. $has_support = $has_support && in_array( $feature, $supports );
  293. }
  294. }
  295. return $has_support;
  296. }
  297. function _learn_press_add_question_type_support() {
  298. learn_press_add_question_type_support(
  299. array(
  300. 'multi_choice',
  301. 'single_choice',
  302. 'true_or_false'
  303. ),
  304. 'check-answer'
  305. );
  306. }
  307. add_action( 'plugins_loaded', '_learn_press_add_question_type_support' );