PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
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
← All changes | src/Donors/Models/DonorModelQueryBuilder.php +110 -0 2.30.04.16.9 View file →
@@ -1,8 +1,9 @@
1 1 <?php
2 2
3 3 namespace Give\Donors\Models;
4 4
5 +use Give\Donors\ValueObjects\DonorAddress;
5 6 use Give\Framework\Database\DB;
6 7 use Give\Framework\Models\ModelQueryBuilder;
7 8
8 9 class DonorModelQueryBuilder extends ModelQueryBuilder
@@ -13,8 +14,10 @@
13 14 *
14 15 * @since 2.24.0
15 16 *
16 17 * @return M|null
18 + *
19 + * @param int $output For inheritance compatibility only, unused.
17 20 */
18 21 public function get($output = OBJECT)
19 22 {
20 23 $row = DB::get_row($this->getSQL(), OBJECT);
@@ -23,8 +26,9 @@
23 26 return null;
24 27 }
25 28
26 29 $row = $this->attachAdditionalEmails($row);
30 + $row = $this->attachAddresses($row);
27 31
28 32 return $this->getRowAsModel($row);
29 33 }
30 34
@@ -33,8 +37,10 @@
33 37 *
34 38 * @since 2.24.0
35 39 *
36 40 * @return M[]|null
41 + *
42 + * @param int $output For inheritance compatibility only, unused.
37 43 */
38 44 public function getAll($output = OBJECT)
39 45 {
40 46 $results = DB::get_results($this->getSQL(), OBJECT);
@@ -43,8 +49,9 @@
43 49 return null;
44 50 }
45 51
46 52 $results = $this->attachAdditionalEmails($results);
53 + $results = $this->attachAddresses($results);
47 54
48 55 if (isset($this->model)) {
49 56 return $this->getAllAsModel($results);
50 57 }
@@ -107,6 +114,109 @@
107 114 return $additionalEmails[$donorIds[0]];
108 115 }
109 116
110 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;
111 221 }
112 222 }