← All changes
|
includes/abstracts/abstract-class-charitable-query.php
+108
-8
1.7.0.7
→
1.8.13
View file →
| @@ -3,9 +3,9 @@ | ||
| 3 | 3 | * An abstract base class defining common methods used by Charitable queries. |
| 4 | 4 | * |
| 5 | 5 | * @package Charitable/Classes/Charitable_Query |
| 6 | 6 | * @author David Bisset |
| 7 | - * @copyright Copyright (c) 2022, WP Charitable LLC | |
| 7 | + * @copyright Copyright (c) 2023, WP Charitable LLC | |
| 8 | 8 | * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
| 9 | 9 | * @since 1.0.0 |
| 10 | 10 | * @version 1.6.8 |
| 11 | 11 | */ |
| @@ -192,9 +192,9 @@ | ||
| 192 | 192 | global $wpdb; |
| 193 | 193 | |
| 194 | 194 | $sql = "SELECT {$this->fields()} {$this->from()} {$this->join()} {$this->where()} {$this->groupby()} {$this->orderby()} {$this->order()} {$this->limit()} {$this->offset()};"; |
| 195 | 195 | |
| 196 | - return $wpdb->get_results( $this->get_prepared_sql( $sql ) ); | |
| 196 | + return $wpdb->get_results( $this->get_prepared_sql( $sql ) ); // phpcs:ignore | |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | /** |
| 200 | 200 | * Run count query, returning the results. |
| @@ -209,9 +209,9 @@ | ||
| 209 | 209 | global $wpdb; |
| 210 | 210 | |
| 211 | 211 | $sql = "SELECT {$this->select_count()} {$this->from()} {$this->join()} {$this->where()};"; |
| 212 | 212 | |
| 213 | - return array( $wpdb->get_var( $this->get_prepared_sql( $sql ) ) ); | |
| 213 | + return array( $wpdb->get_var( $this->get_prepared_sql( $sql ) ) ); // phpcs:ignore | |
| 214 | 214 | } |
| 215 | 215 | |
| 216 | 216 | /** |
| 217 | 217 | * Prepare a query with any passed parameters. |
| @@ -229,9 +229,9 @@ | ||
| 229 | 229 | if ( empty( $this->parameters ) ) { |
| 230 | 230 | return $sql; |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | - return $wpdb->prepare( $sql, $this->parameters ); | |
| 233 | + return $wpdb->prepare( $sql, $this->parameters ); // phpcs:ignore | |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | 236 | /** |
| 237 | 237 | * After a query has been executed, check how many found rows there are. |
| @@ -266,9 +266,9 @@ | ||
| 266 | 266 | * @param Charitable_Query $query The `Charitable_Query` instance. |
| 267 | 267 | */ |
| 268 | 268 | $found_items_query = apply_filters( 'charitable_found_items_query', 'SELECT FOUND_ROWS()', $this ); |
| 269 | 269 | |
| 270 | - return (int) $wpdb->get_var( $found_items_query ); | |
| 270 | + return (int) $wpdb->get_var( $found_items_query ); // phpcs:ignore | |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | 273 | /** |
| 274 | 274 | * Return the count query right after the SELECT part of the query. |
| @@ -426,10 +426,18 @@ | ||
| 426 | 426 | |
| 427 | 427 | /** |
| 428 | 428 | * Return the ORDER part of the query. |
| 429 | 429 | * |
| 430 | - * @since 1.0.0 | |
| 430 | + * The returned value is interpolated directly into the SQL statement | |
| 431 | + * assembled by Charitable_Query::run_query(). A sort direction cannot be | |
| 432 | + * passed to $wpdb->prepare() as a placeholder, so it is validated against | |
| 433 | + * a strict whitelist here instead. Any value other than ASC or DESC -- | |
| 434 | + * including anything supplied through a shortcode attribute or the | |
| 435 | + * `charitable_query_order` filter -- falls back to DESC. | |
| 431 | 436 | * |
| 437 | + * @since 1.0.0 | |
| 438 | + * @version 1.8.12.2 | |
| 439 | + * | |
| 432 | 440 | * @return string |
| 433 | 441 | */ |
| 434 | 442 | public function order() { |
| 435 | 443 | /** |
| @@ -434,14 +442,19 @@ | ||
| 434 | 442 | public function order() { |
| 435 | 443 | /** |
| 436 | 444 | * Filter the `ORDER` statement. |
| 437 | 445 | * |
| 446 | + * Note that the filtered value is validated against ASC/DESC before it | |
| 447 | + * is used in the query, so returning any other value has no effect. | |
| 448 | + * | |
| 438 | 449 | * @since 1.0.0 |
| 439 | 450 | * |
| 440 | 451 | * @param string $sql The `ORDER` statement. DESC by default. |
| 441 | 452 | * @param Charitable_Query $query The `Charitable_Query` instance. |
| 442 | 453 | */ |
| 443 | - return apply_filters( 'charitable_query_order', $this->get( 'order', 'DESC' ), $this ); | |
| 454 | + $order = apply_filters( 'charitable_query_order', $this->get( 'order', 'DESC' ), $this ); | |
| 455 | + | |
| 456 | + return charitable_validate_sort_direction( $order ); | |
| 444 | 457 | } |
| 445 | 458 | |
| 446 | 459 | /** |
| 447 | 460 | * Return the LIMIT part of the query. |
| @@ -665,13 +678,22 @@ | ||
| 665 | 678 | * Filter query by donor ID. |
| 666 | 679 | * |
| 667 | 680 | * @global WPBD $wpdb |
| 668 | 681 | * @since 1.0.0 |
| 682 | + * @version 1.7.0.9 | |
| 669 | 683 | * |
| 670 | 684 | * @param string $where_statement The default where statement. |
| 671 | 685 | * @return string |
| 672 | 686 | */ |
| 673 | 687 | public function where_donor_id_is_in( $where_statement ) { |
| 688 | + | |
| 689 | + $donor_email_passed = isset( $_GET['donor_email'] ) ? sanitize_email( $_GET['donor_email'] ) : false; // phpcs:ignore | |
| 690 | + $donor_email = $this->get( 'email', $donor_email_passed ); | |
| 691 | + | |
| 692 | + if ( $donor_email ) { // stop searching by ID, we will search by email that was supplied. | |
| 693 | + return $where_statement; | |
| 694 | + } | |
| 695 | + | |
| 674 | 696 | $donor_id = $this->get( 'donor_id', false ); |
| 675 | 697 | |
| 676 | 698 | if ( ! $donor_id ) { |
| 677 | 699 | return $where_statement; |
| @@ -682,8 +704,21 @@ | ||
| 682 | 704 | return $where_statement . " AND cd.donor_id IN ({$placeholders})"; |
| 683 | 705 | } |
| 684 | 706 | |
| 685 | 707 | /** |
| 708 | + * Filter query by donor email. | |
| 709 | + * | |
| 710 | + * @global WPBD $wpdb | |
| 711 | + * @since 1.7.0.9 | |
| 712 | + * | |
| 713 | + * @param string $where_statement The default where statement. | |
| 714 | + * @return string | |
| 715 | + */ | |
| 716 | + public function where_donor_email_is_in( $where_statement ) { | |
| 717 | + return $where_statement; | |
| 718 | + } | |
| 719 | + | |
| 720 | + /** | |
| 686 | 721 | * Filter query by user ID. |
| 687 | 722 | * |
| 688 | 723 | * @since 1.5.0 |
| 689 | 724 | * |
| @@ -705,8 +740,53 @@ | ||
| 705 | 740 | return $where_statement . " AND {$wpdb->posts}.post_author IN ({$placeholders})"; |
| 706 | 741 | } |
| 707 | 742 | |
| 708 | 743 | /** |
| 744 | + * Filter query by donation ID(s). | |
| 745 | + * | |
| 746 | + * @since 1.7.0.9 | |
| 747 | + * @version 1.8.8.5 | |
| 748 | + * | |
| 749 | + * @global WPBD $wpdb | |
| 750 | + * @param string $where_statement The default where statement. | |
| 751 | + * @return string | |
| 752 | + */ | |
| 753 | + public function where_donation_id_is_in( $where_statement ) { | |
| 754 | + global $wpdb; | |
| 755 | + | |
| 756 | + $donation_ids_passed = isset( $_GET['donation_ids'] ) ? sanitize_text_field( $_GET['donation_ids'] ) : false; // phpcs:ignore | |
| 757 | + | |
| 758 | + if ( $donation_ids_passed === false ) { | |
| 759 | + return $where_statement; | |
| 760 | + } | |
| 761 | + | |
| 762 | + // this could be a comma delimited list. | |
| 763 | + $donation_ids = explode( ',', $donation_ids_passed ); | |
| 764 | + | |
| 765 | + if ( empty( $donation_ids ) ) { | |
| 766 | + return $where_statement; | |
| 767 | + } | |
| 768 | + | |
| 769 | + // Validate and sanitize each donation ID to ensure they are positive integers | |
| 770 | + $valid_donation_ids = array(); | |
| 771 | + foreach ( $donation_ids as $donation_id ) { | |
| 772 | + $donation_id = trim( $donation_id ); | |
| 773 | + if ( is_numeric( $donation_id ) && intval( $donation_id ) > 0 ) { | |
| 774 | + $valid_donation_ids[] = intval( $donation_id ); | |
| 775 | + } | |
| 776 | + } | |
| 777 | + | |
| 778 | + if ( empty( $valid_donation_ids ) ) { | |
| 779 | + return $where_statement; | |
| 780 | + } | |
| 781 | + | |
| 782 | + // Use proper parameterized query with placeholders | |
| 783 | + $placeholders = $this->get_where_in_placeholders( $valid_donation_ids, 'charitable_validate_absint', '%d' ); | |
| 784 | + | |
| 785 | + return $where_statement . " AND {$wpdb->posts}.ID IN ({$placeholders})"; | |
| 786 | + } | |
| 787 | + | |
| 788 | + /** | |
| 709 | 789 | * Filter a query by date. |
| 710 | 790 | * |
| 711 | 791 | * @uses WP_Date_Query |
| 712 | 792 | * |
| @@ -797,8 +877,23 @@ | ||
| 797 | 877 | return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_campaign_donations cd ON cd.donation_id = $wpdb->posts.ID "; |
| 798 | 878 | } |
| 799 | 879 | |
| 800 | 880 | /** |
| 881 | + * A method used to join the campaign donations table on the campaigns query. | |
| 882 | + * | |
| 883 | + * @global WPBD $wpdb | |
| 884 | + * | |
| 885 | + * @since 1.7.0.9 | |
| 886 | + * | |
| 887 | + * @param string $join_statement The default join statement. | |
| 888 | + * @return string | |
| 889 | + */ | |
| 890 | + public function join_campaign_donors_table_on_donation( $join_statement ) { | |
| 891 | + global $wpdb; | |
| 892 | + return $join_statement . " INNER JOIN {$wpdb->prefix}charitable_donors cdn ON cdn.donor_id = cd.donor_id "; | |
| 893 | + } | |
| 894 | + | |
| 895 | + /** | |
| 801 | 896 | * A method used to join the donors table on the query. |
| 802 | 897 | * |
| 803 | 898 | * @global WPBD $wpdb |
| 804 | 899 | * @since 1.5.0 |
| @@ -925,8 +1020,9 @@ | ||
| 925 | 1020 | * @since 1.0.0 |
| 926 | 1021 | * |
| 927 | 1022 | * @return void |
| 928 | 1023 | */ |
| 1024 | + #[\ReturnTypeWillChange] | |
| 929 | 1025 | public function rewind() { |
| 930 | 1026 | $this->position = 0; |
| 931 | 1027 | } |
| 932 | 1028 | |
| @@ -936,10 +1032,11 @@ | ||
| 936 | 1032 | * @since 1.0.0 |
| 937 | 1033 | * |
| 938 | 1034 | * @return object |
| 939 | 1035 | */ |
| 1036 | + #[\ReturnTypeWillChange] | |
| 940 | 1037 | public function current() { |
| 941 | - return $this->results[ $this->position ]; | |
| 1038 | + return isset( $this->results[ $this->position ] ) ? $this->results[ $this->position ] : false; | |
| 942 | 1039 | } |
| 943 | 1040 | |
| 944 | 1041 | /** |
| 945 | 1042 | * Return current key. |
| @@ -947,8 +1044,9 @@ | ||
| 947 | 1044 | * @since 1.0.0 |
| 948 | 1045 | * |
| 949 | 1046 | * @return int |
| 950 | 1047 | */ |
| 1048 | + #[\ReturnTypeWillChange] | |
| 951 | 1049 | public function key() { |
| 952 | 1050 | return $this->position; |
| 953 | 1051 | } |
| 954 | 1052 | |
| @@ -958,8 +1056,9 @@ | ||
| 958 | 1056 | * @since 1.0.0 |
| 959 | 1057 | * |
| 960 | 1058 | * @return void |
| 961 | 1059 | */ |
| 1060 | + #[\ReturnTypeWillChange] | |
| 962 | 1061 | public function next() { |
| 963 | 1062 | ++$this->position; |
| 964 | 1063 | } |
| 965 | 1064 | |
| @@ -969,8 +1068,9 @@ | ||
| 969 | 1068 | * @since 1.0.0 |
| 970 | 1069 | * |
| 971 | 1070 | * @return boolean |
| 972 | 1071 | */ |
| 1072 | + #[\ReturnTypeWillChange] | |
| 973 | 1073 | public function valid() { |
| 974 | 1074 | return isset( $this->results[ $this->position ] ); |
| 975 | 1075 | } |
| 976 | 1076 | |