PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7.2
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7.2
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / curds / class-lp-quiz-curd.php

class-lp-quiz-curd.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.7.2, at inc/curds/class-lp-quiz-curd.php

793 lines 19.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Quiz_CURD.
4 *
5 * @author ThimPress
6 * @package LearnPress/Classes/CURD
7 * @since 3.0.0
8 */
9
10 /**
11 * Prevent loading this file directly
12 */
13 defined( 'ABSPATH' ) || exit();
14
15 if ( ! function_exists( 'LP_Quiz_CURD' ) ) {
16
17 /**
18 * Class LP_Quiz_CURD
19 *
20 * Class to manipulating quiz with database.
21 */
22 class LP_Quiz_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
23
24 /**
25 * LP_Quiz_CURD constructor.
26 */
27 public function __construct() {
28 $this->_error_messages = array(
29 'QUIZ_NOT_EXISTS' => __( 'Quiz does not exist.', 'learnpress' ),
30 );
31 }
32
33 /**
34 * @param LP_Quiz $quiz
35 *
36 * @return LP_Quiz|mixed
37 * @throws Exception
38 */
39 public function load( &$quiz ) {
40 $id = $quiz->get_id();
41 if ( ! $id || learn_press_get_post_type( $id ) !== LP_QUIZ_CPT ) {
42
43 throw new Exception( sprintf( __( 'Invalid quiz with ID "%d".', 'learnpress' ), $id ) );
44 }
45
46 // LP_Helper_CURD::update_meta_cache( $quiz->get_id() );
47
48 $quiz->set_data_via_methods(
49 array(
50 // 'show_result' => get_post_meta( $quiz->get_id(), '_lp_show_result', true ),
51 'passing_grade_type' => get_post_meta( $quiz->get_id(), '_lp_passing_grade_type', true ),
52 'passing_grade' => get_post_meta( $quiz->get_id(), '_lp_passing_grade', true ),
53 // 'show_check_answer' => get_post_meta( $quiz->get_id(), '_lp_show_check_answer', true ),
54 // 'count_check_answer' => get_post_meta( $quiz->get_id(), '_lp_check_answer_count', true ),
55 // 'show_hint' => get_post_meta( $quiz->get_id(), '_lp_show_hint', true ),
56 // 'archive_history' => get_post_meta( $quiz->get_id(), '_lp_archive_history', true ),
57 // 'count_hint' => get_post_meta( $quiz->get_id(), '_lp_hint_count', true ),
58 'pagination' => get_post_meta( $quiz->get_id(), '_lp_pagination', true ),
59 'review_questions' => get_post_meta( $quiz->get_id(), '_lp_review', true ),
60 'show_correct_review' => get_post_meta( $quiz->get_id(), '_lp_show_correct_review', true ),
61 'preview' => get_post_meta( $quiz->get_id(), '_lp_preview', true ),
62 // 'minus_points' => get_post_meta( $quiz->get_id(), '_lp_minus_points', true ),
63 'minus_skip_questions' => get_post_meta( $quiz->get_id(), '_lp_minus_skip_questions', true ),
64
65 'instant_check' => get_post_meta( $quiz->get_id(), '_lp_instant_check', true ),
66 'negative_marking' => get_post_meta( $quiz->get_id(), '_lp_negative_marking', true ),
67 'retake_count' => get_post_meta( $quiz->get_id(), '_lp_retake_count', true ),
68 )
69 );
70
71 return $quiz;
72 }
73
74 /**
75 * Create quiz, with default meta.
76 *
77 * @param $args
78 *
79 * @return int|WP_Error
80 */
81 public function create( &$args ) {
82
83 $args = wp_parse_args(
84 $args,
85 array(
86 'id' => '',
87 'status' => 'publish',
88 'title' => __( 'New Quiz', 'learnpress' ),
89 'content' => '',
90 'author' => learn_press_get_current_user_id(),
91 )
92 );
93
94 $quiz_id = wp_insert_post(
95 array(
96 'ID' => $args['id'],
97 'post_type' => LP_QUIZ_CPT,
98 'post_status' => $args['status'],
99 'post_title' => $args['title'],
100 'post_content' => $args['content'],
101 'post_author' => $args['author'],
102 )
103 );
104
105 if ( $quiz_id ) {
106 // add default meta for new lesson
107 $default_meta = LP_Quiz::get_default_meta();
108
109 if ( is_array( $default_meta ) ) {
110 foreach ( $default_meta as $key => $value ) {
111 update_post_meta( $quiz_id, '_lp_' . $key, $value );
112 }
113 }
114 }
115
116 return $quiz_id;
117 }
118
119 public function update( &$quiz ) {
120 // TODO: Implement update() method.
121 }
122
123 /**
124 * Delete quiz.
125 *
126 * @since 3.0.0
127 *
128 * @param object $quiz_id
129 */
130 public function delete( &$quiz_id ) {
131 // course curd
132 $curd = new LP_Course_CURD();
133
134 // allow hook
135 do_action( 'learn-press/before-delete-quiz', $quiz_id );
136
137 // remove quiz from course items
138 $curd->remove_item( $quiz_id );
139 // remove questions from quiz
140 $this->remove_questions( $quiz_id, '', true );
141 }
142
143 /**
144 * Duplicate quiz.
145 *
146 * @since 3.0.0
147 *
148 * @param $quiz_id_origin
149 * @param array $args
150 *
151 * @return mixed|WP_Error
152 */
153 public function duplicate( &$quiz_id_origin, $args = array() ) {
154 $quiz_id_new = 0;
155
156 try {
157 if ( ! $quiz_id_origin ) {
158 return new WP_Error( 'lp/clone/quiz/id_null', 'Op! Quiz ID not found' );
159 }
160
161 if ( learn_press_get_post_type( $quiz_id_origin ) != LP_QUIZ_CPT ) {
162 return new WP_Error( 'lp/clone/quiz/type_invalid', 'Op! The quiz does not exist' );
163 }
164
165 // Ensure that user can create quiz
166 if ( ! current_user_can( 'edit_posts' ) ) {
167 return new WP_Error( 'lp/clone/quiz/permission', 'Sorry! You have not permission to duplicate this quiz' );
168 }
169
170 // Duplicate quiz
171 $quiz_id_new = learn_press_duplicate_post( $quiz_id_origin, $args, true );
172
173 if ( ! $quiz_id_new || is_wp_error( $quiz_id_new ) ) {
174 return new WP_Error( 'lp/clone/quiz/clone_error', 'Sorry! Failed to duplicate quiz!' );
175 } else {
176 // duplicate questions.
177 $this->duplicate_questions( $quiz_id_origin, $quiz_id_new );
178
179 do_action( 'learn-press/item/after-duplicate', $quiz_id_origin, $quiz_id_new, $args );
180 }
181 } catch ( Throwable $e ) {
182 error_log( $e->getMessage() );
183 }
184
185 return $quiz_id_new;
186 }
187
188 /**
189 * Duplicate questions.
190 *
191 * @param int $quiz_id_origin
192 * @param int $quiz_id_new
193 *
194 * @return void
195 */
196 public function duplicate_questions( int $quiz_id_origin, int $quiz_id_new ) {
197 $question_curd = new LP_Question_CURD();
198
199 try {
200 $quiz_origin = learn_press_get_quiz( $quiz_id_origin );
201 if ( ! $quiz_origin ) {
202 return;
203 }
204
205 $questions_origin = $quiz_origin->get_questions();
206
207 foreach ( $questions_origin as $question_id_origin ) {
208 $can_clone = true;
209 $args = compact( 'question_id_origin', 'quiz_origin', 'quiz_id_new' );
210 $can_clone = apply_filters( 'lp/quiz/question/can-clone', $can_clone, $args );
211
212 if ( ! $can_clone ) {
213 continue;
214 }
215
216 // duplicate question
217 $question_id_new = $question_curd->duplicate( $question_id_origin, array( 'post_status' => 'publish' ) );
218
219 if ( ! $question_id_new || is_wp_error( $question_id_new ) ) {
220 continue;
221 }
222
223 // add duplicate question to new quiz
224 $this->add_question( $quiz_id_new, $question_id_new );
225 }
226 } catch ( Throwable $e ) {
227 error_log( $e->getMessage() );
228 }
229 }
230
231 /**
232 * @param LP_Quiz $quiz
233 *
234 * @depecated 4.1.7
235 */
236 /*protected function _load_questions( &$quiz ) {
237 $id = $quiz->get_id();
238 $questions = LP_Object_Cache::get( 'questions-' . $id, 'learn-press/quizzes' );
239
240 if ( false === $questions || $quiz->get_no_cache() ) {
241 $this->load_questions( $quiz->get_id() );
242 }
243 }*/
244
245 /**
246 * Read question of a quiz from database
247 *
248 * @param int $quiz_id
249 * @param string $context
250 *
251 * @return array|bool
252 */
253 /*public function read_questions( $quiz_id, $context = 'display' ) {
254 $quiz = learn_press_get_quiz( $quiz_id );
255
256 if ( ! $quiz ) {
257 return false;
258 }
259
260 return $quiz->get_question_ids( $context );
261 }*/
262
263 /**
264 * Read all question ids of a quiz.
265 *
266 * @param int $quiz_id
267 * @param string $context
268 *
269 * @return array
270 * @throws Exception
271 */
272 public function read_question_ids( int $quiz_id = 0, string $context = 'display' ) :array {
273 $quiz = learn_press_get_quiz( $quiz_id );
274
275 if ( ! $quiz ) {
276 return array();
277 }
278
279 $lp_question_db = LP_Question_DB::getInstance();
280
281 if ( $context === 'display' ) {
282 $statuses = array( 'publish' );
283 } else {
284 $statuses = array( 'publish', 'draft', 'auto-draft' );
285 }
286
287 $filter = new LP_Question_Filter();
288 $filter->quiz_id = $quiz_id;
289 $filter->statues = $statuses;
290
291 return $lp_question_db->get_list_question_ids_of_quiz( $filter );
292 }
293
294 /**
295 * @depecated 4.1.7
296 */
297 /*public function update_question_ids( $quiz_id ) {
298 wp_cache_delete( 'quiz-' . $quiz_id, 'quiz-questions' );
299
300 $quiz = learn_press_get_quiz( $quiz_id );
301
302 if ( $quiz ) {
303 $question_ids = $quiz->get_question_ids();
304 } else {
305 $question_ids = array();
306 }
307
308 update_post_meta( $quiz_id, '_questions', $question_ids );
309 update_post_meta( $quiz_id, '_question_count', sizeof( $question_ids ) );
310 }*/
311
312 /**
313 * Get quiz ids that contains a question.
314 *
315 * @since 3.1.0
316 *
317 * @param int $question_id
318 *
319 * @return array
320 */
321 public function get_quiz_by_question( $question_id ) {
322 global $wpdb;
323 $query = $wpdb->prepare(
324 "
325 SELECT ID
326 FROM {$wpdb->posts} p
327 INNER JOIN {$wpdb->learnpress_quiz_questions} qq ON qq.quiz_id = p.ID
328 WHERE qq.question_id = %d
329 ",
330 $question_id
331 );
332
333 return $wpdb->get_col( $query );
334 }
335
336 public function load_questions( $quiz_id ) {
337
338 global $wpdb;
339
340 if ( is_array( $quiz_id ) ) {
341 foreach ( $quiz_id as $q_id ) {
342 $this->load_questions( $q_id );
343 }
344
345 return;
346 }
347
348 $query = $wpdb->prepare(
349 "
350 SELECT ID, post_title, post_content, post_status, post_type, post_author, post_date, post_name
351 FROM {$wpdb->posts} p
352 INNER JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
353 WHERE qq.quiz_id = %d
354 AND p.post_status = %s
355 ORDER BY question_order, quiz_question_id ASC
356 ",
357 $quiz_id,
358 'publish'
359 );
360
361 $question_ids = array();
362 $results = $wpdb->get_results( $query );
363
364 if ( $results ) {
365 foreach ( $results as $k => $v ) {
366 settype( $v, 'object' );
367 wp_cache_set( $v->ID, $v, 'posts' );
368
369 $question_ids[] = $v->ID;
370 }
371 }
372
373 LP_Object_Cache::set( 'questions-' . $quiz_id, $question_ids, 'learn-press/quizzes' );
374
375 // LP_Helper_CURD::cache_posts( $question_ids );
376 $question_factory = new LP_Question_CURD();
377 $question_factory->load_answer_options( $question_ids );
378 }
379
380 /**
381 * @param LP_Quiz $quiz
382 * @depecated 4.1.6.4
383 */
384 protected function _update_meta_cache( &$quiz ) {
385 _deprecated_function( __FUNCTION__, '4.1.6.4' );
386 $meta_ids = LP_Object_Cache::get( 'questions-' . $quiz->get_id(), 'learn-press/quizzes' );
387
388 if ( false === $meta_ids ) {
389 $meta_ids = array( $quiz->get_id() );
390 } else {
391 $meta_ids[] = $quiz->get_id();
392 }
393 // LP_Helper_CURD::update_meta_cache( $meta_ids );
394 }
395
396 /**
397 * @depecated 4.1.6.4
398 */
399 protected function _load_question_answer_meta( $meta_ids ) {
400 global $wpdb;
401
402 $format = array_fill( 0, sizeof( $meta_ids ), '%d' );
403 $query = $wpdb->prepare(
404 "
405 SELECT *
406 FROM {$wpdb->learnpress_question_answermeta}
407 WHERE learnpress_question_answer_id IN(" . join( ',', $format ) . ')
408 ',
409 $meta_ids
410 );
411
412 $metas = $wpdb->get_results( $query );
413
414 if ( $metas ) {
415 foreach ( $metas as $meta ) {
416 $key = $meta->meta_key;
417 $option_key = $meta->learnpress_question_answer_id;
418 if ( ! empty( $answer_options[ $option_key ] ) ) {
419 if ( $key == 'checked' ) {
420 $key = 'is_true';
421 }
422 $answer_options[ $option_key ][ $key ] = $meta->meta_value;
423 }
424 }
425 }
426 }
427
428 /**
429 * Sort questions by order.
430 * Check in an array of questions if there is a key 'order'.
431 *
432 * @param $questions
433 *
434 * @return mixed
435 */
436 protected function _maybe_sort_questions( &$questions ) {
437 if ( ! $questions ) {
438 return $questions;
439 }
440
441 $first = reset( $questions );
442
443 if ( empty( $first['order'] ) ) {
444 return $questions;
445 }
446
447 uasort( $questions, array( $this, '_callback_sort_questions' ) );
448
449 return $questions;
450 }
451
452 public function _callback_sort_questions( $a, $b ) {
453 return $a['order'] > $b['order'];
454 }
455
456 /**
457 * Reorder question by indexed number.
458 *
459 * @param LP_Quiz|WP_Post|int $the_quiz
460 * @param mixed $questions
461 *
462 * @return mixed
463 */
464 public function reorder_questions( $the_quiz, $questions = false ) {
465 global $wpdb;
466
467 $the_quiz = learn_press_get_quiz( $the_quiz );
468
469 if ( ! $the_quiz ) {
470 return false;
471 }
472
473 if ( false == $questions ) {
474 $query = $wpdb->prepare(
475 "
476 SELECT quiz_question_id as id
477 FROM {$wpdb->prefix}learnpress_quiz_questions
478 WHERE quiz_id = %d
479 ORDER BY question_order ASC
480 ",
481 $the_quiz->get_id()
482 );
483
484 $rows = $wpdb->get_results( $query );
485
486 if ( $rows ) {
487 $update = array();
488 $ids = wp_list_pluck( $rows, 'id' );
489 $format = array_fill( 0, sizeof( $ids ), '%d' );
490
491 foreach ( $rows as $order => $row ) {
492 $update[] = $wpdb->prepare( 'WHEN quiz_question_id = %d THEN %d', $row->id, $order + 1 );
493 }
494
495 $query = $wpdb->prepare(
496 "
497 UPDATE {$wpdb->prefix}learnpress_quiz_questions
498 SET question_order = CASE
499 " . join( "\n", $update ) . '
500 ELSE question_order END
501 WHERE quiz_question_id IN(' . join( ',', $format ) . ')
502 ',
503 $ids
504 );
505
506 return $wpdb->query( $query );
507 }
508 } else {
509 $query = "
510 UPDATE {$wpdb->learnpress_quiz_questions}
511 SET question_order = CASE
512 ";
513 for ( $order = 0, $n = sizeof( $questions ); $order < $n; $order ++ ) {
514 $query .= $wpdb->prepare( 'WHEN question_id = %d THEN %d', $questions[ $order ], $order + 1 ) . "\n";
515 }
516 $query .= sprintf( 'ELSE question_order END WHERE quiz_id = %d', $the_quiz->get_id() );
517
518 return $wpdb->query( $query );
519 }
520
521 return false;
522 }
523
524
525 /**
526 * Get all questions in a quiz
527 *
528 * @param LP_Quiz $the_quiz
529 *
530 * @return array|mixed
531 */
532 public function get_questions( $the_quiz ) {
533 $the_quiz = learn_press_get_quiz( $the_quiz );
534
535 if ( ! $the_quiz ) {
536 return $this->get_error( 'QUIZ_NOT_EXISTS' );
537 }
538
539 return LP_Object_Cache::get( 'questions-' . $the_quiz->get_id(), 'learn-press/quizzes' );
540 }
541
542 /**
543 * Add existing question into quiz.
544 *
545 * @param LP_Quiz|int $the_quiz
546 * @param $question_id
547 * @param array $args
548 *
549 * @return mixed false on failed
550 */
551 public function add_question( $the_quiz, $question_id, $args = array() ) {
552 $the_quiz = learn_press_get_quiz( $the_quiz );
553
554 if ( ! $the_quiz ) {
555 return $this->get_error( 'QUIZ_NOT_EXISTS' );
556 }
557
558 $question = learn_press_get_question( $question_id );
559
560 if ( ! $question ) {
561 return false;
562 }
563
564 if ( $this->is_exists_question( $the_quiz->get_id(), $question_id ) ) {
565 return false;
566 }
567
568 // list exist quiz question
569 //$list_questions = $this->get_questions( $the_quiz );
570 // add new question and set to cache
571 //$list_questions[ $question_id ] = strval( $question_id );
572 //LP_Object_Cache::set( 'questions-' . $the_quiz->get_id(), $list_questions, 'learn-press/quizzes' );
573
574 global $wpdb;
575
576 $id = $the_quiz->get_id();
577 $args = wp_parse_args( $args, array( 'order' => - 1 ) );
578
579 if ( $args['order'] >= 0 ) {
580 $query = $wpdb->prepare(
581 "
582 UPDATE {$wpdb->prefix}learnpress_quiz_questions
583 SET question_order = question_order + 1
584 WHERE quiz_id = %d AND question_order >= %d
585 ",
586 $id,
587 $args['order']
588 );
589 $wpdb->get_results( $query );
590 } else {
591 $query = $wpdb->prepare(
592 "
593 SELECT max(question_order) + 1 as ordering
594 FROM {$wpdb->prefix}learnpress_quiz_questions
595 WHERE quiz_id = %d
596 ",
597 $id
598 );
599
600 $order = $wpdb->get_var( $query );
601
602 if ( ! $order ) {
603 $order = 1;
604 }
605
606 $args['order'] = $order;
607 }
608
609 $inserted = $wpdb->insert(
610 $wpdb->prefix . 'learnpress_quiz_questions',
611 array(
612 'quiz_id' => $id,
613 'question_id' => $question_id,
614 'question_order' => $args['order'],
615 ),
616 array( '%d', '%d', '%d' )
617 );
618
619 $return = $inserted ? $wpdb->insert_id : $inserted;
620
621 do_action( 'learn-press/quiz-added-question', $inserted, $question_id, $the_quiz->get_id() );
622
623 return $return;
624 }
625
626 /**
627 * Check if a question (or batch of questions) is already added to quiz.
628 *
629 * @param int $the_id
630 * @param int|array $ids
631 *
632 * @return array|bool|null|object
633 */
634 public function is_exists_question( $the_id, $ids ) {
635 global $wpdb;
636
637 settype( $ids, 'array' );
638 $format = array_fill( 0, sizeof( $ids ), '%d' );
639
640 $questions_ids = implode( ', ', $ids );
641
642 $query = $wpdb->prepare(
643 "
644 SELECT quiz_question_id
645 FROM {$wpdb->learnpress_quiz_questions}
646 WHERE question_id IN( " . join( ',', $format ) . ' )
647 AND quiz_id = %d
648 ',
649 $questions_ids,
650 $the_id
651 );
652
653 $results = $wpdb->get_results( $query );
654
655 if ( $results ) {
656 return $results;
657 }
658
659 return false;
660 }
661
662 /**
663 * Update order question in quiz.
664 *
665 * @param $order
666 *
667 * @return false|int
668 */
669 public function sort_questions( $order ) {
670 global $wpdb;
671
672 foreach ( $order as $index => $question_id ) {
673 $update = $wpdb->update(
674 $wpdb->learnpress_quiz_questions,
675 array( 'question_order' => $index + 1 ),
676 array( 'question_id' => $question_id ),
677 array( '%d' ),
678 array( '%d' )
679 );
680
681 if ( $update === false ) {
682 return false;
683 }
684 }
685
686 return true;
687 }
688
689 /**
690 * Remove question from quiz.
691 *
692 * @since 3.0.0
693 *
694 * @param $quiz_id
695 * @param $question_id
696 * @param bool $force | remove all questions from quiz
697 *
698 * @return bool|false|int|WP_Error
699 */
700 public function remove_questions( $quiz_id, $question_id, $force = false ) {
701 $quiz = learn_press_get_quiz( $quiz_id );
702
703 if ( ! $quiz ) {
704 return $this->get_error( 'QUIZ_NOT_EXISTS' );
705 }
706
707 global $wpdb;
708
709 if ( $force ) {
710 // remove all questions from quiz
711 $delete = $wpdb->delete(
712 $wpdb->prefix . 'learnpress_quiz_questions',
713 array( 'quiz_id' => $quiz_id ),
714 array( '%d' )
715 );
716 } else {
717 do_action( 'learn-press/delete-quiz-question', $question_id, $quiz_id );
718
719 // remove question from quiz
720 $delete = $wpdb->delete(
721 $wpdb->prefix . 'learnpress_quiz_questions',
722 array(
723 'quiz_id' => $quiz_id,
724 'question_id' => $question_id,
725 ),
726 array( '%d', '%d' )
727 );
728
729 do_action( 'learn-press/deleted-quiz-question', $question_id, $quiz_id, $delete );
730
731 // reorder questions
732 $this->reorder_questions( $quiz );
733 }
734
735 // increment quiz questions
736 learn_press_reset_auto_increment( 'learnpress_quiz_questions' );
737
738 return $delete;
739 }
740
741 /**
742 * Update order quiz question answers.
743 *
744 * @since 3.0.0
745 *
746 * @param $answers
747 *
748 * @return array
749 */
750 public function sort_question_answers( $answers ) {
751 global $wpdb;
752
753 $orders = array();
754
755 foreach ( $answers as $index => $answer_id ) {
756 $order = $index + 1;
757
758 $orders[ $answer_id ] = $order;
759
760 $wpdb->update(
761 $wpdb->learnpress_question_answers,
762 array( 'order' => $order ),
763 array( 'question_answer_id' => $answer_id )
764 );
765 }
766
767 return $orders;
768 }
769
770 public function add_meta( &$object, $meta ) {
771 // TODO: Implement add_meta() method.
772 }
773
774 public function delete_meta( &$object, $meta ) {
775 // TODO: Implement delete_meta() method.
776 }
777
778 public function read_meta( &$object ) {
779 // TODO: Implement read_meta() method.
780 }
781
782 /**
783 * @param $object
784 * @param $meta
785 *
786 * @return mixed
787 */
788 public function update_meta( &$object, $meta ) {
789 return learn_press_update_user_item_meta( $object->get_user_item_id(), $meta->meta_key, $meta->meta_value );
790 }
791 }
792 }
793