PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.8.1
GiveWP – Donation Plugin and Fundraising Platform v4.16.8.1
4.16.9 4.16.8.1 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 All 255 releases
give / src / Donors / Models / DonorModelQueryBuilder.php

DonorModelQueryBuilder.php in GiveWP – Donation Plugin and Fundraising Platform 4.16.8.1, at src/Donors/Models/DonorModelQueryBuilder.php

223 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Give\Donors\Models;
4
5 use Give\Donors\ValueObjects\DonorAddress;
6 use Give\Framework\Database\DB;
7 use Give\Framework\Models\ModelQueryBuilder;
8
9 class DonorModelQueryBuilder extends ModelQueryBuilder
10 {
11
12 /**
13 * Get row
14 *
15 * @since 2.24.0
16 *
17 * @return M|null
18 *
19 * @param int $output For inheritance compatibility only, unused.
20 */
21 public function get($output = OBJECT)
22 {
23 $row = DB::get_row($this->getSQL(), OBJECT);
24
25 if ( ! $row) {
26 return null;
27 }
28
29 $row = $this->attachAdditionalEmails($row);
30 $row = $this->attachAddresses($row);
31
32 return $this->getRowAsModel($row);
33 }
34
35 /**
36 * Get results
37 *
38 * @since 2.24.0
39 *
40 * @return M[]|null
41 *
42 * @param int $output For inheritance compatibility only, unused.
43 */
44 public function getAll($output = OBJECT)
45 {
46 $results = DB::get_results($this->getSQL(), OBJECT);
47
48 if ( ! $results) {
49 return null;
50 }
51
52 $results = $this->attachAdditionalEmails($results);
53 $results = $this->attachAddresses($results);
54
55 if (isset($this->model)) {
56 return $this->getAllAsModel($results);
57 }
58
59 return $results;
60 }
61
62 /**
63 * Attach additional emails to query results later so that we can avoid additional Group By on the main query
64 *
65 * @since 2.24.0
66 *
67 * @param array|object $queryResults
68 *
69 * @return array|object
70 */
71 private function attachAdditionalEmails($queryResults)
72 {
73 if (is_array($queryResults)) {
74 $donorIds = wp_list_pluck($queryResults, 'id');
75 $additionalEmails = $this->getAdditionalEmails($donorIds);
76 $queryResults = array_map(function ($donor) use ($additionalEmails) {
77 $donor->additionalEmails = $additionalEmails[$donor->id] ?? [];
78
79 return $donor;
80 }, $queryResults);
81 } else {
82 $queryResults->additionalEmails = $this->getAdditionalEmails([$queryResults->id], true) ?? [];
83 }
84
85 return $queryResults;
86 }
87
88 /**
89 * @since 2.24.0
90 *
91 * @param array $donorIds Array of donor ids
92 * @param bool $single Return additional emails for the first donor id
93 *
94 * @return array|null
95 */
96 private function getAdditionalEmails(array $donorIds, bool $single = false)
97 {
98 $results = DB::table('give_donormeta')
99 ->select(['donor_id', 'donorId'], ['meta_value', 'additionalEmails'])
100 ->whereIn('donor_id', $donorIds)
101 ->where('meta_key', 'additional_email')
102 ->getAll();
103
104 if (!$results) {
105 return null;
106 }
107
108 $additionalEmails = [];
109 foreach ($results as $result) {
110 $additionalEmails[(int)$result->donorId][] = $result->additionalEmails;
111 }
112
113 if ($single) {
114 return $additionalEmails[$donorIds[0]];
115 }
116
117 return $additionalEmails;
118 }
119
120 /**
121 * Attach addresses to query results later so that we can avoid additional Group By on the main query
122 *
123 * @since 4.4.0
124 *
125 * @param array|object $queryResults
126 *
127 * @return array|object
128 */
129 private function attachAddresses($queryResults)
130 {
131 if (is_array($queryResults)) {
132 $donorIds = wp_list_pluck($queryResults, 'id');
133 $addresses = $this->getAddresses($donorIds);
134 $queryResults = array_map(function ($donor) use ($addresses) {
135 $donor->addresses = $addresses[$donor->id] ?? [];
136
137 return $donor;
138 }, $queryResults);
139 } else {
140 $queryResults->addresses = $this->getAddresses([$queryResults->id], true) ?? [];
141 }
142
143 return $queryResults;
144 }
145
146 /**
147 * @since 4.4.0
148 *
149 * @param array $donorIds Array of donor ids
150 * @param bool $single Return addresses for the first donor id
151 *
152 * @return array|null
153 */
154 private function getAddresses(array $donorIds, bool $single = false)
155 {
156 // Get all address-related meta for the donors
157 $results = DB::table('give_donormeta')
158 ->select(['donor_id', 'donorId'], ['meta_key', 'metaKey'], ['meta_value', 'metaValue'])
159 ->whereIn('donor_id', $donorIds)
160 ->where(function($query) {
161 $query->where('meta_key', '_give_donor_address_billing_line1_%', 'LIKE')
162 ->orWhere('meta_key', '_give_donor_address_billing_line2_%', 'LIKE')
163 ->orWhere('meta_key', '_give_donor_address_billing_city_%', 'LIKE')
164 ->orWhere('meta_key', '_give_donor_address_billing_state_%', 'LIKE')
165 ->orWhere('meta_key', '_give_donor_address_billing_country_%', 'LIKE')
166 ->orWhere('meta_key', '_give_donor_address_billing_zip_%', 'LIKE');
167 })
168 ->getAll();
169
170 if (!$results) {
171 return null;
172 }
173
174 // Group by donor and index to build addresses
175 $addressData = [];
176 foreach ($results as $result) {
177 $donorId = (int)$result->donorId;
178
179 // Extract the address field type and index from the meta key
180 if (preg_match('/_give_donor_address_billing_(.+)_(\d+)$/', $result->metaKey, $matches)) {
181 $field = $matches[1];
182 $index = (int)$matches[2];
183
184 if (!isset($addressData[$donorId][$index])) {
185 $addressData[$donorId][$index] = [];
186 }
187
188 // Map field names to Address property names
189 $fieldMap = [
190 'line1' => 'address1',
191 'line2' => 'address2',
192 'city' => 'city',
193 'state' => 'state',
194 'country' => 'country',
195 'zip' => 'zip'
196 ];
197
198 if (isset($fieldMap[$field])) {
199 $addressData[$donorId][$index][$fieldMap[$field]] = $result->metaValue;
200 }
201 }
202 }
203
204 // Convert to Address objects
205 $addresses = [];
206 foreach ($addressData as $donorId => $donorAddresses) {
207 $addresses[$donorId] = [];
208 foreach ($donorAddresses as $addressArray) {
209 // Only create address if we have at least one field
210 if (!empty(array_filter($addressArray))) {
211 $addresses[$donorId][] = DonorAddress::fromArray($addressArray);
212 }
213 }
214 }
215
216 if ($single) {
217 return $addresses[$donorIds[0]] ?? [];
218 }
219
220 return $addresses;
221 }
222 }
223