PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.7
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.7
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 4.2.1 All 138 releases
← All changes | inc/Databases/DataBase.php +890 -890 4.3.94.4.7 View file →
@@ -1,890 +1,890 @@
1 -<?php
2 -
3 -namespace LearnPress\Databases;
4 -
5 -use Exception;
6 -use LearnPress\Filters\FilterBase;
7 -use wpdb;
8 -
9 -defined( 'ABSPATH' ) || exit();
10 -
11 -/**
12 - * Class DataBase
13 - *
14 - * @since 4.2.9.3
15 - * @version 1.0.0
16 - */
17 -class DataBase {
18 - private static $_instance;
19 - public $wpdb, $tb_users;
20 - public $tb_lp_courses;
21 - public $tb_lp_user_items, $tb_lp_user_itemmeta;
22 - public $tb_posts, $tb_postmeta, $tb_options;
23 - public $tb_terms, $tb_term_relationships, $tb_term_taxonomy;
24 - public $tb_lp_order_items, $tb_lp_order_itemmeta;
25 - public $tb_lp_sections, $tb_lp_section_items;
26 - public $tb_lp_quiz_questions;
27 - public $tb_lp_user_item_results;
28 - public $tb_lp_question_answers;
29 - public $tb_lp_question_answermeta;
30 - public $tb_lp_upgrade_db;
31 - public $tb_lp_sessions;
32 - public $tb_lp_files;
33 - public $tb_thim_cache;
34 - private $collate = '';
35 - public $max_index_length = '191';
36 -
37 - protected function __construct() {
38 - /**
39 - * @var wpdb $wpdb
40 - */
41 - global $wpdb;
42 - $prefix = $wpdb->prefix;
43 -
44 - $this->wpdb = $wpdb;
45 - $this->tb_users = $wpdb->users;
46 - $this->tb_posts = $wpdb->posts;
47 - $this->tb_postmeta = $wpdb->postmeta;
48 - $this->tb_options = $wpdb->options;
49 - $this->tb_terms = $wpdb->terms;
50 - $this->tb_term_relationships = $wpdb->term_relationships;
51 - $this->tb_term_taxonomy = $wpdb->term_taxonomy;
52 - $this->tb_lp_courses = $prefix . 'learnpress_courses';
53 - $this->tb_lp_user_items = $prefix . 'learnpress_user_items';
54 - $this->tb_lp_user_itemmeta = $prefix . 'learnpress_user_itemmeta';
55 - $this->tb_lp_order_items = $prefix . 'learnpress_order_items';
56 - $this->tb_lp_order_itemmeta = $prefix . 'learnpress_order_itemmeta';
57 - $this->tb_lp_section_items = $prefix . 'learnpress_section_items';
58 - $this->tb_lp_sections = $prefix . 'learnpress_sections';
59 - $this->tb_lp_quiz_questions = $prefix . 'learnpress_quiz_questions';
60 - $this->tb_lp_user_item_results = $prefix . 'learnpress_user_item_results';
61 - $this->tb_lp_question_answers = $prefix . 'learnpress_question_answers';
62 - $this->tb_lp_question_answermeta = $prefix . 'learnpress_question_answermeta';
63 - $this->tb_lp_upgrade_db = $prefix . 'learnpress_upgrade_db';
64 - $this->tb_lp_sessions = $prefix . 'learnpress_sessions';
65 - $this->tb_lp_files = $prefix . 'learnpress_files';
66 - $this->tb_thim_cache = $prefix . 'thim_cache';
67 - $this->wpdb->hide_errors();
68 - $this->set_collate();
69 - }
70 -
71 - /**
72 - * Get Instance
73 - *
74 - * @return DataBase
75 - */
76 - public static function getInstance() {
77 - if ( is_null( self::$_instance ) ) {
78 - self::$_instance = new self();
79 - }
80 -
81 - return self::$_instance;
82 - }
83 -
84 - public function set_collate() {
85 - $collate = '';
86 -
87 - if ( $this->wpdb->has_cap( 'collation' ) ) {
88 - if ( ! empty( $this->wpdb->charset ) ) {
89 - $collate .= 'DEFAULT CHARACTER SET ' . $this->wpdb->charset;
90 - }
91 -
92 - if ( ! empty( $this->wpdb->collate ) ) {
93 - $collate .= ' COLLATE ' . $this->wpdb->collate;
94 - }
95 - }
96 -
97 - $this->collate = $collate;
98 - }
99 -
100 - public function get_collate(): string {
101 - return $this->collate;
102 - }
103 -
104 - /**
105 - * Check table exists.
106 - *
107 - * @param string $name_table
108 - *
109 - * @return bool|int
110 - */
111 - public function check_table_exists( string $name_table ) {
112 - return $this->wpdb->query( $this->wpdb->prepare( "SHOW TABLES LIKE '%s'", $name_table ) );
113 - }
114 -
115 - /**
116 - * Clone table
117 - *
118 - * @param string $name_table .
119 - *
120 - * @throws Exception
121 - */
122 - public function clone_table( string $name_table ): bool {
123 - if ( ! current_user_can( ADMIN_ROLE ) ) {
124 - throw new Exception( 'You don\'t have permission' );
125 - }
126 -
127 - $table_bk = $name_table . '_bk';
128 -
129 - // Drop table bk if exists.
130 - $this->drop_table( $table_bk );
131 -
132 - // Clone table
133 - $this->wpdb->query( "CREATE TABLE $table_bk LIKE $name_table" );
134 - $this->wpdb->query( "INSERT INTO $table_bk SELECT * FROM $name_table" );
135 -
136 - /*dbDelta(
137 - "CREATE TABLE $table_bk LIKE $name_table;
138 - INSERT INTO $table_bk SELECT * FROM $name_table;"
139 - );*/
140 -
141 - $this->check_execute_has_error();
142 -
143 - return true;
144 - }
145 -
146 - /**
147 - * Check column table
148 - *
149 - * @param string $name_table .
150 - * @param string $name_col .
151 - *
152 - * @return bool|int
153 - */
154 - public function check_col_table( string $name_table = '', string $name_col = '' ) {
155 - $query = $this->wpdb->prepare( "SHOW COLUMNS FROM $name_table LIKE '%s'", $name_col );
156 -
157 - return $this->wpdb->query( $query );
158 - }
159 -
160 - /**
161 - * Drop Column of Table
162 - *
163 - * @param string $name_table .
164 - * @param string $name_col .
165 - *
166 - * @return bool|int
167 - * @throws Exception
168 - */
169 - public function drop_col_table( string $name_table = '', string $name_col = '' ) {
170 - if ( ! current_user_can( 'administrator' ) ) {
171 - return false;
172 - }
173 -
174 - $check_table = $this->check_col_table( $name_table, $name_col );
175 -
176 - if ( $check_table ) {
177 - $execute = $this->wpdb->query( "ALTER TABLE $name_table DROP COLUMN $name_col" );
178 -
179 - $this->check_execute_has_error();
180 -
181 - return $execute;
182 - }
183 -
184 - return true;
185 - }
186 -
187 - /**
188 - * Add Column of Table
189 - *
190 - * @param string $name_table .
191 - * @param string $name_col .
192 - * @param string $type .
193 - * @param string $after_col .
194 - *
195 - * @return bool|int
196 - * @throws Exception
197 - */
198 - public function add_col_table( string $name_table, string $name_col, string $type, string $after_col = '' ) {
199 - if ( ! current_user_can( ADMIN_ROLE ) ) {
200 - throw new Exception( 'You don\'t have permission' );
201 - }
202 -
203 - $query_add = '';
204 -
205 - $col_exists = $this->check_col_table( $name_table, $name_col );
206 -
207 - if ( ! empty( $after_col ) ) {
208 - $query_add .= "AFTER $after_col";
209 - }
210 -
211 - if ( ! $col_exists ) {
212 - $execute = $this->wpdb->query( "ALTER TABLE $name_table ADD COLUMN $name_col $type $query_add" );
213 -
214 - $this->check_execute_has_error();
215 -
216 - return $execute;
217 - }
218 -
219 - return true;
220 - }
221 -
222 - /**
223 - * Drop Index of Table
224 - *
225 - * @param string $name_table .
226 - *
227 - * @return void
228 - * @throws Exception
229 - */
230 - public function drop_indexs_table( string $name_table ) {
231 - $show_index = "SHOW INDEX FROM $name_table";
232 - $indexs = $this->wpdb->get_results( $show_index );
233 -
234 - foreach ( $indexs as $index ) {
235 - if ( 'PRIMARY' === $index->Key_name || '1' !== $index->Seq_in_index ) {
236 - continue;
237 - }
238 -
239 - $query = "ALTER TABLE $name_table DROP INDEX $index->Key_name";
240 -
241 - $this->wpdb->query( $query );
242 - $this->check_execute_has_error();
243 - }
244 - }
245 -
246 - /**
247 - * Add Index of Table
248 - *
249 - * @param string $name_table .
250 - * @param array $indexs .
251 - *
252 - * @return bool|int
253 - * @throws Exception
254 - */
255 - public function add_indexs_table( string $name_table, array $indexs ) {
256 - $add_index = '';
257 - $count_indexs = count( $indexs ) - 1;
258 -
259 - // Drop indexs .
260 - $this->drop_indexs_table( $name_table );
261 -
262 - foreach ( $indexs as $index ) {
263 - if ( $count_indexs === array_search( $index, $indexs ) ) {
264 - $add_index .= ' ADD INDEX ' . $index . ' (' . $index . ')';
265 - } else {
266 - $add_index .= ' ADD INDEX ' . $index . ' (' . $index . '),';
267 - }
268 - }
269 -
270 - $execute = $this->wpdb->query(
271 - "ALTER TABLE $name_table
272 - $add_index"
273 - );
274 -
275 - $this->check_execute_has_error();
276 -
277 - return $execute;
278 - }
279 -
280 - /**
281 - * Drop table
282 - *
283 - * @param string $name_table .
284 - *
285 - * @return bool|int
286 - * @throws Exception
287 - */
288 - public function drop_table( string $name_table = '' ) {
289 - if ( ! current_user_can( ADMIN_ROLE ) ) {
290 - throw new Exception( 'You don\'t have permission' );
291 - }
292 -
293 - // Check table exists.
294 - $tb_exists = $this->check_table_exists( $name_table );
295 - if ( $tb_exists ) {
296 - $execute = $this->wpdb->query( "DROP TABLE $name_table" );
297 -
298 - $this->check_execute_has_error();
299 -
300 - return $execute;
301 - }
302 -
303 - return true;
304 - }
305 -
306 - /**
307 - * Get list columns name of table
308 - *
309 - * @param string $name_table
310 - *
311 - * @return array
312 - * @throws Exception
313 - * @version 1.0.0
314 - * @since 4.1.6
315 - * @author tungnx
316 - */
317 - public function get_cols_of_table( string $name_table ): array {
318 - $query = "SHOW COLUMNS FROM $name_table";
319 -
320 - $result = $this->wpdb->get_col( $query );
321 -
322 - $this->check_execute_has_error();
323 -
324 - return $result;
325 - }
326 -
327 - /**
328 - * Create table learnpress_user_item_results
329 - *
330 - * @return bool|int
331 - * @throws Exception
332 - */
333 - public function create_tb_lp_user_item_results() {
334 - $collate = $this->get_collate();
335 -
336 - $execute = $this->wpdb->query(
337 - "
338 - CREATE TABLE IF NOT EXISTS $this->tb_lp_user_item_results(
339 - id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
340 - user_item_id bigint(20) unsigned NOT NULL,
341 - result longtext,
342 - PRIMARY KEY (id),
343 - KEY user_item_id (user_item_id)
344 - ) $collate
345 - "
346 - );
347 -
348 - $this->check_execute_has_error();
349 -
350 - return $execute;
351 - }
352 -
353 - /**
354 - * Create table learnpress_upgrade_db
355 - *
356 - * @return bool|int
357 - * @throws Exception
358 - */
359 - public function create_tb_lp_upgrade_db() {
360 - $collate = $this->get_collate();
361 -
362 - $execute = $this->wpdb->query(
363 - "
364 - CREATE TABLE IF NOT EXISTS {$this->tb_lp_upgrade_db}(
365 - step varchar(50) PRIMARY KEY UNIQUE,
366 - status varchar(10),
367 - KEY status (status)
368 - ) $collate
369 - "
370 - );
371 -
372 - $this->check_execute_has_error();
373 -
374 - return $execute;
375 - }
376 -
377 - /**
378 - * Set step completed.
379 - *
380 - * @param string $step .
381 - * @param string $status .
382 - *
383 - * @return int|bool
384 - */
385 - public function set_step_complete( string $step, string $status ) {
386 - if ( ! current_user_can( 'administrator' ) ) {
387 - return false;
388 - }
389 -
390 - return $this->wpdb->insert(
391 - $this->tb_lp_upgrade_db,
392 - array(
393 - 'step' => $step,
394 - 'status' => $status,
395 - ),
396 - array( '%s', '%s' )
397 - );
398 - }
399 -
400 - /**
401 - * Get steps completed.
402 - *
403 - * @return array|object|null
404 - */
405 - public function get_steps_completed() {
406 - return $this->wpdb->get_results( "SELECT step, status FROM {$this->tb_lp_upgrade_db}", OBJECT_K );
407 - }
408 -
409 - /**
410 - * Check execute current has any errors.
411 - *
412 - * @throws Exception
413 - */
414 - public function check_execute_has_error() {
415 - if ( $this->wpdb->last_error ) {
416 - throw new Exception( $this->wpdb->last_error );
417 - }
418 - }
419 -
420 - /**
421 - * Important: Reason need set again indexes for table options of WP
422 - * because if want change value of "option_name" will error "database error Duplicate entry"
423 - * So before set must drop and add when done all
424 - *
425 - * @throws Exception
426 - * @version 1.0.0
427 - * @since 4.0.3
428 - * @author tungnx
429 - */
430 - public function create_indexes_tb_options() {
431 - $this->drop_indexs_table( $this->tb_options );
432 - $result = $this->wpdb->query(
433 - "
434 - ALTER TABLE $this->tb_options
435 - ADD UNIQUE option_name (option_name),
436 - ADD INDEX autoload (autoload)
437 - "
438 - );
439 -
440 - $this->check_execute_has_error();
441 -
442 - return $result;
443 - }
444 -
445 - /**
446 - * Rename table
447 - *
448 - * @throws Exception
449 - * @version 1.0.0
450 - * @since 4.0.3
451 - * @author tungnx
452 - */
453 - public function rename_table( string $name_table = '', string $new_name = '' ) {
454 - if ( ! current_user_can( ADMIN_ROLE ) ) {
455 - throw new Exception( 'You don\'t have permission' );
456 - }
457 -
458 - $tb_exists = $this->check_table_exists( $name_table );
459 -
460 - if ( ! $tb_exists ) {
461 - throw new Exception( 'Table not exists' );
462 - }
463 -
464 - $result = $this->wpdb->query(
465 - "
466 - ALTER TABLE $name_table
467 - RENAME $new_name
468 - "
469 - );
470 - $this->check_execute_has_error();
471 -
472 - return $result;
473 - }
474 -
475 - /**
476 - * Check key postmeta exist on Database
477 - *
478 - * @param int $post_id
479 - * @param string $key
480 - *
481 - * @return bool|int
482 - */
483 - public function check_key_postmeta_exists( int $post_id = 0, string $key = '' ) {
484 - return $this->wpdb->query(
485 - $this->wpdb->prepare(
486 - "
487 - SELECT meta_id FROM $this->tb_postmeta
488 - WHERE meta_key = %s
489 - AND post_id = %d
490 - ",
491 - $key,
492 - $post_id
493 - )
494 - );
495 - }
496 -
497 - /**
498 - * Get total pages
499 - *
500 - * @param int $limit
501 - * @param int $total_rows
502 - *
503 - * @return int
504 - */
505 - public static function get_total_pages( int $limit = 0, int $total_rows = 0 ): int {
506 - if ( $limit == 0 ) {
507 - return 0;
508 - }
509 -
510 - $total_pages = (int) ceil( $total_rows / $limit );
511 -
512 - return (int) $total_pages;
513 - }
514 -
515 - /**
516 - * Get query string single row
517 - *
518 - * @param FilterBase $filter
519 - *
520 - * @since 4.2.5
521 - * @version 1.0.1
522 - */
523 - public function get_query_single_row( &$filter ) {
524 - $filter->limit = 1;
525 - $filter->return_string_query = true;
526 - $filter->run_query_count = false;
527 - }
528 -
529 - /**
530 - * Get result query
531 - *
532 - * @param FilterBase $filter
533 - * @param int $total_rows
534 - *
535 - * @return array|object|null|int|string
536 - * @throws Exception
537 - * @author tungnx
538 - * @version 1.0.2
539 - * @since 4.1.6
540 - */
541 - public function execute( $filter, int &$total_rows = 0 ) {
542 - $result = null;
543 -
544 - // Where
545 - $WHERE = array( 'WHERE 1=1' );
546 -
547 - // Fields select
548 - $FIELDS = '*';
549 - if ( ! empty( $filter->only_fields ) ) {
550 - $FIELDS = implode( ',', array_unique( $filter->only_fields ) );
551 - } elseif ( ! empty( $filter->fields ) ) {
552 - // exclude more fields
553 - if ( ! empty( $filter->exclude_fields ) ) {
554 - foreach ( $filter->exclude_fields as $field ) {
555 - $index_field = array_search( $field, $filter->fields );
556 - if ( $index_field ) {
557 - unset( $filter->fields[ $index_field ] );
558 - }
559 - }
560 - }
561 -
562 - foreach ( $filter->fields as $key => $field ) {
563 - if ( $field === 'order' ) {
564 - // Replace order with `order` to avoid conflict with SQL reserved word.
565 - $filter->fields[ $key ] = '`order`';
566 - break;
567 - }
568 - }
569 -
570 - $FIELDS = implode( ',', array_unique( $filter->fields ) );
571 - }
572 - $FIELDS = apply_filters( 'lp/query/fields', $FIELDS, $filter );
573 -
574 - $INNER_JOIN = array();
575 - $INNER_JOIN = array_merge( $INNER_JOIN, $filter->join );
576 - $INNER_JOIN = apply_filters( 'lp/query/inner_join', $INNER_JOIN, $filter );
577 - $INNER_JOIN = implode( ' ', array_unique( $INNER_JOIN ) );
578 -
579 - $WHERE = array_merge( $WHERE, $filter->where );
580 - $WHERE = apply_filters( 'lp/query/where', $WHERE, $filter );
581 - $WHERE = implode( ' ', array_unique( $WHERE ) );
582 -
583 - // Group by
584 - $GROUP_BY = '';
585 - if ( $filter->group_by ) {
586 - $GROUP_BY .= 'GROUP BY ' . $filter->group_by;
587 - $GROUP_BY = apply_filters( 'lp/query/group_by', $GROUP_BY, $filter );
588 - }
589 -
590 - // Order by
591 - $ORDER_BY = '';
592 - if ( $filter->order_by ) {
593 - $filter->order = strtoupper( $filter->order );
594 - if ( ! in_array( $filter->order, [ 'DESC', 'ASC' ] ) ) {
595 - $filter->order = 'DESC';
596 - }
597 -
598 - $ORDER_BY .= 'ORDER BY ' . $filter->order_by . ' ' . $filter->order . ' ';
599 - $ORDER_BY = apply_filters( 'lp/query/order_by', $ORDER_BY, $filter );
600 - }
601 -
602 - // Limit
603 - $LIMIT = '';
604 - if ( $filter->limit != - 1 ) {
605 - $filter->limit = absint( $filter->limit );
606 - /*if ( $filter->limit > $filter->max_limit ) {
607 - $filter->limit = $filter->max_limit;
608 - }*/
609 - $offset = $filter->limit * ( $filter->page - 1 );
610 - $LIMIT = $this->wpdb->prepare( 'LIMIT %d, %d', $offset, $filter->limit );
611 - }
612 -
613 - // For nest query
614 - if ( $filter->return_string_query ) {
615 - $LIMIT = '';
616 - }
617 -
618 - // From table or group select
619 - $COLLECTION = '';
620 - if ( ! empty( $filter->collection ) ) {
621 - $COLLECTION = $filter->collection;
622 - }
623 -
624 - // Alias table
625 - $ALIAS_COLLECTION = 'X';
626 - if ( ! empty( $filter->collection_alias ) ) {
627 - $ALIAS_COLLECTION = $filter->collection_alias;
628 - }
629 -
630 - // Query
631 - $query = "SELECT $FIELDS FROM $COLLECTION AS $ALIAS_COLLECTION
632 - $INNER_JOIN
633 - $WHERE
634 - $GROUP_BY
635 - $ORDER_BY
636 - $LIMIT
637 - ";
638 -
639 - if ( $filter->return_string_query ) {
640 - return $query;
641 - } elseif ( ! empty( $filter->union ) ) {
642 - $query = implode( ' UNION ', array_unique( $filter->union ) );
643 - $query .= $GROUP_BY;
644 - $query .= $ORDER_BY;
645 - $query .= $LIMIT;
646 - }
647 -
648 - if ( ! $filter->query_count ) {
649 - // Debug string query
650 - if ( $filter->debug_string_query ) {
651 - return $query;
652 - }
653 -
654 - $result = $this->wpdb->get_results( $query );
655 - }
656 -
657 - // Query total rows
658 - if ( $filter->run_query_count ) {
659 - $query = str_replace( array( $LIMIT, $ORDER_BY ), '', $query );
660 - $query_total = "SELECT COUNT($filter->field_count) FROM ($query) AS $ALIAS_COLLECTION";
661 - $total_rows = (int) $this->wpdb->get_var( $query_total );
662 -
663 - $this->check_execute_has_error();
664 -
665 - if ( $filter->query_count ) {
666 - // Debug string query
667 - if ( $filter->debug_string_query ) {
668 - return $query_total;
669 - }
670 -
671 - return $total_rows;
672 - }
673 - }
674 -
675 - $this->check_execute_has_error();
676 -
677 - return $result;
678 - }
679 -
680 - /**
681 - * Query update
682 - *
683 - * @param FilterBase $filter
684 - *
685 - * @throws Exception
686 - * @since 4.1.7
687 - * @version 1.0.1
688 - */
689 - public function update_execute( $filter ) {
690 -
691 - $COLLECTION = $filter->collection;
692 -
693 - // SET value
694 - $SET = apply_filters( 'lp/query/update/set', $filter->set, $filter );
695 - $SET = implode( ',', array_unique( $SET ) );
696 -
697 - // Where
698 - $WHERE = array( 'WHERE 1=1' );
699 - $WHERE = array_merge( $WHERE, $filter->where );
700 - $WHERE = apply_filters( 'lp/query/update/where', $WHERE, $filter );
701 - $WHERE = implode( ' ', array_unique( $WHERE ) );
702 -
703 - $query = "
704 - UPDATE $COLLECTION
705 - SET $SET
706 - $WHERE
707 - ";
708 -
709 - $result = $this->wpdb->query( $query );
710 -
711 - $this->check_execute_has_error();
712 -
713 - return $result;
714 - }
715 -
716 - /**
717 - * Query delete
718 - *
719 - * @param FilterBase $filter
720 - * @param string $table
721 - *
722 - * @return bool|int|\mysqli_result|string|null
723 - * @throws Exception
724 - * @since 4.1.7
725 - * @version 1.0.1
726 - */
727 - public function delete_execute( $filter, string $table = '' ) {
728 - $COLLECTION = $filter->collection;
729 -
730 - // Where
731 - $WHERE = array( 'WHERE 1=1' );
732 - $WHERE = array_merge( $WHERE, $filter->where );
733 - $WHERE = apply_filters( 'lp/query/delete/where', $WHERE, $filter );
734 - $WHERE = implode( ' ', array_unique( $WHERE ) );
735 -
736 - // Join
737 - $INNER_JOIN = array();
738 - $INNER_JOIN = array_merge( $INNER_JOIN, $filter->join );
739 - $INNER_JOIN = apply_filters( 'lp/query/delete/inner_join', $INNER_JOIN, $filter );
740 - $INNER_JOIN = implode( ' ', array_unique( $INNER_JOIN ) );
741 -
742 - $query = "
743 - DELETE $table FROM $COLLECTION
744 - $INNER_JOIN
745 - $WHERE
746 - ";
747 -
748 - if ( $filter->return_string_query ) {
749 - return $query;
750 - }
751 -
752 - $result = $this->wpdb->query( $query );
753 -
754 - $this->check_execute_has_error();
755 -
756 - return $result;
757 - }
758 -
759 - /**
760 - * Get values of list object by key
761 - *
762 - * @param array $arr_object
763 - * @param string $key
764 - *
765 - * @return array
766 - */
767 - public static function get_values_by_key( array $arr_object, string $key = 'ID' ): array {
768 - $arr_object_ids = array();
769 - foreach ( $arr_object as $object ) {
770 - $arr_object_ids[] = $object->{$key};
771 - }
772 -
773 - return $arr_object_ids;
774 - }
775 -
776 - /**
777 - * Insert data
778 - *
779 - * @param array $args [ 'data' => [], 'filter' => FilterBase, 'table_name' => '', 'key_auto_increment' => '' ]
780 - *
781 - * @return int
782 - * @throws Exception
783 - * @version 1.0.1
784 - * @since 4.2.9
785 - */
786 - public function insert_data( array $args ): int {
787 - $data = $args['data'] ?? [];
788 - $filter = $args['filter'] ?? null;
789 - $table_name = $args['table_name'] ?? '';
790 - $key_auto_increment = $args['key_auto_increment'] ?? '';
791 - $key_auto_increment = sanitize_key( $key_auto_increment );
792 -
793 - if ( empty( $data ) || ! is_array( $data ) ) {
794 - throw new Exception( __( 'Data must be an array!', 'learnpress' ) . ' | ' . __FUNCTION__ );
795 - }
796 -
797 - /*if ( ! $filter instanceof FilterBase ) {
798 - throw new Exception( __( 'Invalid filter!', 'learnpress' ) . ' | ' . __FUNCTION__ );
799 - }*/
800 -
801 - if ( empty( $filter->all_fields ) ) {
802 - throw new Exception( __( 'Filter must have property all_fields!', 'learnpress' ) . ' | ' . __FUNCTION__ );
803 - }
804 -
805 - if ( empty( $table_name ) ) {
806 - throw new Exception( __( 'Table name is required!', 'learnpress' ) . ' | ' . __FUNCTION__ );
807 - }
808 -
809 - if ( empty( $key_auto_increment ) || ! is_string( $key_auto_increment ) ) {
810 - throw new Exception( __( 'Key auto increment must be a string!', 'learnpress' ) . ' | ' . __FUNCTION__ );
811 - }
812 -
813 - foreach ( $data as $col_name => $value ) {
814 - if ( ! in_array( $col_name, $filter->all_fields ) ) {
815 - unset( $data[ $col_name ] );
816 - }
817 - }
818 -
819 - // unset key is auto increment.
820 - unset( $data[ $key_auto_increment ] );
821 -
822 - $this->wpdb->insert( $table_name, $data );
823 -
824 - $this->check_execute_has_error();
825 -
826 - return $this->wpdb->insert_id;
827 - }
828 -
829 - /**
830 - * Update data
831 - *
832 - * @param array $args
833 - *
834 - * @return bool
835 - *
836 - * @throws Exception
837 - * @since 4.2.9
838 - * @version 1.0.1
839 - */
840 - public function update_data( array $args ): bool {
841 - $data = $args['data'] ?? [];
842 - $filter = $args['filter'] ?? null;
843 - $table_name = $args['table_name'] ?? '';
844 - $where_key = $args['where_key'] ?? '';
845 - $where_key = sanitize_key( $where_key );
846 -
847 - /*if ( ! $filter instanceof FilterBase ) {
848 - throw new Exception( __( 'Invalid filter!', 'learnpress' ) . ' | ' . __FUNCTION__ );
849 - }*/
850 -
851 - if ( empty( $filter->all_fields ) ) {
852 - throw new Exception( __( 'Filter must have property all_fields!', 'learnpress' ) . ' | ' . __FUNCTION__ );
853 - }
854 -
855 - if ( empty( $data ) || ! is_array( $data ) ) {
856 - throw new Exception( __( 'Data must be an array!', 'learnpress' ) . ' | ' . __FUNCTION__ );
857 - }
858 -
859 - if ( empty( $where_key ) ) {
860 - throw new Exception( __( 'Invalid where key!', 'learnpress' ) . ' | ' . __FUNCTION__ );
861 - }
862 -
863 - if ( empty( $table_name ) ) {
864 - throw new Exception( __( 'Table name is required!', 'learnpress' ) . ' | ' . __FUNCTION__ );
865 - }
866 -
867 - $filter->collection = $table_name;
868 - foreach ( $data as $col_name => $value ) {
869 - if ( ! in_array( $col_name, $filter->all_fields ) ) {
870 - continue;
871 - }
872 -
873 - // Key `order` is reserved keyword in MySQL
874 - if ( $col_name === 'order' ) {
875 - $col_name = '`order`';
876 - }
877 -
878 - if ( is_null( $value ) ) {
879 - $filter->set[] = $col_name . ' = null';
880 - } else {
881 - $filter->set[] = $this->wpdb->prepare( $col_name . ' = %s', $value );
882 - }
883 - }
884 -
885 - $filter->where[] = $this->wpdb->prepare( "AND $where_key = %d", $data[ $where_key ] );
886 - $this->update_execute( $filter );
887 -
888 - return true;
889 - }
890 -}
1 +<?php
2 +
3 +namespace LearnPress\Databases;
4 +
5 +use Exception;
6 +use LearnPress\Filters\FilterBase;
7 +use wpdb;
8 +
9 +defined( 'ABSPATH' ) || exit();
10 +
11 +/**
12 + * Class DataBase
13 + *
14 + * @since 4.2.9.3
15 + * @version 1.0.0
16 + */
17 +class DataBase {
18 + private static $_instance;
19 + public $wpdb, $tb_users;
20 + public $tb_lp_courses;
21 + public $tb_lp_user_items, $tb_lp_user_itemmeta;
22 + public $tb_posts, $tb_postmeta, $tb_options;
23 + public $tb_terms, $tb_term_relationships, $tb_term_taxonomy;
24 + public $tb_lp_order_items, $tb_lp_order_itemmeta;
25 + public $tb_lp_sections, $tb_lp_section_items;
26 + public $tb_lp_quiz_questions;
27 + public $tb_lp_user_item_results;
28 + public $tb_lp_question_answers;
29 + public $tb_lp_question_answermeta;
30 + public $tb_lp_upgrade_db;
31 + public $tb_lp_sessions;
32 + public $tb_lp_files;
33 + public $tb_lp_webhooks;
34 + public $tb_thim_cache;
35 + private $collate = '';
36 + public $max_index_length = '191';
37 +
38 + protected function __construct() {
39 + /**
40 + * @var wpdb $wpdb
41 + */
42 + global $wpdb;
43 + $prefix = $wpdb->prefix;
44 +
45 + $this->wpdb = $wpdb;
46 + $this->tb_users = $wpdb->users;
47 + $this->tb_posts = $wpdb->posts;
48 + $this->tb_postmeta = $wpdb->postmeta;
49 + $this->tb_options = $wpdb->options;
50 + $this->tb_terms = $wpdb->terms;
51 + $this->tb_term_relationships = $wpdb->term_relationships;
52 + $this->tb_term_taxonomy = $wpdb->term_taxonomy;
53 + $this->tb_lp_courses = $prefix . 'learnpress_courses';
54 + $this->tb_lp_user_items = $prefix . 'learnpress_user_items';
55 + $this->tb_lp_user_itemmeta = $prefix . 'learnpress_user_itemmeta';
56 + $this->tb_lp_order_items = $prefix . 'learnpress_order_items';
57 + $this->tb_lp_order_itemmeta = $prefix . 'learnpress_order_itemmeta';
58 + $this->tb_lp_section_items = $prefix . 'learnpress_section_items';
59 + $this->tb_lp_sections = $prefix . 'learnpress_sections';
60 + $this->tb_lp_quiz_questions = $prefix . 'learnpress_quiz_questions';
61 + $this->tb_lp_user_item_results = $prefix . 'learnpress_user_item_results';
62 + $this->tb_lp_question_answers = $prefix . 'learnpress_question_answers';
63 + $this->tb_lp_question_answermeta = $prefix . 'learnpress_question_answermeta';
64 + $this->tb_lp_upgrade_db = $prefix . 'learnpress_upgrade_db';
65 + $this->tb_lp_sessions = $prefix . 'learnpress_sessions';
66 + $this->tb_lp_files = $prefix . 'learnpress_files';
67 + $this->tb_lp_webhooks = $prefix . 'learnpress_webhooks';
68 + $this->tb_thim_cache = $prefix . 'thim_cache';
69 + $this->wpdb->hide_errors();
70 + $this->set_collate();
71 + }
72 +
73 + /**
74 + * Get Instance
75 + *
76 + * @return DataBase
77 + */
78 + public static function getInstance() {
79 + if ( is_null( self::$_instance ) ) {
80 + self::$_instance = new self();
81 + }
82 +
83 + return self::$_instance;
84 + }
85 +
86 + public function set_collate() {
87 + $collate = '';
88 +
89 + if ( $this->wpdb->has_cap( 'collation' ) ) {
90 + if ( ! empty( $this->wpdb->charset ) ) {
91 + $collate .= 'DEFAULT CHARACTER SET ' . $this->wpdb->charset;
92 + }
93 +
94 + if ( ! empty( $this->wpdb->collate ) ) {
95 + $collate .= ' COLLATE ' . $this->wpdb->collate;
96 + }
97 + }
98 +
99 + $this->collate = $collate;
100 + }
101 +
102 + public function get_collate(): string {
103 + return $this->collate;
104 + }
105 +
106 + /**
107 + * Check table exists.
108 + *
109 + * @param string $name_table
110 + *
111 + * @return bool|int
112 + */
113 + public function check_table_exists( string $name_table ) {
114 + return $this->wpdb->query( $this->wpdb->prepare( "SHOW TABLES LIKE '%s'", $name_table ) );
115 + }
116 +
117 + /**
118 + * Clone table
119 + *
120 + * @param string $name_table .
121 + *
122 + * @throws Exception
123 + */
124 + public function clone_table( string $name_table ): bool {
125 + if ( ! current_user_can( ADMIN_ROLE ) ) {
126 + throw new Exception( 'You don\'t have permission' );
127 + }
128 +
129 + $table_bk = $name_table . '_bk';
130 +
131 + // Drop table bk if exists.
132 + $this->drop_table( $table_bk );
133 +
134 + // Clone table
135 + $this->wpdb->query( "CREATE TABLE $table_bk LIKE $name_table" );
136 + $this->wpdb->query( "INSERT INTO $table_bk SELECT * FROM $name_table" );
137 +
138 + /*dbDelta(
139 + "CREATE TABLE $table_bk LIKE $name_table;
140 + INSERT INTO $table_bk SELECT * FROM $name_table;"
141 + );*/
142 +
143 + $this->check_execute_has_error();
144 +
145 + return true;
146 + }
147 +
148 + /**
149 + * Check column table
150 + *
151 + * @param string $name_table .
152 + * @param string $name_col .
153 + *
154 + * @return bool|int
155 + */
156 + public function check_col_table( string $name_table = '', string $name_col = '' ) {
157 + $query = $this->wpdb->prepare( "SHOW COLUMNS FROM $name_table LIKE '%s'", $name_col );
158 +
159 + return $this->wpdb->query( $query );
160 + }
161 +
162 + /**
163 + * Drop Column of Table
164 + *
165 + * @param string $name_table .
166 + * @param string $name_col .
167 + *
168 + * @return bool|int
169 + * @throws Exception
170 + */
171 + public function drop_col_table( string $name_table = '', string $name_col = '' ) {
172 + if ( ! current_user_can( 'administrator' ) ) {
173 + return false;
174 + }
175 +
176 + $check_table = $this->check_col_table( $name_table, $name_col );
177 +
178 + if ( $check_table ) {
179 + $execute = $this->wpdb->query( "ALTER TABLE $name_table DROP COLUMN $name_col" );
180 +
181 + $this->check_execute_has_error();
182 +
183 + return $execute;
184 + }
185 +
186 + return true;
187 + }
188 +
189 + /**
190 + * Add Column of Table
191 + *
192 + * @param string $name_table .
193 + * @param string $name_col .
194 + * @param string $type .
195 + * @param string $after_col .
196 + *
197 + * @return bool|int
198 + * @throws Exception
199 + */
200 + public function add_col_table( string $name_table, string $name_col, string $type, string $after_col = '' ) {
201 + if ( ! current_user_can( ADMIN_ROLE ) ) {
202 + return false;
203 + }
204 +
205 + $query_add = '';
206 +
207 + $col_exists = $this->check_col_table( $name_table, $name_col );
208 +
209 + if ( ! empty( $after_col ) ) {
210 + $query_add .= "AFTER $after_col";
211 + }
212 +
213 + if ( ! $col_exists ) {
214 + $execute = $this->wpdb->query( "ALTER TABLE $name_table ADD COLUMN $name_col $type $query_add" );
215 +
216 + $this->check_execute_has_error();
217 +
218 + return $execute;
219 + }
220 +
221 + return true;
222 + }
223 +
224 + /**
225 + * Drop Index of Table
226 + *
227 + * @param string $name_table .
228 + *
229 + * @return void
230 + * @throws Exception
231 + */
232 + public function drop_indexs_table( string $name_table ) {
233 + $show_index = "SHOW INDEX FROM $name_table";
234 + $indexs = $this->wpdb->get_results( $show_index );
235 +
236 + foreach ( $indexs as $index ) {
237 + if ( 'PRIMARY' === $index->Key_name || '1' !== $index->Seq_in_index ) {
238 + continue;
239 + }
240 +
241 + $query = "ALTER TABLE $name_table DROP INDEX $index->Key_name";
242 +
243 + $this->wpdb->query( $query );
244 + $this->check_execute_has_error();
245 + }
246 + }
247 +
248 + /**
249 + * Add Index of Table
250 + *
251 + * @param string $name_table .
252 + * @param array $indexs .
253 + *
254 + * @return bool|int
255 + * @throws Exception
256 + */
257 + public function add_indexs_table( string $name_table, array $indexs ) {
258 + $add_index = '';
259 + $count_indexs = count( $indexs ) - 1;
260 +
261 + // Drop indexs .
262 + $this->drop_indexs_table( $name_table );
263 +
264 + foreach ( $indexs as $index ) {
265 + if ( $count_indexs === array_search( $index, $indexs ) ) {
266 + $add_index .= ' ADD INDEX ' . $index . ' (' . $index . ')';
267 + } else {
268 + $add_index .= ' ADD INDEX ' . $index . ' (' . $index . '),';
269 + }
270 + }
271 +
272 + $execute = $this->wpdb->query(
273 + "ALTER TABLE $name_table
274 + $add_index"
275 + );
276 +
277 + $this->check_execute_has_error();
278 +
279 + return $execute;
280 + }
281 +
282 + /**
283 + * Drop table
284 + *
285 + * @param string $name_table .
286 + *
287 + * @return bool|int
288 + * @throws Exception
289 + */
290 + public function drop_table( string $name_table = '' ) {
291 + if ( ! current_user_can( ADMIN_ROLE ) ) {
292 + throw new Exception( 'You don\'t have permission' );
293 + }
294 +
295 + // Check table exists.
296 + $tb_exists = $this->check_table_exists( $name_table );
297 + if ( $tb_exists ) {
298 + $execute = $this->wpdb->query( "DROP TABLE $name_table" );
299 +
300 + $this->check_execute_has_error();
301 +
302 + return $execute;
303 + }
304 +
305 + return true;
306 + }
307 +
308 + /**
309 + * Get list columns name of table
310 + *
311 + * @param string $name_table
312 + *
313 + * @return array
314 + * @throws Exception
315 + * @version 1.0.0
316 + * @since 4.1.6
317 + * @author tungnx
318 + */
319 + public function get_cols_of_table( string $name_table ): array {
320 + $query = "SHOW COLUMNS FROM $name_table";
321 +
322 + $result = $this->wpdb->get_col( $query );
323 +
324 + $this->check_execute_has_error();
325 +
326 + return $result;
327 + }
328 +
329 + /**
330 + * Create table learnpress_user_item_results
331 + *
332 + * @return bool|int
333 + * @throws Exception
334 + */
335 + public function create_tb_lp_user_item_results() {
336 + $collate = $this->get_collate();
337 +
338 + $execute = $this->wpdb->query(
339 + "
340 + CREATE TABLE IF NOT EXISTS $this->tb_lp_user_item_results(
341 + id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
342 + user_item_id bigint(20) unsigned NOT NULL,
343 + result longtext,
344 + PRIMARY KEY (id),
345 + KEY user_item_id (user_item_id)
346 + ) $collate
347 + "
348 + );
349 +
350 + $this->check_execute_has_error();
351 +
352 + return $execute;
353 + }
354 +
355 + /**
356 + * Create table learnpress_upgrade_db
357 + *
358 + * @return bool|int
359 + * @throws Exception
360 + */
361 + public function create_tb_lp_upgrade_db() {
362 + $collate = $this->get_collate();
363 +
364 + $execute = $this->wpdb->query(
365 + "
366 + CREATE TABLE IF NOT EXISTS {$this->tb_lp_upgrade_db}(
367 + step varchar(50) PRIMARY KEY UNIQUE,
368 + status varchar(10),
369 + KEY status (status)
370 + ) $collate
371 + "
372 + );
373 +
374 + $this->check_execute_has_error();
375 +
376 + return $execute;
377 + }
378 +
379 + /**
380 + * Set step completed.
381 + *
382 + * @param string $step .
383 + * @param string $status .
384 + *
385 + * @return int|bool
386 + */
387 + public function set_step_complete( string $step, string $status ) {
388 + if ( ! current_user_can( 'administrator' ) ) {
389 + return false;
390 + }
391 +
392 + return $this->wpdb->insert(
393 + $this->tb_lp_upgrade_db,
394 + array(
395 + 'step' => $step,
396 + 'status' => $status,
397 + ),
398 + array( '%s', '%s' )
399 + );
400 + }
401 +
402 + /**
403 + * Get steps completed.
404 + *
405 + * @return array|object|null
406 + */
407 + public function get_steps_completed() {
408 + return $this->wpdb->get_results( "SELECT step, status FROM {$this->tb_lp_upgrade_db}", OBJECT_K );
409 + }
410 +
411 + /**
412 + * Check execute current has any errors.
413 + *
414 + * @throws Exception
415 + */
416 + public function check_execute_has_error() {
417 + if ( $this->wpdb->last_error ) {
418 + throw new Exception( $this->wpdb->last_error );
419 + }
420 + }
421 +
422 + /**
423 + * Important: Reason need set again indexes for table options of WP
424 + * because if want change value of "option_name" will error "database error Duplicate entry"
425 + * So before set must drop and add when done all
426 + *
427 + * @throws Exception
428 + * @version 1.0.0
429 + * @since 4.0.3
430 + * @author tungnx
431 + */
432 + public function create_indexes_tb_options() {
433 + $this->drop_indexs_table( $this->tb_options );
434 + $result = $this->wpdb->query(
435 + "
436 + ALTER TABLE $this->tb_options
437 + ADD UNIQUE option_name (option_name),
438 + ADD INDEX autoload (autoload)
439 + "
440 + );
441 +
442 + $this->check_execute_has_error();
443 +
444 + return $result;
445 + }
446 +
447 + /**
448 + * Rename table
449 + *
450 + * @throws Exception
451 + * @version 1.0.0
452 + * @since 4.0.3
453 + * @author tungnx
454 + */
455 + public function rename_table( string $name_table = '', string $new_name = '' ) {
456 + if ( ! current_user_can( ADMIN_ROLE ) ) {
457 + throw new Exception( 'You don\'t have permission' );
458 + }
459 +
460 + $tb_exists = $this->check_table_exists( $name_table );
461 +
462 + if ( ! $tb_exists ) {
463 + throw new Exception( 'Table not exists' );
464 + }
465 +
466 + $result = $this->wpdb->query(
467 + "
468 + ALTER TABLE $name_table
469 + RENAME $new_name
470 + "
471 + );
472 + $this->check_execute_has_error();
473 +
474 + return $result;
475 + }
476 +
477 + /**
478 + * Check key postmeta exist on Database
479 + *
480 + * @param int $post_id
481 + * @param string $key
482 + *
483 + * @return bool|int
484 + */
485 + public function check_key_postmeta_exists( int $post_id = 0, string $key = '' ) {
486 + return $this->wpdb->query(
487 + $this->wpdb->prepare(
488 + "
489 + SELECT meta_id FROM $this->tb_postmeta
490 + WHERE meta_key = %s
491 + AND post_id = %d
492 + ",
493 + $key,
494 + $post_id
495 + )
496 + );
497 + }
498 +
499 + /**
500 + * Get total pages
501 + *
502 + * @param int $limit
503 + * @param int $total_rows
504 + *
505 + * @return int
506 + */
507 + public static function get_total_pages( int $limit = 0, int $total_rows = 0 ): int {
508 + if ( $limit == 0 ) {
509 + return 0;
510 + }
511 +
512 + $total_pages = (int) ceil( $total_rows / $limit );
513 +
514 + return (int) $total_pages;
515 + }
516 +
517 + /**
518 + * Get query string single row
519 + *
520 + * @param FilterBase $filter
521 + *
522 + * @since 4.2.5
523 + * @version 1.0.1
524 + */
525 + public function get_query_single_row( &$filter ) {
526 + $filter->limit = 1;
527 + $filter->return_string_query = true;
528 + $filter->run_query_count = false;
529 + }
530 +
531 + /**
532 + * Get result query
533 + *
534 + * @param FilterBase $filter
535 + * @param int $total_rows
536 + *
537 + * @return array|object|null|int|string
538 + * @throws Exception
539 + * @author tungnx
540 + * @version 1.0.2
541 + * @since 4.1.6
542 + */
543 + public function execute( $filter, int &$total_rows = 0 ) {
544 + $result = null;
545 +
546 + // Where
547 + $WHERE = array( 'WHERE 1=1' );
548 +
549 + // Fields select
550 + $FIELDS = '*';
551 + if ( ! empty( $filter->only_fields ) ) {
552 + $FIELDS = implode( ',', array_unique( $filter->only_fields ) );
553 + } elseif ( ! empty( $filter->fields ) ) {
554 + // exclude more fields
555 + if ( ! empty( $filter->exclude_fields ) ) {
556 + foreach ( $filter->exclude_fields as $field ) {
557 + $index_field = array_search( $field, $filter->fields );
558 + if ( $index_field ) {
559 + unset( $filter->fields[ $index_field ] );
560 + }
561 + }
562 + }
563 +
564 + foreach ( $filter->fields as $key => $field ) {
565 + if ( $field === 'order' ) {
566 + // Replace order with `order` to avoid conflict with SQL reserved word.
567 + $filter->fields[ $key ] = '`order`';
568 + break;
569 + }
570 + }
571 +
572 + $FIELDS = implode( ',', array_unique( $filter->fields ) );
573 + }
574 + $FIELDS = apply_filters( 'lp/query/fields', $FIELDS, $filter );
575 +
576 + $INNER_JOIN = array();
577 + $INNER_JOIN = array_merge( $INNER_JOIN, $filter->join );
578 + $INNER_JOIN = apply_filters( 'lp/query/inner_join', $INNER_JOIN, $filter );
579 + $INNER_JOIN = implode( ' ', array_unique( $INNER_JOIN ) );
580 +
581 + $WHERE = array_merge( $WHERE, $filter->where );
582 + $WHERE = apply_filters( 'lp/query/where', $WHERE, $filter );
583 + $WHERE = implode( ' ', array_unique( $WHERE ) );
584 +
585 + // Group by
586 + $GROUP_BY = '';
587 + if ( $filter->group_by ) {
588 + $GROUP_BY .= 'GROUP BY ' . $filter->group_by;
589 + $GROUP_BY = apply_filters( 'lp/query/group_by', $GROUP_BY, $filter );
590 + }
591 +
592 + // Order by
593 + $ORDER_BY = '';
594 + if ( $filter->order_by ) {
595 + $filter->order = strtoupper( $filter->order );
596 + if ( ! in_array( $filter->order, [ 'DESC', 'ASC' ] ) ) {
597 + $filter->order = 'DESC';
598 + }
599 +
600 + $ORDER_BY .= 'ORDER BY ' . $filter->order_by . ' ' . $filter->order . ' ';
601 + $ORDER_BY = apply_filters( 'lp/query/order_by', $ORDER_BY, $filter );
602 + }
603 +
604 + // Limit
605 + $LIMIT = '';
606 + if ( $filter->limit != - 1 ) {
607 + $filter->limit = absint( $filter->limit );
608 + /*if ( $filter->limit > $filter->max_limit ) {
609 + $filter->limit = $filter->max_limit;
610 + }*/
611 + $offset = $filter->limit * ( $filter->page - 1 );
612 + $LIMIT = $this->wpdb->prepare( 'LIMIT %d, %d', $offset, $filter->limit );
613 + }
614 +
615 + // For nest query
616 + if ( $filter->return_string_query ) {
617 + $LIMIT = '';
618 + }
619 +
620 + // From table or group select
621 + $COLLECTION = '';
622 + if ( ! empty( $filter->collection ) ) {
623 + $COLLECTION = $filter->collection;
624 + }
625 +
626 + // Alias table
627 + $ALIAS_COLLECTION = 'X';
628 + if ( ! empty( $filter->collection_alias ) ) {
629 + $ALIAS_COLLECTION = $filter->collection_alias;
630 + }
631 +
632 + // Query
633 + $query = "SELECT $FIELDS FROM $COLLECTION AS $ALIAS_COLLECTION
634 + $INNER_JOIN
635 + $WHERE
636 + $GROUP_BY
637 + $ORDER_BY
638 + $LIMIT
639 + ";
640 +
641 + if ( $filter->return_string_query ) {
642 + return $query;
643 + } elseif ( ! empty( $filter->union ) ) {
644 + $query = implode( ' UNION ', array_unique( $filter->union ) );
645 + $query .= $GROUP_BY;
646 + $query .= $ORDER_BY;
647 + $query .= $LIMIT;
648 + }
649 +
650 + if ( ! $filter->query_count ) {
651 + // Debug string query
652 + if ( $filter->debug_string_query ) {
653 + return $query;
654 + }
655 +
656 + $result = $this->wpdb->get_results( $query );
657 + }
658 +
659 + // Query total rows
660 + if ( $filter->run_query_count ) {
661 + $query = str_replace( array( $LIMIT, $ORDER_BY ), '', $query );
662 + $query_total = "SELECT COUNT($filter->field_count) FROM ($query) AS $ALIAS_COLLECTION";
663 + $total_rows = (int) $this->wpdb->get_var( $query_total );
664 +
665 + $this->check_execute_has_error();
666 +
667 + if ( $filter->query_count ) {
668 + // Debug string query
669 + if ( $filter->debug_string_query ) {
670 + return $query_total;
671 + }
672 +
673 + return $total_rows;
674 + }
675 + }
676 +
677 + $this->check_execute_has_error();
678 +
679 + return $result;
680 + }
681 +
682 + /**
683 + * Query update
684 + *
685 + * @param FilterBase $filter
686 + *
687 + * @throws Exception
688 + * @since 4.1.7
689 + * @version 1.0.1
690 + */
691 + public function update_execute( $filter ) {
692 +
693 + $COLLECTION = $filter->collection;
694 +
695 + // SET value
696 + $SET = apply_filters( 'lp/query/update/set', $filter->set, $filter );
697 + $SET = implode( ',', array_unique( $SET ) );
698 +
699 + // Where
700 + $WHERE = array( 'WHERE 1=1' );
701 + $WHERE = array_merge( $WHERE, $filter->where );
702 + $WHERE = apply_filters( 'lp/query/update/where', $WHERE, $filter );
703 + $WHERE = implode( ' ', array_unique( $WHERE ) );
704 +
705 + $query = "
706 + UPDATE $COLLECTION
707 + SET $SET
708 + $WHERE
709 + ";
710 +
711 + $result = $this->wpdb->query( $query );
712 +
713 + $this->check_execute_has_error();
714 +
715 + return $result;
716 + }
717 +
718 + /**
719 + * Query delete
720 + *
721 + * @param FilterBase $filter
722 + * @param string $table
723 + *
724 + * @return bool|int|\mysqli_result|string|null
725 + * @throws Exception
726 + * @since 4.1.7
727 + * @version 1.0.1
728 + */
729 + public function delete_execute( $filter, string $table = '' ) {
730 + $COLLECTION = $filter->collection;
731 +
732 + // Where
733 + $WHERE = array( 'WHERE 1=1' );
734 + $WHERE = array_merge( $WHERE, $filter->where );
735 + $WHERE = apply_filters( 'lp/query/delete/where', $WHERE, $filter );
736 + $WHERE = implode( ' ', array_unique( $WHERE ) );
737 +
738 + // Join
739 + $INNER_JOIN = array();
740 + $INNER_JOIN = array_merge( $INNER_JOIN, $filter->join );
741 + $INNER_JOIN = apply_filters( 'lp/query/delete/inner_join', $INNER_JOIN, $filter );
742 + $INNER_JOIN = implode( ' ', array_unique( $INNER_JOIN ) );
743 +
744 + $query = "
745 + DELETE $table FROM $COLLECTION
746 + $INNER_JOIN
747 + $WHERE
748 + ";
749 +
750 + if ( $filter->return_string_query ) {
751 + return $query;
752 + }
753 +
754 + $result = $this->wpdb->query( $query );
755 +
756 + $this->check_execute_has_error();
757 +
758 + return $result;
759 + }
760 +
761 + /**
762 + * Get values of list object by key
763 + *
764 + * @param array $arr_object
765 + * @param string $key
766 + *
767 + * @return array
768 + */
769 + public static function get_values_by_key( array $arr_object, string $key = 'ID' ): array {
770 + $arr_object_ids = array();
771 + foreach ( $arr_object as $object ) {
772 + $arr_object_ids[] = $object->{$key};
773 + }
774 +
775 + return $arr_object_ids;
776 + }
777 +
778 + /**
779 + * Insert data
780 + *
781 + * @param array $args [ 'data' => [], 'filter' => FilterBase, 'table_name' => '', 'key_auto_increment' => '' ]
782 + *
783 + * @return int
784 + * @throws Exception
785 + * @version 1.0.1
786 + * @since 4.2.9
787 + */
788 + public function insert_data( array $args ): int {
789 + $data = $args['data'] ?? [];
790 + $filter = $args['filter'] ?? null;
791 + $table_name = $args['table_name'] ?? '';
792 + $key_auto_increment = $args['key_auto_increment'] ?? '';
793 +
794 + if ( empty( $data ) || ! is_array( $data ) ) {
795 + throw new Exception( __( 'Data must be an array!', 'learnpress' ) . ' | ' . __FUNCTION__ );
796 + }
797 +
798 + /*if ( ! $filter instanceof FilterBase ) {
799 + throw new Exception( __( 'Invalid filter!', 'learnpress' ) . ' | ' . __FUNCTION__ );
800 + }*/
801 +
802 + if ( empty( $filter->all_fields ) ) {
803 + throw new Exception( __( 'Filter must have property all_fields!', 'learnpress' ) . ' | ' . __FUNCTION__ );
804 + }
805 +
806 + if ( empty( $table_name ) ) {
807 + throw new Exception( __( 'Table name is required!', 'learnpress' ) . ' | ' . __FUNCTION__ );
808 + }
809 +
810 + if ( empty( $key_auto_increment ) || ! is_string( $key_auto_increment ) ) {
811 + throw new Exception( __( 'Key auto increment must be a string!', 'learnpress' ) . ' | ' . __FUNCTION__ );
812 + }
813 +
814 + foreach ( $data as $col_name => $value ) {
815 + if ( ! in_array( $col_name, $filter->all_fields ) ) {
816 + unset( $data[ $col_name ] );
817 + }
818 + }
819 +
820 + // unset key is auto increment.
821 + unset( $data[ $key_auto_increment ] );
822 +
823 + $this->wpdb->insert( $table_name, $data );
824 +
825 + $this->check_execute_has_error();
826 +
827 + return $this->wpdb->insert_id;
828 + }
829 +
830 + /**
831 + * Update data
832 + *
833 + * @param array $args
834 + *
835 + * @return bool
836 + *
837 + * @throws Exception
838 + * @since 4.2.9
839 + * @version 1.0.2
840 + */
841 + public function update_data( array $args ): bool {
842 + $data = $args['data'] ?? [];
843 + $filter = $args['filter'] ?? null;
844 + $table_name = $args['table_name'] ?? '';
845 + $where_key = $args['where_key'] ?? '';
846 +
847 + /*if ( ! $filter instanceof FilterBase ) {
848 + throw new Exception( __( 'Invalid filter!', 'learnpress' ) . ' | ' . __FUNCTION__ );
849 + }*/
850 +
851 + if ( empty( $filter->all_fields ) ) {
852 + throw new Exception( __( 'Filter must have property all_fields!', 'learnpress' ) . ' | ' . __FUNCTION__ );
853 + }
854 +
855 + if ( empty( $data ) || ! is_array( $data ) ) {
856 + throw new Exception( __( 'Data must be an array!', 'learnpress' ) . ' | ' . __FUNCTION__ );
857 + }
858 +
859 + if ( empty( $where_key ) ) {
860 + throw new Exception( __( 'Invalid where key!', 'learnpress' ) . ' | ' . __FUNCTION__ );
861 + }
862 +
863 + if ( empty( $table_name ) ) {
864 + throw new Exception( __( 'Table name is required!', 'learnpress' ) . ' | ' . __FUNCTION__ );
865 + }
866 +
867 + $filter->collection = $table_name;
868 + foreach ( $data as $col_name => $value ) {
869 + if ( ! in_array( $col_name, $filter->all_fields ) ) {
870 + continue;
871 + }
872 +
873 + // Key `order` is reserved keyword in MySQL
874 + if ( $col_name === 'order' ) {
875 + $col_name = '`order`';
876 + }
877 +
878 + if ( is_null( $value ) ) {
879 + $filter->set[] = $col_name . ' = null';
880 + } else {
881 + $filter->set[] = $this->wpdb->prepare( $col_name . ' = %s', $value );
882 + }
883 + }
884 +
885 + $filter->where[] = $this->wpdb->prepare( "AND $where_key = %d", $data[ $where_key ] );
886 + $this->update_execute( $filter );
887 +
888 + return true;
889 + }
890 +}