PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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
← All changes | inc/updates/learnpress-upgrade-4.php +1606 -1606 4.3.8 → 4.4.8 View file →
@@ -1,1606 +1,1606 @@
1 -<?php
2 -
3 -/**
4 - * Class LP_Upgrade_4
5 - *
6 - * Helper class for updating database to 4.0.0
7 - *
8 - * @version 1.0.0
9 - * @author tungnx
10 - * @since 4.0.0
11 - */
12 -class LP_Upgrade_4 extends LP_Handle_Upgrade_Steps {
13 - /**
14 - * @var LP_Upgrade_4
15 - */
16 - protected static $instance = null;
17 -
18 - /**
19 - * Get Instance
20 - *
21 - * @return LP_Upgrade_4
22 - */
23 - public static function get_instance(): self {
24 - if ( null === self::$instance ) {
25 - self::$instance = new self();
26 - }
27 -
28 - return self::$instance;
29 - }
30 -
31 - /**
32 - * LP_Upgrade_4 constructor.
33 - *
34 - * @see create_tables
35 - * @see clone_tables
36 - * @see modify_tb_lp_user_items
37 - * @see remove_course_status_cancelled
38 - * @see convert_result_graduation_item
39 - * @see convert_result_items
40 - * @see convert_result_questions
41 - * @see convert_retake_quiz
42 - * @see create_col_extra_value_on_tb_lp_user_itemmeta
43 - * @see convert_meta_value_longtext
44 - * @see modify_tb_lp_user_itemmeta
45 - * @see remove_data_lp_user_itemmeta
46 - * @see modify_tb_lp_quiz_questions
47 - * @see modify_tb_lp_question_answers
48 - * @see update_question_answers
49 - * @see modify_tb_lp_question_answermeta
50 - * @see convert_question_type_fill_in_blank
51 - * @see delete_columns_question_answers
52 - * @see modify_tb_lp_order_items
53 - * @see modify_tb_lp_order_itemmeta
54 - * @see modify_tb_lp_sections
55 - * @see modify_tb_lp_section_items
56 - * @see convert_lp_settings
57 - */
58 - protected function __construct() {
59 - $this->version = '4.0.0';
60 - /**
61 - * Name key not > 50 character
62 - */
63 - $this->group_steps = apply_filters(
64 - 'lp/upgrade/4/steps',
65 - array(
66 - 'learnpress_user_items' => new LP_Group_Step(
67 - 'learnpress_user_items',
68 - '',
69 - array(
70 - 'create_tables' => new LP_Step(
71 - 'create_tables',
72 - 'Create tables',
73 - 'learnpress_user_item_results'
74 - ),
75 - 'clone_tables' => new LP_Step(
76 - 'clone_tables',
77 - 'Backup Tables',
78 - 'learnpress_user_items, learnpress_user_itemmeta, learnpress_question_answers, postmeta, options'
79 - ),
80 - 'modify_tb_lp_user_items' => new LP_Step(
81 - 'modify_tb_lp_user_items',
82 - 'Modify table learnpress_user_items',
83 - 'Modify table learnpress_user_items, move the result of students on table learnpress_uset_itemmeta to learnpress_user_item_results'
84 - ),
85 - 'remove_course_status_cancelled' => new LP_Step(
86 - 'remove_course_status_cancelled',
87 - 'Remove courses has status cancelled',
88 - 'learnpress_user_item_results'
89 - ),
90 - 'convert_result_graduation_item' => new LP_Step(
91 - 'convert_result_graduation_item',
92 - 'Convert Data Graduation items of courses',
93 - ''
94 - ),
95 - 'convert_result_items' => new LP_Step(
96 - 'convert_result_items',
97 - 'Convert Data Result courses, items\' courses',
98 - ''
99 - ),
100 - 'convert_result_questions' => new LP_Step(
101 - 'convert_result_questions',
102 - 'Convert Data Result questions',
103 - ''
104 - ),
105 - 'convert_retake_quiz' => new LP_Step(
106 - 'convert_retake_quiz',
107 - 'Convert retake quizzes',
108 - ''
109 - ),
110 - 'create_col_extra_value_on_tb_lp_user_itemmeta' => new LP_Step(
111 - 'create_col_extra_value_on_tb_lp_user_itemmeta',
112 - 'Create column extra_value',
113 - ''
114 - ),
115 - 'convert_meta_value_longtext' => new LP_Step(
116 - 'convert_meta_value_longtext',
117 - 'Copy meta_value longtext to extra_value',
118 - ''
119 - ),
120 - 'remove_data_lp_user_itemmeta' => new LP_Step(
121 - 'remove_data_lp_user_itemmeta',
122 - 'Remove data results of lp_user_itemmeta',
123 - ''
124 - ),
125 - 'modify_tb_lp_user_itemmeta' => new LP_Step(
126 - 'modify_tb_lp_user_itemmeta',
127 - 'Modify table learnpress_user_itemmeta',
128 - 'Change type columns: meta_key, meta_value. Create Index: user_item_id, meta_key, meta_value'
129 - ),
130 - 'modify_tb_lp_quiz_questions' => new LP_Step(
131 - 'modify_tb_lp_quiz_questions',
132 - 'Modify table learnpress_quiz_questions',
133 - ''
134 - ),
135 - 'modify_tb_lp_question_answers' => new LP_Step(
136 - 'modify_tb_lp_question_answers',
137 - 'Modify table learnpress_question_answers',
138 - ''
139 - ),
140 - 'update_question_answers' => new LP_Step(
141 - 'update_question_answers',
142 - 'Update data table learnpress_question_answers',
143 - ''
144 - ),
145 - 'modify_tb_lp_question_answermeta' => new LP_Step(
146 - 'modify_tb_lp_question_answermeta',
147 - 'Modify table learnpress_question_answermeta',
148 - ''
149 - ),
150 - 'convert_question_type_fill_in_blank' => new LP_Step(
151 - 'convert_question_type_fill_in_blank',
152 - 'Update data question type "Fill in blank"',
153 - ''
154 - ),
155 - 'delete_columns_question_answers' => new LP_Step(
156 - 'delete_columns_question_answers',
157 - 'Delete data table learnpress_question_answers',
158 - ''
159 - ),
160 - 'modify_tb_lp_order_items' => new LP_Step(
161 - 'modify_tb_lp_order_items',
162 - 'Modify data table learnpress_order_items',
163 - ''
164 - ),
165 - 'modify_tb_lp_order_itemmeta' => new LP_Step(
166 - 'modify_tb_lp_order_itemmeta',
167 - 'Modify data table learnpress_order_itemmeta',
168 - ''
169 - ),
170 - 'modify_tb_lp_sections' => new LP_Step(
171 - 'modify_tb_lp_sections',
172 - 'Modify table learnpress_sections',
173 - 'Create Index'
174 - ),
175 - 'modify_tb_lp_section_items' => new LP_Step(
176 - 'modify_tb_lp_section_items',
177 - 'Modify table learnpress_section_items',
178 - 'Create Index'
179 - ),
180 - 'convert_lp_settings' => new LP_Step(
181 - 'convert_lp_settings',
182 - 'Convert data settings learnpress',
183 - 'Courses thumbnail dimensions, Profile thumbnail dimensions, Profile rename dashboard to overview, Block course by duration, Block course when finished, Assessment course by quizzes - Evaluate, '
184 - ),
185 - )
186 - ),
187 - )
188 - );
189 - }
190 -
191 - /**
192 - * Step Create Tables
193 - *
194 - * @param array $data
195 - *
196 - * @return LP_Step
197 - */
198 - protected function create_tables( array $data ): LP_Step {
199 - $response = new LP_Step( __FUNCTION__, 'Create table' );
200 - $key_create_table = 'create_table';
201 - $create_table = '';
202 -
203 - try {
204 - /**
205 - * All tables need create.
206 - * key: name table
207 - * value: function handle create this table
208 - *
209 - * @see LP_Database::create_tb_lp_user_item_results
210 - * @see LP_Database::create_tb_lp_upgrade_db()
211 - */
212 - $lp_db = LP_Database::getInstance();
213 -
214 - $create_tables = array(
215 - 'tb_lp_user_item_results',
216 - 'tb_lp_upgrade_db',
217 - );
218 - $total_tables_need_create = count( $create_tables );
219 -
220 - // Check table need create.
221 - if ( empty( $data ) ) {
222 - $create_table = $create_tables[0];
223 - } elseif ( ! empty( $data[ $key_create_table ] )
224 - && in_array( $data[ $key_create_table ], $create_tables ) ) {
225 - $create_table = $data[ $key_create_table ];
226 - }
227 -
228 - if ( empty( $create_table ) ) {
229 - // Finish this step.
230 - $this->finish_step( $response, __FUNCTION__ . ' finished' );
231 - } else {
232 - // Create table.
233 - $name_method = 'create_' . $create_table;
234 - if ( ! method_exists( $lp_db, $name_method ) ) {
235 - throw new Exception( 'Not found method ' . $name_method . ' of Class ' . get_class( $lp_db ) );
236 - }
237 - $lp_db->{$name_method}();
238 -
239 - // Set param to clone table next.
240 - $index = array_search( $create_table, $create_tables );
241 - $percent = LP_Helper::progress_percent( $index, 1, $total_tables_need_create );
242 - ++ $index;
243 -
244 - if ( ! empty( $create_tables[ $index ] ) ) {
245 - $response->status = 'success';
246 - $response->percent = $percent;
247 - $response->data->create_table = $create_tables[ $index ];
248 - $response->message = 'Table "' . $create_table . '" created';
249 - } else {
250 - // Finish this step.
251 - $this->finish_step( $response, __FUNCTION__ . ' finished' );
252 - }
253 - }
254 - } catch ( Exception $e ) {
255 - $response->message = $this->error_step( $response->name, $e->getMessage() );
256 - }
257 -
258 - return $response;
259 - }
260 -
261 - /**
262 - * Step Clone Tables
263 - *
264 - * @param array $data | keys: clone_table .
265 - *
266 - * @return LP_Step
267 - */
268 - protected function clone_tables( array $data ): LP_Step {
269 - $response = new LP_Step( __FUNCTION__, '' );
270 - $key_clone_table = 'clone_table';
271 - $clone_table = '';
272 -
273 - try {
274 - // All tables need clone.
275 - $lp_db = LP_Database::getInstance();
276 - $lp_db->wpdb->query( "SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'" );
277 -
278 - $clone_tables = array(
279 - $lp_db->tb_lp_user_items,
280 - $lp_db->tb_lp_user_itemmeta,
281 - $lp_db->tb_lp_question_answers,
282 - $lp_db->tb_postmeta,
283 - $lp_db->tb_options,
284 - );
285 -
286 - $total_tables_need_clone = count( $clone_tables );
287 -
288 - // Check table need clone.
289 - if ( empty( $data ) ) {
290 - $clone_table = $clone_tables[0];
291 - } elseif ( ! empty( $data[ $key_clone_table ] )
292 - && in_array( $data[ $key_clone_table ], $clone_tables, true ) ) {
293 - $clone_table = $data[ $key_clone_table ];
294 - }
295 -
296 - if ( empty( $clone_table ) ) {
297 - // Finish this step.
298 - $this->finish_step( $response, __FUNCTION__ . ' finished' );
299 - } else {
300 - // Clone table.
301 - $lp_db->clone_table( $clone_table );
302 -
303 - // Set param to clone table next.
304 - $index = array_search( $clone_table, $clone_tables );
305 - $percent = LP_Helper::progress_percent( $index, 1, $total_tables_need_clone );
306 - ++ $index;
307 -
308 - if ( ! empty( $clone_tables[ $index ] ) ) {
309 - $response->status = 'success';
310 - $response->percent = $percent;
311 - $response->data->clone_table = $clone_tables[ $index ];
312 - $response->message = 'Table "' . $clone_table . '" cloned';
313 - } else {
314 - // Finish this step.
315 - $this->finish_step( $response, __FUNCTION__ . ' finished' );
316 - }
317 - }
318 - } catch ( Exception $e ) {
319 - $response->message = $this->error_step( $response->name, $e->getMessage() );
320 - }
321 -
322 - return $response;
323 - }
324 -
325 - /**
326 - * Modify table learnpress_user_items .
327 - * - Add column graduation varchar(20)
328 - * - Add column access_level varchar(20)
329 - * - Copy value start_time_gmt to start_time if value != '0000-00-00 00:00:00' | And delete column start_time_gmt
330 - * - Copy value end_time_gmt to end_time if value != '0000-00-00 00:00:00' | And delete column end_time_gmt
331 - * - Create indexs
332 - *
333 - * @return LP_Step
334 - */
335 - protected function modify_tb_lp_user_items() : LP_Step {
336 - $response = new LP_Step( __FUNCTION__, '' );
337 - $lp_db = LP_Database::getInstance();
338 -
339 - try {
340 - /**
341 - * Check column graduation, if not exist will be create
342 - */
343 - $lp_db->add_col_table( $lp_db->tb_lp_user_items, 'graduation', 'varchar(20)', 'status' );
344 -
345 - /**
346 - * Check column access_level, if not exist will be create
347 - */
348 - $lp_db->add_col_table( $lp_db->tb_lp_user_items, 'access_level', 'varchar(20)', 'graduation' );
349 -
350 - // Change type columns: start_time, end_time.
351 - $lp_db->wpdb->query(
352 - "
353 - ALTER TABLE $lp_db->tb_lp_user_items
354 - MODIFY start_time datetime default null,
355 - MODIFY end_time datetime default null;
356 - "
357 - );
358 - $lp_db->check_execute_has_error();
359 -
360 - /**
361 - * Check column start_time_gmt exists.
362 - *
363 - * Copy value start_time_gmt to start_time
364 - *
365 - * Drop column start_time_gmt
366 - */
367 - $check_col_start_time_gmt = $lp_db->check_col_table( $lp_db->tb_lp_user_items, 'start_time_gmt' );
368 - if ( $check_col_start_time_gmt ) {
369 - $lp_db->wpdb->query(
370 - "
371 - UPDATE $lp_db->tb_lp_user_items SET start_time = start_time_gmt
372 - WHERE user_item_id > 0
373 - AND start_time_gmt != '0000-00-00 00:00:00'
374 - "
375 - );
376 - $lp_db->check_execute_has_error();
377 - $lp_db->wpdb->query(
378 - "
379 - UPDATE $lp_db->tb_lp_user_items SET start_time = null
380 - WHERE start_time = '0000-00-00 00:00:00'
381 - "
382 - );
383 - $lp_db->check_execute_has_error();
384 - $lp_db->drop_col_table( $lp_db->tb_lp_user_items, 'start_time_gmt' );
385 - }
386 -
387 - /**
388 - * Check column end_time_gmt exists.
389 - *
390 - * Copy value end_time_gmt to end_time
391 - *
392 - * Drop column end_time_gmt
393 - */
394 - $check_col_end_time_gmt = $lp_db->check_col_table( $lp_db->tb_lp_user_items, 'end_time_gmt' );
395 - if ( $check_col_end_time_gmt ) {
396 - $lp_db->wpdb->query(
397 - "
398 - UPDATE $lp_db->tb_lp_user_items SET end_time = end_time_gmt
399 - WHERE user_item_id > 0
400 - AND end_time_gmt != '0000-00-00 00:00:00'
401 - "
402 - );
403 - $lp_db->check_execute_has_error();
404 - $lp_db->wpdb->query(
405 - "
406 - UPDATE $lp_db->tb_lp_user_items SET end_time = null
407 - WHERE end_time_gmt = '0000-00-00 00:00:00'
408 - "
409 - );
410 - $lp_db->check_execute_has_error();
411 - $lp_db->drop_col_table( $lp_db->tb_lp_user_items, 'end_time_gmt' );
412 - }
413 -
414 - // Remove rows have status = 'canceled';
415 -
416 - // Create index.
417 - $indexs = array( 'user_id', 'item_id', 'item_type', 'status', 'ref_type', 'ref_id', 'parent_id' );
418 - $lp_db->add_indexs_table( $lp_db->tb_lp_user_items, $indexs );
419 - } catch ( Exception $e ) {
420 - $response->message = $this->error_step( $response->name, $e->getMessage() );
421 - return $response;
422 - }
423 -
424 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
425 - }
426 -
427 - /**
428 - * Remove courses has status "cancelled" and items child, itemmeta
429 - *
430 - * @return LP_Step
431 - */
432 - protected function remove_course_status_cancelled() : LP_Step {
433 - $response = new LP_Step( __FUNCTION__, '' );
434 - $lp_db = LP_Database::getInstance();
435 -
436 - try {
437 - $user_course_ids = $lp_db->wpdb->get_col(
438 - $lp_db->wpdb->prepare(
439 - "
440 - SELECT user_item_id FROM $lp_db->tb_lp_user_items
441 - WHERE item_type = %s
442 - AND status = %s
443 - ",
444 - LP_COURSE_CPT,
445 - 'cancelled'
446 - )
447 - );
448 -
449 - if ( empty( $user_course_ids ) ) {
450 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
451 - }
452 -
453 - $user_course_ids_str = implode( ',', $user_course_ids );
454 -
455 - $user_item_ids = $lp_db->wpdb->get_col(
456 - "
457 - SELECT user_item_id FROM $lp_db->tb_lp_user_items
458 - WHERE parent_id IN (" . $user_course_ids_str . ')
459 - '
460 - );
461 -
462 - $user_item_ids_concat = array_merge( $user_course_ids, $user_item_ids );
463 - $user_item_ids_concat_str = implode( ',', $user_item_ids_concat );
464 -
465 - // Delete on tb lp_user_items
466 - $lp_db->wpdb->query(
467 - "
468 - DELETE FROM $lp_db->tb_lp_user_items
469 - WHERE user_item_id IN (" . $user_item_ids_concat_str . ')
470 - '
471 - );
472 - $lp_db->check_execute_has_error();
473 -
474 - // Delete on tb lp_user_itemmeta
475 - $lp_db->wpdb->query(
476 - "
477 - DELETE FROM $lp_db->tb_lp_user_itemmeta
478 - WHERE learnpress_user_item_id IN (" . $user_course_ids_str . ')
479 - '
480 - );
481 - $lp_db->check_execute_has_error();
482 - } catch ( Exception $e ) {
483 - $response->message = $this->error_step( $response->name, $e->getMessage() );
484 - return $response;
485 - }
486 -
487 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
488 - }
489 -
490 - /**
491 - * Convert value of meta_key "grade" table learnpress_user_itemmeta LP3 to column graduation LP4 table learnpress_user_item_results
492 - *
493 - * @param array $data .
494 - *
495 - * @return LP_Step
496 - */
497 - protected function convert_result_graduation_item( array $data ): LP_Step {
498 - $response = new LP_Step( __FUNCTION__, '' );
499 - $lp_db = LP_Database::getInstance();
500 - $page = 0;
501 - $offset = 0;
502 - $limit = 100;
503 - $total_row = 0;
504 - $suffix_table_bk = '_bk';
505 -
506 - try {
507 - if ( empty( $data ) ) {
508 - // Check total rows.
509 - $query = $lp_db->wpdb->prepare(
510 - "
511 - SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta{$suffix_table_bk}
512 - WHERE meta_key = %s
513 - ",
514 - 'grade'
515 - );
516 -
517 - $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
518 - } else {
519 - $page = $data['p'];
520 - $offset = $limit * $page;
521 - $total_row = $data['total_rows'];
522 - }
523 -
524 - // Select .
525 - $query = $lp_db->wpdb->prepare(
526 - "
527 - SELECT learnpress_user_item_id AS user_item_id, meta_value AS grade
528 - FROM $lp_db->tb_lp_user_itemmeta{$suffix_table_bk}
529 - WHERE meta_key = %s
530 - LIMIT %d, %d
531 - ",
532 - 'grade',
533 - $offset,
534 - $limit
535 - );
536 - $user_item_grades = $lp_db->wpdb->get_results( $query );
537 -
538 - /**
539 - * Copy value of meta_key "grade" table learnpress_user_itemmeta LP3
540 - * to column "graduation" LP4 table learnpress_user_items
541 - */
542 - foreach ( $user_item_grades as $user_item_grade ) {
543 - $query = $lp_db->wpdb->prepare(
544 - "
545 - UPDATE $lp_db->tb_lp_user_items
546 - SET graduation = %s
547 - WHERE user_item_id = %d;
548 - ",
549 - $user_item_grade->grade,
550 - $user_item_grade->user_item_id
551 - );
552 -
553 - $lp_db->wpdb->query( $query );
554 - $lp_db->check_execute_has_error();
555 - }
556 -
557 - $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
558 - if ( empty( $user_item_grades ) || 100 == $percent ) {
559 - // Update graduation for case grade wrong (null or lesson completed but still 'in-progress').
560 - $lp_db->wpdb->query(
561 - "
562 - UPDATE $lp_db->tb_lp_user_items
563 - SET graduation = 'passed'
564 - WHERE status = 'completed'
565 - AND item_type = 'lp_lesson'
566 - "
567 - );
568 - // Update graduation for case status empty and grade null
569 - $lp_db->wpdb->query(
570 - "
571 - UPDATE $lp_db->tb_lp_user_items
572 - SET graduation = 'in-progress'
573 - WHERE (status = '' OR status = 'enrolled')
574 - "
575 - );
576 -
577 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
578 - }
579 -
580 - $response->status = 'success';
581 - $response->message = 'Insert success';
582 - $response->percent = $percent;
583 - $response->data->p = ++ $page;
584 - $response->data->total_rows = $total_row;
585 - } catch ( Exception $e ) {
586 - $response->message = $this->error_step( $response->name, $e->getMessage() );
587 - }
588 -
589 - return $response;
590 - }
591 -
592 - /**
593 - * Convert result items (lesson).
594 - *
595 - * @param array $data
596 - *
597 - * @return LP_Step
598 - */
599 - protected function convert_result_items( array $data ): LP_Step {
600 - $response = new LP_Step( __FUNCTION__, '' );
601 - $lp_db = LP_Database::getInstance();
602 - $page = 0;
603 - $offset = 0;
604 - $limit = 100;
605 - $total_row = 0;
606 -
607 - try {
608 - if ( empty( $data ) ) {
609 - // Check total rows.
610 - $query = "
611 - SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
612 - WHERE meta_key LIKE '%course_results_evaluate%'
613 - ";
614 -
615 - $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
616 - } else {
617 - $page = $data['p'];
618 - $offset = $limit * $page;
619 - $total_row = $data['total_rows'];
620 - }
621 -
622 - // Convert rows.
623 - $query = $lp_db->wpdb->prepare(
624 - "
625 - SELECT learnpress_user_item_id AS user_item_id, meta_value AS result
626 - FROM $lp_db->tb_lp_user_itemmeta
627 - WHERE meta_key LIKE '%course_results_evaluate%'
628 - LIMIT %d offset %d
629 - ",
630 - $limit,
631 - $offset
632 - );
633 -
634 - $result_lessons = $lp_db->wpdb->get_results( $query );
635 - if ( 0 === count( $result_lessons ) ) {
636 - return $this->finish_step( $response, 'Convert result question success' );
637 - }
638 -
639 - foreach ( $result_lessons as $result_lesson_obj ) {
640 - $result_lesson = maybe_unserialize( ( $result_lesson_obj->result ) );
641 - if ( ! $result_lesson ) {
642 - continue;
643 - }
644 -
645 - $result_json = json_encode( $result_lesson );
646 -
647 - // Check exists user_item_id value on table learnpress_user_item_results.
648 - $check = $lp_db->wpdb->get_var(
649 - $lp_db->wpdb->prepare(
650 - "
651 - SELECT user_item_id FROM $lp_db->tb_lp_user_item_results
652 - WHERE user_item_id = %d
653 - ",
654 - $result_lesson_obj->user_item_id
655 - )
656 - );
657 -
658 - if ( empty( $check ) ) {
659 - $lp_db->wpdb->insert(
660 - $lp_db->tb_lp_user_item_results,
661 - array(
662 - 'result' => $result_json,
663 - 'user_item_id' => $result_lesson_obj->user_item_id,
664 - )
665 - );
666 - $lp_db->check_execute_has_error();
667 - }
668 - }
669 -
670 - $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
671 -
672 - $response->status = 'success';
673 - $response->message = 'Insert lesson result success';
674 - $response->percent = $percent;
675 - $response->data->p = ++ $page;
676 - $response->data->total_rows = $total_row;
677 - } catch ( Throwable $e ) {
678 - $response->message = $this->error_step( $response->name, $e->getMessage() );
679 - }
680 -
681 - return $response;
682 - }
683 -
684 - /**
685 - * Convert value of meta_key "_question_answers" table learnpress_user_itemmeta LP3 to column result LP4 table learnpress_user_item_results
686 - *
687 - * @param array $data .
688 - *
689 - * @return LP_Step
690 - */
691 - protected function convert_result_questions( array $data ): LP_Step {
692 - $response = new LP_Step( __FUNCTION__, '' );
693 - $lp_db = LP_Database::getInstance();
694 - $page = 0;
695 - $offset = 0;
696 - $limit = 100;
697 - $total_row = 0;
698 -
699 - try {
700 - if ( empty( $data ) ) {
701 - // Check total rows.
702 - $query = $lp_db->wpdb->prepare(
703 - "
704 - SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
705 - WHERE meta_key = '_question_answers'
706 - ",
707 - 1
708 - );
709 -
710 - $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
711 - } else {
712 - $page = $data['p'];
713 - $offset = $limit * $page;
714 - $total_row = $data['total_rows'];
715 - }
716 -
717 - // Convert rows.
718 - $query = $lp_db->wpdb->prepare(
719 - "
720 - SELECT learnpress_user_item_id AS user_item_id, meta_value AS answered
721 - FROM $lp_db->tb_lp_user_itemmeta
722 - WHERE meta_key = '_question_answers'
723 - LIMIT %d offset %d
724 - ",
725 - $limit,
726 - $offset
727 - );
728 - $quizs_questions_answered = $lp_db->wpdb->get_results( $query );
729 -
730 - if ( 0 === count( $quizs_questions_answered ) ) {
731 - return $this->finish_step( $response, 'Convert result question success' );
732 - }
733 -
734 - foreach ( $quizs_questions_answered as $quiz_question_answered ) {
735 - $query_quiz_result = $lp_db->wpdb->get_var(
736 - $lp_db->wpdb->prepare(
737 - "
738 - SELECT meta_value AS quiz_result FROM $lp_db->tb_lp_user_itemmeta
739 - WHERE learnpress_user_item_id = %d
740 - AND meta_key = %s
741 - ",
742 - $quiz_question_answered->user_item_id,
743 - 'results'
744 - )
745 - );
746 -
747 - $quiz_result = maybe_unserialize( ( $query_quiz_result ) );
748 - $questions_answered = maybe_unserialize( $quiz_question_answered->answered );
749 -
750 - if ( ! $quiz_result || ! $questions_answered ) {
751 - continue;
752 - }
753 -
754 - foreach ( $questions_answered as $question_id => $question_answered ) {
755 - if ( isset( $quiz_result['questions'][ $question_id ] ) ) {
756 - $quiz_result['questions'][ $question_id ]['answered'] = $question_answered;
757 - }
758 - }
759 -
760 - $result_json = json_encode( $quiz_result );
761 -
762 - // Check exists user_item_id value on table learnpress_user_item_results.
763 - $check = $lp_db->wpdb->get_var(
764 - $lp_db->wpdb->prepare(
765 - "
766 - SELECT user_item_id FROM $lp_db->tb_lp_user_item_results
767 - WHERE user_item_id = %d
768 - ",
769 - $quiz_question_answered->user_item_id
770 - )
771 - );
772 -
773 - if ( empty( $check ) ) {
774 - $lp_db->wpdb->insert(
775 - $lp_db->tb_lp_user_item_results,
776 - array(
777 - 'result' => $result_json,
778 - 'user_item_id' => $quiz_question_answered->user_item_id,
779 - )
780 - );
781 - $lp_db->check_execute_has_error();
782 - } else {
783 - }
784 - }
785 -
786 - $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
787 -
788 - $response->status = 'success';
789 - $response->message = 'Insert success';
790 - $response->percent = $percent;
791 - $response->data->p = ++ $page;
792 - $response->data->total_rows = $total_row;
793 - } catch ( Exception $e ) {
794 - $response->message = $this->error_step( $response->name, $e->getMessage() );
795 - }
796 -
797 - return $response;
798 - }
799 -
800 - /**
801 - * Convert retake quiz.
802 - *
803 - * @param array $data .
804 - *
805 - * @return LP_Step
806 - */
807 - protected function convert_retake_quiz( array $data ): LP_Step {
808 - $response = new LP_Step( __FUNCTION__, '' );
809 - $lp_db = LP_Database::getInstance();
810 - $page = 0;
811 - $offset = 0;
812 - $limit = 100;
813 - $total_row = 0;
814 -
815 - try {
816 - if ( empty( $data ) ) {
817 - // Check total rows.
818 - $query = $lp_db->wpdb->prepare(
819 - "
820 - SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
821 - WHERE meta_key = '_retaken_items'
822 - ",
823 - 1
824 - );
825 -
826 - $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
827 - } else {
828 - $page = $data['p'];
829 - $offset = $limit * $page;
830 - $total_row = $data['total_rows'];
831 - }
832 -
833 - // Convert rows.
834 - $query = $lp_db->wpdb->prepare(
835 - "
836 - SELECT learnpress_user_item_id AS user_item_id, meta_value AS quizzes_retaken
837 - FROM $lp_db->tb_lp_user_itemmeta
838 - WHERE meta_key = '_retaken_items'
839 - LIMIT %d offset %d
840 - ",
841 - $limit,
842 - $offset
843 - );
844 - $courses_quizzes_retaken = $lp_db->wpdb->get_results( $query );
845 -
846 - if ( 0 === count( $courses_quizzes_retaken ) ) {
847 - return $this->finish_step( $response, 'Convert result question success' );
848 - }
849 -
850 - foreach ( $courses_quizzes_retaken as $quizzes_retaken ) {
851 - $user_item_id = $quizzes_retaken->user_item_id;
852 - $retaken = maybe_unserialize( $quizzes_retaken->quizzes_retaken );
853 -
854 - if ( is_array( $retaken ) ) {
855 - foreach ( $retaken as $quiz_id => $v ) {
856 - $quiz_user_item_id = $lp_db->wpdb->get_var(
857 - $lp_db->wpdb->prepare(
858 - "
859 - SELECT user_item_id
860 - FROM $lp_db->tb_lp_user_items
861 - WHERE parent_id = %d
862 - AND item_id = %d
863 - ",
864 - $user_item_id,
865 - $quiz_id
866 - )
867 - );
868 -
869 - if ( $quiz_user_item_id ) {
870 - $lp_db->wpdb->query(
871 - "
872 - INSERT INTO $lp_db->tb_lp_user_itemmeta
873 - (learnpress_user_item_id, meta_key, meta_value)
874 - VALUES ($quiz_user_item_id, '_lp_retake_count', $v)
875 - "
876 - );
877 - $lp_db->check_execute_has_error();
878 - }
879 - }
880 - }
881 - }
882 -
883 - $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
884 -
885 - $response->status = 'success';
886 - $response->message = 'Convert success ';
887 - $response->percent = $percent;
888 - $response->data->p = ++ $page;
889 - $response->data->total_rows = $total_row;
890 - } catch ( Exception $e ) {
891 - $response->message = $this->error_step( $response->name, $e->getMessage() );
892 - }
893 -
894 - return $response;
895 - }
896 -
897 - /**
898 - * Create column extra_value for table learnpress_user_itemmeta.
899 - *
900 - * @return LP_Step
901 - */
902 - protected function create_col_extra_value_on_tb_lp_user_itemmeta(): LP_Step {
903 - $response = new LP_Step( __FUNCTION__, '' );
904 - $lp_db = LP_Database::getInstance();
905 -
906 - try {
907 - $lp_db->add_col_table( $lp_db->tb_lp_user_itemmeta, 'extra_value', 'longtext', 'meta_value' );
908 - } catch ( Exception $e ) {
909 - $response->message = $this->error_step( $response->name, $e->getMessage() );
910 - return $response;
911 - }
912 -
913 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
914 - }
915 -
916 - /**
917 - * Copy meta_value longtext to extra_value.
918 - *
919 - * @return LP_Step
920 - */
921 - protected function convert_meta_value_longtext(): LP_Step {
922 - $response = new LP_Step( __FUNCTION__, '' );
923 - $lp_db = LP_Database::getInstance();
924 -
925 - try {
926 - // Copy meta_value to extra_value.
927 - $lp_db->wpdb->query(
928 - "
929 - UPDATE $lp_db->tb_lp_user_itemmeta SET extra_value = meta_value
930 - WHERE meta_key = '_lp_assignment_answer_note'
931 - OR meta_key = '_lp_assignment_answer_upload'
932 - "
933 - );
934 - $lp_db->check_execute_has_error();
935 -
936 - // Empty meta_value.
937 - $lp_db->wpdb->query(
938 - "
939 - UPDATE $lp_db->tb_lp_user_itemmeta SET meta_value = ''
940 - WHERE meta_key = '_lp_assignment_answer_note'
941 - OR meta_key = '_lp_assignment_answer_upload'
942 - "
943 - );
944 - $lp_db->check_execute_has_error();
945 - } catch ( Exception $e ) {
946 - $response->message = $this->error_step( $response->name, $e->getMessage() );
947 - return $response;
948 - }
949 -
950 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
951 - }
952 -
953 - /**
954 - * Modify table learnpress_user_itemmeta .
955 - * Must run after Step "convert_result_questions"
956 - * Because change name column name 'learnpress_user_item_id' to 'user_item_id' and meta_key change type from 'text' to varchar(255)
957 - *
958 - * @return LP_Step
959 - */
960 - protected function modify_tb_lp_user_itemmeta(): LP_Step {
961 - $response = new LP_Step( __FUNCTION__, '' );
962 - $lp_db = LP_Database::getInstance();
963 -
964 - try {
965 - $lp_db->wpdb->query(
966 - "
967 - ALTER TABLE {$lp_db->tb_lp_user_itemmeta}
968 - CHANGE COLUMN `meta_key` `meta_key` VARCHAR(45) NOT NULL DEFAULT '',
969 - CHANGE COLUMN `meta_value` `meta_value` VARCHAR(45) NOT NULL DEFAULT ''
970 - "
971 - );
972 - $lp_db->check_execute_has_error();
973 -
974 - // Create index.
975 - $indexs = array( 'learnpress_user_item_id', 'meta_key', 'meta_value' );
976 - $lp_db->add_indexs_table( $lp_db->tb_lp_user_itemmeta, $indexs );
977 - } catch ( Exception $e ) {
978 - $response->message = $this->error_step( $response->name, $e->getMessage() );
979 - return $response;
980 - }
981 -
982 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
983 - }
984 -
985 - /**
986 - * Remove data on table learnpress_user_itemmeta
987 - */
988 - protected function remove_data_lp_user_itemmeta() {
989 - $response = new LP_Step( __FUNCTION__, '' );
990 - $lp_db = LP_Database::getInstance();
991 -
992 - try {
993 - /**
994 - * 1. Remove results course.
995 - * 2. Remove results item's course.
996 - * 3. Remove _question_answers.
997 - * 4. Remove grade.
998 - * 5. Remove _last_status.
999 - * 6. Remove _current_status.
1000 - * 7. Remove finishing_type.
1001 - * 8. Remove _retaken_items.
1002 - */
1003 - $lp_db->wpdb->query(
1004 - "
1005 - DELETE FROM {$lp_db->tb_lp_user_itemmeta}
1006 - WHERE meta_key LIKE 'course_results_evaluate_%'
1007 - OR meta_key = '_question_answers'
1008 - OR meta_key = 'results'
1009 - OR meta_key = 'grade'
1010 - OR meta_key = '_last_status'
1011 - OR meta_key = '_current_status'
1012 - OR meta_key = 'finishing_type'
1013 - OR meta_key = '_retaken_items'
1014 - "
1015 - );
1016 - $lp_db->check_execute_has_error();
1017 - } catch ( Exception $e ) {
1018 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1019 - return $response;
1020 - }
1021 -
1022 - return $this->finish_step(
1023 - $response,
1024 - 'Step ' . __FUNCTION__ . ' finished'
1025 - );
1026 - }
1027 -
1028 - /**
1029 - * Modify table learnpress_quiz_questions.
1030 - */
1031 - protected function modify_tb_lp_quiz_questions() {
1032 - $response = new LP_Step( __FUNCTION__, '' );
1033 - $lp_db = LP_Database::getInstance();
1034 -
1035 - try {
1036 - $indexs = array( 'quiz_id', 'question_id' );
1037 - $lp_db->add_indexs_table( $lp_db->tb_lp_quiz_questions, $indexs );
1038 - } catch ( Exception $e ) {
1039 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1040 - return $response;
1041 - }
1042 -
1043 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
1044 - }
1045 -
1046 - /**
1047 - * Modify table learnpress_question_answers
1048 - *
1049 - * @return LP_Step
1050 - * @throws Exception .
1051 - */
1052 - protected function modify_tb_lp_question_answers(): LP_Step {
1053 - $response = new LP_Step( __FUNCTION__, '' );
1054 - $lp_db = LP_Database::getInstance();
1055 -
1056 - try {
1057 - // Add column title.
1058 - $check_col_title = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'title' );
1059 - if ( ! $check_col_title ) {
1060 - $lp_db->wpdb->query(
1061 - "
1062 - ALTER TABLE {$lp_db->tb_lp_question_answers}
1063 - ADD `title` text NULL AFTER `question_id`
1064 - "
1065 - );
1066 - }
1067 -
1068 - // Add column value.
1069 - $check_col_value = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'value' );
1070 - if ( ! $check_col_value ) {
1071 - $lp_db->wpdb->query(
1072 - "
1073 - ALTER TABLE {$lp_db->tb_lp_question_answers}
1074 - ADD `value` varchar(32) NULL AFTER `title`
1075 - "
1076 - );
1077 - }
1078 -
1079 - // Add column order.
1080 - $check_col_order = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'order' );
1081 - if ( ! $check_col_order ) {
1082 - $lp_db->wpdb->query(
1083 - "
1084 - ALTER TABLE {$lp_db->tb_lp_question_answers}
1085 - ADD `order` bigint(20) NULL DEFAULT 1 AFTER `value`
1086 - "
1087 - );
1088 - }
1089 -
1090 - // Add column is_true.
1091 - $check_col_is_true = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'is_true' );
1092 - if ( ! $check_col_is_true ) {
1093 - $lp_db->wpdb->query(
1094 - "
1095 - ALTER TABLE {$lp_db->tb_lp_question_answers}
1096 - ADD `is_true` varchar(3) NULL AFTER `order`
1097 - "
1098 - );
1099 - }
1100 -
1101 - $indexs = array( 'question_id' );
1102 - $lp_db->add_indexs_table( $lp_db->tb_lp_question_answers, $indexs );
1103 -
1104 - if ( ! empty( $lp_db->wpdb->last_error ) ) {
1105 - throw new Exception( $lp_db->wpdb->last_error );
1106 - }
1107 - } catch ( Exception $e ) {
1108 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1109 - return $response;
1110 - }
1111 -
1112 - return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
1113 - }
1114 -
1115 - /**
1116 - * Convert data on table learnpress_question_answers.
1117 - *
1118 - * @param array $data .
1119 - *
1120 - * @return LP_Step
1121 - */
1122 - protected function update_question_answers( array $data ): LP_Step {
1123 - $response = new LP_Step( __FUNCTION__, '' );
1124 - $lp_db = LP_Database::getInstance();
1125 - $wpdb = $lp_db->wpdb;
1126 - $page = 0;
1127 - $offset = 0;
1128 - $limit = 100;
1129 - $total_row = 0;
1130 -
1131 - try {
1132 - $offset = absint( get_transient( 'lp_upgrade_question_answers_offset' ) );
1133 -
1134 - if ( empty( $data ) ) {
1135 - // Check total rows.
1136 - $query = $lp_db->wpdb->prepare(
1137 - "
1138 - SELECT COUNT(question_answer_id) FROM $lp_db->tb_lp_question_answers
1139 - ",
1140 - 1
1141 - );
1142 -
1143 - $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
1144 - } else {
1145 - $page = $data['p'];
1146 - $offset = $limit * $page;
1147 - $total_row = $data['total_rows'];
1148 - }
1149 -
1150 - $query = $wpdb->prepare(
1151 - "
1152 - SELECT *
1153 - FROM {$lp_db->tb_lp_question_answers}
1154 - LIMIT %d OFFSET %d
1155 - ",
1156 - $limit,
1157 - $offset
1158 - );
1159 -
1160 - $rows = $wpdb->get_results( $query );
1161 -
1162 - if ( ! $rows ) {
1163 - return $this->finish_step( $response, 'Finished ' . __FUNCTION__ );
1164 - }
1165 -
1166 - foreach ( $rows as $row ) {
1167 - if ( ! isset( $row->answer_data ) ) {
1168 - continue;
1169 - }
1170 -
1171 - $answers = wp_parse_args(
1172 - maybe_unserialize( $row->answer_data ),
1173 - array(
1174 - 'text' => '',
1175 - 'value' => '',
1176 - 'is_true' => '',
1177 - )
1178 - );
1179 - $update_sql = $lp_db->wpdb->prepare(
1180 - "
1181 - UPDATE {$lp_db->tb_lp_question_answers}
1182 - SET `title`= %s,
1183 - `value`= %s,
1184 - `is_true`= %s,
1185 - `order`= %s
1186 - WHERE question_answer_id=%d
1187 - ",
1188 - $answers['text'],
1189 - $answers['value'] ? $answers['value'] : learn_press_random_value(),
1190 - $answers['is_true'],
1191 - $row->answer_order,
1192 - $row->question_answer_id
1193 - );
1194 - $wpdb->query( $update_sql );
1195 - $lp_db->check_execute_has_error();
1196 - }
1197 -
1198 - $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
1199 -
1200 - $response->status = 'success';
1201 - $response->message = 'Insert success';
1202 - $response->percent = $percent;
1203 - $response->data->p = ++ $page;
1204 - $response->data->total_rows = $total_row;
1205 - } catch ( Exception $e ) {
1206 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1207 - }
1208 -
1209 - return $response;
1210 - }
1211 -
1212 - /**
1213 - * Modify table learnpress_question_answermeta
1214 - */
1215 - protected function modify_tb_lp_question_answermeta() {
1216 - $response = new LP_Step( __FUNCTION__, '' );
1217 - $lp_db = LP_Database::getInstance();
1218 -
1219 - try {
1220 - $lp_db->wpdb->query(
1221 - "
1222 - ALTER TABLE {$lp_db->tb_lp_question_answermeta}
1223 - MODIFY COLUMN `meta_key` VARCHAR(255) NOT NULL DEFAULT '',
1224 - MODIFY COLUMN `meta_value` longtext NULL DEFAULT ''
1225 - "
1226 - );
1227 - $lp_db->check_execute_has_error();
1228 -
1229 - // Create index.
1230 - $lp_db->drop_indexs_table( $lp_db->tb_lp_question_answermeta );
1231 - $lp_db->wpdb->query(
1232 - "
1233 - ALTER TABLE {$lp_db->tb_lp_question_answermeta}
1234 - ADD INDEX question_answer_meta (`learnpress_question_answer_id`, `meta_key`(150))
1235 - "
1236 - );
1237 - $lp_db->check_execute_has_error();
1238 - } catch ( Exception $e ) {
1239 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1240 - return $response;
1241 - }
1242 -
1243 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1244 - }
1245 -
1246 - /**
1247 - * Convert question type fill in blank
1248 - *
1249 - * @param array $data .
1250 - *
1251 - * @return LP_Step
1252 - */
1253 - protected function convert_question_type_fill_in_blank( array $data = array() ): LP_Step {
1254 - $response = new LP_Step( __FUNCTION__, '' );
1255 - $lp_db = LP_Database::getInstance();
1256 - $wpdb = $lp_db->wpdb;
1257 -
1258 - try {
1259 - $query = $wpdb->prepare(
1260 - "
1261 - UPDATE {$lp_db->tb_postmeta}
1262 - SET meta_value = %s
1263 - WHERE meta_key = %s
1264 - AND meta_value = %s
1265 - ",
1266 - 'fill_in_blanks',
1267 - '_lp_type',
1268 - 'fill_in_blank'
1269 - );
1270 - $lp_db->wpdb->query( $query );
1271 -
1272 - if ( $lp_db->wpdb->last_error ) {
1273 - throw new Exception( $lp_db->wpdb->last_error );
1274 - }
1275 -
1276 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1277 - } catch ( Exception $e ) {
1278 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1279 - }
1280 -
1281 - return $response;
1282 - }
1283 -
1284 - /**
1285 - * Delete Columns question answers.
1286 - *
1287 - * @return LP_Step
1288 - */
1289 - protected function delete_columns_question_answers(): LP_Step {
1290 - $response = new LP_Step( __FUNCTION__, '' );
1291 - $lp_db = LP_Database::getInstance();
1292 -
1293 - try {
1294 - $lp_db->drop_col_table( $lp_db->tb_lp_question_answers, 'answer_data' );
1295 - $lp_db->drop_col_table( $lp_db->tb_lp_question_answers, 'answer_order' );
1296 - } catch ( Exception $e ) {
1297 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1298 - return $response;
1299 - }
1300 -
1301 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1302 - }
1303 -
1304 - /**
1305 - * Modify table learnpress_order_items .
1306 - */
1307 - protected function modify_tb_lp_order_items() {
1308 - $response = new LP_Step( __FUNCTION__, '' );
1309 - $lp_db = LP_Database::getInstance();
1310 -
1311 - try {
1312 - $lp_db->add_col_table( $lp_db->tb_lp_order_items, 'item_id', 'bigint(20)', 'order_id' );
1313 - $lp_db->add_col_table( $lp_db->tb_lp_order_items, 'item_type', 'varchar(45)', 'item_id' );
1314 -
1315 - $indexs = array( 'order_id', 'item_id', 'item_type' );
1316 - $lp_db->add_indexs_table( $lp_db->tb_lp_order_items, $indexs );
1317 - } catch ( Exception $e ) {
1318 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1319 - return $response;
1320 - }
1321 -
1322 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1323 - }
1324 -
1325 - /**
1326 - * Modify table learnpress_order_itemmeta.
1327 - *
1328 - * @return LP_Step
1329 - */
1330 - protected function modify_tb_lp_order_itemmeta(): LP_Step {
1331 - $response = new LP_Step( __FUNCTION__, '' );
1332 - $lp_db = LP_Database::getInstance();
1333 -
1334 - try {
1335 - $lp_db->wpdb->query(
1336 - "
1337 - ALTER TABLE {$lp_db->tb_lp_order_itemmeta}
1338 - MODIFY COLUMN `meta_key` VARCHAR(45) NOT NULL DEFAULT '',
1339 - MODIFY COLUMN `meta_value` VARCHAR(45) NOT NULL DEFAULT ''
1340 - "
1341 - );
1342 - $lp_db->check_execute_has_error();
1343 -
1344 - $lp_db->add_col_table( $lp_db->tb_lp_order_itemmeta, 'extra_value', 'longtext', 'meta_value' );
1345 -
1346 - $indexs = array( 'learnpress_order_item_id', 'meta_key', 'meta_value' );
1347 - $lp_db->add_indexs_table( $lp_db->tb_lp_order_itemmeta, $indexs );
1348 - } catch ( Exception $e ) {
1349 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1350 - return $response;
1351 - }
1352 -
1353 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1354 - }
1355 -
1356 - /**
1357 - * Create index table learnpress_sections
1358 - */
1359 - protected function modify_tb_lp_sections() {
1360 - $response = new LP_Step( __FUNCTION__, '' );
1361 - $lp_db = LP_Database::getInstance();
1362 -
1363 - try {
1364 - $indexs = array( 'section_course_id' );
1365 -
1366 - $lp_db->add_indexs_table( $lp_db->tb_lp_sections, $indexs );
1367 - } catch ( Exception $e ) {
1368 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1369 - return $response;
1370 - }
1371 -
1372 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1373 - }
1374 -
1375 - /**
1376 - * Create index table learnpress_section_items
1377 - */
1378 - protected function modify_tb_lp_section_items(): LP_Step {
1379 - $response = new LP_Step( __FUNCTION__, '' );
1380 - $lp_db = LP_Database::getInstance();
1381 -
1382 - try {
1383 - $lp_db->drop_indexs_table( $lp_db->tb_lp_section_items );
1384 -
1385 - $lp_db->wpdb->query(
1386 - "
1387 - ALTER TABLE {$lp_db->tb_lp_section_items}
1388 - ADD INDEX section_item (`section_id`, `item_id`)
1389 - "
1390 - );
1391 - $lp_db->check_execute_has_error();
1392 - } catch ( Exception $e ) {
1393 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1394 - return $response;
1395 - }
1396 -
1397 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1398 - }
1399 -
1400 - /**
1401 - * Convert Learnpress Settings
1402 - * 1. Courses thumbnail dimensions convert.
1403 - * 2. Profile thumbnail dimensions convert.
1404 - * 3. Profile rename dashboard to overview.
1405 - * 4. Block course by duration.
1406 - * 5. Block course when finished.
1407 - * 6. Assessment course by quizzes - Evaluate.
1408 - *
1409 - * @return LP_Step
1410 - */
1411 - protected function convert_lp_settings(): LP_Step {
1412 - $response = new LP_Step( __FUNCTION__, '' );
1413 - $lp_db = LP_Database::getInstance();
1414 -
1415 - try {
1416 - /**
1417 - * Update value on column option_name.
1418 - * Code update value option_name must write before re create indexes if not error "Duplicate entry".
1419 - */
1420 - // Drop table options.
1421 - $lp_db->drop_indexs_table( $lp_db->tb_options );
1422 -
1423 - // Courses thumbnail dimensions convert.
1424 - $check_option_thumbnail_dimensions_exists = $lp_db->wpdb->get_var(
1425 - "
1426 - SELECT option_name FROM $lp_db->tb_options
1427 - WHERE option_name = 'learn_press_course_thumbnail_dimensions'
1428 - "
1429 - );
1430 - if ( empty( $check_option_thumbnail_dimensions_exists ) ) {
1431 - $lp_db->wpdb->query(
1432 - "UPDATE $lp_db->tb_options
1433 - SET option_name = 'learn_press_course_thumbnail_dimensions'
1434 - WHERE option_name = 'learn_press_course_thumbnail_image_size'
1435 - "
1436 - );
1437 - $lp_db->check_execute_has_error();
1438 - }
1439 -
1440 - // Profile thumbnail dimensions convert.
1441 - $check_option_avatar_dimensions_exists = $lp_db->wpdb->get_var(
1442 - "
1443 - SELECT option_name FROM $lp_db->tb_options
1444 - WHERE option_name = 'learn_press_avatar_dimensions'
1445 - "
1446 - );
1447 - if ( empty( $check_option_avatar_dimensions_exists ) ) {
1448 - $lp_db->wpdb->query(
1449 - "UPDATE $lp_db->tb_options
1450 - SET option_name = 'learn_press_avatar_dimensions'
1451 - WHERE option_name = 'learn_press_profile_picture_thumbnail_size'
1452 - "
1453 - );
1454 - $lp_db->check_execute_has_error();
1455 - }
1456 -
1457 - // Delete value same of column "option_name" before re-create indexes for table options.
1458 - $data_sames = $lp_db->wpdb->get_results(
1459 - "
1460 - SELECT option_id, option_name, COUNT(option_name) as total
1461 - FROM $lp_db->tb_options
1462 - GROUP BY option_name
1463 - HAVING total > 1;
1464 - "
1465 - );
1466 - if ( $data_sames ) {
1467 - foreach ( $data_sames as $data_same ) {
1468 - $lp_db->wpdb->query(
1469 - $lp_db->wpdb->prepare(
1470 - "
1471 - DELETE FROM $lp_db->tb_options
1472 - WHERE option_name = %s
1473 - AND option_id != %d
1474 - ",
1475 - $data_same->option_name,
1476 - $data_same->option_id
1477 - )
1478 - );
1479 -
1480 - $lp_db->check_execute_has_error();
1481 - }
1482 - }
1483 -
1484 - // Create indexes for table options.
1485 - $lp_db->create_indexes_tb_options();
1486 - // End.
1487 -
1488 - // Profile rename dashboard to overview.
1489 - $learn_press_profile_endpoints = $lp_db->wpdb->get_var(
1490 - "
1491 - SELECT option_value FROM $lp_db->tb_options
1492 - WHERE option_name = 'learn_press_profile_endpoints'
1493 - "
1494 - );
1495 - $lp_db->check_execute_has_error();
1496 -
1497 - $learn_press_profile_endpoints = maybe_unserialize( $learn_press_profile_endpoints );
1498 -
1499 - $learn_press_profile_endpoints_tmp = array();
1500 - if ( $learn_press_profile_endpoints ) {
1501 - foreach ( $learn_press_profile_endpoints as $k => $val ) {
1502 - if ( 'profile-dashboard' === $k ) {
1503 - $learn_press_profile_endpoints_tmp['overview'] = $val;
1504 - } else {
1505 - $learn_press_profile_endpoints_tmp[ str_replace( 'profile-', '', $k ) ] = $val;
1506 - }
1507 - }
1508 - }
1509 -
1510 - $lp_db->wpdb->query(
1511 - $lp_db->wpdb->prepare(
1512 - "UPDATE $lp_db->tb_options
1513 - SET option_value = %s
1514 - WHERE option_name = 'learn_press_profile_endpoints'
1515 - ",
1516 - maybe_serialize( $learn_press_profile_endpoints_tmp )
1517 - )
1518 - );
1519 - $lp_db->check_execute_has_error();
1520 -
1521 - // Course settings.
1522 - // Block course by duration.
1523 - $lp_db->wpdb->query(
1524 - "UPDATE $lp_db->tb_postmeta
1525 - SET meta_key = '_lp_block_expire_duration'
1526 - WHERE meta_key = '_lp_block_course_item_duration_content'
1527 - "
1528 - );
1529 - $lp_db->check_execute_has_error();
1530 -
1531 - // Block course when finished.
1532 - $lp_db->wpdb->query(
1533 - "UPDATE $lp_db->tb_postmeta
1534 - SET meta_key = '_lp_block_finished'
1535 - WHERE meta_key = '_lp_block_lesson_content'
1536 - "
1537 - );
1538 - $lp_db->check_execute_has_error();
1539 -
1540 - // Assessment course by quizzes - Evaluate.
1541 - $lp_db->wpdb->query(
1542 - "UPDATE $lp_db->tb_postmeta
1543 - SET meta_value = 'evaluate_quiz'
1544 - WHERE meta_key = '_lp_course_result'
1545 - AND meta_value = 'evaluate_quizzes'
1546 - "
1547 - );
1548 - $lp_db->check_execute_has_error();
1549 -
1550 - // End course settings.
1551 -
1552 - // Quiz settings.
1553 - $lp_db->wpdb->query(
1554 - "
1555 - UPDATE $lp_db->tb_postmeta
1556 - SET meta_key = 'lp_review'
1557 - WHERE meta_key = '_lp_review_questions'
1558 - "
1559 - );
1560 - $lp_db->check_execute_has_error();
1561 -
1562 - $lp_db->wpdb->query(
1563 - "
1564 - UPDATE $lp_db->tb_postmeta
1565 - SET meta_key = '_lp_negative_marking'
1566 - WHERE meta_key = '_lp_minus_points'
1567 - "
1568 - );
1569 - $lp_db->check_execute_has_error();
1570 -
1571 - $lp_db->wpdb->query(
1572 - "
1573 - UPDATE $lp_db->tb_postmeta
1574 - SET meta_value = 'yes'
1575 - WHERE meta_key = '_lp_negative_marking'
1576 - AND meta_value > 0
1577 - "
1578 - );
1579 - $lp_db->check_execute_has_error();
1580 -
1581 - $lp_db->wpdb->query(
1582 - "
1583 - UPDATE $lp_db->tb_postmeta
1584 - SET meta_value = 'no'
1585 - WHERE meta_key = '_lp_negative_marking'
1586 - AND meta_value != 'yes'
1587 - "
1588 - );
1589 - $lp_db->check_execute_has_error();
1590 -
1591 - // Delete some fields not use.
1592 -
1593 - // Finish upgrade.
1594 - update_option( LP_KEY_DB_VERSION, 4 );
1595 - // update_option( 'learnpress_version', LEARNPRESS_VERSION );
1596 - // delete_option( 'lp_db_need_upgrade' );
1597 - } catch ( Exception $e ) {
1598 - $response->message = $this->error_step( $response->name, $e->getMessage() );
1599 - return $response;
1600 - }
1601 -
1602 - return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1603 - }
1604 -}
1605 -
1606 -LP_Upgrade_4::get_instance();
1 +<?php
2 +
3 +/**
4 + * Class LP_Upgrade_4
5 + *
6 + * Helper class for updating database to 4.0.0
7 + *
8 + * @version 1.0.0
9 + * @author tungnx
10 + * @since 4.0.0
11 + */
12 +class LP_Upgrade_4 extends LP_Handle_Upgrade_Steps {
13 + /**
14 + * @var LP_Upgrade_4
15 + */
16 + protected static $instance = null;
17 +
18 + /**
19 + * Get Instance
20 + *
21 + * @return LP_Upgrade_4
22 + */
23 + public static function get_instance(): self {
24 + if ( null === self::$instance ) {
25 + self::$instance = new self();
26 + }
27 +
28 + return self::$instance;
29 + }
30 +
31 + /**
32 + * LP_Upgrade_4 constructor.
33 + *
34 + * @see create_tables
35 + * @see clone_tables
36 + * @see modify_tb_lp_user_items
37 + * @see remove_course_status_cancelled
38 + * @see convert_result_graduation_item
39 + * @see convert_result_items
40 + * @see convert_result_questions
41 + * @see convert_retake_quiz
42 + * @see create_col_extra_value_on_tb_lp_user_itemmeta
43 + * @see convert_meta_value_longtext
44 + * @see modify_tb_lp_user_itemmeta
45 + * @see remove_data_lp_user_itemmeta
46 + * @see modify_tb_lp_quiz_questions
47 + * @see modify_tb_lp_question_answers
48 + * @see update_question_answers
49 + * @see modify_tb_lp_question_answermeta
50 + * @see convert_question_type_fill_in_blank
51 + * @see delete_columns_question_answers
52 + * @see modify_tb_lp_order_items
53 + * @see modify_tb_lp_order_itemmeta
54 + * @see modify_tb_lp_sections
55 + * @see modify_tb_lp_section_items
56 + * @see convert_lp_settings
57 + */
58 + protected function __construct() {
59 + $this->version = '4.0.0';
60 + /**
61 + * Name key not > 50 character
62 + */
63 + $this->group_steps = apply_filters(
64 + 'lp/upgrade/4/steps',
65 + array(
66 + 'learnpress_user_items' => new LP_Group_Step(
67 + 'learnpress_user_items',
68 + '',
69 + array(
70 + 'create_tables' => new LP_Step(
71 + 'create_tables',
72 + 'Create tables',
73 + 'learnpress_user_item_results'
74 + ),
75 + 'clone_tables' => new LP_Step(
76 + 'clone_tables',
77 + 'Backup Tables',
78 + 'learnpress_user_items, learnpress_user_itemmeta, learnpress_question_answers, postmeta, options'
79 + ),
80 + 'modify_tb_lp_user_items' => new LP_Step(
81 + 'modify_tb_lp_user_items',
82 + 'Modify table learnpress_user_items',
83 + 'Modify table learnpress_user_items, move the result of students on table learnpress_uset_itemmeta to learnpress_user_item_results'
84 + ),
85 + 'remove_course_status_cancelled' => new LP_Step(
86 + 'remove_course_status_cancelled',
87 + 'Remove courses has status cancelled',
88 + 'learnpress_user_item_results'
89 + ),
90 + 'convert_result_graduation_item' => new LP_Step(
91 + 'convert_result_graduation_item',
92 + 'Convert Data Graduation items of courses',
93 + ''
94 + ),
95 + 'convert_result_items' => new LP_Step(
96 + 'convert_result_items',
97 + 'Convert Data Result courses, items\' courses',
98 + ''
99 + ),
100 + 'convert_result_questions' => new LP_Step(
101 + 'convert_result_questions',
102 + 'Convert Data Result questions',
103 + ''
104 + ),
105 + 'convert_retake_quiz' => new LP_Step(
106 + 'convert_retake_quiz',
107 + 'Convert retake quizzes',
108 + ''
109 + ),
110 + 'create_col_extra_value_on_tb_lp_user_itemmeta' => new LP_Step(
111 + 'create_col_extra_value_on_tb_lp_user_itemmeta',
112 + 'Create column extra_value',
113 + ''
114 + ),
115 + 'convert_meta_value_longtext' => new LP_Step(
116 + 'convert_meta_value_longtext',
117 + 'Copy meta_value longtext to extra_value',
118 + ''
119 + ),
120 + 'remove_data_lp_user_itemmeta' => new LP_Step(
121 + 'remove_data_lp_user_itemmeta',
122 + 'Remove data results of lp_user_itemmeta',
123 + ''
124 + ),
125 + 'modify_tb_lp_user_itemmeta' => new LP_Step(
126 + 'modify_tb_lp_user_itemmeta',
127 + 'Modify table learnpress_user_itemmeta',
128 + 'Change type columns: meta_key, meta_value. Create Index: user_item_id, meta_key, meta_value'
129 + ),
130 + 'modify_tb_lp_quiz_questions' => new LP_Step(
131 + 'modify_tb_lp_quiz_questions',
132 + 'Modify table learnpress_quiz_questions',
133 + ''
134 + ),
135 + 'modify_tb_lp_question_answers' => new LP_Step(
136 + 'modify_tb_lp_question_answers',
137 + 'Modify table learnpress_question_answers',
138 + ''
139 + ),
140 + 'update_question_answers' => new LP_Step(
141 + 'update_question_answers',
142 + 'Update data table learnpress_question_answers',
143 + ''
144 + ),
145 + 'modify_tb_lp_question_answermeta' => new LP_Step(
146 + 'modify_tb_lp_question_answermeta',
147 + 'Modify table learnpress_question_answermeta',
148 + ''
149 + ),
150 + 'convert_question_type_fill_in_blank' => new LP_Step(
151 + 'convert_question_type_fill_in_blank',
152 + 'Update data question type "Fill in blank"',
153 + ''
154 + ),
155 + 'delete_columns_question_answers' => new LP_Step(
156 + 'delete_columns_question_answers',
157 + 'Delete data table learnpress_question_answers',
158 + ''
159 + ),
160 + 'modify_tb_lp_order_items' => new LP_Step(
161 + 'modify_tb_lp_order_items',
162 + 'Modify data table learnpress_order_items',
163 + ''
164 + ),
165 + 'modify_tb_lp_order_itemmeta' => new LP_Step(
166 + 'modify_tb_lp_order_itemmeta',
167 + 'Modify data table learnpress_order_itemmeta',
168 + ''
169 + ),
170 + 'modify_tb_lp_sections' => new LP_Step(
171 + 'modify_tb_lp_sections',
172 + 'Modify table learnpress_sections',
173 + 'Create Index'
174 + ),
175 + 'modify_tb_lp_section_items' => new LP_Step(
176 + 'modify_tb_lp_section_items',
177 + 'Modify table learnpress_section_items',
178 + 'Create Index'
179 + ),
180 + 'convert_lp_settings' => new LP_Step(
181 + 'convert_lp_settings',
182 + 'Convert data settings learnpress',
183 + 'Courses thumbnail dimensions, Profile thumbnail dimensions, Profile rename dashboard to overview, Block course by duration, Block course when finished, Assessment course by quizzes - Evaluate, '
184 + ),
185 + )
186 + ),
187 + )
188 + );
189 + }
190 +
191 + /**
192 + * Step Create Tables
193 + *
194 + * @param array $data
195 + *
196 + * @return LP_Step
197 + */
198 + protected function create_tables( array $data ): LP_Step {
199 + $response = new LP_Step( __FUNCTION__, 'Create table' );
200 + $key_create_table = 'create_table';
201 + $create_table = '';
202 +
203 + try {
204 + /**
205 + * All tables need create.
206 + * key: name table
207 + * value: function handle create this table
208 + *
209 + * @see LP_Database::create_tb_lp_user_item_results
210 + * @see LP_Database::create_tb_lp_upgrade_db()
211 + */
212 + $lp_db = LP_Database::getInstance();
213 +
214 + $create_tables = array(
215 + 'tb_lp_user_item_results',
216 + 'tb_lp_upgrade_db',
217 + );
218 + $total_tables_need_create = count( $create_tables );
219 +
220 + // Check table need create.
221 + if ( empty( $data ) ) {
222 + $create_table = $create_tables[0];
223 + } elseif ( ! empty( $data[ $key_create_table ] )
224 + && in_array( $data[ $key_create_table ], $create_tables ) ) {
225 + $create_table = $data[ $key_create_table ];
226 + }
227 +
228 + if ( empty( $create_table ) ) {
229 + // Finish this step.
230 + $this->finish_step( $response, __FUNCTION__ . ' finished' );
231 + } else {
232 + // Create table.
233 + $name_method = 'create_' . $create_table;
234 + if ( ! method_exists( $lp_db, $name_method ) ) {
235 + throw new Exception( 'Not found method ' . $name_method . ' of Class ' . get_class( $lp_db ) );
236 + }
237 + $lp_db->{$name_method}();
238 +
239 + // Set param to clone table next.
240 + $index = array_search( $create_table, $create_tables );
241 + $percent = LP_Helper::progress_percent( $index, 1, $total_tables_need_create );
242 + ++ $index;
243 +
244 + if ( ! empty( $create_tables[ $index ] ) ) {
245 + $response->status = 'success';
246 + $response->percent = $percent;
247 + $response->data->create_table = $create_tables[ $index ];
248 + $response->message = 'Table "' . $create_table . '" created';
249 + } else {
250 + // Finish this step.
251 + $this->finish_step( $response, __FUNCTION__ . ' finished' );
252 + }
253 + }
254 + } catch ( Exception $e ) {
255 + $response->message = $this->error_step( $response->name, $e->getMessage() );
256 + }
257 +
258 + return $response;
259 + }
260 +
261 + /**
262 + * Step Clone Tables
263 + *
264 + * @param array $data | keys: clone_table .
265 + *
266 + * @return LP_Step
267 + */
268 + protected function clone_tables( array $data ): LP_Step {
269 + $response = new LP_Step( __FUNCTION__, '' );
270 + $key_clone_table = 'clone_table';
271 + $clone_table = '';
272 +
273 + try {
274 + // All tables need clone.
275 + $lp_db = LP_Database::getInstance();
276 + $lp_db->wpdb->query( "SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'" );
277 +
278 + $clone_tables = array(
279 + $lp_db->tb_lp_user_items,
280 + $lp_db->tb_lp_user_itemmeta,
281 + $lp_db->tb_lp_question_answers,
282 + $lp_db->tb_postmeta,
283 + $lp_db->tb_options,
284 + );
285 +
286 + $total_tables_need_clone = count( $clone_tables );
287 +
288 + // Check table need clone.
289 + if ( empty( $data ) ) {
290 + $clone_table = $clone_tables[0];
291 + } elseif ( ! empty( $data[ $key_clone_table ] )
292 + && in_array( $data[ $key_clone_table ], $clone_tables, true ) ) {
293 + $clone_table = $data[ $key_clone_table ];
294 + }
295 +
296 + if ( empty( $clone_table ) ) {
297 + // Finish this step.
298 + $this->finish_step( $response, __FUNCTION__ . ' finished' );
299 + } else {
300 + // Clone table.
301 + $lp_db->clone_table( $clone_table );
302 +
303 + // Set param to clone table next.
304 + $index = array_search( $clone_table, $clone_tables );
305 + $percent = LP_Helper::progress_percent( $index, 1, $total_tables_need_clone );
306 + ++ $index;
307 +
308 + if ( ! empty( $clone_tables[ $index ] ) ) {
309 + $response->status = 'success';
310 + $response->percent = $percent;
311 + $response->data->clone_table = $clone_tables[ $index ];
312 + $response->message = 'Table "' . $clone_table . '" cloned';
313 + } else {
314 + // Finish this step.
315 + $this->finish_step( $response, __FUNCTION__ . ' finished' );
316 + }
317 + }
318 + } catch ( Exception $e ) {
319 + $response->message = $this->error_step( $response->name, $e->getMessage() );
320 + }
321 +
322 + return $response;
323 + }
324 +
325 + /**
326 + * Modify table learnpress_user_items .
327 + * - Add column graduation varchar(20)
328 + * - Add column access_level varchar(20)
329 + * - Copy value start_time_gmt to start_time if value != '0000-00-00 00:00:00' | And delete column start_time_gmt
330 + * - Copy value end_time_gmt to end_time if value != '0000-00-00 00:00:00' | And delete column end_time_gmt
331 + * - Create indexs
332 + *
333 + * @return LP_Step
334 + */
335 + protected function modify_tb_lp_user_items() : LP_Step {
336 + $response = new LP_Step( __FUNCTION__, '' );
337 + $lp_db = LP_Database::getInstance();
338 +
339 + try {
340 + /**
341 + * Check column graduation, if not exist will be create
342 + */
343 + $lp_db->add_col_table( $lp_db->tb_lp_user_items, 'graduation', 'varchar(20)', 'status' );
344 +
345 + /**
346 + * Check column access_level, if not exist will be create
347 + */
348 + $lp_db->add_col_table( $lp_db->tb_lp_user_items, 'access_level', 'varchar(20)', 'graduation' );
349 +
350 + // Change type columns: start_time, end_time.
351 + $lp_db->wpdb->query(
352 + "
353 + ALTER TABLE $lp_db->tb_lp_user_items
354 + MODIFY start_time datetime default null,
355 + MODIFY end_time datetime default null;
356 + "
357 + );
358 + $lp_db->check_execute_has_error();
359 +
360 + /**
361 + * Check column start_time_gmt exists.
362 + *
363 + * Copy value start_time_gmt to start_time
364 + *
365 + * Drop column start_time_gmt
366 + */
367 + $check_col_start_time_gmt = $lp_db->check_col_table( $lp_db->tb_lp_user_items, 'start_time_gmt' );
368 + if ( $check_col_start_time_gmt ) {
369 + $lp_db->wpdb->query(
370 + "
371 + UPDATE $lp_db->tb_lp_user_items SET start_time = start_time_gmt
372 + WHERE user_item_id > 0
373 + AND start_time_gmt != '0000-00-00 00:00:00'
374 + "
375 + );
376 + $lp_db->check_execute_has_error();
377 + $lp_db->wpdb->query(
378 + "
379 + UPDATE $lp_db->tb_lp_user_items SET start_time = null
380 + WHERE start_time = '0000-00-00 00:00:00'
381 + "
382 + );
383 + $lp_db->check_execute_has_error();
384 + $lp_db->drop_col_table( $lp_db->tb_lp_user_items, 'start_time_gmt' );
385 + }
386 +
387 + /**
388 + * Check column end_time_gmt exists.
389 + *
390 + * Copy value end_time_gmt to end_time
391 + *
392 + * Drop column end_time_gmt
393 + */
394 + $check_col_end_time_gmt = $lp_db->check_col_table( $lp_db->tb_lp_user_items, 'end_time_gmt' );
395 + if ( $check_col_end_time_gmt ) {
396 + $lp_db->wpdb->query(
397 + "
398 + UPDATE $lp_db->tb_lp_user_items SET end_time = end_time_gmt
399 + WHERE user_item_id > 0
400 + AND end_time_gmt != '0000-00-00 00:00:00'
401 + "
402 + );
403 + $lp_db->check_execute_has_error();
404 + $lp_db->wpdb->query(
405 + "
406 + UPDATE $lp_db->tb_lp_user_items SET end_time = null
407 + WHERE end_time_gmt = '0000-00-00 00:00:00'
408 + "
409 + );
410 + $lp_db->check_execute_has_error();
411 + $lp_db->drop_col_table( $lp_db->tb_lp_user_items, 'end_time_gmt' );
412 + }
413 +
414 + // Remove rows have status = 'canceled';
415 +
416 + // Create index.
417 + $indexs = array( 'user_id', 'item_id', 'item_type', 'status', 'ref_type', 'ref_id', 'parent_id' );
418 + $lp_db->add_indexs_table( $lp_db->tb_lp_user_items, $indexs );
419 + } catch ( Exception $e ) {
420 + $response->message = $this->error_step( $response->name, $e->getMessage() );
421 + return $response;
422 + }
423 +
424 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
425 + }
426 +
427 + /**
428 + * Remove courses has status "cancelled" and items child, itemmeta
429 + *
430 + * @return LP_Step
431 + */
432 + protected function remove_course_status_cancelled() : LP_Step {
433 + $response = new LP_Step( __FUNCTION__, '' );
434 + $lp_db = LP_Database::getInstance();
435 +
436 + try {
437 + $user_course_ids = $lp_db->wpdb->get_col(
438 + $lp_db->wpdb->prepare(
439 + "
440 + SELECT user_item_id FROM $lp_db->tb_lp_user_items
441 + WHERE item_type = %s
442 + AND status = %s
443 + ",
444 + LP_COURSE_CPT,
445 + 'cancelled'
446 + )
447 + );
448 +
449 + if ( empty( $user_course_ids ) ) {
450 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
451 + }
452 +
453 + $user_course_ids_str = implode( ',', $user_course_ids );
454 +
455 + $user_item_ids = $lp_db->wpdb->get_col(
456 + "
457 + SELECT user_item_id FROM $lp_db->tb_lp_user_items
458 + WHERE parent_id IN (" . $user_course_ids_str . ')
459 + '
460 + );
461 +
462 + $user_item_ids_concat = array_merge( $user_course_ids, $user_item_ids );
463 + $user_item_ids_concat_str = implode( ',', $user_item_ids_concat );
464 +
465 + // Delete on tb lp_user_items
466 + $lp_db->wpdb->query(
467 + "
468 + DELETE FROM $lp_db->tb_lp_user_items
469 + WHERE user_item_id IN (" . $user_item_ids_concat_str . ')
470 + '
471 + );
472 + $lp_db->check_execute_has_error();
473 +
474 + // Delete on tb lp_user_itemmeta
475 + $lp_db->wpdb->query(
476 + "
477 + DELETE FROM $lp_db->tb_lp_user_itemmeta
478 + WHERE learnpress_user_item_id IN (" . $user_course_ids_str . ')
479 + '
480 + );
481 + $lp_db->check_execute_has_error();
482 + } catch ( Exception $e ) {
483 + $response->message = $this->error_step( $response->name, $e->getMessage() );
484 + return $response;
485 + }
486 +
487 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
488 + }
489 +
490 + /**
491 + * Convert value of meta_key "grade" table learnpress_user_itemmeta LP3 to column graduation LP4 table learnpress_user_item_results
492 + *
493 + * @param array $data .
494 + *
495 + * @return LP_Step
496 + */
497 + protected function convert_result_graduation_item( array $data ): LP_Step {
498 + $response = new LP_Step( __FUNCTION__, '' );
499 + $lp_db = LP_Database::getInstance();
500 + $page = 0;
501 + $offset = 0;
502 + $limit = 100;
503 + $total_row = 0;
504 + $suffix_table_bk = '_bk';
505 +
506 + try {
507 + if ( empty( $data ) ) {
508 + // Check total rows.
509 + $query = $lp_db->wpdb->prepare(
510 + "
511 + SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta{$suffix_table_bk}
512 + WHERE meta_key = %s
513 + ",
514 + 'grade'
515 + );
516 +
517 + $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
518 + } else {
519 + $page = $data['p'];
520 + $offset = $limit * $page;
521 + $total_row = $data['total_rows'];
522 + }
523 +
524 + // Select .
525 + $query = $lp_db->wpdb->prepare(
526 + "
527 + SELECT learnpress_user_item_id AS user_item_id, meta_value AS grade
528 + FROM $lp_db->tb_lp_user_itemmeta{$suffix_table_bk}
529 + WHERE meta_key = %s
530 + LIMIT %d, %d
531 + ",
532 + 'grade',
533 + $offset,
534 + $limit
535 + );
536 + $user_item_grades = $lp_db->wpdb->get_results( $query );
537 +
538 + /**
539 + * Copy value of meta_key "grade" table learnpress_user_itemmeta LP3
540 + * to column "graduation" LP4 table learnpress_user_items
541 + */
542 + foreach ( $user_item_grades as $user_item_grade ) {
543 + $query = $lp_db->wpdb->prepare(
544 + "
545 + UPDATE $lp_db->tb_lp_user_items
546 + SET graduation = %s
547 + WHERE user_item_id = %d;
548 + ",
549 + $user_item_grade->grade,
550 + $user_item_grade->user_item_id
551 + );
552 +
553 + $lp_db->wpdb->query( $query );
554 + $lp_db->check_execute_has_error();
555 + }
556 +
557 + $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
558 + if ( empty( $user_item_grades ) || 100 == $percent ) {
559 + // Update graduation for case grade wrong (null or lesson completed but still 'in-progress').
560 + $lp_db->wpdb->query(
561 + "
562 + UPDATE $lp_db->tb_lp_user_items
563 + SET graduation = 'passed'
564 + WHERE status = 'completed'
565 + AND item_type = 'lp_lesson'
566 + "
567 + );
568 + // Update graduation for case status empty and grade null
569 + $lp_db->wpdb->query(
570 + "
571 + UPDATE $lp_db->tb_lp_user_items
572 + SET graduation = 'in-progress'
573 + WHERE (status = '' OR status = 'enrolled')
574 + "
575 + );
576 +
577 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
578 + }
579 +
580 + $response->status = 'success';
581 + $response->message = 'Insert success';
582 + $response->percent = $percent;
583 + $response->data->p = ++ $page;
584 + $response->data->total_rows = $total_row;
585 + } catch ( Exception $e ) {
586 + $response->message = $this->error_step( $response->name, $e->getMessage() );
587 + }
588 +
589 + return $response;
590 + }
591 +
592 + /**
593 + * Convert result items (lesson).
594 + *
595 + * @param array $data
596 + *
597 + * @return LP_Step
598 + */
599 + protected function convert_result_items( array $data ): LP_Step {
600 + $response = new LP_Step( __FUNCTION__, '' );
601 + $lp_db = LP_Database::getInstance();
602 + $page = 0;
603 + $offset = 0;
604 + $limit = 100;
605 + $total_row = 0;
606 +
607 + try {
608 + if ( empty( $data ) ) {
609 + // Check total rows.
610 + $query = "
611 + SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
612 + WHERE meta_key LIKE '%course_results_evaluate%'
613 + ";
614 +
615 + $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
616 + } else {
617 + $page = $data['p'];
618 + $offset = $limit * $page;
619 + $total_row = $data['total_rows'];
620 + }
621 +
622 + // Convert rows.
623 + $query = $lp_db->wpdb->prepare(
624 + "
625 + SELECT learnpress_user_item_id AS user_item_id, meta_value AS result
626 + FROM $lp_db->tb_lp_user_itemmeta
627 + WHERE meta_key LIKE '%course_results_evaluate%'
628 + LIMIT %d offset %d
629 + ",
630 + $limit,
631 + $offset
632 + );
633 +
634 + $result_lessons = $lp_db->wpdb->get_results( $query );
635 + if ( 0 === count( $result_lessons ) ) {
636 + return $this->finish_step( $response, 'Convert result question success' );
637 + }
638 +
639 + foreach ( $result_lessons as $result_lesson_obj ) {
640 + $result_lesson = maybe_unserialize( ( $result_lesson_obj->result ) );
641 + if ( ! $result_lesson ) {
642 + continue;
643 + }
644 +
645 + $result_json = json_encode( $result_lesson );
646 +
647 + // Check exists user_item_id value on table learnpress_user_item_results.
648 + $check = $lp_db->wpdb->get_var(
649 + $lp_db->wpdb->prepare(
650 + "
651 + SELECT user_item_id FROM $lp_db->tb_lp_user_item_results
652 + WHERE user_item_id = %d
653 + ",
654 + $result_lesson_obj->user_item_id
655 + )
656 + );
657 +
658 + if ( empty( $check ) ) {
659 + $lp_db->wpdb->insert(
660 + $lp_db->tb_lp_user_item_results,
661 + array(
662 + 'result' => $result_json,
663 + 'user_item_id' => $result_lesson_obj->user_item_id,
664 + )
665 + );
666 + $lp_db->check_execute_has_error();
667 + }
668 + }
669 +
670 + $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
671 +
672 + $response->status = 'success';
673 + $response->message = 'Insert lesson result success';
674 + $response->percent = $percent;
675 + $response->data->p = ++ $page;
676 + $response->data->total_rows = $total_row;
677 + } catch ( Throwable $e ) {
678 + $response->message = $this->error_step( $response->name, $e->getMessage() );
679 + }
680 +
681 + return $response;
682 + }
683 +
684 + /**
685 + * Convert value of meta_key "_question_answers" table learnpress_user_itemmeta LP3 to column result LP4 table learnpress_user_item_results
686 + *
687 + * @param array $data .
688 + *
689 + * @return LP_Step
690 + */
691 + protected function convert_result_questions( array $data ): LP_Step {
692 + $response = new LP_Step( __FUNCTION__, '' );
693 + $lp_db = LP_Database::getInstance();
694 + $page = 0;
695 + $offset = 0;
696 + $limit = 100;
697 + $total_row = 0;
698 +
699 + try {
700 + if ( empty( $data ) ) {
701 + // Check total rows.
702 + $query = $lp_db->wpdb->prepare(
703 + "
704 + SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
705 + WHERE meta_key = '_question_answers'
706 + ",
707 + 1
708 + );
709 +
710 + $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
711 + } else {
712 + $page = $data['p'];
713 + $offset = $limit * $page;
714 + $total_row = $data['total_rows'];
715 + }
716 +
717 + // Convert rows.
718 + $query = $lp_db->wpdb->prepare(
719 + "
720 + SELECT learnpress_user_item_id AS user_item_id, meta_value AS answered
721 + FROM $lp_db->tb_lp_user_itemmeta
722 + WHERE meta_key = '_question_answers'
723 + LIMIT %d offset %d
724 + ",
725 + $limit,
726 + $offset
727 + );
728 + $quizs_questions_answered = $lp_db->wpdb->get_results( $query );
729 +
730 + if ( 0 === count( $quizs_questions_answered ) ) {
731 + return $this->finish_step( $response, 'Convert result question success' );
732 + }
733 +
734 + foreach ( $quizs_questions_answered as $quiz_question_answered ) {
735 + $query_quiz_result = $lp_db->wpdb->get_var(
736 + $lp_db->wpdb->prepare(
737 + "
738 + SELECT meta_value AS quiz_result FROM $lp_db->tb_lp_user_itemmeta
739 + WHERE learnpress_user_item_id = %d
740 + AND meta_key = %s
741 + ",
742 + $quiz_question_answered->user_item_id,
743 + 'results'
744 + )
745 + );
746 +
747 + $quiz_result = maybe_unserialize( ( $query_quiz_result ) );
748 + $questions_answered = maybe_unserialize( $quiz_question_answered->answered );
749 +
750 + if ( ! $quiz_result || ! $questions_answered ) {
751 + continue;
752 + }
753 +
754 + foreach ( $questions_answered as $question_id => $question_answered ) {
755 + if ( isset( $quiz_result['questions'][ $question_id ] ) ) {
756 + $quiz_result['questions'][ $question_id ]['answered'] = $question_answered;
757 + }
758 + }
759 +
760 + $result_json = json_encode( $quiz_result );
761 +
762 + // Check exists user_item_id value on table learnpress_user_item_results.
763 + $check = $lp_db->wpdb->get_var(
764 + $lp_db->wpdb->prepare(
765 + "
766 + SELECT user_item_id FROM $lp_db->tb_lp_user_item_results
767 + WHERE user_item_id = %d
768 + ",
769 + $quiz_question_answered->user_item_id
770 + )
771 + );
772 +
773 + if ( empty( $check ) ) {
774 + $lp_db->wpdb->insert(
775 + $lp_db->tb_lp_user_item_results,
776 + array(
777 + 'result' => $result_json,
778 + 'user_item_id' => $quiz_question_answered->user_item_id,
779 + )
780 + );
781 + $lp_db->check_execute_has_error();
782 + } else {
783 + }
784 + }
785 +
786 + $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
787 +
788 + $response->status = 'success';
789 + $response->message = 'Insert success';
790 + $response->percent = $percent;
791 + $response->data->p = ++ $page;
792 + $response->data->total_rows = $total_row;
793 + } catch ( Exception $e ) {
794 + $response->message = $this->error_step( $response->name, $e->getMessage() );
795 + }
796 +
797 + return $response;
798 + }
799 +
800 + /**
801 + * Convert retake quiz.
802 + *
803 + * @param array $data .
804 + *
805 + * @return LP_Step
806 + */
807 + protected function convert_retake_quiz( array $data ): LP_Step {
808 + $response = new LP_Step( __FUNCTION__, '' );
809 + $lp_db = LP_Database::getInstance();
810 + $page = 0;
811 + $offset = 0;
812 + $limit = 100;
813 + $total_row = 0;
814 +
815 + try {
816 + if ( empty( $data ) ) {
817 + // Check total rows.
818 + $query = $lp_db->wpdb->prepare(
819 + "
820 + SELECT COUNT(learnpress_user_item_id) FROM $lp_db->tb_lp_user_itemmeta
821 + WHERE meta_key = '_retaken_items'
822 + ",
823 + 1
824 + );
825 +
826 + $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
827 + } else {
828 + $page = $data['p'];
829 + $offset = $limit * $page;
830 + $total_row = $data['total_rows'];
831 + }
832 +
833 + // Convert rows.
834 + $query = $lp_db->wpdb->prepare(
835 + "
836 + SELECT learnpress_user_item_id AS user_item_id, meta_value AS quizzes_retaken
837 + FROM $lp_db->tb_lp_user_itemmeta
838 + WHERE meta_key = '_retaken_items'
839 + LIMIT %d offset %d
840 + ",
841 + $limit,
842 + $offset
843 + );
844 + $courses_quizzes_retaken = $lp_db->wpdb->get_results( $query );
845 +
846 + if ( 0 === count( $courses_quizzes_retaken ) ) {
847 + return $this->finish_step( $response, 'Convert result question success' );
848 + }
849 +
850 + foreach ( $courses_quizzes_retaken as $quizzes_retaken ) {
851 + $user_item_id = $quizzes_retaken->user_item_id;
852 + $retaken = maybe_unserialize( $quizzes_retaken->quizzes_retaken );
853 +
854 + if ( is_array( $retaken ) ) {
855 + foreach ( $retaken as $quiz_id => $v ) {
856 + $quiz_user_item_id = $lp_db->wpdb->get_var(
857 + $lp_db->wpdb->prepare(
858 + "
859 + SELECT user_item_id
860 + FROM $lp_db->tb_lp_user_items
861 + WHERE parent_id = %d
862 + AND item_id = %d
863 + ",
864 + $user_item_id,
865 + $quiz_id
866 + )
867 + );
868 +
869 + if ( $quiz_user_item_id ) {
870 + $lp_db->wpdb->query(
871 + "
872 + INSERT INTO $lp_db->tb_lp_user_itemmeta
873 + (learnpress_user_item_id, meta_key, meta_value)
874 + VALUES ($quiz_user_item_id, '_lp_retake_count', $v)
875 + "
876 + );
877 + $lp_db->check_execute_has_error();
878 + }
879 + }
880 + }
881 + }
882 +
883 + $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
884 +
885 + $response->status = 'success';
886 + $response->message = 'Convert success ';
887 + $response->percent = $percent;
888 + $response->data->p = ++ $page;
889 + $response->data->total_rows = $total_row;
890 + } catch ( Exception $e ) {
891 + $response->message = $this->error_step( $response->name, $e->getMessage() );
892 + }
893 +
894 + return $response;
895 + }
896 +
897 + /**
898 + * Create column extra_value for table learnpress_user_itemmeta.
899 + *
900 + * @return LP_Step
901 + */
902 + protected function create_col_extra_value_on_tb_lp_user_itemmeta(): LP_Step {
903 + $response = new LP_Step( __FUNCTION__, '' );
904 + $lp_db = LP_Database::getInstance();
905 +
906 + try {
907 + $lp_db->add_col_table( $lp_db->tb_lp_user_itemmeta, 'extra_value', 'longtext', 'meta_value' );
908 + } catch ( Exception $e ) {
909 + $response->message = $this->error_step( $response->name, $e->getMessage() );
910 + return $response;
911 + }
912 +
913 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
914 + }
915 +
916 + /**
917 + * Copy meta_value longtext to extra_value.
918 + *
919 + * @return LP_Step
920 + */
921 + protected function convert_meta_value_longtext(): LP_Step {
922 + $response = new LP_Step( __FUNCTION__, '' );
923 + $lp_db = LP_Database::getInstance();
924 +
925 + try {
926 + // Copy meta_value to extra_value.
927 + $lp_db->wpdb->query(
928 + "
929 + UPDATE $lp_db->tb_lp_user_itemmeta SET extra_value = meta_value
930 + WHERE meta_key = '_lp_assignment_answer_note'
931 + OR meta_key = '_lp_assignment_answer_upload'
932 + "
933 + );
934 + $lp_db->check_execute_has_error();
935 +
936 + // Empty meta_value.
937 + $lp_db->wpdb->query(
938 + "
939 + UPDATE $lp_db->tb_lp_user_itemmeta SET meta_value = ''
940 + WHERE meta_key = '_lp_assignment_answer_note'
941 + OR meta_key = '_lp_assignment_answer_upload'
942 + "
943 + );
944 + $lp_db->check_execute_has_error();
945 + } catch ( Exception $e ) {
946 + $response->message = $this->error_step( $response->name, $e->getMessage() );
947 + return $response;
948 + }
949 +
950 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
951 + }
952 +
953 + /**
954 + * Modify table learnpress_user_itemmeta .
955 + * Must run after Step "convert_result_questions"
956 + * Because change name column name 'learnpress_user_item_id' to 'user_item_id' and meta_key change type from 'text' to varchar(255)
957 + *
958 + * @return LP_Step
959 + */
960 + protected function modify_tb_lp_user_itemmeta(): LP_Step {
961 + $response = new LP_Step( __FUNCTION__, '' );
962 + $lp_db = LP_Database::getInstance();
963 +
964 + try {
965 + $lp_db->wpdb->query(
966 + "
967 + ALTER TABLE {$lp_db->tb_lp_user_itemmeta}
968 + CHANGE COLUMN `meta_key` `meta_key` VARCHAR(45) NOT NULL DEFAULT '',
969 + CHANGE COLUMN `meta_value` `meta_value` VARCHAR(45) NOT NULL DEFAULT ''
970 + "
971 + );
972 + $lp_db->check_execute_has_error();
973 +
974 + // Create index.
975 + $indexs = array( 'learnpress_user_item_id', 'meta_key', 'meta_value' );
976 + $lp_db->add_indexs_table( $lp_db->tb_lp_user_itemmeta, $indexs );
977 + } catch ( Exception $e ) {
978 + $response->message = $this->error_step( $response->name, $e->getMessage() );
979 + return $response;
980 + }
981 +
982 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
983 + }
984 +
985 + /**
986 + * Remove data on table learnpress_user_itemmeta
987 + */
988 + protected function remove_data_lp_user_itemmeta() {
989 + $response = new LP_Step( __FUNCTION__, '' );
990 + $lp_db = LP_Database::getInstance();
991 +
992 + try {
993 + /**
994 + * 1. Remove results course.
995 + * 2. Remove results item's course.
996 + * 3. Remove _question_answers.
997 + * 4. Remove grade.
998 + * 5. Remove _last_status.
999 + * 6. Remove _current_status.
1000 + * 7. Remove finishing_type.
1001 + * 8. Remove _retaken_items.
1002 + */
1003 + $lp_db->wpdb->query(
1004 + "
1005 + DELETE FROM {$lp_db->tb_lp_user_itemmeta}
1006 + WHERE meta_key LIKE 'course_results_evaluate_%'
1007 + OR meta_key = '_question_answers'
1008 + OR meta_key = 'results'
1009 + OR meta_key = 'grade'
1010 + OR meta_key = '_last_status'
1011 + OR meta_key = '_current_status'
1012 + OR meta_key = 'finishing_type'
1013 + OR meta_key = '_retaken_items'
1014 + "
1015 + );
1016 + $lp_db->check_execute_has_error();
1017 + } catch ( Exception $e ) {
1018 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1019 + return $response;
1020 + }
1021 +
1022 + return $this->finish_step(
1023 + $response,
1024 + 'Step ' . __FUNCTION__ . ' finished'
1025 + );
1026 + }
1027 +
1028 + /**
1029 + * Modify table learnpress_quiz_questions.
1030 + */
1031 + protected function modify_tb_lp_quiz_questions() {
1032 + $response = new LP_Step( __FUNCTION__, '' );
1033 + $lp_db = LP_Database::getInstance();
1034 +
1035 + try {
1036 + $indexs = array( 'quiz_id', 'question_id' );
1037 + $lp_db->add_indexs_table( $lp_db->tb_lp_quiz_questions, $indexs );
1038 + } catch ( Exception $e ) {
1039 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1040 + return $response;
1041 + }
1042 +
1043 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
1044 + }
1045 +
1046 + /**
1047 + * Modify table learnpress_question_answers
1048 + *
1049 + * @return LP_Step
1050 + * @throws Exception .
1051 + */
1052 + protected function modify_tb_lp_question_answers(): LP_Step {
1053 + $response = new LP_Step( __FUNCTION__, '' );
1054 + $lp_db = LP_Database::getInstance();
1055 +
1056 + try {
1057 + // Add column title.
1058 + $check_col_title = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'title' );
1059 + if ( ! $check_col_title ) {
1060 + $lp_db->wpdb->query(
1061 + "
1062 + ALTER TABLE {$lp_db->tb_lp_question_answers}
1063 + ADD `title` text NULL AFTER `question_id`
1064 + "
1065 + );
1066 + }
1067 +
1068 + // Add column value.
1069 + $check_col_value = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'value' );
1070 + if ( ! $check_col_value ) {
1071 + $lp_db->wpdb->query(
1072 + "
1073 + ALTER TABLE {$lp_db->tb_lp_question_answers}
1074 + ADD `value` varchar(32) NULL AFTER `title`
1075 + "
1076 + );
1077 + }
1078 +
1079 + // Add column order.
1080 + $check_col_order = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'order' );
1081 + if ( ! $check_col_order ) {
1082 + $lp_db->wpdb->query(
1083 + "
1084 + ALTER TABLE {$lp_db->tb_lp_question_answers}
1085 + ADD `order` bigint(20) NULL DEFAULT 1 AFTER `value`
1086 + "
1087 + );
1088 + }
1089 +
1090 + // Add column is_true.
1091 + $check_col_is_true = $lp_db->check_col_table( $lp_db->tb_lp_question_answers, 'is_true' );
1092 + if ( ! $check_col_is_true ) {
1093 + $lp_db->wpdb->query(
1094 + "
1095 + ALTER TABLE {$lp_db->tb_lp_question_answers}
1096 + ADD `is_true` varchar(3) NULL AFTER `order`
1097 + "
1098 + );
1099 + }
1100 +
1101 + $indexs = array( 'question_id' );
1102 + $lp_db->add_indexs_table( $lp_db->tb_lp_question_answers, $indexs );
1103 +
1104 + if ( ! empty( $lp_db->wpdb->last_error ) ) {
1105 + throw new Exception( $lp_db->wpdb->last_error );
1106 + }
1107 + } catch ( Exception $e ) {
1108 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1109 + return $response;
1110 + }
1111 +
1112 + return $this->finish_step( $response, 'Step ' . __FUNCTION__ . ' finished' );
1113 + }
1114 +
1115 + /**
1116 + * Convert data on table learnpress_question_answers.
1117 + *
1118 + * @param array $data .
1119 + *
1120 + * @return LP_Step
1121 + */
1122 + protected function update_question_answers( array $data ): LP_Step {
1123 + $response = new LP_Step( __FUNCTION__, '' );
1124 + $lp_db = LP_Database::getInstance();
1125 + $wpdb = $lp_db->wpdb;
1126 + $page = 0;
1127 + $offset = 0;
1128 + $limit = 100;
1129 + $total_row = 0;
1130 +
1131 + try {
1132 + $offset = absint( get_transient( 'lp_upgrade_question_answers_offset' ) );
1133 +
1134 + if ( empty( $data ) ) {
1135 + // Check total rows.
1136 + $query = $lp_db->wpdb->prepare(
1137 + "
1138 + SELECT COUNT(question_answer_id) FROM $lp_db->tb_lp_question_answers
1139 + ",
1140 + 1
1141 + );
1142 +
1143 + $total_row = $response->data->total_rows = (int) $lp_db->wpdb->get_var( $query );
1144 + } else {
1145 + $page = $data['p'];
1146 + $offset = $limit * $page;
1147 + $total_row = $data['total_rows'];
1148 + }
1149 +
1150 + $query = $wpdb->prepare(
1151 + "
1152 + SELECT *
1153 + FROM {$lp_db->tb_lp_question_answers}
1154 + LIMIT %d OFFSET %d
1155 + ",
1156 + $limit,
1157 + $offset
1158 + );
1159 +
1160 + $rows = $wpdb->get_results( $query );
1161 +
1162 + if ( ! $rows ) {
1163 + return $this->finish_step( $response, 'Finished ' . __FUNCTION__ );
1164 + }
1165 +
1166 + foreach ( $rows as $row ) {
1167 + if ( ! isset( $row->answer_data ) ) {
1168 + continue;
1169 + }
1170 +
1171 + $answers = wp_parse_args(
1172 + maybe_unserialize( $row->answer_data ),
1173 + array(
1174 + 'text' => '',
1175 + 'value' => '',
1176 + 'is_true' => '',
1177 + )
1178 + );
1179 + $update_sql = $lp_db->wpdb->prepare(
1180 + "
1181 + UPDATE {$lp_db->tb_lp_question_answers}
1182 + SET `title`= %s,
1183 + `value`= %s,
1184 + `is_true`= %s,
1185 + `order`= %s
1186 + WHERE question_answer_id=%d
1187 + ",
1188 + $answers['text'],
1189 + $answers['value'] ? $answers['value'] : learn_press_random_value(),
1190 + $answers['is_true'],
1191 + $row->answer_order,
1192 + $row->question_answer_id
1193 + );
1194 + $wpdb->query( $update_sql );
1195 + $lp_db->check_execute_has_error();
1196 + }
1197 +
1198 + $percent = LP_Helper::progress_percent( $offset, $limit, $total_row );
1199 +
1200 + $response->status = 'success';
1201 + $response->message = 'Insert success';
1202 + $response->percent = $percent;
1203 + $response->data->p = ++ $page;
1204 + $response->data->total_rows = $total_row;
1205 + } catch ( Exception $e ) {
1206 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1207 + }
1208 +
1209 + return $response;
1210 + }
1211 +
1212 + /**
1213 + * Modify table learnpress_question_answermeta
1214 + */
1215 + protected function modify_tb_lp_question_answermeta() {
1216 + $response = new LP_Step( __FUNCTION__, '' );
1217 + $lp_db = LP_Database::getInstance();
1218 +
1219 + try {
1220 + $lp_db->wpdb->query(
1221 + "
1222 + ALTER TABLE {$lp_db->tb_lp_question_answermeta}
1223 + MODIFY COLUMN `meta_key` VARCHAR(255) NOT NULL DEFAULT '',
1224 + MODIFY COLUMN `meta_value` longtext NULL DEFAULT ''
1225 + "
1226 + );
1227 + $lp_db->check_execute_has_error();
1228 +
1229 + // Create index.
1230 + $lp_db->drop_indexs_table( $lp_db->tb_lp_question_answermeta );
1231 + $lp_db->wpdb->query(
1232 + "
1233 + ALTER TABLE {$lp_db->tb_lp_question_answermeta}
1234 + ADD INDEX question_answer_meta (`learnpress_question_answer_id`, `meta_key`(150))
1235 + "
1236 + );
1237 + $lp_db->check_execute_has_error();
1238 + } catch ( Exception $e ) {
1239 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1240 + return $response;
1241 + }
1242 +
1243 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1244 + }
1245 +
1246 + /**
1247 + * Convert question type fill in blank
1248 + *
1249 + * @param array $data .
1250 + *
1251 + * @return LP_Step
1252 + */
1253 + protected function convert_question_type_fill_in_blank( array $data = array() ): LP_Step {
1254 + $response = new LP_Step( __FUNCTION__, '' );
1255 + $lp_db = LP_Database::getInstance();
1256 + $wpdb = $lp_db->wpdb;
1257 +
1258 + try {
1259 + $query = $wpdb->prepare(
1260 + "
1261 + UPDATE {$lp_db->tb_postmeta}
1262 + SET meta_value = %s
1263 + WHERE meta_key = %s
1264 + AND meta_value = %s
1265 + ",
1266 + 'fill_in_blanks',
1267 + '_lp_type',
1268 + 'fill_in_blank'
1269 + );
1270 + $lp_db->wpdb->query( $query );
1271 +
1272 + if ( $lp_db->wpdb->last_error ) {
1273 + throw new Exception( $lp_db->wpdb->last_error );
1274 + }
1275 +
1276 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1277 + } catch ( Exception $e ) {
1278 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1279 + }
1280 +
1281 + return $response;
1282 + }
1283 +
1284 + /**
1285 + * Delete Columns question answers.
1286 + *
1287 + * @return LP_Step
1288 + */
1289 + protected function delete_columns_question_answers(): LP_Step {
1290 + $response = new LP_Step( __FUNCTION__, '' );
1291 + $lp_db = LP_Database::getInstance();
1292 +
1293 + try {
1294 + $lp_db->drop_col_table( $lp_db->tb_lp_question_answers, 'answer_data' );
1295 + $lp_db->drop_col_table( $lp_db->tb_lp_question_answers, 'answer_order' );
1296 + } catch ( Exception $e ) {
1297 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1298 + return $response;
1299 + }
1300 +
1301 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1302 + }
1303 +
1304 + /**
1305 + * Modify table learnpress_order_items .
1306 + */
1307 + protected function modify_tb_lp_order_items() {
1308 + $response = new LP_Step( __FUNCTION__, '' );
1309 + $lp_db = LP_Database::getInstance();
1310 +
1311 + try {
1312 + $lp_db->add_col_table( $lp_db->tb_lp_order_items, 'item_id', 'bigint(20)', 'order_id' );
1313 + $lp_db->add_col_table( $lp_db->tb_lp_order_items, 'item_type', 'varchar(45)', 'item_id' );
1314 +
1315 + $indexs = array( 'order_id', 'item_id', 'item_type' );
1316 + $lp_db->add_indexs_table( $lp_db->tb_lp_order_items, $indexs );
1317 + } catch ( Exception $e ) {
1318 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1319 + return $response;
1320 + }
1321 +
1322 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1323 + }
1324 +
1325 + /**
1326 + * Modify table learnpress_order_itemmeta.
1327 + *
1328 + * @return LP_Step
1329 + */
1330 + protected function modify_tb_lp_order_itemmeta(): LP_Step {
1331 + $response = new LP_Step( __FUNCTION__, '' );
1332 + $lp_db = LP_Database::getInstance();
1333 +
1334 + try {
1335 + $lp_db->wpdb->query(
1336 + "
1337 + ALTER TABLE {$lp_db->tb_lp_order_itemmeta}
1338 + MODIFY COLUMN `meta_key` VARCHAR(45) NOT NULL DEFAULT '',
1339 + MODIFY COLUMN `meta_value` VARCHAR(45) NOT NULL DEFAULT ''
1340 + "
1341 + );
1342 + $lp_db->check_execute_has_error();
1343 +
1344 + $lp_db->add_col_table( $lp_db->tb_lp_order_itemmeta, 'extra_value', 'longtext', 'meta_value' );
1345 +
1346 + $indexs = array( 'learnpress_order_item_id', 'meta_key', 'meta_value' );
1347 + $lp_db->add_indexs_table( $lp_db->tb_lp_order_itemmeta, $indexs );
1348 + } catch ( Exception $e ) {
1349 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1350 + return $response;
1351 + }
1352 +
1353 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1354 + }
1355 +
1356 + /**
1357 + * Create index table learnpress_sections
1358 + */
1359 + protected function modify_tb_lp_sections() {
1360 + $response = new LP_Step( __FUNCTION__, '' );
1361 + $lp_db = LP_Database::getInstance();
1362 +
1363 + try {
1364 + $indexs = array( 'section_course_id' );
1365 +
1366 + $lp_db->add_indexs_table( $lp_db->tb_lp_sections, $indexs );
1367 + } catch ( Exception $e ) {
1368 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1369 + return $response;
1370 + }
1371 +
1372 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1373 + }
1374 +
1375 + /**
1376 + * Create index table learnpress_section_items
1377 + */
1378 + protected function modify_tb_lp_section_items(): LP_Step {
1379 + $response = new LP_Step( __FUNCTION__, '' );
1380 + $lp_db = LP_Database::getInstance();
1381 +
1382 + try {
1383 + $lp_db->drop_indexs_table( $lp_db->tb_lp_section_items );
1384 +
1385 + $lp_db->wpdb->query(
1386 + "
1387 + ALTER TABLE {$lp_db->tb_lp_section_items}
1388 + ADD INDEX section_item (`section_id`, `item_id`)
1389 + "
1390 + );
1391 + $lp_db->check_execute_has_error();
1392 + } catch ( Exception $e ) {
1393 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1394 + return $response;
1395 + }
1396 +
1397 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1398 + }
1399 +
1400 + /**
1401 + * Convert Learnpress Settings
1402 + * 1. Courses thumbnail dimensions convert.
1403 + * 2. Profile thumbnail dimensions convert.
1404 + * 3. Profile rename dashboard to overview.
1405 + * 4. Block course by duration.
1406 + * 5. Block course when finished.
1407 + * 6. Assessment course by quizzes - Evaluate.
1408 + *
1409 + * @return LP_Step
1410 + */
1411 + protected function convert_lp_settings(): LP_Step {
1412 + $response = new LP_Step( __FUNCTION__, '' );
1413 + $lp_db = LP_Database::getInstance();
1414 +
1415 + try {
1416 + /**
1417 + * Update value on column option_name.
1418 + * Code update value option_name must write before re create indexes if not error "Duplicate entry".
1419 + */
1420 + // Drop table options.
1421 + $lp_db->drop_indexs_table( $lp_db->tb_options );
1422 +
1423 + // Courses thumbnail dimensions convert.
1424 + $check_option_thumbnail_dimensions_exists = $lp_db->wpdb->get_var(
1425 + "
1426 + SELECT option_name FROM $lp_db->tb_options
1427 + WHERE option_name = 'learn_press_course_thumbnail_dimensions'
1428 + "
1429 + );
1430 + if ( empty( $check_option_thumbnail_dimensions_exists ) ) {
1431 + $lp_db->wpdb->query(
1432 + "UPDATE $lp_db->tb_options
1433 + SET option_name = 'learn_press_course_thumbnail_dimensions'
1434 + WHERE option_name = 'learn_press_course_thumbnail_image_size'
1435 + "
1436 + );
1437 + $lp_db->check_execute_has_error();
1438 + }
1439 +
1440 + // Profile thumbnail dimensions convert.
1441 + $check_option_avatar_dimensions_exists = $lp_db->wpdb->get_var(
1442 + "
1443 + SELECT option_name FROM $lp_db->tb_options
1444 + WHERE option_name = 'learn_press_avatar_dimensions'
1445 + "
1446 + );
1447 + if ( empty( $check_option_avatar_dimensions_exists ) ) {
1448 + $lp_db->wpdb->query(
1449 + "UPDATE $lp_db->tb_options
1450 + SET option_name = 'learn_press_avatar_dimensions'
1451 + WHERE option_name = 'learn_press_profile_picture_thumbnail_size'
1452 + "
1453 + );
1454 + $lp_db->check_execute_has_error();
1455 + }
1456 +
1457 + // Delete value same of column "option_name" before re-create indexes for table options.
1458 + $data_sames = $lp_db->wpdb->get_results(
1459 + "
1460 + SELECT option_id, option_name, COUNT(option_name) as total
1461 + FROM $lp_db->tb_options
1462 + GROUP BY option_name
1463 + HAVING total > 1;
1464 + "
1465 + );
1466 + if ( $data_sames ) {
1467 + foreach ( $data_sames as $data_same ) {
1468 + $lp_db->wpdb->query(
1469 + $lp_db->wpdb->prepare(
1470 + "
1471 + DELETE FROM $lp_db->tb_options
1472 + WHERE option_name = %s
1473 + AND option_id != %d
1474 + ",
1475 + $data_same->option_name,
1476 + $data_same->option_id
1477 + )
1478 + );
1479 +
1480 + $lp_db->check_execute_has_error();
1481 + }
1482 + }
1483 +
1484 + // Create indexes for table options.
1485 + $lp_db->create_indexes_tb_options();
1486 + // End.
1487 +
1488 + // Profile rename dashboard to overview.
1489 + $learn_press_profile_endpoints = $lp_db->wpdb->get_var(
1490 + "
1491 + SELECT option_value FROM $lp_db->tb_options
1492 + WHERE option_name = 'learn_press_profile_endpoints'
1493 + "
1494 + );
1495 + $lp_db->check_execute_has_error();
1496 +
1497 + $learn_press_profile_endpoints = maybe_unserialize( $learn_press_profile_endpoints );
1498 +
1499 + $learn_press_profile_endpoints_tmp = array();
1500 + if ( $learn_press_profile_endpoints ) {
1501 + foreach ( $learn_press_profile_endpoints as $k => $val ) {
1502 + if ( 'profile-dashboard' === $k ) {
1503 + $learn_press_profile_endpoints_tmp['overview'] = $val;
1504 + } else {
1505 + $learn_press_profile_endpoints_tmp[ str_replace( 'profile-', '', $k ) ] = $val;
1506 + }
1507 + }
1508 + }
1509 +
1510 + $lp_db->wpdb->query(
1511 + $lp_db->wpdb->prepare(
1512 + "UPDATE $lp_db->tb_options
1513 + SET option_value = %s
1514 + WHERE option_name = 'learn_press_profile_endpoints'
1515 + ",
1516 + maybe_serialize( $learn_press_profile_endpoints_tmp )
1517 + )
1518 + );
1519 + $lp_db->check_execute_has_error();
1520 +
1521 + // Course settings.
1522 + // Block course by duration.
1523 + $lp_db->wpdb->query(
1524 + "UPDATE $lp_db->tb_postmeta
1525 + SET meta_key = '_lp_block_expire_duration'
1526 + WHERE meta_key = '_lp_block_course_item_duration_content'
1527 + "
1528 + );
1529 + $lp_db->check_execute_has_error();
1530 +
1531 + // Block course when finished.
1532 + $lp_db->wpdb->query(
1533 + "UPDATE $lp_db->tb_postmeta
1534 + SET meta_key = '_lp_block_finished'
1535 + WHERE meta_key = '_lp_block_lesson_content'
1536 + "
1537 + );
1538 + $lp_db->check_execute_has_error();
1539 +
1540 + // Assessment course by quizzes - Evaluate.
1541 + $lp_db->wpdb->query(
1542 + "UPDATE $lp_db->tb_postmeta
1543 + SET meta_value = 'evaluate_quiz'
1544 + WHERE meta_key = '_lp_course_result'
1545 + AND meta_value = 'evaluate_quizzes'
1546 + "
1547 + );
1548 + $lp_db->check_execute_has_error();
1549 +
1550 + // End course settings.
1551 +
1552 + // Quiz settings.
1553 + $lp_db->wpdb->query(
1554 + "
1555 + UPDATE $lp_db->tb_postmeta
1556 + SET meta_key = 'lp_review'
1557 + WHERE meta_key = '_lp_review_questions'
1558 + "
1559 + );
1560 + $lp_db->check_execute_has_error();
1561 +
1562 + $lp_db->wpdb->query(
1563 + "
1564 + UPDATE $lp_db->tb_postmeta
1565 + SET meta_key = '_lp_negative_marking'
1566 + WHERE meta_key = '_lp_minus_points'
1567 + "
1568 + );
1569 + $lp_db->check_execute_has_error();
1570 +
1571 + $lp_db->wpdb->query(
1572 + "
1573 + UPDATE $lp_db->tb_postmeta
1574 + SET meta_value = 'yes'
1575 + WHERE meta_key = '_lp_negative_marking'
1576 + AND meta_value > 0
1577 + "
1578 + );
1579 + $lp_db->check_execute_has_error();
1580 +
1581 + $lp_db->wpdb->query(
1582 + "
1583 + UPDATE $lp_db->tb_postmeta
1584 + SET meta_value = 'no'
1585 + WHERE meta_key = '_lp_negative_marking'
1586 + AND meta_value != 'yes'
1587 + "
1588 + );
1589 + $lp_db->check_execute_has_error();
1590 +
1591 + // Delete some fields not use.
1592 +
1593 + // Finish upgrade.
1594 + update_option( LP_KEY_DB_VERSION, 4 );
1595 + // update_option( 'learnpress_version', LEARNPRESS_VERSION );
1596 + // delete_option( 'lp_db_need_upgrade' );
1597 + } catch ( Exception $e ) {
1598 + $response->message = $this->error_step( $response->name, $e->getMessage() );
1599 + return $response;
1600 + }
1601 +
1602 + return $this->finish_step( $response, __FUNCTION__ . ' finished' );
1603 + }
1604 +}
1605 +
1606 +LP_Upgrade_4::get_instance();