PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.8
GiveWP – Donation Plugin and Fundraising Platform v4.16.8
4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / database / class-give-db-meta.php
give / includes / database Last commit date
class-give-db-comments-meta.php 7 years ago class-give-db-comments.php 6 years ago class-give-db-donor-meta.php 6 years ago class-give-db-donors.php 4 weeks ago class-give-db-form-meta.php 7 years ago class-give-db-meta.php 1 day ago class-give-db-payment-meta.php 7 months ago class-give-db-sequential-ordering.php 6 years ago class-give-db-sessions.php 1 week ago class-give-db.php 6 years ago
class-give-db-meta.php
653 lines
1 <?php
2 /**
3 * Give DB Meta
4 *
5 * @package Give
6 * @subpackage Classes/Give_DB_Meta
7 * @copyright Copyright (c) 2017, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 2.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 class Give_DB_Meta extends Give_DB {
18 /**
19 * Post type
20 *
21 * @since 2.0
22 * @access protected
23 * @var bool
24 */
25 protected $post_type = '';
26
27 /**
28 * Meta type
29 *
30 * @since 2.0
31 * @access protected
32 * @var bool
33 */
34 protected $meta_type = '';
35
36 /**
37 * Flag to handle result type
38 *
39 * @since 2.0
40 * @access protected
41 */
42 protected $raw_result = false;
43
44 /**
45 * Flag for short circuit of meta function
46 *
47 * @since 2.0
48 * @access protected
49 */
50 protected $check = false;
51
52 /**
53 * Flag to check whether meta function called by WP filter or directly
54 *
55 * @since 2.0
56 * @access protected
57 */
58 private $is_filter_callback = false;
59
60
61 /**
62 * Meta supports.
63 *
64 * @since 2.0
65 * @access protected
66 * @var array
67 */
68 protected $supports = [
69 'add_post_metadata',
70 'get_post_metadata',
71 'update_post_metadata',
72 'delete_post_metadata',
73 'posts_where',
74 'posts_join',
75 'posts_groupby',
76 'posts_orderby',
77 ];
78
79 /**
80 * Give_DB_Meta constructor.
81 *
82 * @since 2.0
83 */
84 function __construct() {
85 parent::__construct();
86
87 // Bailout.
88 if ( empty( $this->supports ) || ! $this->is_custom_meta_table_active() ) {
89 return;
90 }
91
92 if ( in_array( 'add_post_metadata', $this->supports ) ) {
93 add_filter( 'add_post_metadata', [ $this, '__add_meta' ], 0, 5 );
94 }
95
96 if ( in_array( 'get_post_metadata', $this->supports ) ) {
97 add_filter( 'get_post_metadata', [ $this, '__get_meta' ], 10, 4 );
98 }
99
100 if ( in_array( 'update_post_metadata', $this->supports ) ) {
101 add_filter( 'update_post_metadata', [ $this, '__update_meta' ], 0, 5 );
102 }
103
104 if ( in_array( 'delete_post_metadata', $this->supports ) ) {
105 add_filter( 'delete_post_metadata', [ $this, '__delete_meta' ], 0, 5 );
106 }
107
108 if ( in_array( 'posts_where', $this->supports ) ) {
109 add_filter( 'posts_where', [$this, 'rename_meta_table_name_in_query'], 99999, 2 );
110 }
111
112 if ( in_array( 'posts_join', $this->supports ) ) {
113 add_filter( 'posts_join', [$this, 'rename_meta_table_name_in_query'], 99999, 2 );
114 }
115
116 if ( in_array( 'posts_groupby', $this->supports ) ) {
117 add_filter( 'posts_groupby', [$this, 'rename_meta_table_name_in_query'], 99999, 2 );
118 }
119
120 if ( in_array( 'posts_orderby', $this->supports ) ) {
121 add_filter( 'posts_orderby', [$this, 'rename_meta_table_name_in_query'], 99999, 2 );
122 }
123 }
124
125 /**
126 * Retrieve payment meta field for a payment.
127 *
128 * @since 3.1.0 Return empty array, when request raw metadata if $single is set to false and metadata does not exist.
129 * @since 2.0
130 *
131 * @param int $id Pst Type ID.
132 * @param string $meta_key The meta key to retrieve.
133 * @param bool $single Whether to return a single value.
134 *
135 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
136 * is true.
137 */
138 public function get_meta( $id = 0, $meta_key = '', $single = false ) {
139 $previousMetaTableName = $this->setMetaTableName();
140
141 try {
142 if ( ! $this->is_filter_callback ) {
143 return get_metadata( $this->meta_type, $id, $meta_key, $single );
144 }
145
146 $id = $this->sanitize_id( $id );
147
148 // Bailout.
149 if ( ! $this->is_valid_post_type( $id ) ) {
150 return $this->check;
151 }
152
153 if ( $this->raw_result ) {
154 if ( ! ( $value = get_metadata( $this->meta_type, $id, $meta_key, false ) ) ) {
155 $value = $single ? '' : array();
156 }
157
158 // Reset flag.
159 $this->raw_result = false;
160
161 } else {
162 $value = get_metadata( $this->meta_type, $id, $meta_key, $single );
163 }
164
165 $this->is_filter_callback = false;
166
167 return $value;
168 } finally {
169 $this->restoreMetaTableName( $previousMetaTableName );
170 }
171 }
172
173
174 /**
175 * Add meta data field to a payment.
176 *
177 * For internal use only. Use Give_Payment->add_meta() for public usage.
178 *
179 * @access private
180 * @since 2.0
181 *
182 * @param int $id Post Type ID.
183 * @param string $meta_key Metadata name.
184 * @param mixed $meta_value Metadata value.
185 * @param bool $unique Optional, default is false. Whether the same key should not be added.
186 *
187 * @return int|bool False for failure. True for success.
188 */
189 public function add_meta( $id, $meta_key, $meta_value, $unique = false ) {
190 $previousMetaTableName = $this->setMetaTableName();
191
192 try {
193 if ( $this->is_filter_callback ) {
194 $id = $this->sanitize_id( $id );
195
196 // Bailout.
197 if ( ! $this->is_valid_post_type( $id ) ) {
198 return $this->check;
199 }
200 }
201
202 $meta_id = add_metadata( $this->meta_type, $id, $meta_key, $meta_value, $unique );
203
204 if ( $meta_id ) {
205 $this->delete_cache( $id );
206 }
207
208 $this->is_filter_callback = false;
209
210 return $meta_id;
211 } finally {
212 $this->restoreMetaTableName( $previousMetaTableName );
213 }
214 }
215
216 /**
217 * Update payment meta field based on Post Type ID.
218 *
219 * For internal use only. Use Give_Payment->update_meta() for public usage.
220 *
221 * Use the $prev_value parameter to differentiate between meta fields with the
222 * same key and Post Type ID.
223 *
224 * If the meta field for the payment does not exist, it will be added.
225 *
226 * @access public
227 * @since 2.0
228 *
229 * @param int $id Post Type ID.
230 * @param string $meta_key Metadata key.
231 * @param mixed $meta_value Metadata value.
232 * @param mixed $prev_value Optional. Previous value to check before removing.
233 *
234 * @return int|bool False on failure, true if success.
235 */
236 public function update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
237 $previousMetaTableName = $this->setMetaTableName();
238
239 try {
240 if ( $this->is_filter_callback ) {
241 $id = $this->sanitize_id( $id );
242
243 // Bailout.
244 if ( ! $this->is_valid_post_type( $id ) ) {
245 return $this->check;
246 }
247 }
248
249 $meta_id = update_metadata( $this->meta_type, $id, $meta_key, $meta_value, $prev_value );
250
251 if ( $meta_id ) {
252 $this->delete_cache( $id );
253 }
254
255 $this->is_filter_callback = false;
256
257 return $meta_id;
258 } finally {
259 $this->restoreMetaTableName( $previousMetaTableName );
260 }
261 }
262
263 /**
264 * Remove metadata matching criteria from a payment.
265 *
266 * You can match based on the key, or key and value. Removing based on key and
267 * value, will keep from removing duplicate metadata with the same key. It also
268 * allows removing all metadata matching key, if needed.
269 *
270 * @access public
271 * @since 2.0
272 *
273 * @param int $id Post Type ID.
274 * @param string $meta_key Metadata name.
275 * @param mixed $meta_value Optional. Metadata value.
276 * @param mixed $delete_all Optional.
277 *
278 * @return bool False for failure. True for success.
279 */
280 public function delete_meta( $id = 0, $meta_key = '', $meta_value = '', $delete_all = '' ) {
281 $previousMetaTableName = $this->setMetaTableName();
282
283 try {
284 if ( $this->is_filter_callback ) {
285 $id = $this->sanitize_id( $id );
286
287 // Bailout.
288 if ( ! $this->is_valid_post_type( $id ) ) {
289 return $this->check;
290 }
291 }
292
293 $is_meta_deleted = delete_metadata( $this->meta_type, $id, $meta_key, $meta_value, $delete_all );
294
295 if ( $is_meta_deleted ) {
296 $this->delete_cache( $id );
297 }
298
299 $this->is_filter_callback = false;
300
301 return $is_meta_deleted;
302 } finally {
303 $this->restoreMetaTableName( $previousMetaTableName );
304 }
305 }
306
307 /**
308 * Rename query clauses of every query for new meta table
309 *
310 * @since 4.9.0 rename function - PHP 8 compatibility
311 * @since 2.0
312 * @access public
313 *
314 * @param string $clause
315 * @param WP_Query $wp_query
316 *
317 * @return string
318 */
319 public function rename_meta_table_name_in_query( $clause, $wp_query ) {
320 // Add new table to sql query.
321 if ( $this->is_post_type_query( $wp_query ) && ! empty( $wp_query->meta_query->queries ) ) {
322 $clause = $this->rename_meta_table_name( $clause, current_filter() );
323 }
324
325 return $clause;
326 }
327
328
329 /**
330 * Rename query clauses for new meta table
331 *
332 * @since 4.9.0 rename function - PHP 8 compatibility
333 * @param $clause
334 * @param $filter
335 *
336 * @return mixed
337 */
338 public function rename_meta_table_name( $clause, $filter ) {
339 global $wpdb;
340
341 $clause = str_replace( "{$wpdb->postmeta}.post_id", "{$this->table_name}.{$this->meta_type}_id", $clause );
342 $clause = str_replace( $wpdb->postmeta, $this->table_name, $clause );
343
344 switch ( $filter ) {
345 case 'posts_join':
346 $joins = [ 'INNER JOIN', 'LEFT JOIN' ];
347
348 foreach ( $joins as $join ) {
349 if ( false !== strpos( $clause, $join ) ) {
350 $clause = explode( $join, $clause );
351
352 foreach ( $clause as $key => $clause_part ) {
353 if ( empty( $clause_part ) ) {
354 continue;
355 }
356
357 preg_match( '/' . $wpdb->prefix . 'give_' . $this->meta_type . 'meta AS (.*) ON/', $clause_part, $alias_table_name );
358
359 if ( isset( $alias_table_name[1] ) ) {
360 $clause[ $key ] = str_replace( "{$alias_table_name[1]}.post_id", "{$alias_table_name[1]}.{$this->meta_type}_id", $clause_part );
361 }
362 }
363
364 $clause = implode( "{$join} ", $clause );
365 }
366 }
367 break;
368
369 case 'posts_where':
370 $clause = str_replace(
371 [ 'mt2.post_id', 'mt1.post_id' ],
372 [
373 "mt2.{$this->meta_type}_id",
374 "mt1.{$this->meta_type}_id",
375 ],
376 $clause
377 );
378 break;
379 }
380
381 return $clause;
382 }
383
384
385 /**
386 * Check if current query for post type or not.
387 *
388 * @since 2.0
389 * @access protected
390 *
391 * @param WP_Query $wp_query
392 *
393 * @return bool
394 */
395 protected function is_post_type_query( $wp_query ) {
396 $status = false;
397
398 // Check if it is payment query.
399 if ( ! empty( $wp_query->query['post_type'] ) ) {
400 if (
401 is_string( $wp_query->query['post_type'] ) &&
402 $this->post_type === $wp_query->query['post_type']
403 ) {
404 $status = true;
405 } elseif (
406 is_array( $wp_query->query['post_type'] ) &&
407 1 === count( $wp_query->query['post_type'] ) &&
408 in_array( $this->post_type, $wp_query->query['post_type'] )
409 ) {
410 $status = true;
411 }
412 }
413
414 return $status;
415 }
416
417 /**
418 * Check if current id of post type or not
419 *
420 * @since 2.0
421 * @access protected
422 *
423 * @param $ID
424 *
425 * @return bool
426 */
427 protected function is_valid_post_type( $ID ) {
428 return $ID && ( $this->post_type === get_post_type( $ID ) );
429 }
430
431 /**
432 * check if custom meta table enabled or not.
433 *
434 * @since 2.0
435 * @access protected
436 * @return bool
437 */
438 protected function is_custom_meta_table_active() {
439 return false;
440 }
441
442
443 /**
444 * Update last_changed key
445 *
446 * @since 2.0
447 * @access private
448 *
449 * @param int $id
450 * @param string $meta_type
451 *
452 * @return void
453 */
454 private function delete_cache( $id, $meta_type = '' ) {
455 $meta_type = empty( $meta_type ) ? $this->meta_type : $meta_type;
456
457 $group = [
458 'payment' => 'give-donations', // Backward compatibility
459 'donation' => 'give-donations',
460 'donor' => 'give-donors',
461 'customer' => 'give-donors', // Backward compatibility for pre upgrade in 2.0
462 ];
463
464 if ( array_key_exists( $meta_type, $group ) ) {
465 Give_Cache::delete_group( $id, $group[ $meta_type ] );
466 wp_cache_delete( $id, $this->meta_type . '_meta' );
467 }
468 }
469
470 /**
471 * Add support for hidden functions.
472 *
473 * @since 2.0
474 * @since 2.9.6 Added a Short circuit check when updating meta.
475 *
476 * @access public
477 *
478 * @param $name
479 * @param $arguments
480 *
481 * @return mixed
482 */
483 public function __call( $name, $arguments ) {
484 switch ( $name ) {
485 case '__add_meta':
486 $this->check = $arguments[0];
487 $id = $arguments[1];
488 $meta_key = $arguments[2];
489 $meta_value = $arguments[3];
490 $unique = $arguments[4];
491 $this->is_filter_callback = true;
492
493 // Bailout.
494 if ( ! $this->is_valid_post_type( $id ) ) {
495 return $this->check;
496 }
497
498 return $this->add_meta( $id, $meta_key, $meta_value, $unique );
499
500 case '__get_meta':
501 $this->check = $arguments[0];
502 $id = $arguments[1];
503 $meta_key = $arguments[2];
504 $single = $arguments[3];
505 $this->is_filter_callback = true;
506
507 // Bailout.
508 if ( ! $this->is_valid_post_type( $id ) ) {
509 return $this->check;
510 }
511
512 $this->raw_result = true;
513
514 return $this->get_meta( $id, $meta_key, $single );
515
516 case '__update_meta':
517 $this->check = $arguments[0];
518 $id = $arguments[1];
519 $meta_key = $arguments[2];
520 $meta_value = $arguments[3];
521 $this->is_filter_callback = true;
522
523 // Short circuit if the meta value has already been updated.
524 if ( null !== $this->check ) {
525 return $this->check;
526 }
527
528 // Bailout.
529 if ( ! $this->is_valid_post_type( $id ) ) {
530 return $this->check;
531 }
532
533 return $this->update_meta( $id, $meta_key, $meta_value );
534
535 case '__delete_meta':
536 $this->check = $arguments[0];
537 $id = $arguments[1];
538 $meta_key = $arguments[2];
539 $meta_value = $arguments[3];
540 $delete_all = $arguments[3];
541 $this->is_filter_callback = true;
542
543 // Bailout.
544 if ( ! $this->is_valid_post_type( $id ) ) {
545 return $this->check;
546 }
547
548 return $this->delete_meta( $id, $meta_key, $meta_value, $delete_all );
549 }
550 }
551
552 /**
553 * Create Meta Tables.
554 *
555 * @since 2.0.1
556 * @access public
557 */
558 public function create_table() {
559 global $wpdb;
560
561 $charset_collate = $wpdb->get_charset_collate();
562
563 $sql = "CREATE TABLE {$this->table_name} (
564 meta_id bigint(20) NOT NULL AUTO_INCREMENT,
565 {$this->meta_type}_id bigint(20) NOT NULL,
566 meta_key varchar(255) DEFAULT NULL,
567 meta_value longtext,
568 PRIMARY KEY (meta_id),
569 KEY {$this->meta_type}_id ({$this->meta_type}_id),
570 KEY meta_key (meta_key({$this->min_index_length}))
571 ) {$charset_collate};";
572
573 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
574 dbDelta( $sql );
575
576 update_option( $this->table_name . '_db_version', $this->version, false );
577 }
578
579
580 /**
581 * Get meta type
582 *
583 * @since 2.0.4
584 * @access public
585 *
586 * @return string
587 */
588 public function get_meta_type() {
589 return $this->meta_type;
590 }
591
592 /**
593 * Remove all meta data matching criteria from a meta table.
594 *
595 * @since 2.1.3
596 * @access public
597 *
598 * @param int $id ID.
599 *
600 * @return bool False for failure. True for success.
601 */
602 public function delete_all_meta( $id = 0 ) {
603 global $wpdb;
604 $status = $wpdb->delete( $this->table_name, [ "{$this->meta_type}_id" => $id ], [ '%d' ] );
605
606 if ( $status ) {
607 $this->delete_cache( $id, $this->meta_type );
608 }
609
610 return $status;
611 }
612
613 /**
614 * Temporarily re-assert the meta table name in the global $wpdb object.
615 *
616 * Other plugins can overwrite the global meta table property. For example, both GiveWP and
617 * Charitable register a "donor" meta type, and Charitable re-assigns $wpdb->donormeta to its
618 * own table after GiveWP loads. Point the global at GiveWP's own table before each metadata
619 * operation so data is always written to and read from GiveWP's table, then restore the
620 * previous value afterwards so other plugins are unaffected.
621 *
622 * @since 4.16.8
623 *
624 * @return string The previous meta table name to restore.
625 */
626 private function setMetaTableName() {
627 global $wpdb;
628
629 $metaTableProperty = $this->meta_type . 'meta';
630 $previousMetaTableName = $wpdb->{$metaTableProperty};
631
632 $wpdb->{$metaTableProperty} = $this->table_name;
633
634 return $previousMetaTableName;
635 }
636
637 /**
638 * Restore a previously saved meta table name.
639 *
640 * @since 4.16.8
641 *
642 * @param string $metaTableName The meta table name to restore.
643 *
644 * @return void
645 */
646 private function restoreMetaTableName( $metaTableName ) {
647 global $wpdb;
648
649 $wpdb->{$this->meta_type . 'meta'} = $metaTableName;
650 }
651
652 }
653