@@ -88,7 +88,7 @@ discard block |
||
88 | 88 | protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
89 | 89 | { |
90 | 90 | parent::__construct($fieldValues, $bydb, $timezone); |
91 | - if (! $this->get('LIN_code')) { |
|
91 | + if ( ! $this->get('LIN_code')) { |
|
92 | 92 | $this->set_code($this->generate_code()); |
93 | 93 | } |
94 | 94 | } |
@@ -155,7 +155,7 @@ discard block |
||
155 | 155 | public function name() |
156 | 156 | { |
157 | 157 | $name = $this->get('LIN_name'); |
158 | - if (! $name) { |
|
158 | + if ( ! $name) { |
|
159 | 159 | $name = ucwords(str_replace('-', ' ', $this->type())); |
160 | 160 | } |
161 | 161 | return $name; |
@@ -615,7 +615,7 @@ discard block |
||
615 | 615 | ) |
616 | 616 | ); |
617 | 617 | } |
618 | - if (! is_array($this->_children)) { |
|
618 | + if ( ! is_array($this->_children)) { |
|
619 | 619 | $this->_children = array(); |
620 | 620 | } |
621 | 621 | return $this->_children; |
@@ -856,7 +856,7 @@ discard block |
||
856 | 856 | } |
857 | 857 | return $line_item->save(); |
858 | 858 | } |
859 | - $this->_children[ $line_item->code() ] = $line_item; |
|
859 | + $this->_children[$line_item->code()] = $line_item; |
|
860 | 860 | if ($line_item->parent() !== $this) { |
861 | 861 | $line_item->set_parent($this); |
862 | 862 | } |
@@ -880,7 +880,7 @@ discard block |
||
880 | 880 | public function set_parent($line_item) |
881 | 881 | { |
882 | 882 | if ($this->ID()) { |
883 | - if (! $line_item->ID()) { |
|
883 | + if ( ! $line_item->ID()) { |
|
884 | 884 | $line_item->save(); |
885 | 885 | } |
886 | 886 | $this->set_parent_ID($line_item->ID()); |
@@ -912,8 +912,8 @@ discard block |
||
912 | 912 | array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
913 | 913 | ); |
914 | 914 | } |
915 | - return isset($this->_children[ $code ]) |
|
916 | - ? $this->_children[ $code ] |
|
915 | + return isset($this->_children[$code]) |
|
916 | + ? $this->_children[$code] |
|
917 | 917 | : null; |
918 | 918 | } |
919 | 919 | |
@@ -973,8 +973,8 @@ discard block |
||
973 | 973 | } |
974 | 974 | return $items_deleted; |
975 | 975 | } |
976 | - if (isset($this->_children[ $code ])) { |
|
977 | - unset($this->_children[ $code ]); |
|
976 | + if (isset($this->_children[$code])) { |
|
977 | + unset($this->_children[$code]); |
|
978 | 978 | return 1; |
979 | 979 | } |
980 | 980 | return 0; |
@@ -1015,7 +1015,7 @@ discard block |
||
1015 | 1015 | public function generate_code() |
1016 | 1016 | { |
1017 | 1017 | // each line item in the cart requires a unique identifier |
1018 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
1018 | + return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime()); |
|
1019 | 1019 | } |
1020 | 1020 | |
1021 | 1021 | |
@@ -1228,7 +1228,7 @@ discard block |
||
1228 | 1228 | $has_children = ! empty($my_children); |
1229 | 1229 | if ($has_children && $this->is_line_item()) { |
1230 | 1230 | $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
1231 | - } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1231 | + } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1232 | 1232 | $total = $this->unit_price() * $this->quantity(); |
1233 | 1233 | } elseif ($this->is_sub_total() || $this->is_total()) { |
1234 | 1234 | $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
@@ -1243,13 +1243,13 @@ discard block |
||
1243 | 1243 | if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
1244 | 1244 | $this->set_quantity(1); |
1245 | 1245 | } |
1246 | - if (! $this->is_percent()) { |
|
1246 | + if ( ! $this->is_percent()) { |
|
1247 | 1247 | $this->set_unit_price($total); |
1248 | 1248 | } |
1249 | 1249 | } |
1250 | 1250 | // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
1251 | 1251 | // so it ought to be |
1252 | - if (! $this->is_total()) { |
|
1252 | + if ( ! $this->is_total()) { |
|
1253 | 1253 | $this->set_total($total); |
1254 | 1254 | // if not a percent line item, make sure we keep the unit price in sync |
1255 | 1255 | if ( |
@@ -1597,7 +1597,7 @@ discard block |
||
1597 | 1597 | public function save_this_and_descendants_to_txn($txn_id = null) |
1598 | 1598 | { |
1599 | 1599 | $count = 0; |
1600 | - if (! $txn_id) { |
|
1600 | + if ( ! $txn_id) { |
|
1601 | 1601 | $txn_id = $this->TXN_ID(); |
1602 | 1602 | } |
1603 | 1603 | $this->set_TXN_ID($txn_id); |
@@ -13,1742 +13,1742 @@ |
||
13 | 13 | */ |
14 | 14 | class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item |
15 | 15 | { |
16 | - /** |
|
17 | - * for children line items (currently not a normal relation) |
|
18 | - * |
|
19 | - * @type EE_Line_Item[] |
|
20 | - */ |
|
21 | - protected $_children = array(); |
|
22 | - |
|
23 | - /** |
|
24 | - * for the parent line item |
|
25 | - * |
|
26 | - * @var EE_Line_Item |
|
27 | - */ |
|
28 | - protected $_parent; |
|
29 | - |
|
30 | - |
|
31 | - /** |
|
32 | - * @param array $props_n_values incoming values |
|
33 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
34 | - * used.) |
|
35 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
36 | - * date_format and the second value is the time format |
|
37 | - * @return EE_Line_Item |
|
38 | - * @throws EE_Error |
|
39 | - * @throws InvalidArgumentException |
|
40 | - * @throws InvalidDataTypeException |
|
41 | - * @throws InvalidInterfaceException |
|
42 | - * @throws ReflectionException |
|
43 | - */ |
|
44 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
45 | - { |
|
46 | - $has_object = parent::_check_for_object( |
|
47 | - $props_n_values, |
|
48 | - __CLASS__, |
|
49 | - $timezone, |
|
50 | - $date_formats |
|
51 | - ); |
|
52 | - return $has_object |
|
53 | - ? $has_object |
|
54 | - : new self($props_n_values, false, $timezone); |
|
55 | - } |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * @param array $props_n_values incoming values from the database |
|
60 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
61 | - * the website will be used. |
|
62 | - * @return EE_Line_Item |
|
63 | - * @throws EE_Error |
|
64 | - * @throws InvalidArgumentException |
|
65 | - * @throws InvalidDataTypeException |
|
66 | - * @throws InvalidInterfaceException |
|
67 | - * @throws ReflectionException |
|
68 | - */ |
|
69 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
70 | - { |
|
71 | - return new self($props_n_values, true, $timezone); |
|
72 | - } |
|
73 | - |
|
74 | - |
|
75 | - /** |
|
76 | - * Adds some defaults if they're not specified |
|
77 | - * |
|
78 | - * @param array $fieldValues |
|
79 | - * @param bool $bydb |
|
80 | - * @param string $timezone |
|
81 | - * @throws EE_Error |
|
82 | - * @throws InvalidArgumentException |
|
83 | - * @throws InvalidDataTypeException |
|
84 | - * @throws InvalidInterfaceException |
|
85 | - * @throws ReflectionException |
|
86 | - */ |
|
87 | - protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
88 | - { |
|
89 | - parent::__construct($fieldValues, $bydb, $timezone); |
|
90 | - if (! $this->get('LIN_code')) { |
|
91 | - $this->set_code($this->generate_code()); |
|
92 | - } |
|
93 | - } |
|
94 | - |
|
95 | - |
|
96 | - /** |
|
97 | - * Gets ID |
|
98 | - * |
|
99 | - * @return int |
|
100 | - * @throws EE_Error |
|
101 | - * @throws InvalidArgumentException |
|
102 | - * @throws InvalidDataTypeException |
|
103 | - * @throws InvalidInterfaceException |
|
104 | - * @throws ReflectionException |
|
105 | - */ |
|
106 | - public function ID() |
|
107 | - { |
|
108 | - return $this->get('LIN_ID'); |
|
109 | - } |
|
110 | - |
|
111 | - |
|
112 | - /** |
|
113 | - * Gets TXN_ID |
|
114 | - * |
|
115 | - * @return int |
|
116 | - * @throws EE_Error |
|
117 | - * @throws InvalidArgumentException |
|
118 | - * @throws InvalidDataTypeException |
|
119 | - * @throws InvalidInterfaceException |
|
120 | - * @throws ReflectionException |
|
121 | - */ |
|
122 | - public function TXN_ID() |
|
123 | - { |
|
124 | - return $this->get('TXN_ID'); |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - /** |
|
129 | - * Sets TXN_ID |
|
130 | - * |
|
131 | - * @param int $TXN_ID |
|
132 | - * @throws EE_Error |
|
133 | - * @throws InvalidArgumentException |
|
134 | - * @throws InvalidDataTypeException |
|
135 | - * @throws InvalidInterfaceException |
|
136 | - * @throws ReflectionException |
|
137 | - */ |
|
138 | - public function set_TXN_ID($TXN_ID) |
|
139 | - { |
|
140 | - $this->set('TXN_ID', $TXN_ID); |
|
141 | - } |
|
142 | - |
|
143 | - |
|
144 | - /** |
|
145 | - * Gets name |
|
146 | - * |
|
147 | - * @return string |
|
148 | - * @throws EE_Error |
|
149 | - * @throws InvalidArgumentException |
|
150 | - * @throws InvalidDataTypeException |
|
151 | - * @throws InvalidInterfaceException |
|
152 | - * @throws ReflectionException |
|
153 | - */ |
|
154 | - public function name() |
|
155 | - { |
|
156 | - $name = $this->get('LIN_name'); |
|
157 | - if (! $name) { |
|
158 | - $name = ucwords(str_replace('-', ' ', $this->type())); |
|
159 | - } |
|
160 | - return $name; |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * Sets name |
|
166 | - * |
|
167 | - * @param string $name |
|
168 | - * @throws EE_Error |
|
169 | - * @throws InvalidArgumentException |
|
170 | - * @throws InvalidDataTypeException |
|
171 | - * @throws InvalidInterfaceException |
|
172 | - * @throws ReflectionException |
|
173 | - */ |
|
174 | - public function set_name($name) |
|
175 | - { |
|
176 | - $this->set('LIN_name', $name); |
|
177 | - } |
|
178 | - |
|
179 | - |
|
180 | - /** |
|
181 | - * Gets desc |
|
182 | - * |
|
183 | - * @return string |
|
184 | - * @throws EE_Error |
|
185 | - * @throws InvalidArgumentException |
|
186 | - * @throws InvalidDataTypeException |
|
187 | - * @throws InvalidInterfaceException |
|
188 | - * @throws ReflectionException |
|
189 | - */ |
|
190 | - public function desc() |
|
191 | - { |
|
192 | - return $this->get('LIN_desc'); |
|
193 | - } |
|
194 | - |
|
195 | - |
|
196 | - /** |
|
197 | - * Sets desc |
|
198 | - * |
|
199 | - * @param string $desc |
|
200 | - * @throws EE_Error |
|
201 | - * @throws InvalidArgumentException |
|
202 | - * @throws InvalidDataTypeException |
|
203 | - * @throws InvalidInterfaceException |
|
204 | - * @throws ReflectionException |
|
205 | - */ |
|
206 | - public function set_desc($desc) |
|
207 | - { |
|
208 | - $this->set('LIN_desc', $desc); |
|
209 | - } |
|
210 | - |
|
211 | - |
|
212 | - /** |
|
213 | - * Gets quantity |
|
214 | - * |
|
215 | - * @return int |
|
216 | - * @throws EE_Error |
|
217 | - * @throws InvalidArgumentException |
|
218 | - * @throws InvalidDataTypeException |
|
219 | - * @throws InvalidInterfaceException |
|
220 | - * @throws ReflectionException |
|
221 | - */ |
|
222 | - public function quantity() |
|
223 | - { |
|
224 | - return $this->get('LIN_quantity'); |
|
225 | - } |
|
226 | - |
|
227 | - |
|
228 | - /** |
|
229 | - * Sets quantity |
|
230 | - * |
|
231 | - * @param int $quantity |
|
232 | - * @throws EE_Error |
|
233 | - * @throws InvalidArgumentException |
|
234 | - * @throws InvalidDataTypeException |
|
235 | - * @throws InvalidInterfaceException |
|
236 | - * @throws ReflectionException |
|
237 | - */ |
|
238 | - public function set_quantity($quantity) |
|
239 | - { |
|
240 | - $this->set('LIN_quantity', max($quantity, 0)); |
|
241 | - } |
|
242 | - |
|
243 | - |
|
244 | - /** |
|
245 | - * Gets item_id |
|
246 | - * |
|
247 | - * @return string |
|
248 | - * @throws EE_Error |
|
249 | - * @throws InvalidArgumentException |
|
250 | - * @throws InvalidDataTypeException |
|
251 | - * @throws InvalidInterfaceException |
|
252 | - * @throws ReflectionException |
|
253 | - */ |
|
254 | - public function OBJ_ID() |
|
255 | - { |
|
256 | - return $this->get('OBJ_ID'); |
|
257 | - } |
|
258 | - |
|
259 | - |
|
260 | - /** |
|
261 | - * Sets item_id |
|
262 | - * |
|
263 | - * @param string $item_id |
|
264 | - * @throws EE_Error |
|
265 | - * @throws InvalidArgumentException |
|
266 | - * @throws InvalidDataTypeException |
|
267 | - * @throws InvalidInterfaceException |
|
268 | - * @throws ReflectionException |
|
269 | - */ |
|
270 | - public function set_OBJ_ID($item_id) |
|
271 | - { |
|
272 | - $this->set('OBJ_ID', $item_id); |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - /** |
|
277 | - * Gets item_type |
|
278 | - * |
|
279 | - * @return string |
|
280 | - * @throws EE_Error |
|
281 | - * @throws InvalidArgumentException |
|
282 | - * @throws InvalidDataTypeException |
|
283 | - * @throws InvalidInterfaceException |
|
284 | - * @throws ReflectionException |
|
285 | - */ |
|
286 | - public function OBJ_type() |
|
287 | - { |
|
288 | - return $this->get('OBJ_type'); |
|
289 | - } |
|
290 | - |
|
291 | - |
|
292 | - /** |
|
293 | - * Gets item_type |
|
294 | - * |
|
295 | - * @return string |
|
296 | - * @throws EE_Error |
|
297 | - * @throws InvalidArgumentException |
|
298 | - * @throws InvalidDataTypeException |
|
299 | - * @throws InvalidInterfaceException |
|
300 | - * @throws ReflectionException |
|
301 | - */ |
|
302 | - public function OBJ_type_i18n() |
|
303 | - { |
|
304 | - $obj_type = $this->OBJ_type(); |
|
305 | - switch ($obj_type) { |
|
306 | - case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
307 | - $obj_type = esc_html__('Event', 'event_espresso'); |
|
308 | - break; |
|
309 | - case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
310 | - $obj_type = esc_html__('Price', 'event_espresso'); |
|
311 | - break; |
|
312 | - case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
313 | - $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
314 | - break; |
|
315 | - case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
316 | - $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
317 | - break; |
|
318 | - case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
319 | - $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
320 | - break; |
|
321 | - } |
|
322 | - return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - /** |
|
327 | - * Sets item_type |
|
328 | - * |
|
329 | - * @param string $OBJ_type |
|
330 | - * @throws EE_Error |
|
331 | - * @throws InvalidArgumentException |
|
332 | - * @throws InvalidDataTypeException |
|
333 | - * @throws InvalidInterfaceException |
|
334 | - * @throws ReflectionException |
|
335 | - */ |
|
336 | - public function set_OBJ_type($OBJ_type) |
|
337 | - { |
|
338 | - $this->set('OBJ_type', $OBJ_type); |
|
339 | - } |
|
340 | - |
|
341 | - |
|
342 | - /** |
|
343 | - * Gets unit_price |
|
344 | - * |
|
345 | - * @return float |
|
346 | - * @throws EE_Error |
|
347 | - * @throws InvalidArgumentException |
|
348 | - * @throws InvalidDataTypeException |
|
349 | - * @throws InvalidInterfaceException |
|
350 | - * @throws ReflectionException |
|
351 | - */ |
|
352 | - public function unit_price() |
|
353 | - { |
|
354 | - return $this->get('LIN_unit_price'); |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * Sets unit_price |
|
360 | - * |
|
361 | - * @param float $unit_price |
|
362 | - * @throws EE_Error |
|
363 | - * @throws InvalidArgumentException |
|
364 | - * @throws InvalidDataTypeException |
|
365 | - * @throws InvalidInterfaceException |
|
366 | - * @throws ReflectionException |
|
367 | - */ |
|
368 | - public function set_unit_price($unit_price) |
|
369 | - { |
|
370 | - $this->set('LIN_unit_price', $unit_price); |
|
371 | - } |
|
372 | - |
|
373 | - |
|
374 | - /** |
|
375 | - * Checks if this item is a percentage modifier or not |
|
376 | - * |
|
377 | - * @return boolean |
|
378 | - * @throws EE_Error |
|
379 | - * @throws InvalidArgumentException |
|
380 | - * @throws InvalidDataTypeException |
|
381 | - * @throws InvalidInterfaceException |
|
382 | - * @throws ReflectionException |
|
383 | - */ |
|
384 | - public function is_percent() |
|
385 | - { |
|
386 | - if ($this->is_tax_sub_total()) { |
|
387 | - // tax subtotals HAVE a percent on them, that percentage only applies |
|
388 | - // to taxable items, so its' an exception. Treat it like a flat line item |
|
389 | - return false; |
|
390 | - } |
|
391 | - $unit_price = abs($this->get('LIN_unit_price')); |
|
392 | - $percent = abs($this->get('LIN_percent')); |
|
393 | - if ($unit_price < .001 && $percent) { |
|
394 | - return true; |
|
395 | - } |
|
396 | - if ($unit_price >= .001 && ! $percent) { |
|
397 | - return false; |
|
398 | - } |
|
399 | - if ($unit_price >= .001 && $percent) { |
|
400 | - throw new EE_Error( |
|
401 | - sprintf( |
|
402 | - esc_html__( |
|
403 | - 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
404 | - 'event_espresso' |
|
405 | - ), |
|
406 | - $unit_price, |
|
407 | - $percent |
|
408 | - ) |
|
409 | - ); |
|
410 | - } |
|
411 | - // if they're both 0, assume its not a percent item |
|
412 | - return false; |
|
413 | - } |
|
414 | - |
|
415 | - |
|
416 | - /** |
|
417 | - * Gets percent (between 100-.001) |
|
418 | - * |
|
419 | - * @return float |
|
420 | - * @throws EE_Error |
|
421 | - * @throws InvalidArgumentException |
|
422 | - * @throws InvalidDataTypeException |
|
423 | - * @throws InvalidInterfaceException |
|
424 | - * @throws ReflectionException |
|
425 | - */ |
|
426 | - public function percent() |
|
427 | - { |
|
428 | - return $this->get('LIN_percent'); |
|
429 | - } |
|
430 | - |
|
431 | - |
|
432 | - /** |
|
433 | - * Sets percent (between 100-0.01) |
|
434 | - * |
|
435 | - * @param float $percent |
|
436 | - * @throws EE_Error |
|
437 | - * @throws InvalidArgumentException |
|
438 | - * @throws InvalidDataTypeException |
|
439 | - * @throws InvalidInterfaceException |
|
440 | - * @throws ReflectionException |
|
441 | - */ |
|
442 | - public function set_percent($percent) |
|
443 | - { |
|
444 | - $this->set('LIN_percent', $percent); |
|
445 | - } |
|
446 | - |
|
447 | - |
|
448 | - /** |
|
449 | - * Gets total |
|
450 | - * |
|
451 | - * @return float |
|
452 | - * @throws EE_Error |
|
453 | - * @throws InvalidArgumentException |
|
454 | - * @throws InvalidDataTypeException |
|
455 | - * @throws InvalidInterfaceException |
|
456 | - * @throws ReflectionException |
|
457 | - */ |
|
458 | - public function total() |
|
459 | - { |
|
460 | - return $this->get('LIN_total'); |
|
461 | - } |
|
462 | - |
|
463 | - |
|
464 | - /** |
|
465 | - * Sets total |
|
466 | - * |
|
467 | - * @param float $total |
|
468 | - * @throws EE_Error |
|
469 | - * @throws InvalidArgumentException |
|
470 | - * @throws InvalidDataTypeException |
|
471 | - * @throws InvalidInterfaceException |
|
472 | - * @throws ReflectionException |
|
473 | - */ |
|
474 | - public function set_total($total) |
|
475 | - { |
|
476 | - $this->set('LIN_total', $total); |
|
477 | - } |
|
478 | - |
|
479 | - |
|
480 | - /** |
|
481 | - * Gets order |
|
482 | - * |
|
483 | - * @return int |
|
484 | - * @throws EE_Error |
|
485 | - * @throws InvalidArgumentException |
|
486 | - * @throws InvalidDataTypeException |
|
487 | - * @throws InvalidInterfaceException |
|
488 | - * @throws ReflectionException |
|
489 | - */ |
|
490 | - public function order() |
|
491 | - { |
|
492 | - return $this->get('LIN_order'); |
|
493 | - } |
|
494 | - |
|
495 | - |
|
496 | - /** |
|
497 | - * Sets order |
|
498 | - * |
|
499 | - * @param int $order |
|
500 | - * @throws EE_Error |
|
501 | - * @throws InvalidArgumentException |
|
502 | - * @throws InvalidDataTypeException |
|
503 | - * @throws InvalidInterfaceException |
|
504 | - * @throws ReflectionException |
|
505 | - */ |
|
506 | - public function set_order($order) |
|
507 | - { |
|
508 | - $this->set('LIN_order', $order); |
|
509 | - } |
|
510 | - |
|
511 | - |
|
512 | - /** |
|
513 | - * Gets parent |
|
514 | - * |
|
515 | - * @return int |
|
516 | - * @throws EE_Error |
|
517 | - * @throws InvalidArgumentException |
|
518 | - * @throws InvalidDataTypeException |
|
519 | - * @throws InvalidInterfaceException |
|
520 | - * @throws ReflectionException |
|
521 | - */ |
|
522 | - public function parent_ID() |
|
523 | - { |
|
524 | - return $this->get('LIN_parent'); |
|
525 | - } |
|
526 | - |
|
527 | - |
|
528 | - /** |
|
529 | - * Sets parent |
|
530 | - * |
|
531 | - * @param int $parent |
|
532 | - * @throws EE_Error |
|
533 | - * @throws InvalidArgumentException |
|
534 | - * @throws InvalidDataTypeException |
|
535 | - * @throws InvalidInterfaceException |
|
536 | - * @throws ReflectionException |
|
537 | - */ |
|
538 | - public function set_parent_ID($parent) |
|
539 | - { |
|
540 | - $this->set('LIN_parent', $parent); |
|
541 | - } |
|
542 | - |
|
543 | - |
|
544 | - /** |
|
545 | - * Gets type |
|
546 | - * |
|
547 | - * @return string |
|
548 | - * @throws EE_Error |
|
549 | - * @throws InvalidArgumentException |
|
550 | - * @throws InvalidDataTypeException |
|
551 | - * @throws InvalidInterfaceException |
|
552 | - * @throws ReflectionException |
|
553 | - */ |
|
554 | - public function type() |
|
555 | - { |
|
556 | - return $this->get('LIN_type'); |
|
557 | - } |
|
558 | - |
|
559 | - |
|
560 | - /** |
|
561 | - * Sets type |
|
562 | - * |
|
563 | - * @param string $type |
|
564 | - * @throws EE_Error |
|
565 | - * @throws InvalidArgumentException |
|
566 | - * @throws InvalidDataTypeException |
|
567 | - * @throws InvalidInterfaceException |
|
568 | - * @throws ReflectionException |
|
569 | - */ |
|
570 | - public function set_type($type) |
|
571 | - { |
|
572 | - $this->set('LIN_type', $type); |
|
573 | - } |
|
574 | - |
|
575 | - |
|
576 | - /** |
|
577 | - * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
578 | - * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB |
|
579 | - * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
580 | - * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
581 | - * |
|
582 | - * @return EE_Base_Class|EE_Line_Item |
|
583 | - * @throws EE_Error |
|
584 | - * @throws InvalidArgumentException |
|
585 | - * @throws InvalidDataTypeException |
|
586 | - * @throws InvalidInterfaceException |
|
587 | - * @throws ReflectionException |
|
588 | - */ |
|
589 | - public function parent() |
|
590 | - { |
|
591 | - return $this->ID() |
|
592 | - ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
593 | - : $this->_parent; |
|
594 | - } |
|
595 | - |
|
596 | - |
|
597 | - /** |
|
598 | - * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
599 | - * |
|
600 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
601 | - * @throws EE_Error |
|
602 | - * @throws InvalidArgumentException |
|
603 | - * @throws InvalidDataTypeException |
|
604 | - * @throws InvalidInterfaceException |
|
605 | - * @throws ReflectionException |
|
606 | - */ |
|
607 | - public function children() |
|
608 | - { |
|
609 | - if ($this->ID()) { |
|
610 | - return $this->get_model()->get_all( |
|
611 | - array( |
|
612 | - array('LIN_parent' => $this->ID()), |
|
613 | - 'order_by' => array('LIN_order' => 'ASC'), |
|
614 | - ) |
|
615 | - ); |
|
616 | - } |
|
617 | - if (! is_array($this->_children)) { |
|
618 | - $this->_children = array(); |
|
619 | - } |
|
620 | - return $this->_children; |
|
621 | - } |
|
622 | - |
|
623 | - |
|
624 | - /** |
|
625 | - * Gets code |
|
626 | - * |
|
627 | - * @return string |
|
628 | - * @throws EE_Error |
|
629 | - * @throws InvalidArgumentException |
|
630 | - * @throws InvalidDataTypeException |
|
631 | - * @throws InvalidInterfaceException |
|
632 | - * @throws ReflectionException |
|
633 | - */ |
|
634 | - public function code() |
|
635 | - { |
|
636 | - return $this->get('LIN_code'); |
|
637 | - } |
|
638 | - |
|
639 | - |
|
640 | - /** |
|
641 | - * Sets code |
|
642 | - * |
|
643 | - * @param string $code |
|
644 | - * @throws EE_Error |
|
645 | - * @throws InvalidArgumentException |
|
646 | - * @throws InvalidDataTypeException |
|
647 | - * @throws InvalidInterfaceException |
|
648 | - * @throws ReflectionException |
|
649 | - */ |
|
650 | - public function set_code($code) |
|
651 | - { |
|
652 | - $this->set('LIN_code', $code); |
|
653 | - } |
|
654 | - |
|
655 | - |
|
656 | - /** |
|
657 | - * Gets is_taxable |
|
658 | - * |
|
659 | - * @return boolean |
|
660 | - * @throws EE_Error |
|
661 | - * @throws InvalidArgumentException |
|
662 | - * @throws InvalidDataTypeException |
|
663 | - * @throws InvalidInterfaceException |
|
664 | - * @throws ReflectionException |
|
665 | - */ |
|
666 | - public function is_taxable() |
|
667 | - { |
|
668 | - return $this->get('LIN_is_taxable'); |
|
669 | - } |
|
670 | - |
|
671 | - |
|
672 | - /** |
|
673 | - * Sets is_taxable |
|
674 | - * |
|
675 | - * @param boolean $is_taxable |
|
676 | - * @throws EE_Error |
|
677 | - * @throws InvalidArgumentException |
|
678 | - * @throws InvalidDataTypeException |
|
679 | - * @throws InvalidInterfaceException |
|
680 | - * @throws ReflectionException |
|
681 | - */ |
|
682 | - public function set_is_taxable($is_taxable) |
|
683 | - { |
|
684 | - $this->set('LIN_is_taxable', $is_taxable); |
|
685 | - } |
|
686 | - |
|
687 | - |
|
688 | - /** |
|
689 | - * Gets the object that this model-joins-to. |
|
690 | - * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
691 | - * EEM_Promotion_Object |
|
692 | - * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
693 | - * |
|
694 | - * @return EE_Base_Class | NULL |
|
695 | - * @throws EE_Error |
|
696 | - * @throws InvalidArgumentException |
|
697 | - * @throws InvalidDataTypeException |
|
698 | - * @throws InvalidInterfaceException |
|
699 | - * @throws ReflectionException |
|
700 | - */ |
|
701 | - public function get_object() |
|
702 | - { |
|
703 | - $model_name_of_related_obj = $this->OBJ_type(); |
|
704 | - return $this->get_model()->has_relation($model_name_of_related_obj) |
|
705 | - ? $this->get_first_related($model_name_of_related_obj) |
|
706 | - : null; |
|
707 | - } |
|
708 | - |
|
709 | - |
|
710 | - /** |
|
711 | - * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
712 | - * (IE, if this line item is for a price or something else, will return NULL) |
|
713 | - * |
|
714 | - * @param array $query_params |
|
715 | - * @return EE_Base_Class|EE_Ticket |
|
716 | - * @throws EE_Error |
|
717 | - * @throws InvalidArgumentException |
|
718 | - * @throws InvalidDataTypeException |
|
719 | - * @throws InvalidInterfaceException |
|
720 | - * @throws ReflectionException |
|
721 | - */ |
|
722 | - public function ticket($query_params = array()) |
|
723 | - { |
|
724 | - // we're going to assume that when this method is called |
|
725 | - // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
726 | - // This can be overridden via the incoming $query_params argument |
|
727 | - $remove_defaults = array('default_where_conditions' => 'none'); |
|
728 | - $query_params = array_merge($remove_defaults, $query_params); |
|
729 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
730 | - } |
|
731 | - |
|
732 | - |
|
733 | - /** |
|
734 | - * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
735 | - * |
|
736 | - * @return EE_Datetime | NULL |
|
737 | - * @throws EE_Error |
|
738 | - * @throws InvalidArgumentException |
|
739 | - * @throws InvalidDataTypeException |
|
740 | - * @throws InvalidInterfaceException |
|
741 | - * @throws ReflectionException |
|
742 | - */ |
|
743 | - public function get_ticket_datetime() |
|
744 | - { |
|
745 | - if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
746 | - $ticket = $this->ticket(); |
|
747 | - if ($ticket instanceof EE_Ticket) { |
|
748 | - $datetime = $ticket->first_datetime(); |
|
749 | - if ($datetime instanceof EE_Datetime) { |
|
750 | - return $datetime; |
|
751 | - } |
|
752 | - } |
|
753 | - } |
|
754 | - return null; |
|
755 | - } |
|
756 | - |
|
757 | - |
|
758 | - /** |
|
759 | - * Gets the event's name that's related to the ticket, if this is for |
|
760 | - * a ticket |
|
761 | - * |
|
762 | - * @return string |
|
763 | - * @throws EE_Error |
|
764 | - * @throws InvalidArgumentException |
|
765 | - * @throws InvalidDataTypeException |
|
766 | - * @throws InvalidInterfaceException |
|
767 | - * @throws ReflectionException |
|
768 | - */ |
|
769 | - public function ticket_event_name() |
|
770 | - { |
|
771 | - $event_name = esc_html__('Unknown', 'event_espresso'); |
|
772 | - $event = $this->ticket_event(); |
|
773 | - if ($event instanceof EE_Event) { |
|
774 | - $event_name = $event->name(); |
|
775 | - } |
|
776 | - return $event_name; |
|
777 | - } |
|
778 | - |
|
779 | - |
|
780 | - /** |
|
781 | - * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
782 | - * |
|
783 | - * @return EE_Event|null |
|
784 | - * @throws EE_Error |
|
785 | - * @throws InvalidArgumentException |
|
786 | - * @throws InvalidDataTypeException |
|
787 | - * @throws InvalidInterfaceException |
|
788 | - * @throws ReflectionException |
|
789 | - */ |
|
790 | - public function ticket_event() |
|
791 | - { |
|
792 | - $event = null; |
|
793 | - $ticket = $this->ticket(); |
|
794 | - if ($ticket instanceof EE_Ticket) { |
|
795 | - $datetime = $ticket->first_datetime(); |
|
796 | - if ($datetime instanceof EE_Datetime) { |
|
797 | - $event = $datetime->event(); |
|
798 | - } |
|
799 | - } |
|
800 | - return $event; |
|
801 | - } |
|
802 | - |
|
803 | - |
|
804 | - /** |
|
805 | - * Gets the first datetime for this lien item, assuming it's for a ticket |
|
806 | - * |
|
807 | - * @param string $date_format |
|
808 | - * @param string $time_format |
|
809 | - * @return string |
|
810 | - * @throws EE_Error |
|
811 | - * @throws InvalidArgumentException |
|
812 | - * @throws InvalidDataTypeException |
|
813 | - * @throws InvalidInterfaceException |
|
814 | - * @throws ReflectionException |
|
815 | - */ |
|
816 | - public function ticket_datetime_start($date_format = '', $time_format = '') |
|
817 | - { |
|
818 | - $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
819 | - $datetime = $this->get_ticket_datetime(); |
|
820 | - if ($datetime) { |
|
821 | - $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
822 | - } |
|
823 | - return $first_datetime_string; |
|
824 | - } |
|
825 | - |
|
826 | - |
|
827 | - /** |
|
828 | - * Adds the line item as a child to this line item. If there is another child line |
|
829 | - * item with the same LIN_code, it is overwritten by this new one |
|
830 | - * |
|
831 | - * @param EEI_Line_Item $line_item |
|
832 | - * @param bool $set_order |
|
833 | - * @return bool success |
|
834 | - * @throws EE_Error |
|
835 | - * @throws InvalidArgumentException |
|
836 | - * @throws InvalidDataTypeException |
|
837 | - * @throws InvalidInterfaceException |
|
838 | - * @throws ReflectionException |
|
839 | - */ |
|
840 | - public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
841 | - { |
|
842 | - // should we calculate the LIN_order for this line item ? |
|
843 | - if ($set_order || $line_item->order() === null) { |
|
844 | - $line_item->set_order(count($this->children())); |
|
845 | - } |
|
846 | - if ($this->ID()) { |
|
847 | - // check for any duplicate line items (with the same code), if so, this replaces it |
|
848 | - $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
849 | - if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
850 | - $this->delete_child_line_item($line_item_with_same_code->code()); |
|
851 | - } |
|
852 | - $line_item->set_parent_ID($this->ID()); |
|
853 | - if ($this->TXN_ID()) { |
|
854 | - $line_item->set_TXN_ID($this->TXN_ID()); |
|
855 | - } |
|
856 | - return $line_item->save(); |
|
857 | - } |
|
858 | - $this->_children[ $line_item->code() ] = $line_item; |
|
859 | - if ($line_item->parent() !== $this) { |
|
860 | - $line_item->set_parent($this); |
|
861 | - } |
|
862 | - return true; |
|
863 | - } |
|
864 | - |
|
865 | - |
|
866 | - /** |
|
867 | - * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
868 | - * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
869 | - * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
870 | - * the EE_Line_Item::_parent property. |
|
871 | - * |
|
872 | - * @param EE_Line_Item $line_item |
|
873 | - * @throws EE_Error |
|
874 | - * @throws InvalidArgumentException |
|
875 | - * @throws InvalidDataTypeException |
|
876 | - * @throws InvalidInterfaceException |
|
877 | - * @throws ReflectionException |
|
878 | - */ |
|
879 | - public function set_parent($line_item) |
|
880 | - { |
|
881 | - if ($this->ID()) { |
|
882 | - if (! $line_item->ID()) { |
|
883 | - $line_item->save(); |
|
884 | - } |
|
885 | - $this->set_parent_ID($line_item->ID()); |
|
886 | - $this->save(); |
|
887 | - } else { |
|
888 | - $this->_parent = $line_item; |
|
889 | - $this->set_parent_ID($line_item->ID()); |
|
890 | - } |
|
891 | - } |
|
892 | - |
|
893 | - |
|
894 | - /** |
|
895 | - * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
896 | - * you can modify this child line item and the parent (this object) can know about them |
|
897 | - * because it also has a reference to that line item |
|
898 | - * |
|
899 | - * @param string $code |
|
900 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
901 | - * @throws EE_Error |
|
902 | - * @throws InvalidArgumentException |
|
903 | - * @throws InvalidDataTypeException |
|
904 | - * @throws InvalidInterfaceException |
|
905 | - * @throws ReflectionException |
|
906 | - */ |
|
907 | - public function get_child_line_item($code) |
|
908 | - { |
|
909 | - if ($this->ID()) { |
|
910 | - return $this->get_model()->get_one( |
|
911 | - array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
912 | - ); |
|
913 | - } |
|
914 | - return isset($this->_children[ $code ]) |
|
915 | - ? $this->_children[ $code ] |
|
916 | - : null; |
|
917 | - } |
|
918 | - |
|
919 | - |
|
920 | - /** |
|
921 | - * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
922 | - * cached on it) |
|
923 | - * |
|
924 | - * @return int |
|
925 | - * @throws EE_Error |
|
926 | - * @throws InvalidArgumentException |
|
927 | - * @throws InvalidDataTypeException |
|
928 | - * @throws InvalidInterfaceException |
|
929 | - * @throws ReflectionException |
|
930 | - */ |
|
931 | - public function delete_children_line_items() |
|
932 | - { |
|
933 | - if ($this->ID()) { |
|
934 | - return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
935 | - } |
|
936 | - $count = count($this->_children); |
|
937 | - $this->_children = array(); |
|
938 | - return $count; |
|
939 | - } |
|
940 | - |
|
941 | - |
|
942 | - /** |
|
943 | - * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
944 | - * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
945 | - * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
946 | - * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
947 | - * deleted) |
|
948 | - * |
|
949 | - * @param string $code |
|
950 | - * @param bool $stop_search_once_found |
|
951 | - * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
952 | - * the DB yet) |
|
953 | - * @throws EE_Error |
|
954 | - * @throws InvalidArgumentException |
|
955 | - * @throws InvalidDataTypeException |
|
956 | - * @throws InvalidInterfaceException |
|
957 | - * @throws ReflectionException |
|
958 | - */ |
|
959 | - public function delete_child_line_item($code, $stop_search_once_found = true) |
|
960 | - { |
|
961 | - if ($this->ID()) { |
|
962 | - $items_deleted = 0; |
|
963 | - if ($this->code() === $code) { |
|
964 | - $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
965 | - $items_deleted += (int) $this->delete(); |
|
966 | - if ($stop_search_once_found) { |
|
967 | - return $items_deleted; |
|
968 | - } |
|
969 | - } |
|
970 | - foreach ($this->children() as $child_line_item) { |
|
971 | - $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
972 | - } |
|
973 | - return $items_deleted; |
|
974 | - } |
|
975 | - if (isset($this->_children[ $code ])) { |
|
976 | - unset($this->_children[ $code ]); |
|
977 | - return 1; |
|
978 | - } |
|
979 | - return 0; |
|
980 | - } |
|
981 | - |
|
982 | - |
|
983 | - /** |
|
984 | - * If this line item is in the database, is of the type subtotal, and |
|
985 | - * has no children, why do we have it? It should be deleted so this function |
|
986 | - * does that |
|
987 | - * |
|
988 | - * @return boolean |
|
989 | - * @throws EE_Error |
|
990 | - * @throws InvalidArgumentException |
|
991 | - * @throws InvalidDataTypeException |
|
992 | - * @throws InvalidInterfaceException |
|
993 | - * @throws ReflectionException |
|
994 | - */ |
|
995 | - public function delete_if_childless_subtotal() |
|
996 | - { |
|
997 | - if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
998 | - return $this->delete(); |
|
999 | - } |
|
1000 | - return false; |
|
1001 | - } |
|
1002 | - |
|
1003 | - |
|
1004 | - /** |
|
1005 | - * Creates a code and returns a string. doesn't assign the code to this model object |
|
1006 | - * |
|
1007 | - * @return string |
|
1008 | - * @throws EE_Error |
|
1009 | - * @throws InvalidArgumentException |
|
1010 | - * @throws InvalidDataTypeException |
|
1011 | - * @throws InvalidInterfaceException |
|
1012 | - * @throws ReflectionException |
|
1013 | - */ |
|
1014 | - public function generate_code() |
|
1015 | - { |
|
1016 | - // each line item in the cart requires a unique identifier |
|
1017 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
1018 | - } |
|
1019 | - |
|
1020 | - |
|
1021 | - /** |
|
1022 | - * @return bool |
|
1023 | - * @throws EE_Error |
|
1024 | - * @throws InvalidArgumentException |
|
1025 | - * @throws InvalidDataTypeException |
|
1026 | - * @throws InvalidInterfaceException |
|
1027 | - * @throws ReflectionException |
|
1028 | - */ |
|
1029 | - public function is_tax() |
|
1030 | - { |
|
1031 | - return $this->type() === EEM_Line_Item::type_tax; |
|
1032 | - } |
|
1033 | - |
|
1034 | - |
|
1035 | - /** |
|
1036 | - * @return bool |
|
1037 | - * @throws EE_Error |
|
1038 | - * @throws InvalidArgumentException |
|
1039 | - * @throws InvalidDataTypeException |
|
1040 | - * @throws InvalidInterfaceException |
|
1041 | - * @throws ReflectionException |
|
1042 | - */ |
|
1043 | - public function is_tax_sub_total() |
|
1044 | - { |
|
1045 | - return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
1046 | - } |
|
1047 | - |
|
1048 | - |
|
1049 | - /** |
|
1050 | - * @return bool |
|
1051 | - * @throws EE_Error |
|
1052 | - * @throws InvalidArgumentException |
|
1053 | - * @throws InvalidDataTypeException |
|
1054 | - * @throws InvalidInterfaceException |
|
1055 | - * @throws ReflectionException |
|
1056 | - */ |
|
1057 | - public function is_line_item() |
|
1058 | - { |
|
1059 | - return $this->type() === EEM_Line_Item::type_line_item; |
|
1060 | - } |
|
1061 | - |
|
1062 | - |
|
1063 | - /** |
|
1064 | - * @return bool |
|
1065 | - * @throws EE_Error |
|
1066 | - * @throws InvalidArgumentException |
|
1067 | - * @throws InvalidDataTypeException |
|
1068 | - * @throws InvalidInterfaceException |
|
1069 | - * @throws ReflectionException |
|
1070 | - */ |
|
1071 | - public function is_sub_line_item() |
|
1072 | - { |
|
1073 | - return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
1074 | - } |
|
1075 | - |
|
1076 | - |
|
1077 | - /** |
|
1078 | - * @return bool |
|
1079 | - * @throws EE_Error |
|
1080 | - * @throws InvalidArgumentException |
|
1081 | - * @throws InvalidDataTypeException |
|
1082 | - * @throws InvalidInterfaceException |
|
1083 | - * @throws ReflectionException |
|
1084 | - */ |
|
1085 | - public function is_sub_total() |
|
1086 | - { |
|
1087 | - return $this->type() === EEM_Line_Item::type_sub_total; |
|
1088 | - } |
|
1089 | - |
|
1090 | - |
|
1091 | - /** |
|
1092 | - * Whether or not this line item is a cancellation line item |
|
1093 | - * |
|
1094 | - * @return boolean |
|
1095 | - * @throws EE_Error |
|
1096 | - * @throws InvalidArgumentException |
|
1097 | - * @throws InvalidDataTypeException |
|
1098 | - * @throws InvalidInterfaceException |
|
1099 | - * @throws ReflectionException |
|
1100 | - */ |
|
1101 | - public function is_cancellation() |
|
1102 | - { |
|
1103 | - return EEM_Line_Item::type_cancellation === $this->type(); |
|
1104 | - } |
|
1105 | - |
|
1106 | - |
|
1107 | - /** |
|
1108 | - * @return bool |
|
1109 | - * @throws EE_Error |
|
1110 | - * @throws InvalidArgumentException |
|
1111 | - * @throws InvalidDataTypeException |
|
1112 | - * @throws InvalidInterfaceException |
|
1113 | - * @throws ReflectionException |
|
1114 | - */ |
|
1115 | - public function is_total() |
|
1116 | - { |
|
1117 | - return $this->type() === EEM_Line_Item::type_total; |
|
1118 | - } |
|
1119 | - |
|
1120 | - |
|
1121 | - /** |
|
1122 | - * @return bool |
|
1123 | - * @throws EE_Error |
|
1124 | - * @throws InvalidArgumentException |
|
1125 | - * @throws InvalidDataTypeException |
|
1126 | - * @throws InvalidInterfaceException |
|
1127 | - * @throws ReflectionException |
|
1128 | - */ |
|
1129 | - public function is_cancelled() |
|
1130 | - { |
|
1131 | - return $this->type() === EEM_Line_Item::type_cancellation; |
|
1132 | - } |
|
1133 | - |
|
1134 | - |
|
1135 | - /** |
|
1136 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
1137 | - * @throws EE_Error |
|
1138 | - * @throws InvalidArgumentException |
|
1139 | - * @throws InvalidDataTypeException |
|
1140 | - * @throws InvalidInterfaceException |
|
1141 | - * @throws ReflectionException |
|
1142 | - */ |
|
1143 | - public function unit_price_no_code() |
|
1144 | - { |
|
1145 | - return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
1146 | - } |
|
1147 | - |
|
1148 | - |
|
1149 | - /** |
|
1150 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
1151 | - * @throws EE_Error |
|
1152 | - * @throws InvalidArgumentException |
|
1153 | - * @throws InvalidDataTypeException |
|
1154 | - * @throws InvalidInterfaceException |
|
1155 | - * @throws ReflectionException |
|
1156 | - */ |
|
1157 | - public function total_no_code() |
|
1158 | - { |
|
1159 | - return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
1160 | - } |
|
1161 | - |
|
1162 | - |
|
1163 | - /** |
|
1164 | - * Gets the final total on this item, taking taxes into account. |
|
1165 | - * Has the side-effect of setting the sub-total as it was just calculated. |
|
1166 | - * If this is used on a grand-total line item, also updates the transaction's |
|
1167 | - * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
1168 | - * want to change a persistable transaction with info from a non-persistent line item) |
|
1169 | - * |
|
1170 | - * @param bool $update_txn_status |
|
1171 | - * @return float |
|
1172 | - * @throws EE_Error |
|
1173 | - * @throws InvalidArgumentException |
|
1174 | - * @throws InvalidDataTypeException |
|
1175 | - * @throws InvalidInterfaceException |
|
1176 | - * @throws ReflectionException |
|
1177 | - * @throws RuntimeException |
|
1178 | - */ |
|
1179 | - public function recalculate_total_including_taxes($update_txn_status = false) |
|
1180 | - { |
|
1181 | - $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
1182 | - $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
1183 | - $total = $pre_tax_total + $tax_total; |
|
1184 | - // no negative totals plz |
|
1185 | - $total = max($total, 0); |
|
1186 | - $this->set_total($total); |
|
1187 | - // only update the related transaction's total |
|
1188 | - // if we intend to save this line item and its a grand total |
|
1189 | - if ( |
|
1190 | - $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
1191 | - && $this->transaction() |
|
1192 | - instanceof |
|
1193 | - EE_Transaction |
|
1194 | - ) { |
|
1195 | - $this->transaction()->set_total($total); |
|
1196 | - if ($update_txn_status) { |
|
1197 | - // don't save the TXN because that will be done below |
|
1198 | - // and the following method only saves if the status changes |
|
1199 | - $this->transaction()->update_status_based_on_total_paid(false); |
|
1200 | - } |
|
1201 | - if ($this->transaction()->ID()) { |
|
1202 | - $this->transaction()->save(); |
|
1203 | - } |
|
1204 | - } |
|
1205 | - $this->maybe_save(); |
|
1206 | - return $total; |
|
1207 | - } |
|
1208 | - |
|
1209 | - |
|
1210 | - /** |
|
1211 | - * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
1212 | - * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
1213 | - * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
1214 | - * when this is called on the grand total |
|
1215 | - * |
|
1216 | - * @return float |
|
1217 | - * @throws EE_Error |
|
1218 | - * @throws InvalidArgumentException |
|
1219 | - * @throws InvalidDataTypeException |
|
1220 | - * @throws InvalidInterfaceException |
|
1221 | - * @throws ReflectionException |
|
1222 | - */ |
|
1223 | - public function recalculate_pre_tax_total() |
|
1224 | - { |
|
1225 | - $total = 0; |
|
1226 | - $my_children = $this->children(); |
|
1227 | - $has_children = ! empty($my_children); |
|
1228 | - if ($has_children && $this->is_line_item()) { |
|
1229 | - $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
1230 | - } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1231 | - $total = $this->unit_price() * $this->quantity(); |
|
1232 | - } elseif ($this->is_sub_total() || $this->is_total()) { |
|
1233 | - $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
1234 | - } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
1235 | - // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
1236 | - return 0; |
|
1237 | - } |
|
1238 | - // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
1239 | - if ( |
|
1240 | - ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
1241 | - ) { |
|
1242 | - if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
1243 | - $this->set_quantity(1); |
|
1244 | - } |
|
1245 | - if (! $this->is_percent()) { |
|
1246 | - $this->set_unit_price($total); |
|
1247 | - } |
|
1248 | - } |
|
1249 | - // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
1250 | - // so it ought to be |
|
1251 | - if (! $this->is_total()) { |
|
1252 | - $this->set_total($total); |
|
1253 | - // if not a percent line item, make sure we keep the unit price in sync |
|
1254 | - if ( |
|
1255 | - $has_children |
|
1256 | - && $this->is_line_item() |
|
1257 | - && ! $this->is_percent() |
|
1258 | - ) { |
|
1259 | - if ($this->quantity() === 0) { |
|
1260 | - $new_unit_price = 0; |
|
1261 | - } else { |
|
1262 | - $new_unit_price = $this->total() / $this->quantity(); |
|
1263 | - } |
|
1264 | - $this->set_unit_price($new_unit_price); |
|
1265 | - } |
|
1266 | - $this->maybe_save(); |
|
1267 | - } |
|
1268 | - return $total; |
|
1269 | - } |
|
1270 | - |
|
1271 | - |
|
1272 | - /** |
|
1273 | - * Calculates the pretax total when this line item is a subtotal or total line item. |
|
1274 | - * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
1275 | - * will calculate their total based on the un-rounded total we're working with so far, and |
|
1276 | - * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
1277 | - * |
|
1278 | - * @param float $calculated_total_so_far |
|
1279 | - * @param EE_Line_Item[] $my_children |
|
1280 | - * @return float |
|
1281 | - * @throws EE_Error |
|
1282 | - * @throws InvalidArgumentException |
|
1283 | - * @throws InvalidDataTypeException |
|
1284 | - * @throws InvalidInterfaceException |
|
1285 | - * @throws ReflectionException |
|
1286 | - */ |
|
1287 | - protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
1288 | - { |
|
1289 | - if ($my_children === null) { |
|
1290 | - $my_children = $this->children(); |
|
1291 | - } |
|
1292 | - $subtotal_quantity = 0; |
|
1293 | - // get the total of all its children |
|
1294 | - foreach ($my_children as $child_line_item) { |
|
1295 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1296 | - // percentage line items are based on total so far |
|
1297 | - if ($child_line_item->is_percent()) { |
|
1298 | - // round as we go so that the line items add up ok |
|
1299 | - $percent_total = round( |
|
1300 | - $calculated_total_so_far * $child_line_item->percent() / 100, |
|
1301 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
1302 | - ); |
|
1303 | - $child_line_item->set_total($percent_total); |
|
1304 | - // so far all percent line items should have a quantity of 1 |
|
1305 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
1306 | - $child_line_item->set_quantity(1); |
|
1307 | - $child_line_item->maybe_save(); |
|
1308 | - $calculated_total_so_far += $percent_total; |
|
1309 | - } else { |
|
1310 | - // verify flat sub-line-item quantities match their parent |
|
1311 | - if ($child_line_item->is_sub_line_item()) { |
|
1312 | - $child_line_item->set_quantity($this->quantity()); |
|
1313 | - } |
|
1314 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1315 | - $subtotal_quantity += $child_line_item->quantity(); |
|
1316 | - } |
|
1317 | - } |
|
1318 | - } |
|
1319 | - if ($this->is_sub_total()) { |
|
1320 | - // no negative totals plz |
|
1321 | - $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
1322 | - $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
1323 | - $this->set_quantity($subtotal_quantity); |
|
1324 | - $this->maybe_save(); |
|
1325 | - } |
|
1326 | - return $calculated_total_so_far; |
|
1327 | - } |
|
1328 | - |
|
1329 | - |
|
1330 | - /** |
|
1331 | - * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
1332 | - * (where each sub-line-item is applied to the base price for the line item |
|
1333 | - * and the result is immediately rounded, rather than summing all the sub-line-items |
|
1334 | - * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
1335 | - * |
|
1336 | - * @param float $calculated_total_so_far |
|
1337 | - * @param EE_Line_Item[] $my_children |
|
1338 | - * @return float |
|
1339 | - * @throws EE_Error |
|
1340 | - * @throws InvalidArgumentException |
|
1341 | - * @throws InvalidDataTypeException |
|
1342 | - * @throws InvalidInterfaceException |
|
1343 | - * @throws ReflectionException |
|
1344 | - */ |
|
1345 | - protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
1346 | - { |
|
1347 | - if ($my_children === null) { |
|
1348 | - $my_children = $this->children(); |
|
1349 | - } |
|
1350 | - // we need to keep track of the running total for a single item, |
|
1351 | - // because we need to round as we go |
|
1352 | - $unit_price_for_total = 0; |
|
1353 | - $quantity_for_total = 1; |
|
1354 | - // get the total of all its children |
|
1355 | - foreach ($my_children as $child_line_item) { |
|
1356 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1357 | - if ($child_line_item->is_percent()) { |
|
1358 | - // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
1359 | - // not total multiplied by percent, because that ignores rounding along-the-way |
|
1360 | - $percent_unit_price = round( |
|
1361 | - $unit_price_for_total * $child_line_item->percent() / 100, |
|
1362 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
1363 | - ); |
|
1364 | - $percent_total = $percent_unit_price * $quantity_for_total; |
|
1365 | - $child_line_item->set_total($percent_total); |
|
1366 | - // so far all percent line items should have a quantity of 1 |
|
1367 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
1368 | - $child_line_item->set_quantity(1); |
|
1369 | - $child_line_item->maybe_save(); |
|
1370 | - $calculated_total_so_far += $percent_total; |
|
1371 | - $unit_price_for_total += $percent_unit_price; |
|
1372 | - } else { |
|
1373 | - // verify flat sub-line-item quantities match their parent |
|
1374 | - if ($child_line_item->is_sub_line_item()) { |
|
1375 | - $child_line_item->set_quantity($this->quantity()); |
|
1376 | - } |
|
1377 | - $quantity_for_total = $child_line_item->quantity(); |
|
1378 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1379 | - $unit_price_for_total += $child_line_item->unit_price(); |
|
1380 | - } |
|
1381 | - } |
|
1382 | - } |
|
1383 | - return $calculated_total_so_far; |
|
1384 | - } |
|
1385 | - |
|
1386 | - |
|
1387 | - /** |
|
1388 | - * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
1389 | - * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
1390 | - * and tax sub-total if already in the DB |
|
1391 | - * |
|
1392 | - * @return float |
|
1393 | - * @throws EE_Error |
|
1394 | - * @throws InvalidArgumentException |
|
1395 | - * @throws InvalidDataTypeException |
|
1396 | - * @throws InvalidInterfaceException |
|
1397 | - * @throws ReflectionException |
|
1398 | - */ |
|
1399 | - public function recalculate_taxes_and_tax_total() |
|
1400 | - { |
|
1401 | - // get all taxes |
|
1402 | - $taxes = $this->tax_descendants(); |
|
1403 | - // calculate the pretax total |
|
1404 | - $taxable_total = $this->taxable_total(); |
|
1405 | - $tax_total = 0; |
|
1406 | - foreach ($taxes as $tax) { |
|
1407 | - $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
1408 | - // remember the total on this line item |
|
1409 | - $tax->set_total($total_on_this_tax); |
|
1410 | - $tax->maybe_save(); |
|
1411 | - $tax_total += $tax->total(); |
|
1412 | - } |
|
1413 | - $this->_recalculate_tax_sub_total(); |
|
1414 | - return $tax_total; |
|
1415 | - } |
|
1416 | - |
|
1417 | - |
|
1418 | - /** |
|
1419 | - * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
1420 | - * |
|
1421 | - * @return void |
|
1422 | - * @throws EE_Error |
|
1423 | - * @throws InvalidArgumentException |
|
1424 | - * @throws InvalidDataTypeException |
|
1425 | - * @throws InvalidInterfaceException |
|
1426 | - * @throws ReflectionException |
|
1427 | - */ |
|
1428 | - private function _recalculate_tax_sub_total() |
|
1429 | - { |
|
1430 | - if ($this->is_tax_sub_total()) { |
|
1431 | - $total = 0; |
|
1432 | - $total_percent = 0; |
|
1433 | - // simply loop through all its children (which should be taxes) and sum their total |
|
1434 | - foreach ($this->children() as $child_tax) { |
|
1435 | - if ($child_tax instanceof EE_Line_Item) { |
|
1436 | - $total += $child_tax->total(); |
|
1437 | - $total_percent += $child_tax->percent(); |
|
1438 | - } |
|
1439 | - } |
|
1440 | - $this->set_total($total); |
|
1441 | - $this->set_percent($total_percent); |
|
1442 | - $this->maybe_save(); |
|
1443 | - } elseif ($this->is_total()) { |
|
1444 | - foreach ($this->children() as $maybe_tax_subtotal) { |
|
1445 | - if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
1446 | - $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
1447 | - } |
|
1448 | - } |
|
1449 | - } |
|
1450 | - } |
|
1451 | - |
|
1452 | - |
|
1453 | - /** |
|
1454 | - * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
1455 | - * recalculate_taxes_and_total |
|
1456 | - * |
|
1457 | - * @return float |
|
1458 | - * @throws EE_Error |
|
1459 | - * @throws InvalidArgumentException |
|
1460 | - * @throws InvalidDataTypeException |
|
1461 | - * @throws InvalidInterfaceException |
|
1462 | - * @throws ReflectionException |
|
1463 | - */ |
|
1464 | - public function get_total_tax() |
|
1465 | - { |
|
1466 | - $this->_recalculate_tax_sub_total(); |
|
1467 | - $total = 0; |
|
1468 | - foreach ($this->tax_descendants() as $tax_line_item) { |
|
1469 | - if ($tax_line_item instanceof EE_Line_Item) { |
|
1470 | - $total += $tax_line_item->total(); |
|
1471 | - } |
|
1472 | - } |
|
1473 | - return $total; |
|
1474 | - } |
|
1475 | - |
|
1476 | - |
|
1477 | - /** |
|
1478 | - * Gets the total for all the items purchased only |
|
1479 | - * |
|
1480 | - * @return float |
|
1481 | - * @throws EE_Error |
|
1482 | - * @throws InvalidArgumentException |
|
1483 | - * @throws InvalidDataTypeException |
|
1484 | - * @throws InvalidInterfaceException |
|
1485 | - * @throws ReflectionException |
|
1486 | - */ |
|
1487 | - public function get_items_total() |
|
1488 | - { |
|
1489 | - // by default, let's make sure we're consistent with the existing line item |
|
1490 | - if ($this->is_total()) { |
|
1491 | - $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
1492 | - if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
1493 | - return $pretax_subtotal_li->total(); |
|
1494 | - } |
|
1495 | - } |
|
1496 | - $total = 0; |
|
1497 | - foreach ($this->get_items() as $item) { |
|
1498 | - if ($item instanceof EE_Line_Item) { |
|
1499 | - $total += $item->total(); |
|
1500 | - } |
|
1501 | - } |
|
1502 | - return $total; |
|
1503 | - } |
|
1504 | - |
|
1505 | - |
|
1506 | - /** |
|
1507 | - * Gets all the descendants (ie, children or children of children etc) that |
|
1508 | - * are of the type 'tax' |
|
1509 | - * |
|
1510 | - * @return EE_Line_Item[] |
|
1511 | - * @throws EE_Error |
|
1512 | - */ |
|
1513 | - public function tax_descendants() |
|
1514 | - { |
|
1515 | - return EEH_Line_Item::get_tax_descendants($this); |
|
1516 | - } |
|
1517 | - |
|
1518 | - |
|
1519 | - /** |
|
1520 | - * Gets all the real items purchased which are children of this item |
|
1521 | - * |
|
1522 | - * @return EE_Line_Item[] |
|
1523 | - * @throws EE_Error |
|
1524 | - */ |
|
1525 | - public function get_items() |
|
1526 | - { |
|
1527 | - return EEH_Line_Item::get_line_item_descendants($this); |
|
1528 | - } |
|
1529 | - |
|
1530 | - |
|
1531 | - /** |
|
1532 | - * Returns the amount taxable among this line item's children (or if it has no children, |
|
1533 | - * how much of it is taxable). Does not recalculate totals or subtotals. |
|
1534 | - * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
1535 | - * but there is a "Taxable" discount), returns 0. |
|
1536 | - * |
|
1537 | - * @return float |
|
1538 | - * @throws EE_Error |
|
1539 | - * @throws InvalidArgumentException |
|
1540 | - * @throws InvalidDataTypeException |
|
1541 | - * @throws InvalidInterfaceException |
|
1542 | - * @throws ReflectionException |
|
1543 | - */ |
|
1544 | - public function taxable_total() |
|
1545 | - { |
|
1546 | - $total = 0; |
|
1547 | - if ($this->children()) { |
|
1548 | - foreach ($this->children() as $child_line_item) { |
|
1549 | - if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
1550 | - // if it's a percent item, only take into account the percent |
|
1551 | - // that's taxable too (the taxable total so far) |
|
1552 | - if ($child_line_item->is_percent()) { |
|
1553 | - $total += ($total * $child_line_item->percent() / 100); |
|
1554 | - } else { |
|
1555 | - $total += $child_line_item->total(); |
|
1556 | - } |
|
1557 | - } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
1558 | - $total += $child_line_item->taxable_total(); |
|
1559 | - } |
|
1560 | - } |
|
1561 | - } |
|
1562 | - return max($total, 0); |
|
1563 | - } |
|
1564 | - |
|
1565 | - |
|
1566 | - /** |
|
1567 | - * Gets the transaction for this line item |
|
1568 | - * |
|
1569 | - * @return EE_Base_Class|EE_Transaction |
|
1570 | - * @throws EE_Error |
|
1571 | - * @throws InvalidArgumentException |
|
1572 | - * @throws InvalidDataTypeException |
|
1573 | - * @throws InvalidInterfaceException |
|
1574 | - * @throws ReflectionException |
|
1575 | - */ |
|
1576 | - public function transaction() |
|
1577 | - { |
|
1578 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
1579 | - } |
|
1580 | - |
|
1581 | - |
|
1582 | - /** |
|
1583 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
1584 | - * Because there currently is no proper parent-child relation on the model, |
|
1585 | - * save_this_and_cached() will NOT save the descendants. |
|
1586 | - * Also sets the transaction on this line item and all its descendants before saving |
|
1587 | - * |
|
1588 | - * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
1589 | - * @return int count of items saved |
|
1590 | - * @throws EE_Error |
|
1591 | - * @throws InvalidArgumentException |
|
1592 | - * @throws InvalidDataTypeException |
|
1593 | - * @throws InvalidInterfaceException |
|
1594 | - * @throws ReflectionException |
|
1595 | - */ |
|
1596 | - public function save_this_and_descendants_to_txn($txn_id = null) |
|
1597 | - { |
|
1598 | - $count = 0; |
|
1599 | - if (! $txn_id) { |
|
1600 | - $txn_id = $this->TXN_ID(); |
|
1601 | - } |
|
1602 | - $this->set_TXN_ID($txn_id); |
|
1603 | - $children = $this->children(); |
|
1604 | - $count += $this->save() |
|
1605 | - ? 1 |
|
1606 | - : 0; |
|
1607 | - foreach ($children as $child_line_item) { |
|
1608 | - if ($child_line_item instanceof EE_Line_Item) { |
|
1609 | - $child_line_item->set_parent_ID($this->ID()); |
|
1610 | - $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
1611 | - } |
|
1612 | - } |
|
1613 | - return $count; |
|
1614 | - } |
|
1615 | - |
|
1616 | - |
|
1617 | - /** |
|
1618 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
1619 | - * |
|
1620 | - * @return int count of items saved |
|
1621 | - * @throws EE_Error |
|
1622 | - * @throws InvalidArgumentException |
|
1623 | - * @throws InvalidDataTypeException |
|
1624 | - * @throws InvalidInterfaceException |
|
1625 | - * @throws ReflectionException |
|
1626 | - */ |
|
1627 | - public function save_this_and_descendants() |
|
1628 | - { |
|
1629 | - $count = 0; |
|
1630 | - $children = $this->children(); |
|
1631 | - $count += $this->save() |
|
1632 | - ? 1 |
|
1633 | - : 0; |
|
1634 | - foreach ($children as $child_line_item) { |
|
1635 | - if ($child_line_item instanceof EE_Line_Item) { |
|
1636 | - $child_line_item->set_parent_ID($this->ID()); |
|
1637 | - $count += $child_line_item->save_this_and_descendants(); |
|
1638 | - } |
|
1639 | - } |
|
1640 | - return $count; |
|
1641 | - } |
|
1642 | - |
|
1643 | - |
|
1644 | - /** |
|
1645 | - * returns the cancellation line item if this item was cancelled |
|
1646 | - * |
|
1647 | - * @return EE_Line_Item[] |
|
1648 | - * @throws InvalidArgumentException |
|
1649 | - * @throws InvalidInterfaceException |
|
1650 | - * @throws InvalidDataTypeException |
|
1651 | - * @throws ReflectionException |
|
1652 | - * @throws EE_Error |
|
1653 | - */ |
|
1654 | - public function get_cancellations() |
|
1655 | - { |
|
1656 | - EE_Registry::instance()->load_helper('Line_Item'); |
|
1657 | - return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
1658 | - } |
|
1659 | - |
|
1660 | - |
|
1661 | - /** |
|
1662 | - * If this item has an ID, then this saves it again to update the db |
|
1663 | - * |
|
1664 | - * @return int count of items saved |
|
1665 | - * @throws EE_Error |
|
1666 | - * @throws InvalidArgumentException |
|
1667 | - * @throws InvalidDataTypeException |
|
1668 | - * @throws InvalidInterfaceException |
|
1669 | - * @throws ReflectionException |
|
1670 | - */ |
|
1671 | - public function maybe_save() |
|
1672 | - { |
|
1673 | - if ($this->ID()) { |
|
1674 | - return $this->save(); |
|
1675 | - } |
|
1676 | - return false; |
|
1677 | - } |
|
1678 | - |
|
1679 | - |
|
1680 | - /** |
|
1681 | - * clears the cached children and parent from the line item |
|
1682 | - * |
|
1683 | - * @return void |
|
1684 | - */ |
|
1685 | - public function clear_related_line_item_cache() |
|
1686 | - { |
|
1687 | - $this->_children = array(); |
|
1688 | - $this->_parent = null; |
|
1689 | - } |
|
1690 | - |
|
1691 | - |
|
1692 | - /** |
|
1693 | - * @param bool $raw |
|
1694 | - * @return int |
|
1695 | - * @throws EE_Error |
|
1696 | - * @throws InvalidArgumentException |
|
1697 | - * @throws InvalidDataTypeException |
|
1698 | - * @throws InvalidInterfaceException |
|
1699 | - * @throws ReflectionException |
|
1700 | - */ |
|
1701 | - public function timestamp($raw = false) |
|
1702 | - { |
|
1703 | - return $raw |
|
1704 | - ? $this->get_raw('LIN_timestamp') |
|
1705 | - : $this->get('LIN_timestamp'); |
|
1706 | - } |
|
1707 | - |
|
1708 | - |
|
1709 | - |
|
1710 | - |
|
1711 | - /************************* DEPRECATED *************************/ |
|
1712 | - /** |
|
1713 | - * @deprecated 4.6.0 |
|
1714 | - * @param string $type one of the constants on EEM_Line_Item |
|
1715 | - * @return EE_Line_Item[] |
|
1716 | - * @throws EE_Error |
|
1717 | - */ |
|
1718 | - protected function _get_descendants_of_type($type) |
|
1719 | - { |
|
1720 | - EE_Error::doing_it_wrong( |
|
1721 | - 'EE_Line_Item::_get_descendants_of_type()', |
|
1722 | - sprintf( |
|
1723 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1724 | - 'EEH_Line_Item::get_descendants_of_type()' |
|
1725 | - ), |
|
1726 | - '4.6.0' |
|
1727 | - ); |
|
1728 | - return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
1729 | - } |
|
1730 | - |
|
1731 | - |
|
1732 | - /** |
|
1733 | - * @deprecated 4.6.0 |
|
1734 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
1735 | - * @return EE_Line_Item |
|
1736 | - * @throws EE_Error |
|
1737 | - * @throws InvalidArgumentException |
|
1738 | - * @throws InvalidDataTypeException |
|
1739 | - * @throws InvalidInterfaceException |
|
1740 | - * @throws ReflectionException |
|
1741 | - */ |
|
1742 | - public function get_nearest_descendant_of_type($type) |
|
1743 | - { |
|
1744 | - EE_Error::doing_it_wrong( |
|
1745 | - 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
1746 | - sprintf( |
|
1747 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1748 | - 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
1749 | - ), |
|
1750 | - '4.6.0' |
|
1751 | - ); |
|
1752 | - return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
1753 | - } |
|
16 | + /** |
|
17 | + * for children line items (currently not a normal relation) |
|
18 | + * |
|
19 | + * @type EE_Line_Item[] |
|
20 | + */ |
|
21 | + protected $_children = array(); |
|
22 | + |
|
23 | + /** |
|
24 | + * for the parent line item |
|
25 | + * |
|
26 | + * @var EE_Line_Item |
|
27 | + */ |
|
28 | + protected $_parent; |
|
29 | + |
|
30 | + |
|
31 | + /** |
|
32 | + * @param array $props_n_values incoming values |
|
33 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
34 | + * used.) |
|
35 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
36 | + * date_format and the second value is the time format |
|
37 | + * @return EE_Line_Item |
|
38 | + * @throws EE_Error |
|
39 | + * @throws InvalidArgumentException |
|
40 | + * @throws InvalidDataTypeException |
|
41 | + * @throws InvalidInterfaceException |
|
42 | + * @throws ReflectionException |
|
43 | + */ |
|
44 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
45 | + { |
|
46 | + $has_object = parent::_check_for_object( |
|
47 | + $props_n_values, |
|
48 | + __CLASS__, |
|
49 | + $timezone, |
|
50 | + $date_formats |
|
51 | + ); |
|
52 | + return $has_object |
|
53 | + ? $has_object |
|
54 | + : new self($props_n_values, false, $timezone); |
|
55 | + } |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * @param array $props_n_values incoming values from the database |
|
60 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
61 | + * the website will be used. |
|
62 | + * @return EE_Line_Item |
|
63 | + * @throws EE_Error |
|
64 | + * @throws InvalidArgumentException |
|
65 | + * @throws InvalidDataTypeException |
|
66 | + * @throws InvalidInterfaceException |
|
67 | + * @throws ReflectionException |
|
68 | + */ |
|
69 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
70 | + { |
|
71 | + return new self($props_n_values, true, $timezone); |
|
72 | + } |
|
73 | + |
|
74 | + |
|
75 | + /** |
|
76 | + * Adds some defaults if they're not specified |
|
77 | + * |
|
78 | + * @param array $fieldValues |
|
79 | + * @param bool $bydb |
|
80 | + * @param string $timezone |
|
81 | + * @throws EE_Error |
|
82 | + * @throws InvalidArgumentException |
|
83 | + * @throws InvalidDataTypeException |
|
84 | + * @throws InvalidInterfaceException |
|
85 | + * @throws ReflectionException |
|
86 | + */ |
|
87 | + protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
88 | + { |
|
89 | + parent::__construct($fieldValues, $bydb, $timezone); |
|
90 | + if (! $this->get('LIN_code')) { |
|
91 | + $this->set_code($this->generate_code()); |
|
92 | + } |
|
93 | + } |
|
94 | + |
|
95 | + |
|
96 | + /** |
|
97 | + * Gets ID |
|
98 | + * |
|
99 | + * @return int |
|
100 | + * @throws EE_Error |
|
101 | + * @throws InvalidArgumentException |
|
102 | + * @throws InvalidDataTypeException |
|
103 | + * @throws InvalidInterfaceException |
|
104 | + * @throws ReflectionException |
|
105 | + */ |
|
106 | + public function ID() |
|
107 | + { |
|
108 | + return $this->get('LIN_ID'); |
|
109 | + } |
|
110 | + |
|
111 | + |
|
112 | + /** |
|
113 | + * Gets TXN_ID |
|
114 | + * |
|
115 | + * @return int |
|
116 | + * @throws EE_Error |
|
117 | + * @throws InvalidArgumentException |
|
118 | + * @throws InvalidDataTypeException |
|
119 | + * @throws InvalidInterfaceException |
|
120 | + * @throws ReflectionException |
|
121 | + */ |
|
122 | + public function TXN_ID() |
|
123 | + { |
|
124 | + return $this->get('TXN_ID'); |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + /** |
|
129 | + * Sets TXN_ID |
|
130 | + * |
|
131 | + * @param int $TXN_ID |
|
132 | + * @throws EE_Error |
|
133 | + * @throws InvalidArgumentException |
|
134 | + * @throws InvalidDataTypeException |
|
135 | + * @throws InvalidInterfaceException |
|
136 | + * @throws ReflectionException |
|
137 | + */ |
|
138 | + public function set_TXN_ID($TXN_ID) |
|
139 | + { |
|
140 | + $this->set('TXN_ID', $TXN_ID); |
|
141 | + } |
|
142 | + |
|
143 | + |
|
144 | + /** |
|
145 | + * Gets name |
|
146 | + * |
|
147 | + * @return string |
|
148 | + * @throws EE_Error |
|
149 | + * @throws InvalidArgumentException |
|
150 | + * @throws InvalidDataTypeException |
|
151 | + * @throws InvalidInterfaceException |
|
152 | + * @throws ReflectionException |
|
153 | + */ |
|
154 | + public function name() |
|
155 | + { |
|
156 | + $name = $this->get('LIN_name'); |
|
157 | + if (! $name) { |
|
158 | + $name = ucwords(str_replace('-', ' ', $this->type())); |
|
159 | + } |
|
160 | + return $name; |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * Sets name |
|
166 | + * |
|
167 | + * @param string $name |
|
168 | + * @throws EE_Error |
|
169 | + * @throws InvalidArgumentException |
|
170 | + * @throws InvalidDataTypeException |
|
171 | + * @throws InvalidInterfaceException |
|
172 | + * @throws ReflectionException |
|
173 | + */ |
|
174 | + public function set_name($name) |
|
175 | + { |
|
176 | + $this->set('LIN_name', $name); |
|
177 | + } |
|
178 | + |
|
179 | + |
|
180 | + /** |
|
181 | + * Gets desc |
|
182 | + * |
|
183 | + * @return string |
|
184 | + * @throws EE_Error |
|
185 | + * @throws InvalidArgumentException |
|
186 | + * @throws InvalidDataTypeException |
|
187 | + * @throws InvalidInterfaceException |
|
188 | + * @throws ReflectionException |
|
189 | + */ |
|
190 | + public function desc() |
|
191 | + { |
|
192 | + return $this->get('LIN_desc'); |
|
193 | + } |
|
194 | + |
|
195 | + |
|
196 | + /** |
|
197 | + * Sets desc |
|
198 | + * |
|
199 | + * @param string $desc |
|
200 | + * @throws EE_Error |
|
201 | + * @throws InvalidArgumentException |
|
202 | + * @throws InvalidDataTypeException |
|
203 | + * @throws InvalidInterfaceException |
|
204 | + * @throws ReflectionException |
|
205 | + */ |
|
206 | + public function set_desc($desc) |
|
207 | + { |
|
208 | + $this->set('LIN_desc', $desc); |
|
209 | + } |
|
210 | + |
|
211 | + |
|
212 | + /** |
|
213 | + * Gets quantity |
|
214 | + * |
|
215 | + * @return int |
|
216 | + * @throws EE_Error |
|
217 | + * @throws InvalidArgumentException |
|
218 | + * @throws InvalidDataTypeException |
|
219 | + * @throws InvalidInterfaceException |
|
220 | + * @throws ReflectionException |
|
221 | + */ |
|
222 | + public function quantity() |
|
223 | + { |
|
224 | + return $this->get('LIN_quantity'); |
|
225 | + } |
|
226 | + |
|
227 | + |
|
228 | + /** |
|
229 | + * Sets quantity |
|
230 | + * |
|
231 | + * @param int $quantity |
|
232 | + * @throws EE_Error |
|
233 | + * @throws InvalidArgumentException |
|
234 | + * @throws InvalidDataTypeException |
|
235 | + * @throws InvalidInterfaceException |
|
236 | + * @throws ReflectionException |
|
237 | + */ |
|
238 | + public function set_quantity($quantity) |
|
239 | + { |
|
240 | + $this->set('LIN_quantity', max($quantity, 0)); |
|
241 | + } |
|
242 | + |
|
243 | + |
|
244 | + /** |
|
245 | + * Gets item_id |
|
246 | + * |
|
247 | + * @return string |
|
248 | + * @throws EE_Error |
|
249 | + * @throws InvalidArgumentException |
|
250 | + * @throws InvalidDataTypeException |
|
251 | + * @throws InvalidInterfaceException |
|
252 | + * @throws ReflectionException |
|
253 | + */ |
|
254 | + public function OBJ_ID() |
|
255 | + { |
|
256 | + return $this->get('OBJ_ID'); |
|
257 | + } |
|
258 | + |
|
259 | + |
|
260 | + /** |
|
261 | + * Sets item_id |
|
262 | + * |
|
263 | + * @param string $item_id |
|
264 | + * @throws EE_Error |
|
265 | + * @throws InvalidArgumentException |
|
266 | + * @throws InvalidDataTypeException |
|
267 | + * @throws InvalidInterfaceException |
|
268 | + * @throws ReflectionException |
|
269 | + */ |
|
270 | + public function set_OBJ_ID($item_id) |
|
271 | + { |
|
272 | + $this->set('OBJ_ID', $item_id); |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + /** |
|
277 | + * Gets item_type |
|
278 | + * |
|
279 | + * @return string |
|
280 | + * @throws EE_Error |
|
281 | + * @throws InvalidArgumentException |
|
282 | + * @throws InvalidDataTypeException |
|
283 | + * @throws InvalidInterfaceException |
|
284 | + * @throws ReflectionException |
|
285 | + */ |
|
286 | + public function OBJ_type() |
|
287 | + { |
|
288 | + return $this->get('OBJ_type'); |
|
289 | + } |
|
290 | + |
|
291 | + |
|
292 | + /** |
|
293 | + * Gets item_type |
|
294 | + * |
|
295 | + * @return string |
|
296 | + * @throws EE_Error |
|
297 | + * @throws InvalidArgumentException |
|
298 | + * @throws InvalidDataTypeException |
|
299 | + * @throws InvalidInterfaceException |
|
300 | + * @throws ReflectionException |
|
301 | + */ |
|
302 | + public function OBJ_type_i18n() |
|
303 | + { |
|
304 | + $obj_type = $this->OBJ_type(); |
|
305 | + switch ($obj_type) { |
|
306 | + case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
307 | + $obj_type = esc_html__('Event', 'event_espresso'); |
|
308 | + break; |
|
309 | + case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
310 | + $obj_type = esc_html__('Price', 'event_espresso'); |
|
311 | + break; |
|
312 | + case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
313 | + $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
314 | + break; |
|
315 | + case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
316 | + $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
317 | + break; |
|
318 | + case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
319 | + $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
320 | + break; |
|
321 | + } |
|
322 | + return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + /** |
|
327 | + * Sets item_type |
|
328 | + * |
|
329 | + * @param string $OBJ_type |
|
330 | + * @throws EE_Error |
|
331 | + * @throws InvalidArgumentException |
|
332 | + * @throws InvalidDataTypeException |
|
333 | + * @throws InvalidInterfaceException |
|
334 | + * @throws ReflectionException |
|
335 | + */ |
|
336 | + public function set_OBJ_type($OBJ_type) |
|
337 | + { |
|
338 | + $this->set('OBJ_type', $OBJ_type); |
|
339 | + } |
|
340 | + |
|
341 | + |
|
342 | + /** |
|
343 | + * Gets unit_price |
|
344 | + * |
|
345 | + * @return float |
|
346 | + * @throws EE_Error |
|
347 | + * @throws InvalidArgumentException |
|
348 | + * @throws InvalidDataTypeException |
|
349 | + * @throws InvalidInterfaceException |
|
350 | + * @throws ReflectionException |
|
351 | + */ |
|
352 | + public function unit_price() |
|
353 | + { |
|
354 | + return $this->get('LIN_unit_price'); |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * Sets unit_price |
|
360 | + * |
|
361 | + * @param float $unit_price |
|
362 | + * @throws EE_Error |
|
363 | + * @throws InvalidArgumentException |
|
364 | + * @throws InvalidDataTypeException |
|
365 | + * @throws InvalidInterfaceException |
|
366 | + * @throws ReflectionException |
|
367 | + */ |
|
368 | + public function set_unit_price($unit_price) |
|
369 | + { |
|
370 | + $this->set('LIN_unit_price', $unit_price); |
|
371 | + } |
|
372 | + |
|
373 | + |
|
374 | + /** |
|
375 | + * Checks if this item is a percentage modifier or not |
|
376 | + * |
|
377 | + * @return boolean |
|
378 | + * @throws EE_Error |
|
379 | + * @throws InvalidArgumentException |
|
380 | + * @throws InvalidDataTypeException |
|
381 | + * @throws InvalidInterfaceException |
|
382 | + * @throws ReflectionException |
|
383 | + */ |
|
384 | + public function is_percent() |
|
385 | + { |
|
386 | + if ($this->is_tax_sub_total()) { |
|
387 | + // tax subtotals HAVE a percent on them, that percentage only applies |
|
388 | + // to taxable items, so its' an exception. Treat it like a flat line item |
|
389 | + return false; |
|
390 | + } |
|
391 | + $unit_price = abs($this->get('LIN_unit_price')); |
|
392 | + $percent = abs($this->get('LIN_percent')); |
|
393 | + if ($unit_price < .001 && $percent) { |
|
394 | + return true; |
|
395 | + } |
|
396 | + if ($unit_price >= .001 && ! $percent) { |
|
397 | + return false; |
|
398 | + } |
|
399 | + if ($unit_price >= .001 && $percent) { |
|
400 | + throw new EE_Error( |
|
401 | + sprintf( |
|
402 | + esc_html__( |
|
403 | + 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
404 | + 'event_espresso' |
|
405 | + ), |
|
406 | + $unit_price, |
|
407 | + $percent |
|
408 | + ) |
|
409 | + ); |
|
410 | + } |
|
411 | + // if they're both 0, assume its not a percent item |
|
412 | + return false; |
|
413 | + } |
|
414 | + |
|
415 | + |
|
416 | + /** |
|
417 | + * Gets percent (between 100-.001) |
|
418 | + * |
|
419 | + * @return float |
|
420 | + * @throws EE_Error |
|
421 | + * @throws InvalidArgumentException |
|
422 | + * @throws InvalidDataTypeException |
|
423 | + * @throws InvalidInterfaceException |
|
424 | + * @throws ReflectionException |
|
425 | + */ |
|
426 | + public function percent() |
|
427 | + { |
|
428 | + return $this->get('LIN_percent'); |
|
429 | + } |
|
430 | + |
|
431 | + |
|
432 | + /** |
|
433 | + * Sets percent (between 100-0.01) |
|
434 | + * |
|
435 | + * @param float $percent |
|
436 | + * @throws EE_Error |
|
437 | + * @throws InvalidArgumentException |
|
438 | + * @throws InvalidDataTypeException |
|
439 | + * @throws InvalidInterfaceException |
|
440 | + * @throws ReflectionException |
|
441 | + */ |
|
442 | + public function set_percent($percent) |
|
443 | + { |
|
444 | + $this->set('LIN_percent', $percent); |
|
445 | + } |
|
446 | + |
|
447 | + |
|
448 | + /** |
|
449 | + * Gets total |
|
450 | + * |
|
451 | + * @return float |
|
452 | + * @throws EE_Error |
|
453 | + * @throws InvalidArgumentException |
|
454 | + * @throws InvalidDataTypeException |
|
455 | + * @throws InvalidInterfaceException |
|
456 | + * @throws ReflectionException |
|
457 | + */ |
|
458 | + public function total() |
|
459 | + { |
|
460 | + return $this->get('LIN_total'); |
|
461 | + } |
|
462 | + |
|
463 | + |
|
464 | + /** |
|
465 | + * Sets total |
|
466 | + * |
|
467 | + * @param float $total |
|
468 | + * @throws EE_Error |
|
469 | + * @throws InvalidArgumentException |
|
470 | + * @throws InvalidDataTypeException |
|
471 | + * @throws InvalidInterfaceException |
|
472 | + * @throws ReflectionException |
|
473 | + */ |
|
474 | + public function set_total($total) |
|
475 | + { |
|
476 | + $this->set('LIN_total', $total); |
|
477 | + } |
|
478 | + |
|
479 | + |
|
480 | + /** |
|
481 | + * Gets order |
|
482 | + * |
|
483 | + * @return int |
|
484 | + * @throws EE_Error |
|
485 | + * @throws InvalidArgumentException |
|
486 | + * @throws InvalidDataTypeException |
|
487 | + * @throws InvalidInterfaceException |
|
488 | + * @throws ReflectionException |
|
489 | + */ |
|
490 | + public function order() |
|
491 | + { |
|
492 | + return $this->get('LIN_order'); |
|
493 | + } |
|
494 | + |
|
495 | + |
|
496 | + /** |
|
497 | + * Sets order |
|
498 | + * |
|
499 | + * @param int $order |
|
500 | + * @throws EE_Error |
|
501 | + * @throws InvalidArgumentException |
|
502 | + * @throws InvalidDataTypeException |
|
503 | + * @throws InvalidInterfaceException |
|
504 | + * @throws ReflectionException |
|
505 | + */ |
|
506 | + public function set_order($order) |
|
507 | + { |
|
508 | + $this->set('LIN_order', $order); |
|
509 | + } |
|
510 | + |
|
511 | + |
|
512 | + /** |
|
513 | + * Gets parent |
|
514 | + * |
|
515 | + * @return int |
|
516 | + * @throws EE_Error |
|
517 | + * @throws InvalidArgumentException |
|
518 | + * @throws InvalidDataTypeException |
|
519 | + * @throws InvalidInterfaceException |
|
520 | + * @throws ReflectionException |
|
521 | + */ |
|
522 | + public function parent_ID() |
|
523 | + { |
|
524 | + return $this->get('LIN_parent'); |
|
525 | + } |
|
526 | + |
|
527 | + |
|
528 | + /** |
|
529 | + * Sets parent |
|
530 | + * |
|
531 | + * @param int $parent |
|
532 | + * @throws EE_Error |
|
533 | + * @throws InvalidArgumentException |
|
534 | + * @throws InvalidDataTypeException |
|
535 | + * @throws InvalidInterfaceException |
|
536 | + * @throws ReflectionException |
|
537 | + */ |
|
538 | + public function set_parent_ID($parent) |
|
539 | + { |
|
540 | + $this->set('LIN_parent', $parent); |
|
541 | + } |
|
542 | + |
|
543 | + |
|
544 | + /** |
|
545 | + * Gets type |
|
546 | + * |
|
547 | + * @return string |
|
548 | + * @throws EE_Error |
|
549 | + * @throws InvalidArgumentException |
|
550 | + * @throws InvalidDataTypeException |
|
551 | + * @throws InvalidInterfaceException |
|
552 | + * @throws ReflectionException |
|
553 | + */ |
|
554 | + public function type() |
|
555 | + { |
|
556 | + return $this->get('LIN_type'); |
|
557 | + } |
|
558 | + |
|
559 | + |
|
560 | + /** |
|
561 | + * Sets type |
|
562 | + * |
|
563 | + * @param string $type |
|
564 | + * @throws EE_Error |
|
565 | + * @throws InvalidArgumentException |
|
566 | + * @throws InvalidDataTypeException |
|
567 | + * @throws InvalidInterfaceException |
|
568 | + * @throws ReflectionException |
|
569 | + */ |
|
570 | + public function set_type($type) |
|
571 | + { |
|
572 | + $this->set('LIN_type', $type); |
|
573 | + } |
|
574 | + |
|
575 | + |
|
576 | + /** |
|
577 | + * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
578 | + * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB |
|
579 | + * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
580 | + * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
581 | + * |
|
582 | + * @return EE_Base_Class|EE_Line_Item |
|
583 | + * @throws EE_Error |
|
584 | + * @throws InvalidArgumentException |
|
585 | + * @throws InvalidDataTypeException |
|
586 | + * @throws InvalidInterfaceException |
|
587 | + * @throws ReflectionException |
|
588 | + */ |
|
589 | + public function parent() |
|
590 | + { |
|
591 | + return $this->ID() |
|
592 | + ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
593 | + : $this->_parent; |
|
594 | + } |
|
595 | + |
|
596 | + |
|
597 | + /** |
|
598 | + * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
599 | + * |
|
600 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
601 | + * @throws EE_Error |
|
602 | + * @throws InvalidArgumentException |
|
603 | + * @throws InvalidDataTypeException |
|
604 | + * @throws InvalidInterfaceException |
|
605 | + * @throws ReflectionException |
|
606 | + */ |
|
607 | + public function children() |
|
608 | + { |
|
609 | + if ($this->ID()) { |
|
610 | + return $this->get_model()->get_all( |
|
611 | + array( |
|
612 | + array('LIN_parent' => $this->ID()), |
|
613 | + 'order_by' => array('LIN_order' => 'ASC'), |
|
614 | + ) |
|
615 | + ); |
|
616 | + } |
|
617 | + if (! is_array($this->_children)) { |
|
618 | + $this->_children = array(); |
|
619 | + } |
|
620 | + return $this->_children; |
|
621 | + } |
|
622 | + |
|
623 | + |
|
624 | + /** |
|
625 | + * Gets code |
|
626 | + * |
|
627 | + * @return string |
|
628 | + * @throws EE_Error |
|
629 | + * @throws InvalidArgumentException |
|
630 | + * @throws InvalidDataTypeException |
|
631 | + * @throws InvalidInterfaceException |
|
632 | + * @throws ReflectionException |
|
633 | + */ |
|
634 | + public function code() |
|
635 | + { |
|
636 | + return $this->get('LIN_code'); |
|
637 | + } |
|
638 | + |
|
639 | + |
|
640 | + /** |
|
641 | + * Sets code |
|
642 | + * |
|
643 | + * @param string $code |
|
644 | + * @throws EE_Error |
|
645 | + * @throws InvalidArgumentException |
|
646 | + * @throws InvalidDataTypeException |
|
647 | + * @throws InvalidInterfaceException |
|
648 | + * @throws ReflectionException |
|
649 | + */ |
|
650 | + public function set_code($code) |
|
651 | + { |
|
652 | + $this->set('LIN_code', $code); |
|
653 | + } |
|
654 | + |
|
655 | + |
|
656 | + /** |
|
657 | + * Gets is_taxable |
|
658 | + * |
|
659 | + * @return boolean |
|
660 | + * @throws EE_Error |
|
661 | + * @throws InvalidArgumentException |
|
662 | + * @throws InvalidDataTypeException |
|
663 | + * @throws InvalidInterfaceException |
|
664 | + * @throws ReflectionException |
|
665 | + */ |
|
666 | + public function is_taxable() |
|
667 | + { |
|
668 | + return $this->get('LIN_is_taxable'); |
|
669 | + } |
|
670 | + |
|
671 | + |
|
672 | + /** |
|
673 | + * Sets is_taxable |
|
674 | + * |
|
675 | + * @param boolean $is_taxable |
|
676 | + * @throws EE_Error |
|
677 | + * @throws InvalidArgumentException |
|
678 | + * @throws InvalidDataTypeException |
|
679 | + * @throws InvalidInterfaceException |
|
680 | + * @throws ReflectionException |
|
681 | + */ |
|
682 | + public function set_is_taxable($is_taxable) |
|
683 | + { |
|
684 | + $this->set('LIN_is_taxable', $is_taxable); |
|
685 | + } |
|
686 | + |
|
687 | + |
|
688 | + /** |
|
689 | + * Gets the object that this model-joins-to. |
|
690 | + * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
691 | + * EEM_Promotion_Object |
|
692 | + * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
693 | + * |
|
694 | + * @return EE_Base_Class | NULL |
|
695 | + * @throws EE_Error |
|
696 | + * @throws InvalidArgumentException |
|
697 | + * @throws InvalidDataTypeException |
|
698 | + * @throws InvalidInterfaceException |
|
699 | + * @throws ReflectionException |
|
700 | + */ |
|
701 | + public function get_object() |
|
702 | + { |
|
703 | + $model_name_of_related_obj = $this->OBJ_type(); |
|
704 | + return $this->get_model()->has_relation($model_name_of_related_obj) |
|
705 | + ? $this->get_first_related($model_name_of_related_obj) |
|
706 | + : null; |
|
707 | + } |
|
708 | + |
|
709 | + |
|
710 | + /** |
|
711 | + * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
712 | + * (IE, if this line item is for a price or something else, will return NULL) |
|
713 | + * |
|
714 | + * @param array $query_params |
|
715 | + * @return EE_Base_Class|EE_Ticket |
|
716 | + * @throws EE_Error |
|
717 | + * @throws InvalidArgumentException |
|
718 | + * @throws InvalidDataTypeException |
|
719 | + * @throws InvalidInterfaceException |
|
720 | + * @throws ReflectionException |
|
721 | + */ |
|
722 | + public function ticket($query_params = array()) |
|
723 | + { |
|
724 | + // we're going to assume that when this method is called |
|
725 | + // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
726 | + // This can be overridden via the incoming $query_params argument |
|
727 | + $remove_defaults = array('default_where_conditions' => 'none'); |
|
728 | + $query_params = array_merge($remove_defaults, $query_params); |
|
729 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
730 | + } |
|
731 | + |
|
732 | + |
|
733 | + /** |
|
734 | + * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
735 | + * |
|
736 | + * @return EE_Datetime | NULL |
|
737 | + * @throws EE_Error |
|
738 | + * @throws InvalidArgumentException |
|
739 | + * @throws InvalidDataTypeException |
|
740 | + * @throws InvalidInterfaceException |
|
741 | + * @throws ReflectionException |
|
742 | + */ |
|
743 | + public function get_ticket_datetime() |
|
744 | + { |
|
745 | + if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
746 | + $ticket = $this->ticket(); |
|
747 | + if ($ticket instanceof EE_Ticket) { |
|
748 | + $datetime = $ticket->first_datetime(); |
|
749 | + if ($datetime instanceof EE_Datetime) { |
|
750 | + return $datetime; |
|
751 | + } |
|
752 | + } |
|
753 | + } |
|
754 | + return null; |
|
755 | + } |
|
756 | + |
|
757 | + |
|
758 | + /** |
|
759 | + * Gets the event's name that's related to the ticket, if this is for |
|
760 | + * a ticket |
|
761 | + * |
|
762 | + * @return string |
|
763 | + * @throws EE_Error |
|
764 | + * @throws InvalidArgumentException |
|
765 | + * @throws InvalidDataTypeException |
|
766 | + * @throws InvalidInterfaceException |
|
767 | + * @throws ReflectionException |
|
768 | + */ |
|
769 | + public function ticket_event_name() |
|
770 | + { |
|
771 | + $event_name = esc_html__('Unknown', 'event_espresso'); |
|
772 | + $event = $this->ticket_event(); |
|
773 | + if ($event instanceof EE_Event) { |
|
774 | + $event_name = $event->name(); |
|
775 | + } |
|
776 | + return $event_name; |
|
777 | + } |
|
778 | + |
|
779 | + |
|
780 | + /** |
|
781 | + * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
782 | + * |
|
783 | + * @return EE_Event|null |
|
784 | + * @throws EE_Error |
|
785 | + * @throws InvalidArgumentException |
|
786 | + * @throws InvalidDataTypeException |
|
787 | + * @throws InvalidInterfaceException |
|
788 | + * @throws ReflectionException |
|
789 | + */ |
|
790 | + public function ticket_event() |
|
791 | + { |
|
792 | + $event = null; |
|
793 | + $ticket = $this->ticket(); |
|
794 | + if ($ticket instanceof EE_Ticket) { |
|
795 | + $datetime = $ticket->first_datetime(); |
|
796 | + if ($datetime instanceof EE_Datetime) { |
|
797 | + $event = $datetime->event(); |
|
798 | + } |
|
799 | + } |
|
800 | + return $event; |
|
801 | + } |
|
802 | + |
|
803 | + |
|
804 | + /** |
|
805 | + * Gets the first datetime for this lien item, assuming it's for a ticket |
|
806 | + * |
|
807 | + * @param string $date_format |
|
808 | + * @param string $time_format |
|
809 | + * @return string |
|
810 | + * @throws EE_Error |
|
811 | + * @throws InvalidArgumentException |
|
812 | + * @throws InvalidDataTypeException |
|
813 | + * @throws InvalidInterfaceException |
|
814 | + * @throws ReflectionException |
|
815 | + */ |
|
816 | + public function ticket_datetime_start($date_format = '', $time_format = '') |
|
817 | + { |
|
818 | + $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
819 | + $datetime = $this->get_ticket_datetime(); |
|
820 | + if ($datetime) { |
|
821 | + $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
822 | + } |
|
823 | + return $first_datetime_string; |
|
824 | + } |
|
825 | + |
|
826 | + |
|
827 | + /** |
|
828 | + * Adds the line item as a child to this line item. If there is another child line |
|
829 | + * item with the same LIN_code, it is overwritten by this new one |
|
830 | + * |
|
831 | + * @param EEI_Line_Item $line_item |
|
832 | + * @param bool $set_order |
|
833 | + * @return bool success |
|
834 | + * @throws EE_Error |
|
835 | + * @throws InvalidArgumentException |
|
836 | + * @throws InvalidDataTypeException |
|
837 | + * @throws InvalidInterfaceException |
|
838 | + * @throws ReflectionException |
|
839 | + */ |
|
840 | + public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
841 | + { |
|
842 | + // should we calculate the LIN_order for this line item ? |
|
843 | + if ($set_order || $line_item->order() === null) { |
|
844 | + $line_item->set_order(count($this->children())); |
|
845 | + } |
|
846 | + if ($this->ID()) { |
|
847 | + // check for any duplicate line items (with the same code), if so, this replaces it |
|
848 | + $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
849 | + if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
850 | + $this->delete_child_line_item($line_item_with_same_code->code()); |
|
851 | + } |
|
852 | + $line_item->set_parent_ID($this->ID()); |
|
853 | + if ($this->TXN_ID()) { |
|
854 | + $line_item->set_TXN_ID($this->TXN_ID()); |
|
855 | + } |
|
856 | + return $line_item->save(); |
|
857 | + } |
|
858 | + $this->_children[ $line_item->code() ] = $line_item; |
|
859 | + if ($line_item->parent() !== $this) { |
|
860 | + $line_item->set_parent($this); |
|
861 | + } |
|
862 | + return true; |
|
863 | + } |
|
864 | + |
|
865 | + |
|
866 | + /** |
|
867 | + * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
868 | + * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
869 | + * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
870 | + * the EE_Line_Item::_parent property. |
|
871 | + * |
|
872 | + * @param EE_Line_Item $line_item |
|
873 | + * @throws EE_Error |
|
874 | + * @throws InvalidArgumentException |
|
875 | + * @throws InvalidDataTypeException |
|
876 | + * @throws InvalidInterfaceException |
|
877 | + * @throws ReflectionException |
|
878 | + */ |
|
879 | + public function set_parent($line_item) |
|
880 | + { |
|
881 | + if ($this->ID()) { |
|
882 | + if (! $line_item->ID()) { |
|
883 | + $line_item->save(); |
|
884 | + } |
|
885 | + $this->set_parent_ID($line_item->ID()); |
|
886 | + $this->save(); |
|
887 | + } else { |
|
888 | + $this->_parent = $line_item; |
|
889 | + $this->set_parent_ID($line_item->ID()); |
|
890 | + } |
|
891 | + } |
|
892 | + |
|
893 | + |
|
894 | + /** |
|
895 | + * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
896 | + * you can modify this child line item and the parent (this object) can know about them |
|
897 | + * because it also has a reference to that line item |
|
898 | + * |
|
899 | + * @param string $code |
|
900 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
901 | + * @throws EE_Error |
|
902 | + * @throws InvalidArgumentException |
|
903 | + * @throws InvalidDataTypeException |
|
904 | + * @throws InvalidInterfaceException |
|
905 | + * @throws ReflectionException |
|
906 | + */ |
|
907 | + public function get_child_line_item($code) |
|
908 | + { |
|
909 | + if ($this->ID()) { |
|
910 | + return $this->get_model()->get_one( |
|
911 | + array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
912 | + ); |
|
913 | + } |
|
914 | + return isset($this->_children[ $code ]) |
|
915 | + ? $this->_children[ $code ] |
|
916 | + : null; |
|
917 | + } |
|
918 | + |
|
919 | + |
|
920 | + /** |
|
921 | + * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
922 | + * cached on it) |
|
923 | + * |
|
924 | + * @return int |
|
925 | + * @throws EE_Error |
|
926 | + * @throws InvalidArgumentException |
|
927 | + * @throws InvalidDataTypeException |
|
928 | + * @throws InvalidInterfaceException |
|
929 | + * @throws ReflectionException |
|
930 | + */ |
|
931 | + public function delete_children_line_items() |
|
932 | + { |
|
933 | + if ($this->ID()) { |
|
934 | + return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
935 | + } |
|
936 | + $count = count($this->_children); |
|
937 | + $this->_children = array(); |
|
938 | + return $count; |
|
939 | + } |
|
940 | + |
|
941 | + |
|
942 | + /** |
|
943 | + * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
944 | + * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
945 | + * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
946 | + * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
947 | + * deleted) |
|
948 | + * |
|
949 | + * @param string $code |
|
950 | + * @param bool $stop_search_once_found |
|
951 | + * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
952 | + * the DB yet) |
|
953 | + * @throws EE_Error |
|
954 | + * @throws InvalidArgumentException |
|
955 | + * @throws InvalidDataTypeException |
|
956 | + * @throws InvalidInterfaceException |
|
957 | + * @throws ReflectionException |
|
958 | + */ |
|
959 | + public function delete_child_line_item($code, $stop_search_once_found = true) |
|
960 | + { |
|
961 | + if ($this->ID()) { |
|
962 | + $items_deleted = 0; |
|
963 | + if ($this->code() === $code) { |
|
964 | + $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
965 | + $items_deleted += (int) $this->delete(); |
|
966 | + if ($stop_search_once_found) { |
|
967 | + return $items_deleted; |
|
968 | + } |
|
969 | + } |
|
970 | + foreach ($this->children() as $child_line_item) { |
|
971 | + $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
972 | + } |
|
973 | + return $items_deleted; |
|
974 | + } |
|
975 | + if (isset($this->_children[ $code ])) { |
|
976 | + unset($this->_children[ $code ]); |
|
977 | + return 1; |
|
978 | + } |
|
979 | + return 0; |
|
980 | + } |
|
981 | + |
|
982 | + |
|
983 | + /** |
|
984 | + * If this line item is in the database, is of the type subtotal, and |
|
985 | + * has no children, why do we have it? It should be deleted so this function |
|
986 | + * does that |
|
987 | + * |
|
988 | + * @return boolean |
|
989 | + * @throws EE_Error |
|
990 | + * @throws InvalidArgumentException |
|
991 | + * @throws InvalidDataTypeException |
|
992 | + * @throws InvalidInterfaceException |
|
993 | + * @throws ReflectionException |
|
994 | + */ |
|
995 | + public function delete_if_childless_subtotal() |
|
996 | + { |
|
997 | + if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
998 | + return $this->delete(); |
|
999 | + } |
|
1000 | + return false; |
|
1001 | + } |
|
1002 | + |
|
1003 | + |
|
1004 | + /** |
|
1005 | + * Creates a code and returns a string. doesn't assign the code to this model object |
|
1006 | + * |
|
1007 | + * @return string |
|
1008 | + * @throws EE_Error |
|
1009 | + * @throws InvalidArgumentException |
|
1010 | + * @throws InvalidDataTypeException |
|
1011 | + * @throws InvalidInterfaceException |
|
1012 | + * @throws ReflectionException |
|
1013 | + */ |
|
1014 | + public function generate_code() |
|
1015 | + { |
|
1016 | + // each line item in the cart requires a unique identifier |
|
1017 | + return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
1018 | + } |
|
1019 | + |
|
1020 | + |
|
1021 | + /** |
|
1022 | + * @return bool |
|
1023 | + * @throws EE_Error |
|
1024 | + * @throws InvalidArgumentException |
|
1025 | + * @throws InvalidDataTypeException |
|
1026 | + * @throws InvalidInterfaceException |
|
1027 | + * @throws ReflectionException |
|
1028 | + */ |
|
1029 | + public function is_tax() |
|
1030 | + { |
|
1031 | + return $this->type() === EEM_Line_Item::type_tax; |
|
1032 | + } |
|
1033 | + |
|
1034 | + |
|
1035 | + /** |
|
1036 | + * @return bool |
|
1037 | + * @throws EE_Error |
|
1038 | + * @throws InvalidArgumentException |
|
1039 | + * @throws InvalidDataTypeException |
|
1040 | + * @throws InvalidInterfaceException |
|
1041 | + * @throws ReflectionException |
|
1042 | + */ |
|
1043 | + public function is_tax_sub_total() |
|
1044 | + { |
|
1045 | + return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
1046 | + } |
|
1047 | + |
|
1048 | + |
|
1049 | + /** |
|
1050 | + * @return bool |
|
1051 | + * @throws EE_Error |
|
1052 | + * @throws InvalidArgumentException |
|
1053 | + * @throws InvalidDataTypeException |
|
1054 | + * @throws InvalidInterfaceException |
|
1055 | + * @throws ReflectionException |
|
1056 | + */ |
|
1057 | + public function is_line_item() |
|
1058 | + { |
|
1059 | + return $this->type() === EEM_Line_Item::type_line_item; |
|
1060 | + } |
|
1061 | + |
|
1062 | + |
|
1063 | + /** |
|
1064 | + * @return bool |
|
1065 | + * @throws EE_Error |
|
1066 | + * @throws InvalidArgumentException |
|
1067 | + * @throws InvalidDataTypeException |
|
1068 | + * @throws InvalidInterfaceException |
|
1069 | + * @throws ReflectionException |
|
1070 | + */ |
|
1071 | + public function is_sub_line_item() |
|
1072 | + { |
|
1073 | + return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
1074 | + } |
|
1075 | + |
|
1076 | + |
|
1077 | + /** |
|
1078 | + * @return bool |
|
1079 | + * @throws EE_Error |
|
1080 | + * @throws InvalidArgumentException |
|
1081 | + * @throws InvalidDataTypeException |
|
1082 | + * @throws InvalidInterfaceException |
|
1083 | + * @throws ReflectionException |
|
1084 | + */ |
|
1085 | + public function is_sub_total() |
|
1086 | + { |
|
1087 | + return $this->type() === EEM_Line_Item::type_sub_total; |
|
1088 | + } |
|
1089 | + |
|
1090 | + |
|
1091 | + /** |
|
1092 | + * Whether or not this line item is a cancellation line item |
|
1093 | + * |
|
1094 | + * @return boolean |
|
1095 | + * @throws EE_Error |
|
1096 | + * @throws InvalidArgumentException |
|
1097 | + * @throws InvalidDataTypeException |
|
1098 | + * @throws InvalidInterfaceException |
|
1099 | + * @throws ReflectionException |
|
1100 | + */ |
|
1101 | + public function is_cancellation() |
|
1102 | + { |
|
1103 | + return EEM_Line_Item::type_cancellation === $this->type(); |
|
1104 | + } |
|
1105 | + |
|
1106 | + |
|
1107 | + /** |
|
1108 | + * @return bool |
|
1109 | + * @throws EE_Error |
|
1110 | + * @throws InvalidArgumentException |
|
1111 | + * @throws InvalidDataTypeException |
|
1112 | + * @throws InvalidInterfaceException |
|
1113 | + * @throws ReflectionException |
|
1114 | + */ |
|
1115 | + public function is_total() |
|
1116 | + { |
|
1117 | + return $this->type() === EEM_Line_Item::type_total; |
|
1118 | + } |
|
1119 | + |
|
1120 | + |
|
1121 | + /** |
|
1122 | + * @return bool |
|
1123 | + * @throws EE_Error |
|
1124 | + * @throws InvalidArgumentException |
|
1125 | + * @throws InvalidDataTypeException |
|
1126 | + * @throws InvalidInterfaceException |
|
1127 | + * @throws ReflectionException |
|
1128 | + */ |
|
1129 | + public function is_cancelled() |
|
1130 | + { |
|
1131 | + return $this->type() === EEM_Line_Item::type_cancellation; |
|
1132 | + } |
|
1133 | + |
|
1134 | + |
|
1135 | + /** |
|
1136 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
1137 | + * @throws EE_Error |
|
1138 | + * @throws InvalidArgumentException |
|
1139 | + * @throws InvalidDataTypeException |
|
1140 | + * @throws InvalidInterfaceException |
|
1141 | + * @throws ReflectionException |
|
1142 | + */ |
|
1143 | + public function unit_price_no_code() |
|
1144 | + { |
|
1145 | + return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
1146 | + } |
|
1147 | + |
|
1148 | + |
|
1149 | + /** |
|
1150 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
1151 | + * @throws EE_Error |
|
1152 | + * @throws InvalidArgumentException |
|
1153 | + * @throws InvalidDataTypeException |
|
1154 | + * @throws InvalidInterfaceException |
|
1155 | + * @throws ReflectionException |
|
1156 | + */ |
|
1157 | + public function total_no_code() |
|
1158 | + { |
|
1159 | + return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
1160 | + } |
|
1161 | + |
|
1162 | + |
|
1163 | + /** |
|
1164 | + * Gets the final total on this item, taking taxes into account. |
|
1165 | + * Has the side-effect of setting the sub-total as it was just calculated. |
|
1166 | + * If this is used on a grand-total line item, also updates the transaction's |
|
1167 | + * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
1168 | + * want to change a persistable transaction with info from a non-persistent line item) |
|
1169 | + * |
|
1170 | + * @param bool $update_txn_status |
|
1171 | + * @return float |
|
1172 | + * @throws EE_Error |
|
1173 | + * @throws InvalidArgumentException |
|
1174 | + * @throws InvalidDataTypeException |
|
1175 | + * @throws InvalidInterfaceException |
|
1176 | + * @throws ReflectionException |
|
1177 | + * @throws RuntimeException |
|
1178 | + */ |
|
1179 | + public function recalculate_total_including_taxes($update_txn_status = false) |
|
1180 | + { |
|
1181 | + $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
1182 | + $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
1183 | + $total = $pre_tax_total + $tax_total; |
|
1184 | + // no negative totals plz |
|
1185 | + $total = max($total, 0); |
|
1186 | + $this->set_total($total); |
|
1187 | + // only update the related transaction's total |
|
1188 | + // if we intend to save this line item and its a grand total |
|
1189 | + if ( |
|
1190 | + $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
1191 | + && $this->transaction() |
|
1192 | + instanceof |
|
1193 | + EE_Transaction |
|
1194 | + ) { |
|
1195 | + $this->transaction()->set_total($total); |
|
1196 | + if ($update_txn_status) { |
|
1197 | + // don't save the TXN because that will be done below |
|
1198 | + // and the following method only saves if the status changes |
|
1199 | + $this->transaction()->update_status_based_on_total_paid(false); |
|
1200 | + } |
|
1201 | + if ($this->transaction()->ID()) { |
|
1202 | + $this->transaction()->save(); |
|
1203 | + } |
|
1204 | + } |
|
1205 | + $this->maybe_save(); |
|
1206 | + return $total; |
|
1207 | + } |
|
1208 | + |
|
1209 | + |
|
1210 | + /** |
|
1211 | + * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
1212 | + * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
1213 | + * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
1214 | + * when this is called on the grand total |
|
1215 | + * |
|
1216 | + * @return float |
|
1217 | + * @throws EE_Error |
|
1218 | + * @throws InvalidArgumentException |
|
1219 | + * @throws InvalidDataTypeException |
|
1220 | + * @throws InvalidInterfaceException |
|
1221 | + * @throws ReflectionException |
|
1222 | + */ |
|
1223 | + public function recalculate_pre_tax_total() |
|
1224 | + { |
|
1225 | + $total = 0; |
|
1226 | + $my_children = $this->children(); |
|
1227 | + $has_children = ! empty($my_children); |
|
1228 | + if ($has_children && $this->is_line_item()) { |
|
1229 | + $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
1230 | + } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
1231 | + $total = $this->unit_price() * $this->quantity(); |
|
1232 | + } elseif ($this->is_sub_total() || $this->is_total()) { |
|
1233 | + $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
1234 | + } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
1235 | + // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
1236 | + return 0; |
|
1237 | + } |
|
1238 | + // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
1239 | + if ( |
|
1240 | + ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
1241 | + ) { |
|
1242 | + if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
1243 | + $this->set_quantity(1); |
|
1244 | + } |
|
1245 | + if (! $this->is_percent()) { |
|
1246 | + $this->set_unit_price($total); |
|
1247 | + } |
|
1248 | + } |
|
1249 | + // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
1250 | + // so it ought to be |
|
1251 | + if (! $this->is_total()) { |
|
1252 | + $this->set_total($total); |
|
1253 | + // if not a percent line item, make sure we keep the unit price in sync |
|
1254 | + if ( |
|
1255 | + $has_children |
|
1256 | + && $this->is_line_item() |
|
1257 | + && ! $this->is_percent() |
|
1258 | + ) { |
|
1259 | + if ($this->quantity() === 0) { |
|
1260 | + $new_unit_price = 0; |
|
1261 | + } else { |
|
1262 | + $new_unit_price = $this->total() / $this->quantity(); |
|
1263 | + } |
|
1264 | + $this->set_unit_price($new_unit_price); |
|
1265 | + } |
|
1266 | + $this->maybe_save(); |
|
1267 | + } |
|
1268 | + return $total; |
|
1269 | + } |
|
1270 | + |
|
1271 | + |
|
1272 | + /** |
|
1273 | + * Calculates the pretax total when this line item is a subtotal or total line item. |
|
1274 | + * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
1275 | + * will calculate their total based on the un-rounded total we're working with so far, and |
|
1276 | + * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
1277 | + * |
|
1278 | + * @param float $calculated_total_so_far |
|
1279 | + * @param EE_Line_Item[] $my_children |
|
1280 | + * @return float |
|
1281 | + * @throws EE_Error |
|
1282 | + * @throws InvalidArgumentException |
|
1283 | + * @throws InvalidDataTypeException |
|
1284 | + * @throws InvalidInterfaceException |
|
1285 | + * @throws ReflectionException |
|
1286 | + */ |
|
1287 | + protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
1288 | + { |
|
1289 | + if ($my_children === null) { |
|
1290 | + $my_children = $this->children(); |
|
1291 | + } |
|
1292 | + $subtotal_quantity = 0; |
|
1293 | + // get the total of all its children |
|
1294 | + foreach ($my_children as $child_line_item) { |
|
1295 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1296 | + // percentage line items are based on total so far |
|
1297 | + if ($child_line_item->is_percent()) { |
|
1298 | + // round as we go so that the line items add up ok |
|
1299 | + $percent_total = round( |
|
1300 | + $calculated_total_so_far * $child_line_item->percent() / 100, |
|
1301 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
1302 | + ); |
|
1303 | + $child_line_item->set_total($percent_total); |
|
1304 | + // so far all percent line items should have a quantity of 1 |
|
1305 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
1306 | + $child_line_item->set_quantity(1); |
|
1307 | + $child_line_item->maybe_save(); |
|
1308 | + $calculated_total_so_far += $percent_total; |
|
1309 | + } else { |
|
1310 | + // verify flat sub-line-item quantities match their parent |
|
1311 | + if ($child_line_item->is_sub_line_item()) { |
|
1312 | + $child_line_item->set_quantity($this->quantity()); |
|
1313 | + } |
|
1314 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1315 | + $subtotal_quantity += $child_line_item->quantity(); |
|
1316 | + } |
|
1317 | + } |
|
1318 | + } |
|
1319 | + if ($this->is_sub_total()) { |
|
1320 | + // no negative totals plz |
|
1321 | + $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
1322 | + $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
1323 | + $this->set_quantity($subtotal_quantity); |
|
1324 | + $this->maybe_save(); |
|
1325 | + } |
|
1326 | + return $calculated_total_so_far; |
|
1327 | + } |
|
1328 | + |
|
1329 | + |
|
1330 | + /** |
|
1331 | + * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
1332 | + * (where each sub-line-item is applied to the base price for the line item |
|
1333 | + * and the result is immediately rounded, rather than summing all the sub-line-items |
|
1334 | + * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
1335 | + * |
|
1336 | + * @param float $calculated_total_so_far |
|
1337 | + * @param EE_Line_Item[] $my_children |
|
1338 | + * @return float |
|
1339 | + * @throws EE_Error |
|
1340 | + * @throws InvalidArgumentException |
|
1341 | + * @throws InvalidDataTypeException |
|
1342 | + * @throws InvalidInterfaceException |
|
1343 | + * @throws ReflectionException |
|
1344 | + */ |
|
1345 | + protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
1346 | + { |
|
1347 | + if ($my_children === null) { |
|
1348 | + $my_children = $this->children(); |
|
1349 | + } |
|
1350 | + // we need to keep track of the running total for a single item, |
|
1351 | + // because we need to round as we go |
|
1352 | + $unit_price_for_total = 0; |
|
1353 | + $quantity_for_total = 1; |
|
1354 | + // get the total of all its children |
|
1355 | + foreach ($my_children as $child_line_item) { |
|
1356 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
1357 | + if ($child_line_item->is_percent()) { |
|
1358 | + // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
1359 | + // not total multiplied by percent, because that ignores rounding along-the-way |
|
1360 | + $percent_unit_price = round( |
|
1361 | + $unit_price_for_total * $child_line_item->percent() / 100, |
|
1362 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
1363 | + ); |
|
1364 | + $percent_total = $percent_unit_price * $quantity_for_total; |
|
1365 | + $child_line_item->set_total($percent_total); |
|
1366 | + // so far all percent line items should have a quantity of 1 |
|
1367 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
1368 | + $child_line_item->set_quantity(1); |
|
1369 | + $child_line_item->maybe_save(); |
|
1370 | + $calculated_total_so_far += $percent_total; |
|
1371 | + $unit_price_for_total += $percent_unit_price; |
|
1372 | + } else { |
|
1373 | + // verify flat sub-line-item quantities match their parent |
|
1374 | + if ($child_line_item->is_sub_line_item()) { |
|
1375 | + $child_line_item->set_quantity($this->quantity()); |
|
1376 | + } |
|
1377 | + $quantity_for_total = $child_line_item->quantity(); |
|
1378 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
1379 | + $unit_price_for_total += $child_line_item->unit_price(); |
|
1380 | + } |
|
1381 | + } |
|
1382 | + } |
|
1383 | + return $calculated_total_so_far; |
|
1384 | + } |
|
1385 | + |
|
1386 | + |
|
1387 | + /** |
|
1388 | + * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
1389 | + * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
1390 | + * and tax sub-total if already in the DB |
|
1391 | + * |
|
1392 | + * @return float |
|
1393 | + * @throws EE_Error |
|
1394 | + * @throws InvalidArgumentException |
|
1395 | + * @throws InvalidDataTypeException |
|
1396 | + * @throws InvalidInterfaceException |
|
1397 | + * @throws ReflectionException |
|
1398 | + */ |
|
1399 | + public function recalculate_taxes_and_tax_total() |
|
1400 | + { |
|
1401 | + // get all taxes |
|
1402 | + $taxes = $this->tax_descendants(); |
|
1403 | + // calculate the pretax total |
|
1404 | + $taxable_total = $this->taxable_total(); |
|
1405 | + $tax_total = 0; |
|
1406 | + foreach ($taxes as $tax) { |
|
1407 | + $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
1408 | + // remember the total on this line item |
|
1409 | + $tax->set_total($total_on_this_tax); |
|
1410 | + $tax->maybe_save(); |
|
1411 | + $tax_total += $tax->total(); |
|
1412 | + } |
|
1413 | + $this->_recalculate_tax_sub_total(); |
|
1414 | + return $tax_total; |
|
1415 | + } |
|
1416 | + |
|
1417 | + |
|
1418 | + /** |
|
1419 | + * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
1420 | + * |
|
1421 | + * @return void |
|
1422 | + * @throws EE_Error |
|
1423 | + * @throws InvalidArgumentException |
|
1424 | + * @throws InvalidDataTypeException |
|
1425 | + * @throws InvalidInterfaceException |
|
1426 | + * @throws ReflectionException |
|
1427 | + */ |
|
1428 | + private function _recalculate_tax_sub_total() |
|
1429 | + { |
|
1430 | + if ($this->is_tax_sub_total()) { |
|
1431 | + $total = 0; |
|
1432 | + $total_percent = 0; |
|
1433 | + // simply loop through all its children (which should be taxes) and sum their total |
|
1434 | + foreach ($this->children() as $child_tax) { |
|
1435 | + if ($child_tax instanceof EE_Line_Item) { |
|
1436 | + $total += $child_tax->total(); |
|
1437 | + $total_percent += $child_tax->percent(); |
|
1438 | + } |
|
1439 | + } |
|
1440 | + $this->set_total($total); |
|
1441 | + $this->set_percent($total_percent); |
|
1442 | + $this->maybe_save(); |
|
1443 | + } elseif ($this->is_total()) { |
|
1444 | + foreach ($this->children() as $maybe_tax_subtotal) { |
|
1445 | + if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
1446 | + $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
1447 | + } |
|
1448 | + } |
|
1449 | + } |
|
1450 | + } |
|
1451 | + |
|
1452 | + |
|
1453 | + /** |
|
1454 | + * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
1455 | + * recalculate_taxes_and_total |
|
1456 | + * |
|
1457 | + * @return float |
|
1458 | + * @throws EE_Error |
|
1459 | + * @throws InvalidArgumentException |
|
1460 | + * @throws InvalidDataTypeException |
|
1461 | + * @throws InvalidInterfaceException |
|
1462 | + * @throws ReflectionException |
|
1463 | + */ |
|
1464 | + public function get_total_tax() |
|
1465 | + { |
|
1466 | + $this->_recalculate_tax_sub_total(); |
|
1467 | + $total = 0; |
|
1468 | + foreach ($this->tax_descendants() as $tax_line_item) { |
|
1469 | + if ($tax_line_item instanceof EE_Line_Item) { |
|
1470 | + $total += $tax_line_item->total(); |
|
1471 | + } |
|
1472 | + } |
|
1473 | + return $total; |
|
1474 | + } |
|
1475 | + |
|
1476 | + |
|
1477 | + /** |
|
1478 | + * Gets the total for all the items purchased only |
|
1479 | + * |
|
1480 | + * @return float |
|
1481 | + * @throws EE_Error |
|
1482 | + * @throws InvalidArgumentException |
|
1483 | + * @throws InvalidDataTypeException |
|
1484 | + * @throws InvalidInterfaceException |
|
1485 | + * @throws ReflectionException |
|
1486 | + */ |
|
1487 | + public function get_items_total() |
|
1488 | + { |
|
1489 | + // by default, let's make sure we're consistent with the existing line item |
|
1490 | + if ($this->is_total()) { |
|
1491 | + $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
1492 | + if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
1493 | + return $pretax_subtotal_li->total(); |
|
1494 | + } |
|
1495 | + } |
|
1496 | + $total = 0; |
|
1497 | + foreach ($this->get_items() as $item) { |
|
1498 | + if ($item instanceof EE_Line_Item) { |
|
1499 | + $total += $item->total(); |
|
1500 | + } |
|
1501 | + } |
|
1502 | + return $total; |
|
1503 | + } |
|
1504 | + |
|
1505 | + |
|
1506 | + /** |
|
1507 | + * Gets all the descendants (ie, children or children of children etc) that |
|
1508 | + * are of the type 'tax' |
|
1509 | + * |
|
1510 | + * @return EE_Line_Item[] |
|
1511 | + * @throws EE_Error |
|
1512 | + */ |
|
1513 | + public function tax_descendants() |
|
1514 | + { |
|
1515 | + return EEH_Line_Item::get_tax_descendants($this); |
|
1516 | + } |
|
1517 | + |
|
1518 | + |
|
1519 | + /** |
|
1520 | + * Gets all the real items purchased which are children of this item |
|
1521 | + * |
|
1522 | + * @return EE_Line_Item[] |
|
1523 | + * @throws EE_Error |
|
1524 | + */ |
|
1525 | + public function get_items() |
|
1526 | + { |
|
1527 | + return EEH_Line_Item::get_line_item_descendants($this); |
|
1528 | + } |
|
1529 | + |
|
1530 | + |
|
1531 | + /** |
|
1532 | + * Returns the amount taxable among this line item's children (or if it has no children, |
|
1533 | + * how much of it is taxable). Does not recalculate totals or subtotals. |
|
1534 | + * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
1535 | + * but there is a "Taxable" discount), returns 0. |
|
1536 | + * |
|
1537 | + * @return float |
|
1538 | + * @throws EE_Error |
|
1539 | + * @throws InvalidArgumentException |
|
1540 | + * @throws InvalidDataTypeException |
|
1541 | + * @throws InvalidInterfaceException |
|
1542 | + * @throws ReflectionException |
|
1543 | + */ |
|
1544 | + public function taxable_total() |
|
1545 | + { |
|
1546 | + $total = 0; |
|
1547 | + if ($this->children()) { |
|
1548 | + foreach ($this->children() as $child_line_item) { |
|
1549 | + if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
1550 | + // if it's a percent item, only take into account the percent |
|
1551 | + // that's taxable too (the taxable total so far) |
|
1552 | + if ($child_line_item->is_percent()) { |
|
1553 | + $total += ($total * $child_line_item->percent() / 100); |
|
1554 | + } else { |
|
1555 | + $total += $child_line_item->total(); |
|
1556 | + } |
|
1557 | + } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
1558 | + $total += $child_line_item->taxable_total(); |
|
1559 | + } |
|
1560 | + } |
|
1561 | + } |
|
1562 | + return max($total, 0); |
|
1563 | + } |
|
1564 | + |
|
1565 | + |
|
1566 | + /** |
|
1567 | + * Gets the transaction for this line item |
|
1568 | + * |
|
1569 | + * @return EE_Base_Class|EE_Transaction |
|
1570 | + * @throws EE_Error |
|
1571 | + * @throws InvalidArgumentException |
|
1572 | + * @throws InvalidDataTypeException |
|
1573 | + * @throws InvalidInterfaceException |
|
1574 | + * @throws ReflectionException |
|
1575 | + */ |
|
1576 | + public function transaction() |
|
1577 | + { |
|
1578 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
1579 | + } |
|
1580 | + |
|
1581 | + |
|
1582 | + /** |
|
1583 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
1584 | + * Because there currently is no proper parent-child relation on the model, |
|
1585 | + * save_this_and_cached() will NOT save the descendants. |
|
1586 | + * Also sets the transaction on this line item and all its descendants before saving |
|
1587 | + * |
|
1588 | + * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
1589 | + * @return int count of items saved |
|
1590 | + * @throws EE_Error |
|
1591 | + * @throws InvalidArgumentException |
|
1592 | + * @throws InvalidDataTypeException |
|
1593 | + * @throws InvalidInterfaceException |
|
1594 | + * @throws ReflectionException |
|
1595 | + */ |
|
1596 | + public function save_this_and_descendants_to_txn($txn_id = null) |
|
1597 | + { |
|
1598 | + $count = 0; |
|
1599 | + if (! $txn_id) { |
|
1600 | + $txn_id = $this->TXN_ID(); |
|
1601 | + } |
|
1602 | + $this->set_TXN_ID($txn_id); |
|
1603 | + $children = $this->children(); |
|
1604 | + $count += $this->save() |
|
1605 | + ? 1 |
|
1606 | + : 0; |
|
1607 | + foreach ($children as $child_line_item) { |
|
1608 | + if ($child_line_item instanceof EE_Line_Item) { |
|
1609 | + $child_line_item->set_parent_ID($this->ID()); |
|
1610 | + $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
1611 | + } |
|
1612 | + } |
|
1613 | + return $count; |
|
1614 | + } |
|
1615 | + |
|
1616 | + |
|
1617 | + /** |
|
1618 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
1619 | + * |
|
1620 | + * @return int count of items saved |
|
1621 | + * @throws EE_Error |
|
1622 | + * @throws InvalidArgumentException |
|
1623 | + * @throws InvalidDataTypeException |
|
1624 | + * @throws InvalidInterfaceException |
|
1625 | + * @throws ReflectionException |
|
1626 | + */ |
|
1627 | + public function save_this_and_descendants() |
|
1628 | + { |
|
1629 | + $count = 0; |
|
1630 | + $children = $this->children(); |
|
1631 | + $count += $this->save() |
|
1632 | + ? 1 |
|
1633 | + : 0; |
|
1634 | + foreach ($children as $child_line_item) { |
|
1635 | + if ($child_line_item instanceof EE_Line_Item) { |
|
1636 | + $child_line_item->set_parent_ID($this->ID()); |
|
1637 | + $count += $child_line_item->save_this_and_descendants(); |
|
1638 | + } |
|
1639 | + } |
|
1640 | + return $count; |
|
1641 | + } |
|
1642 | + |
|
1643 | + |
|
1644 | + /** |
|
1645 | + * returns the cancellation line item if this item was cancelled |
|
1646 | + * |
|
1647 | + * @return EE_Line_Item[] |
|
1648 | + * @throws InvalidArgumentException |
|
1649 | + * @throws InvalidInterfaceException |
|
1650 | + * @throws InvalidDataTypeException |
|
1651 | + * @throws ReflectionException |
|
1652 | + * @throws EE_Error |
|
1653 | + */ |
|
1654 | + public function get_cancellations() |
|
1655 | + { |
|
1656 | + EE_Registry::instance()->load_helper('Line_Item'); |
|
1657 | + return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
1658 | + } |
|
1659 | + |
|
1660 | + |
|
1661 | + /** |
|
1662 | + * If this item has an ID, then this saves it again to update the db |
|
1663 | + * |
|
1664 | + * @return int count of items saved |
|
1665 | + * @throws EE_Error |
|
1666 | + * @throws InvalidArgumentException |
|
1667 | + * @throws InvalidDataTypeException |
|
1668 | + * @throws InvalidInterfaceException |
|
1669 | + * @throws ReflectionException |
|
1670 | + */ |
|
1671 | + public function maybe_save() |
|
1672 | + { |
|
1673 | + if ($this->ID()) { |
|
1674 | + return $this->save(); |
|
1675 | + } |
|
1676 | + return false; |
|
1677 | + } |
|
1678 | + |
|
1679 | + |
|
1680 | + /** |
|
1681 | + * clears the cached children and parent from the line item |
|
1682 | + * |
|
1683 | + * @return void |
|
1684 | + */ |
|
1685 | + public function clear_related_line_item_cache() |
|
1686 | + { |
|
1687 | + $this->_children = array(); |
|
1688 | + $this->_parent = null; |
|
1689 | + } |
|
1690 | + |
|
1691 | + |
|
1692 | + /** |
|
1693 | + * @param bool $raw |
|
1694 | + * @return int |
|
1695 | + * @throws EE_Error |
|
1696 | + * @throws InvalidArgumentException |
|
1697 | + * @throws InvalidDataTypeException |
|
1698 | + * @throws InvalidInterfaceException |
|
1699 | + * @throws ReflectionException |
|
1700 | + */ |
|
1701 | + public function timestamp($raw = false) |
|
1702 | + { |
|
1703 | + return $raw |
|
1704 | + ? $this->get_raw('LIN_timestamp') |
|
1705 | + : $this->get('LIN_timestamp'); |
|
1706 | + } |
|
1707 | + |
|
1708 | + |
|
1709 | + |
|
1710 | + |
|
1711 | + /************************* DEPRECATED *************************/ |
|
1712 | + /** |
|
1713 | + * @deprecated 4.6.0 |
|
1714 | + * @param string $type one of the constants on EEM_Line_Item |
|
1715 | + * @return EE_Line_Item[] |
|
1716 | + * @throws EE_Error |
|
1717 | + */ |
|
1718 | + protected function _get_descendants_of_type($type) |
|
1719 | + { |
|
1720 | + EE_Error::doing_it_wrong( |
|
1721 | + 'EE_Line_Item::_get_descendants_of_type()', |
|
1722 | + sprintf( |
|
1723 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1724 | + 'EEH_Line_Item::get_descendants_of_type()' |
|
1725 | + ), |
|
1726 | + '4.6.0' |
|
1727 | + ); |
|
1728 | + return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
1729 | + } |
|
1730 | + |
|
1731 | + |
|
1732 | + /** |
|
1733 | + * @deprecated 4.6.0 |
|
1734 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
1735 | + * @return EE_Line_Item |
|
1736 | + * @throws EE_Error |
|
1737 | + * @throws InvalidArgumentException |
|
1738 | + * @throws InvalidDataTypeException |
|
1739 | + * @throws InvalidInterfaceException |
|
1740 | + * @throws ReflectionException |
|
1741 | + */ |
|
1742 | + public function get_nearest_descendant_of_type($type) |
|
1743 | + { |
|
1744 | + EE_Error::doing_it_wrong( |
|
1745 | + 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
1746 | + sprintf( |
|
1747 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
1748 | + 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
1749 | + ), |
|
1750 | + '4.6.0' |
|
1751 | + ); |
|
1752 | + return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
1753 | + } |
|
1754 | 1754 | } |
@@ -154,19 +154,19 @@ |
||
154 | 154 | $sanitized_attributes = array(); |
155 | 155 | foreach ($attributes as $attribute => $value) { |
156 | 156 | $convert = $this->getAttributesMap(); |
157 | - if (isset($convert[ $attribute ])) { |
|
158 | - $sanitize = $convert[ $attribute ]; |
|
157 | + if (isset($convert[$attribute])) { |
|
158 | + $sanitize = $convert[$attribute]; |
|
159 | 159 | if ($sanitize === 'bool') { |
160 | - $sanitized_attributes[ $attribute ] = filter_var( |
|
160 | + $sanitized_attributes[$attribute] = filter_var( |
|
161 | 161 | $value, |
162 | 162 | FILTER_VALIDATE_BOOLEAN |
163 | 163 | ); |
164 | 164 | } else { |
165 | - $sanitized_attributes[ $attribute ] = $sanitize($value); |
|
165 | + $sanitized_attributes[$attribute] = $sanitize($value); |
|
166 | 166 | } |
167 | 167 | // don't pass along attributes with a 0 value |
168 | - if ($sanitized_attributes[ $attribute ] === 0) { |
|
169 | - unset($sanitized_attributes[ $attribute ]); |
|
168 | + if ($sanitized_attributes[$attribute] === 0) { |
|
169 | + unset($sanitized_attributes[$attribute]); |
|
170 | 170 | } |
171 | 171 | } |
172 | 172 | } |
@@ -20,172 +20,172 @@ |
||
20 | 20 | */ |
21 | 21 | class EventAttendees extends Block |
22 | 22 | { |
23 | - const BLOCK_TYPE = 'event-attendees'; |
|
23 | + const BLOCK_TYPE = 'event-attendees'; |
|
24 | 24 | |
25 | - /** |
|
26 | - * @var EventAttendeesBlockRenderer $renderer |
|
27 | - */ |
|
28 | - protected $renderer; |
|
25 | + /** |
|
26 | + * @var EventAttendeesBlockRenderer $renderer |
|
27 | + */ |
|
28 | + protected $renderer; |
|
29 | 29 | |
30 | 30 | |
31 | - /** |
|
32 | - * EventAttendees constructor. |
|
33 | - * |
|
34 | - * @param CoreBlocksAssetManager $block_asset_manager |
|
35 | - * @param RequestInterface $request |
|
36 | - * @param EventAttendeesBlockRenderer $renderer |
|
37 | - */ |
|
38 | - public function __construct( |
|
39 | - CoreBlocksAssetManager $block_asset_manager, |
|
40 | - RequestInterface $request, |
|
41 | - EventAttendeesBlockRenderer $renderer |
|
42 | - ) { |
|
43 | - parent::__construct($block_asset_manager, $request); |
|
44 | - $this->renderer = $renderer; |
|
45 | - } |
|
31 | + /** |
|
32 | + * EventAttendees constructor. |
|
33 | + * |
|
34 | + * @param CoreBlocksAssetManager $block_asset_manager |
|
35 | + * @param RequestInterface $request |
|
36 | + * @param EventAttendeesBlockRenderer $renderer |
|
37 | + */ |
|
38 | + public function __construct( |
|
39 | + CoreBlocksAssetManager $block_asset_manager, |
|
40 | + RequestInterface $request, |
|
41 | + EventAttendeesBlockRenderer $renderer |
|
42 | + ) { |
|
43 | + parent::__construct($block_asset_manager, $request); |
|
44 | + $this->renderer = $renderer; |
|
45 | + } |
|
46 | 46 | |
47 | 47 | |
48 | - /** |
|
49 | - * Perform any early setup required by the block |
|
50 | - * including setting the block type and supported post types |
|
51 | - * |
|
52 | - * @return void |
|
53 | - */ |
|
54 | - public function initialize() |
|
55 | - { |
|
56 | - $this->setBlockType(self::BLOCK_TYPE); |
|
57 | - $this->setSupportedRoutes( |
|
58 | - array( |
|
59 | - 'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor', |
|
60 | - 'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor', |
|
61 | - 'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer', |
|
62 | - 'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest' |
|
63 | - ) |
|
64 | - ); |
|
65 | - $EVT_ID = $this->request->getRequestParam('page') === 'espresso_events' |
|
66 | - ? $this->request->getRequestParam('post', 0, 'int') |
|
67 | - : 0; |
|
68 | - $this->setAttributes( |
|
69 | - array( |
|
70 | - 'eventId' => array( |
|
71 | - 'type' => 'number', |
|
72 | - 'default' => $EVT_ID, |
|
73 | - ), |
|
74 | - 'datetimeId' => array( |
|
75 | - 'type' => 'number', |
|
76 | - 'default' => 0, |
|
77 | - ), |
|
78 | - 'ticketId' => array( |
|
79 | - 'type' => 'number', |
|
80 | - 'default' => 0, |
|
81 | - ), |
|
82 | - 'status' => array( |
|
83 | - 'type' => 'string', |
|
84 | - 'default' => EEM_Registration::status_id_approved, |
|
85 | - ), |
|
86 | - 'limit' => array( |
|
87 | - 'type' => 'number', |
|
88 | - 'default' => 100, |
|
89 | - ), |
|
90 | - 'order' => array( |
|
91 | - 'type' => 'string', |
|
92 | - 'default' => 'ASC' |
|
93 | - ), |
|
94 | - 'orderBy' => array( |
|
95 | - 'type' => 'string', |
|
96 | - 'default' => 'lastThenFirstName', |
|
97 | - ), |
|
98 | - 'showGravatar' => array( |
|
99 | - 'type' => 'boolean', |
|
100 | - 'default' => false, |
|
101 | - ), |
|
102 | - 'avatarClass' => array( |
|
103 | - 'type' => 'string', |
|
104 | - 'default' => 'contact', |
|
105 | - ), |
|
106 | - 'avatarSize' => array( |
|
107 | - 'type' => 'number', |
|
108 | - 'default' => 24, |
|
109 | - ), |
|
110 | - 'displayOnArchives' => array( |
|
111 | - 'type' => 'boolean', |
|
112 | - 'default' => false, |
|
113 | - ), |
|
114 | - ) |
|
115 | - ); |
|
116 | - $this->setDynamic(); |
|
117 | - } |
|
48 | + /** |
|
49 | + * Perform any early setup required by the block |
|
50 | + * including setting the block type and supported post types |
|
51 | + * |
|
52 | + * @return void |
|
53 | + */ |
|
54 | + public function initialize() |
|
55 | + { |
|
56 | + $this->setBlockType(self::BLOCK_TYPE); |
|
57 | + $this->setSupportedRoutes( |
|
58 | + array( |
|
59 | + 'EventEspresso\core\domain\entities\route_match\specifications\admin\EspressoStandardPostTypeEditor', |
|
60 | + 'EventEspresso\core\domain\entities\route_match\specifications\admin\WordPressPostTypeEditor', |
|
61 | + 'EventEspresso\core\domain\entities\route_match\specifications\frontend\EspressoBlockRenderer', |
|
62 | + 'EventEspresso\core\domain\entities\route_match\specifications\frontend\AnyFrontendRequest' |
|
63 | + ) |
|
64 | + ); |
|
65 | + $EVT_ID = $this->request->getRequestParam('page') === 'espresso_events' |
|
66 | + ? $this->request->getRequestParam('post', 0, 'int') |
|
67 | + : 0; |
|
68 | + $this->setAttributes( |
|
69 | + array( |
|
70 | + 'eventId' => array( |
|
71 | + 'type' => 'number', |
|
72 | + 'default' => $EVT_ID, |
|
73 | + ), |
|
74 | + 'datetimeId' => array( |
|
75 | + 'type' => 'number', |
|
76 | + 'default' => 0, |
|
77 | + ), |
|
78 | + 'ticketId' => array( |
|
79 | + 'type' => 'number', |
|
80 | + 'default' => 0, |
|
81 | + ), |
|
82 | + 'status' => array( |
|
83 | + 'type' => 'string', |
|
84 | + 'default' => EEM_Registration::status_id_approved, |
|
85 | + ), |
|
86 | + 'limit' => array( |
|
87 | + 'type' => 'number', |
|
88 | + 'default' => 100, |
|
89 | + ), |
|
90 | + 'order' => array( |
|
91 | + 'type' => 'string', |
|
92 | + 'default' => 'ASC' |
|
93 | + ), |
|
94 | + 'orderBy' => array( |
|
95 | + 'type' => 'string', |
|
96 | + 'default' => 'lastThenFirstName', |
|
97 | + ), |
|
98 | + 'showGravatar' => array( |
|
99 | + 'type' => 'boolean', |
|
100 | + 'default' => false, |
|
101 | + ), |
|
102 | + 'avatarClass' => array( |
|
103 | + 'type' => 'string', |
|
104 | + 'default' => 'contact', |
|
105 | + ), |
|
106 | + 'avatarSize' => array( |
|
107 | + 'type' => 'number', |
|
108 | + 'default' => 24, |
|
109 | + ), |
|
110 | + 'displayOnArchives' => array( |
|
111 | + 'type' => 'boolean', |
|
112 | + 'default' => false, |
|
113 | + ), |
|
114 | + ) |
|
115 | + ); |
|
116 | + $this->setDynamic(); |
|
117 | + } |
|
118 | 118 | |
119 | 119 | |
120 | - /** |
|
121 | - * Returns an array where the key corresponds to the incoming attribute name from the WP block |
|
122 | - * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode |
|
123 | - * |
|
124 | - * @since 4.9.71.p |
|
125 | - * @return array |
|
126 | - */ |
|
127 | - private function getAttributesMap() |
|
128 | - { |
|
129 | - return array( |
|
130 | - 'eventId' => 'absint', |
|
131 | - 'datetimeId' => 'absint', |
|
132 | - 'ticketId' => 'absint', |
|
133 | - 'status' => 'sanitize_text_field', |
|
134 | - 'limit' => 'intval', |
|
135 | - 'showGravatar' => 'bool', |
|
136 | - 'avatarClass' => 'sanitize_text_field', |
|
137 | - 'avatarSize' => 'absint', |
|
138 | - 'displayOnArchives' => 'bool', |
|
139 | - 'order' => 'sanitize_text_field', |
|
140 | - 'orderBy' => 'sanitize_text_field', |
|
141 | - ); |
|
142 | - } |
|
120 | + /** |
|
121 | + * Returns an array where the key corresponds to the incoming attribute name from the WP block |
|
122 | + * and the value corresponds to the attribute name for the existing EspressoEventAttendees shortcode |
|
123 | + * |
|
124 | + * @since 4.9.71.p |
|
125 | + * @return array |
|
126 | + */ |
|
127 | + private function getAttributesMap() |
|
128 | + { |
|
129 | + return array( |
|
130 | + 'eventId' => 'absint', |
|
131 | + 'datetimeId' => 'absint', |
|
132 | + 'ticketId' => 'absint', |
|
133 | + 'status' => 'sanitize_text_field', |
|
134 | + 'limit' => 'intval', |
|
135 | + 'showGravatar' => 'bool', |
|
136 | + 'avatarClass' => 'sanitize_text_field', |
|
137 | + 'avatarSize' => 'absint', |
|
138 | + 'displayOnArchives' => 'bool', |
|
139 | + 'order' => 'sanitize_text_field', |
|
140 | + 'orderBy' => 'sanitize_text_field', |
|
141 | + ); |
|
142 | + } |
|
143 | 143 | |
144 | 144 | |
145 | - /** |
|
146 | - * Sanitizes attributes. |
|
147 | - * |
|
148 | - * @param array $attributes |
|
149 | - * @return array |
|
150 | - */ |
|
151 | - private function sanitizeAttributes(array $attributes) |
|
152 | - { |
|
153 | - $sanitized_attributes = array(); |
|
154 | - foreach ($attributes as $attribute => $value) { |
|
155 | - $convert = $this->getAttributesMap(); |
|
156 | - if (isset($convert[ $attribute ])) { |
|
157 | - $sanitize = $convert[ $attribute ]; |
|
158 | - if ($sanitize === 'bool') { |
|
159 | - $sanitized_attributes[ $attribute ] = filter_var( |
|
160 | - $value, |
|
161 | - FILTER_VALIDATE_BOOLEAN |
|
162 | - ); |
|
163 | - } else { |
|
164 | - $sanitized_attributes[ $attribute ] = $sanitize($value); |
|
165 | - } |
|
166 | - // don't pass along attributes with a 0 value |
|
167 | - if ($sanitized_attributes[ $attribute ] === 0) { |
|
168 | - unset($sanitized_attributes[ $attribute ]); |
|
169 | - } |
|
170 | - } |
|
171 | - } |
|
172 | - return $attributes; |
|
173 | - } |
|
145 | + /** |
|
146 | + * Sanitizes attributes. |
|
147 | + * |
|
148 | + * @param array $attributes |
|
149 | + * @return array |
|
150 | + */ |
|
151 | + private function sanitizeAttributes(array $attributes) |
|
152 | + { |
|
153 | + $sanitized_attributes = array(); |
|
154 | + foreach ($attributes as $attribute => $value) { |
|
155 | + $convert = $this->getAttributesMap(); |
|
156 | + if (isset($convert[ $attribute ])) { |
|
157 | + $sanitize = $convert[ $attribute ]; |
|
158 | + if ($sanitize === 'bool') { |
|
159 | + $sanitized_attributes[ $attribute ] = filter_var( |
|
160 | + $value, |
|
161 | + FILTER_VALIDATE_BOOLEAN |
|
162 | + ); |
|
163 | + } else { |
|
164 | + $sanitized_attributes[ $attribute ] = $sanitize($value); |
|
165 | + } |
|
166 | + // don't pass along attributes with a 0 value |
|
167 | + if ($sanitized_attributes[ $attribute ] === 0) { |
|
168 | + unset($sanitized_attributes[ $attribute ]); |
|
169 | + } |
|
170 | + } |
|
171 | + } |
|
172 | + return $attributes; |
|
173 | + } |
|
174 | 174 | |
175 | 175 | |
176 | - /** |
|
177 | - * Returns the rendered HTML for the block |
|
178 | - * |
|
179 | - * @param array $attributes |
|
180 | - * @return string |
|
181 | - * @throws DomainException |
|
182 | - * @throws EE_Error |
|
183 | - */ |
|
184 | - public function renderBlock(array $attributes = array()) |
|
185 | - { |
|
186 | - $attributes = $this->sanitizeAttributes($attributes); |
|
187 | - return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives'] |
|
188 | - ? '' |
|
189 | - : $this->renderer->render($attributes); |
|
190 | - } |
|
176 | + /** |
|
177 | + * Returns the rendered HTML for the block |
|
178 | + * |
|
179 | + * @param array $attributes |
|
180 | + * @return string |
|
181 | + * @throws DomainException |
|
182 | + * @throws EE_Error |
|
183 | + */ |
|
184 | + public function renderBlock(array $attributes = array()) |
|
185 | + { |
|
186 | + $attributes = $this->sanitizeAttributes($attributes); |
|
187 | + return (is_archive() || is_front_page() || is_home()) && ! $attributes['displayOnArchives'] |
|
188 | + ? '' |
|
189 | + : $this->renderer->render($attributes); |
|
190 | + } |
|
191 | 191 | } |
@@ -17,85 +17,85 @@ |
||
17 | 17 | */ |
18 | 18 | class EE_Restriction_Generator_Default_Protected extends EE_Restriction_Generator_Base |
19 | 19 | { |
20 | - /** |
|
21 | - * Name of the field on this model (or a related model, including the model chain to it) |
|
22 | - * that is a boolean indicating whether or not a model object is considered "Default" or not |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - protected $_default_field_name; |
|
20 | + /** |
|
21 | + * Name of the field on this model (or a related model, including the model chain to it) |
|
22 | + * that is a boolean indicating whether or not a model object is considered "Default" or not |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + protected $_default_field_name; |
|
26 | 26 | |
27 | - /** |
|
28 | - * The model chain to follow to get to the event model, including the event model itself. |
|
29 | - * Eg 'Ticket.Datetime.Event' |
|
30 | - * @var string |
|
31 | - */ |
|
32 | - protected $_path_to_event_model; |
|
33 | - /** |
|
34 | - * |
|
35 | - * @param string $default_field_name the name of the field Name of the field on this model (or a related model, including the model chain to it) |
|
36 | - * that is a boolean indicating whether or not a model object is considered "Default" or not |
|
37 | - * @param string $path_to_event_model The model chain to follow to get to the event model, including the event model itself. |
|
38 | - * Eg 'Ticket.Datetime.Event' |
|
39 | - */ |
|
40 | - public function __construct($default_field_name, $path_to_event_model) |
|
41 | - { |
|
42 | - $this->_default_field_name = $default_field_name; |
|
43 | - if (substr($path_to_event_model, -1, 1) != '.') { |
|
44 | - $path_to_event_model .= '.'; |
|
45 | - } |
|
46 | - $this->_path_to_event_model = $path_to_event_model; |
|
47 | - } |
|
27 | + /** |
|
28 | + * The model chain to follow to get to the event model, including the event model itself. |
|
29 | + * Eg 'Ticket.Datetime.Event' |
|
30 | + * @var string |
|
31 | + */ |
|
32 | + protected $_path_to_event_model; |
|
33 | + /** |
|
34 | + * |
|
35 | + * @param string $default_field_name the name of the field Name of the field on this model (or a related model, including the model chain to it) |
|
36 | + * that is a boolean indicating whether or not a model object is considered "Default" or not |
|
37 | + * @param string $path_to_event_model The model chain to follow to get to the event model, including the event model itself. |
|
38 | + * Eg 'Ticket.Datetime.Event' |
|
39 | + */ |
|
40 | + public function __construct($default_field_name, $path_to_event_model) |
|
41 | + { |
|
42 | + $this->_default_field_name = $default_field_name; |
|
43 | + if (substr($path_to_event_model, -1, 1) != '.') { |
|
44 | + $path_to_event_model .= '.'; |
|
45 | + } |
|
46 | + $this->_path_to_event_model = $path_to_event_model; |
|
47 | + } |
|
48 | 48 | |
49 | 49 | |
50 | 50 | |
51 | - /** |
|
52 | - * |
|
53 | - * @return \EE_Default_Where_Conditions |
|
54 | - */ |
|
55 | - protected function _generate_restrictions() |
|
56 | - { |
|
57 | - // if there are no standard caps for this model, then for now all we know is |
|
58 | - // if they need the default cap to access this |
|
59 | - if (! $this->model()->cap_slug()) { |
|
60 | - return array( |
|
61 | - self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions() |
|
62 | - ); |
|
63 | - } |
|
51 | + /** |
|
52 | + * |
|
53 | + * @return \EE_Default_Where_Conditions |
|
54 | + */ |
|
55 | + protected function _generate_restrictions() |
|
56 | + { |
|
57 | + // if there are no standard caps for this model, then for now all we know is |
|
58 | + // if they need the default cap to access this |
|
59 | + if (! $this->model()->cap_slug()) { |
|
60 | + return array( |
|
61 | + self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions() |
|
62 | + ); |
|
63 | + } |
|
64 | 64 | |
65 | - $event_model = EEM_Event::instance(); |
|
65 | + $event_model = EEM_Event::instance(); |
|
66 | 66 | |
67 | - $restrictions = array( |
|
68 | - // first: basically access to non-defaults is essentially controlled by which events are accessible |
|
69 | - // if they don't have the basic event cap, they can't access ANY non-default items |
|
70 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )), |
|
71 | - // if they don't have the others event cap, they can't access others' non-default items |
|
72 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array( |
|
73 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array( |
|
74 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ), |
|
75 | - $this->_default_field_name => true )), |
|
76 | - // if they have basic and others, but not private, they can't access others' private non-default items |
|
77 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array( |
|
78 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array( |
|
79 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
80 | - $this->_path_to_event_model . 'status' => array( '!=', 'private' ), |
|
81 | - $this->_default_field_name => true ) )), |
|
82 | - // second: access to defaults is controlled by the defaulty capabilities |
|
83 | - // if they don't have the default capability, restrict access to only non-default items |
|
84 | - EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )), |
|
85 | - // if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones |
|
86 | - ); |
|
87 | - if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) { |
|
88 | - $restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array( |
|
89 | - // if they don't have the others default cap, they can't access others default items (but they can access |
|
90 | - // their own default items, and non-default items) |
|
91 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array( |
|
92 | - 'AND' => array( |
|
93 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
94 | - $this->_default_field_name => true |
|
95 | - ), |
|
96 | - $this->_default_field_name => false |
|
97 | - ) )); |
|
98 | - } |
|
99 | - return $restrictions; |
|
100 | - } |
|
67 | + $restrictions = array( |
|
68 | + // first: basically access to non-defaults is essentially controlled by which events are accessible |
|
69 | + // if they don't have the basic event cap, they can't access ANY non-default items |
|
70 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )), |
|
71 | + // if they don't have the others event cap, they can't access others' non-default items |
|
72 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array( |
|
73 | + 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array( |
|
74 | + $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ), |
|
75 | + $this->_default_field_name => true )), |
|
76 | + // if they have basic and others, but not private, they can't access others' private non-default items |
|
77 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array( |
|
78 | + 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array( |
|
79 | + $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
80 | + $this->_path_to_event_model . 'status' => array( '!=', 'private' ), |
|
81 | + $this->_default_field_name => true ) )), |
|
82 | + // second: access to defaults is controlled by the defaulty capabilities |
|
83 | + // if they don't have the default capability, restrict access to only non-default items |
|
84 | + EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )), |
|
85 | + // if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones |
|
86 | + ); |
|
87 | + if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) { |
|
88 | + $restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array( |
|
89 | + // if they don't have the others default cap, they can't access others default items (but they can access |
|
90 | + // their own default items, and non-default items) |
|
91 | + 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array( |
|
92 | + 'AND' => array( |
|
93 | + $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
94 | + $this->_default_field_name => true |
|
95 | + ), |
|
96 | + $this->_default_field_name => false |
|
97 | + ) )); |
|
98 | + } |
|
99 | + return $restrictions; |
|
100 | + } |
|
101 | 101 | } |
@@ -56,7 +56,7 @@ discard block |
||
56 | 56 | { |
57 | 57 | // if there are no standard caps for this model, then for now all we know is |
58 | 58 | // if they need the default cap to access this |
59 | - if (! $this->model()->cap_slug()) { |
|
59 | + if ( ! $this->model()->cap_slug()) { |
|
60 | 60 | return array( |
61 | 61 | self::get_default_restrictions_cap() => new EE_Return_None_Where_Conditions() |
62 | 62 | ); |
@@ -64,33 +64,33 @@ discard block |
||
64 | 64 | |
65 | 65 | $event_model = EEM_Event::instance(); |
66 | 66 | |
67 | - $restrictions = array( |
|
67 | + $restrictions = array( |
|
68 | 68 | // first: basically access to non-defaults is essentially controlled by which events are accessible |
69 | 69 | // if they don't have the basic event cap, they can't access ANY non-default items |
70 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array( $this->_default_field_name => true )), |
|
70 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action()) => new EE_Default_Where_Conditions(array($this->_default_field_name => true)), |
|
71 | 71 | // if they don't have the others event cap, they can't access others' non-default items |
72 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => new EE_Default_Where_Conditions(array( |
|
73 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_others') => array( |
|
74 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ), |
|
72 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_others') => new EE_Default_Where_Conditions(array( |
|
73 | + 'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_others') => array( |
|
74 | + $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder ), |
|
75 | 75 | $this->_default_field_name => true )), |
76 | 76 | // if they have basic and others, but not private, they can't access others' private non-default items |
77 | - EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => new EE_Default_Where_Conditions(array( |
|
78 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action() . '_private') => array( |
|
79 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
80 | - $this->_path_to_event_model . 'status' => array( '!=', 'private' ), |
|
77 | + EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_private') => new EE_Default_Where_Conditions(array( |
|
78 | + 'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($event_model, $this->action().'_private') => array( |
|
79 | + $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
80 | + $this->_path_to_event_model.'status' => array('!=', 'private'), |
|
81 | 81 | $this->_default_field_name => true ) )), |
82 | 82 | // second: access to defaults is controlled by the defaulty capabilities |
83 | 83 | // if they don't have the default capability, restrict access to only non-default items |
84 | - EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_default') => new EE_Default_Where_Conditions(array( $this->_default_field_name => false )), |
|
84 | + EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_default') => new EE_Default_Where_Conditions(array($this->_default_field_name => false)), |
|
85 | 85 | // if they don't have the "others" default capability, restrict access to only their default ones, and non-default ones |
86 | 86 | ); |
87 | - if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action() . '_others_default')) { |
|
88 | - $restrictions[ EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') ] = new EE_Default_Where_Conditions(array( |
|
87 | + if (EE_Restriction_Generator_Base::is_cap($this->model(), $this->action().'_others_default')) { |
|
88 | + $restrictions[EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_others_default')] = new EE_Default_Where_Conditions(array( |
|
89 | 89 | // if they don't have the others default cap, they can't access others default items (but they can access |
90 | 90 | // their own default items, and non-default items) |
91 | - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action() . '_others_default') => array( |
|
91 | + 'OR*no_'.EE_Restriction_Generator_Base::get_cap_name($this->model(), $this->action().'_others_default') => array( |
|
92 | 92 | 'AND' => array( |
93 | - $this->_path_to_event_model . 'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
93 | + $this->_path_to_event_model.'EVT_wp_user' => EE_Default_Where_Conditions::current_user_placeholder, |
|
94 | 94 | $this->_default_field_name => true |
95 | 95 | ), |
96 | 96 | $this->_default_field_name => false |
@@ -216,7 +216,7 @@ discard block |
||
216 | 216 | { |
217 | 217 | if (EEH_Event_Query::apply_query_filters($wp_query)) { |
218 | 218 | global $wpdb; |
219 | - $clauses['groupby'] = $wpdb->posts . '.ID '; |
|
219 | + $clauses['groupby'] = $wpdb->posts.'.ID '; |
|
220 | 220 | } |
221 | 221 | return $clauses; |
222 | 222 | } |
@@ -251,23 +251,23 @@ discard block |
||
251 | 251 | */ |
252 | 252 | public static function posts_fields_sql_for_orderby(array $orderby_params = []) |
253 | 253 | { |
254 | - $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
254 | + $SQL = ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date '; |
|
255 | 255 | foreach ($orderby_params as $orderby) { |
256 | 256 | switch ($orderby) { |
257 | 257 | case 'ticket_start': |
258 | - $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date'; |
|
258 | + $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_start_date'; |
|
259 | 259 | break; |
260 | 260 | case 'ticket_end': |
261 | - $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date'; |
|
261 | + $SQL .= ', '.EEM_Ticket::instance()->table().'.TKT_end_date'; |
|
262 | 262 | break; |
263 | 263 | case 'venue_title': |
264 | 264 | $SQL .= ', Venue.post_title AS venue_title'; |
265 | 265 | break; |
266 | 266 | case 'city': |
267 | - $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city'; |
|
267 | + $SQL .= ', '.EEM_Venue::instance()->second_table().'.VNU_city'; |
|
268 | 268 | break; |
269 | 269 | case 'state': |
270 | - $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name'; |
|
270 | + $SQL .= ', '.EEM_State::instance()->table().'.STA_name'; |
|
271 | 271 | break; |
272 | 272 | } |
273 | 273 | } |
@@ -307,12 +307,12 @@ discard block |
||
307 | 307 | */ |
308 | 308 | public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false) |
309 | 309 | { |
310 | - if (! $show_expired) { |
|
311 | - $join = EEM_Event::instance()->table() . '.ID = '; |
|
312 | - $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
310 | + if ( ! $show_expired) { |
|
311 | + $join = EEM_Event::instance()->table().'.ID = '; |
|
312 | + $join .= EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name(); |
|
313 | 313 | // don't add if this is already in the SQL |
314 | 314 | if (strpos($SQL, $join) === false) { |
315 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) '; |
|
315 | + $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' ) '; |
|
316 | 316 | } |
317 | 317 | } |
318 | 318 | return $SQL; |
@@ -327,7 +327,7 @@ discard block |
||
327 | 327 | */ |
328 | 328 | public static function posts_join_sql_for_terms($SQL = '', $join_terms = '') |
329 | 329 | { |
330 | - if (! empty($join_terms)) { |
|
330 | + if ( ! empty($join_terms)) { |
|
331 | 331 | global $wpdb; |
332 | 332 | $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)"; |
333 | 333 | $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)"; |
@@ -356,13 +356,13 @@ discard block |
||
356 | 356 | case 'ticket_end': |
357 | 357 | $SQL .= EEH_Event_Query::_posts_join_for_datetime( |
358 | 358 | $SQL, |
359 | - EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name() |
|
359 | + EEM_Datetime_Ticket::instance()->table().'.'.EEM_Datetime::instance()->primary_key_name() |
|
360 | 360 | ); |
361 | - $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table(); |
|
361 | + $SQL .= ' LEFT JOIN '.EEM_Ticket::instance()->table(); |
|
362 | 362 | $SQL .= ' ON ('; |
363 | - $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
363 | + $SQL .= EEM_Datetime_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name(); |
|
364 | 364 | $SQL .= ' = '; |
365 | - $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
365 | + $SQL .= EEM_Ticket::instance()->table().'.'.EEM_Ticket::instance()->primary_key_name(); |
|
366 | 366 | $SQL .= ' )'; |
367 | 367 | break; |
368 | 368 | case 'venue_title': |
@@ -375,7 +375,7 @@ discard block |
||
375 | 375 | break; |
376 | 376 | case 'start_date': |
377 | 377 | default: |
378 | - $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID'); |
|
378 | + $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table().'.ID'); |
|
379 | 379 | break; |
380 | 380 | } |
381 | 381 | } |
@@ -394,10 +394,10 @@ discard block |
||
394 | 394 | */ |
395 | 395 | protected static function _posts_join_for_datetime($SQL = '', $join = '') |
396 | 396 | { |
397 | - if (! empty($join)) { |
|
398 | - $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
397 | + if ( ! empty($join)) { |
|
398 | + $join .= ' = '.EEM_Datetime::instance()->table().'.'.EEM_Event::instance()->primary_key_name(); |
|
399 | 399 | if (strpos($SQL, $join) === false) { |
400 | - return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )'; |
|
400 | + return ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.$join.' )'; |
|
401 | 401 | } |
402 | 402 | } |
403 | 403 | return ''; |
@@ -417,8 +417,8 @@ discard block |
||
417 | 417 | // Event Venue table name |
418 | 418 | $event_venue_table = EEM_Event_Venue::instance()->table(); |
419 | 419 | // generate conditions for: Event <=> Event Venue JOIN clause |
420 | - $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = '; |
|
421 | - $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name(); |
|
420 | + $event_to_event_venue_join = EEM_Event::instance()->table().'.ID = '; |
|
421 | + $event_to_event_venue_join .= $event_venue_table.'.'.EEM_Event::instance()->primary_key_name(); |
|
422 | 422 | // don't add joins if they have already been added |
423 | 423 | if (strpos($SQL, $event_to_event_venue_join) === false) { |
424 | 424 | // Venue table name |
@@ -506,7 +506,7 @@ discard block |
||
506 | 506 | public static function posts_where_sql_for_show_expired($show_expired = false) |
507 | 507 | { |
508 | 508 | return ! $show_expired |
509 | - ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' ' |
|
509 | + ? ' AND '.EEM_Datetime::instance()->table().'.DTT_EVT_end > \''.current_time('mysql', true).'\' ' |
|
510 | 510 | : ''; |
511 | 511 | } |
512 | 512 | |
@@ -518,7 +518,7 @@ discard block |
||
518 | 518 | public static function posts_where_sql_for_event_category_slug($event_category_slug = null) |
519 | 519 | { |
520 | 520 | global $wpdb; |
521 | - if (! empty($event_category_slug)) { |
|
521 | + if ( ! empty($event_category_slug)) { |
|
522 | 522 | $event_category_slugs_array = array_map('trim', explode(',', $event_category_slug)); |
523 | 523 | $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s')); |
524 | 524 | return $wpdb->prepare( |
@@ -541,14 +541,14 @@ discard block |
||
541 | 541 | public static function posts_where_sql_for_event_list_month($month = null) |
542 | 542 | { |
543 | 543 | $SQL = ''; |
544 | - if (! empty($month)) { |
|
544 | + if ( ! empty($month)) { |
|
545 | 545 | $datetime_table = EEM_Datetime::instance()->table(); |
546 | 546 | // event start date is LESS than the end of the month ( so nothing that doesn't start until next month ) |
547 | 547 | $SQL = " AND {$datetime_table}.DTT_EVT_start <= '"; |
548 | - $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'"; |
|
548 | + $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month))."'"; |
|
549 | 549 | // event end date is GREATER than the start of the month ( so nothing that ended before this month ) |
550 | 550 | $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '"; |
551 | - $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' "; |
|
551 | + $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month))."' "; |
|
552 | 552 | } |
553 | 553 | return $SQL; |
554 | 554 | } |
@@ -609,15 +609,15 @@ discard block |
||
609 | 609 | ? strtoupper($sort) |
610 | 610 | : 'ASC'; |
611 | 611 | // make sure 'orderby' is set in query params |
612 | - if (! isset(self::$_query_params['orderby'])) { |
|
612 | + if ( ! isset(self::$_query_params['orderby'])) { |
|
613 | 613 | self::$_query_params['orderby'] = []; |
614 | 614 | } |
615 | 615 | // loop thru $orderby_params (type cast as array) |
616 | 616 | foreach ($orderby_params as $orderby) { |
617 | 617 | // check if we have already added this param |
618 | - if (isset(self::$_query_params['orderby'][ $orderby ])) { |
|
618 | + if (isset(self::$_query_params['orderby'][$orderby])) { |
|
619 | 619 | // if so then remove from the $orderby_params so that the count() method below is accurate |
620 | - unset($orderby_params[ $orderby ]); |
|
620 | + unset($orderby_params[$orderby]); |
|
621 | 621 | // then bump ahead to the next param |
622 | 622 | continue; |
623 | 623 | } |
@@ -627,39 +627,39 @@ discard block |
||
627 | 627 | switch ($orderby) { |
628 | 628 | case 'id': |
629 | 629 | case 'ID': |
630 | - $SQL .= $glue . $wpdb->posts . '.ID ' . $sort; |
|
630 | + $SQL .= $glue.$wpdb->posts.'.ID '.$sort; |
|
631 | 631 | break; |
632 | 632 | case 'end_date': |
633 | - $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort; |
|
633 | + $SQL .= $glue.EEM_Datetime::instance()->table().'.DTT_EVT_end '.$sort; |
|
634 | 634 | break; |
635 | 635 | case 'event_name': |
636 | - $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort; |
|
636 | + $SQL .= $glue.$wpdb->posts.'.post_title '.$sort; |
|
637 | 637 | break; |
638 | 638 | case 'category_slug': |
639 | - $SQL .= $glue . $wpdb->terms . '.slug ' . $sort; |
|
639 | + $SQL .= $glue.$wpdb->terms.'.slug '.$sort; |
|
640 | 640 | break; |
641 | 641 | case 'ticket_start': |
642 | - $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort; |
|
642 | + $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_start_date '.$sort; |
|
643 | 643 | break; |
644 | 644 | case 'ticket_end': |
645 | - $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort; |
|
645 | + $SQL .= $glue.EEM_Ticket::instance()->table().'.TKT_end_date '.$sort; |
|
646 | 646 | break; |
647 | 647 | case 'venue_title': |
648 | - $SQL .= $glue . 'venue_title ' . $sort; |
|
648 | + $SQL .= $glue.'venue_title '.$sort; |
|
649 | 649 | break; |
650 | 650 | case 'city': |
651 | - $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort; |
|
651 | + $SQL .= $glue.EEM_Venue::instance()->second_table().'.VNU_city '.$sort; |
|
652 | 652 | break; |
653 | 653 | case 'state': |
654 | - $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort; |
|
654 | + $SQL .= $glue.EEM_State::instance()->table().'.STA_name '.$sort; |
|
655 | 655 | break; |
656 | 656 | case 'start_date': |
657 | 657 | default: |
658 | - $SQL .= $glue . ' event_start_date ' . $sort; |
|
658 | + $SQL .= $glue.' event_start_date '.$sort; |
|
659 | 659 | break; |
660 | 660 | } |
661 | 661 | // add to array of orderby params that have been added |
662 | - self::$_query_params['orderby'][ $orderby ] = true; |
|
662 | + self::$_query_params['orderby'][$orderby] = true; |
|
663 | 663 | $counter++; |
664 | 664 | } |
665 | 665 | return $SQL; |
@@ -17,666 +17,666 @@ |
||
17 | 17 | */ |
18 | 18 | class EEH_Event_Query |
19 | 19 | { |
20 | - /** |
|
21 | - * Start Date |
|
22 | - * |
|
23 | - * @var $_event_query_month |
|
24 | - */ |
|
25 | - protected static $_event_query_month; |
|
26 | - |
|
27 | - /** |
|
28 | - * Category |
|
29 | - * |
|
30 | - * @var $_event_query_category |
|
31 | - */ |
|
32 | - protected static $_event_query_category; |
|
33 | - |
|
34 | - /** |
|
35 | - * whether to display expired events in the event list |
|
36 | - * |
|
37 | - * @var bool $_show_expired |
|
38 | - */ |
|
39 | - protected static $_event_query_show_expired = false; |
|
40 | - |
|
41 | - /** |
|
42 | - * list of params for controlling how the query results are ordered |
|
43 | - * |
|
44 | - * @var array $_event_query_orderby |
|
45 | - */ |
|
46 | - protected static $_event_query_orderby = []; |
|
47 | - |
|
48 | - /** |
|
49 | - * direction list is sorted |
|
50 | - * |
|
51 | - * @var string $_event_query_sort |
|
52 | - */ |
|
53 | - protected static $_event_query_sort; |
|
54 | - |
|
55 | - /** |
|
56 | - * list of params used to build the query's various clauses |
|
57 | - * |
|
58 | - * @var $_query_params |
|
59 | - */ |
|
60 | - protected static $_query_params = []; |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * @return void |
|
65 | - */ |
|
66 | - public static function add_query_filters() |
|
67 | - { |
|
68 | - // add query filters |
|
69 | - add_action('pre_get_posts', ['EEH_Event_Query', 'filter_query_parts'], 10, 1); |
|
70 | - } |
|
71 | - |
|
72 | - |
|
73 | - /** |
|
74 | - * @param WP_Query $WP_Query |
|
75 | - * @return bool |
|
76 | - */ |
|
77 | - public static function apply_query_filters(WP_Query $WP_Query) |
|
78 | - { |
|
79 | - return ( |
|
80 | - isset($WP_Query->query['post_type']) |
|
81 | - && $WP_Query->query['post_type'] === 'espresso_events' |
|
82 | - ) |
|
83 | - || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false); |
|
84 | - } |
|
85 | - |
|
86 | - |
|
87 | - /** |
|
88 | - * @param WP_Query $WP_Query |
|
89 | - */ |
|
90 | - public static function filter_query_parts(WP_Query $WP_Query) |
|
91 | - { |
|
92 | - // ONLY add our filters if this isn't the main wp_query, |
|
93 | - // because if this is the main wp_query we already have |
|
94 | - // our cpt strategies take care of adding things in. |
|
95 | - if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) { |
|
96 | - // build event list query |
|
97 | - add_filter('posts_fields', ['EEH_Event_Query', 'posts_fields'], 10, 2); |
|
98 | - add_filter('posts_join', ['EEH_Event_Query', 'posts_join'], 10, 2); |
|
99 | - add_filter('posts_where', ['EEH_Event_Query', 'posts_where'], 10, 2); |
|
100 | - add_filter('posts_orderby', ['EEH_Event_Query', 'posts_orderby'], 10, 2); |
|
101 | - add_filter('posts_clauses_request', ['EEH_Event_Query', 'posts_clauses'], 10, 2); |
|
102 | - } |
|
103 | - } |
|
104 | - |
|
105 | - |
|
106 | - /** |
|
107 | - * @param string $month |
|
108 | - * @param string $category |
|
109 | - * @param bool $show_expired |
|
110 | - * @param array|string $orderby |
|
111 | - * @param string $sort |
|
112 | - * @throws InvalidArgumentException |
|
113 | - * @throws InvalidDataTypeException |
|
114 | - * @throws InvalidInterfaceException |
|
115 | - */ |
|
116 | - public static function set_query_params( |
|
117 | - $month = '', |
|
118 | - $category = '', |
|
119 | - $show_expired = false, |
|
120 | - $orderby = 'start_date', |
|
121 | - $sort = 'ASC' |
|
122 | - ) { |
|
123 | - self::$_query_params = []; |
|
124 | - EEH_Event_Query::$_event_query_month = EEH_Event_Query::_display_month($month); |
|
125 | - EEH_Event_Query::$_event_query_category = EEH_Event_Query::_event_category_slug($category); |
|
126 | - EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired); |
|
127 | - EEH_Event_Query::$_event_query_orderby = EEH_Event_Query::_orderby($orderby); |
|
128 | - EEH_Event_Query::$_event_query_sort = EEH_Event_Query::_sort($sort); |
|
129 | - } |
|
130 | - |
|
131 | - |
|
132 | - /** |
|
133 | - * what month should the event list display events for? |
|
134 | - * |
|
135 | - * @param string $month |
|
136 | - * @return string |
|
137 | - * @throws InvalidArgumentException |
|
138 | - * @throws InvalidDataTypeException |
|
139 | - * @throws InvalidInterfaceException |
|
140 | - */ |
|
141 | - private static function _display_month($month = '') |
|
142 | - { |
|
143 | - return self::getRequest()->getRequestParam('event_query_month', $month); |
|
144 | - } |
|
145 | - |
|
146 | - |
|
147 | - /** |
|
148 | - * @param string $category |
|
149 | - * @return string |
|
150 | - * @throws InvalidArgumentException |
|
151 | - * @throws InvalidDataTypeException |
|
152 | - * @throws InvalidInterfaceException |
|
153 | - */ |
|
154 | - private static function _event_category_slug($category = '') |
|
155 | - { |
|
156 | - return self::getRequest()->getRequestParam('event_query_category', $category); |
|
157 | - } |
|
158 | - |
|
159 | - |
|
160 | - /** |
|
161 | - * @param bool $show_expired |
|
162 | - * @return bool |
|
163 | - * @throws InvalidArgumentException |
|
164 | - * @throws InvalidDataTypeException |
|
165 | - * @throws InvalidInterfaceException |
|
166 | - */ |
|
167 | - private static function _show_expired($show_expired = false) |
|
168 | - { |
|
169 | - // override default expired option if set via filter |
|
170 | - return self::getRequest()->getRequestParam('event_query_show_expired', $show_expired, 'bool'); |
|
171 | - } |
|
172 | - |
|
173 | - |
|
174 | - /** |
|
175 | - * @param array|string $orderby |
|
176 | - * @return array |
|
177 | - * @throws InvalidArgumentException |
|
178 | - * @throws InvalidDataTypeException |
|
179 | - * @throws InvalidInterfaceException |
|
180 | - */ |
|
181 | - private static function _orderby($orderby = 'start_date') |
|
182 | - { |
|
183 | - $event_query_orderby = self::getRequest()->getRequestParam( |
|
184 | - 'event_query_orderby', |
|
185 | - (array) $orderby, |
|
186 | - DataType::STRING, |
|
187 | - true |
|
188 | - ); |
|
189 | - $event_query_orderby = is_array($event_query_orderby) |
|
190 | - ? $event_query_orderby |
|
191 | - : explode(',', $event_query_orderby); |
|
192 | - $event_query_orderby = array_map('trim', $event_query_orderby); |
|
193 | - return array_map('sanitize_text_field', $event_query_orderby); |
|
194 | - } |
|
195 | - |
|
196 | - |
|
197 | - /** |
|
198 | - * @param string $sort |
|
199 | - * @return string |
|
200 | - * @throws InvalidArgumentException |
|
201 | - * @throws InvalidDataTypeException |
|
202 | - * @throws InvalidInterfaceException |
|
203 | - */ |
|
204 | - private static function _sort($sort = 'ASC') |
|
205 | - { |
|
206 | - $sort = self::getRequest()->getRequestParam('event_query_sort', $sort); |
|
207 | - return in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true) |
|
208 | - ? strtoupper($sort) |
|
209 | - : 'ASC'; |
|
210 | - } |
|
211 | - |
|
212 | - |
|
213 | - /** |
|
214 | - * Filters the clauses for the WP_Query object |
|
215 | - * |
|
216 | - * @param array $clauses array of clauses |
|
217 | - * @param WP_Query $wp_query |
|
218 | - * @return array array of clauses |
|
219 | - */ |
|
220 | - public static function posts_clauses($clauses, WP_Query $wp_query) |
|
221 | - { |
|
222 | - if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
223 | - global $wpdb; |
|
224 | - $clauses['groupby'] = $wpdb->posts . '.ID '; |
|
225 | - } |
|
226 | - return $clauses; |
|
227 | - } |
|
228 | - |
|
229 | - |
|
230 | - /** |
|
231 | - * @param string $SQL |
|
232 | - * @param WP_Query $wp_query |
|
233 | - * @return string |
|
234 | - * @throws EE_Error |
|
235 | - * @throws InvalidArgumentException |
|
236 | - * @throws InvalidDataTypeException |
|
237 | - * @throws InvalidInterfaceException |
|
238 | - */ |
|
239 | - public static function posts_fields($SQL, WP_Query $wp_query) |
|
240 | - { |
|
241 | - if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
242 | - // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
243 | - $SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby); |
|
244 | - } |
|
245 | - return $SQL; |
|
246 | - } |
|
247 | - |
|
248 | - |
|
249 | - /** |
|
250 | - * @param array $orderby_params |
|
251 | - * @return string |
|
252 | - * @throws EE_Error |
|
253 | - * @throws InvalidArgumentException |
|
254 | - * @throws InvalidDataTypeException |
|
255 | - * @throws InvalidInterfaceException |
|
256 | - */ |
|
257 | - public static function posts_fields_sql_for_orderby(array $orderby_params = []) |
|
258 | - { |
|
259 | - $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
260 | - foreach ($orderby_params as $orderby) { |
|
261 | - switch ($orderby) { |
|
262 | - case 'ticket_start': |
|
263 | - $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date'; |
|
264 | - break; |
|
265 | - case 'ticket_end': |
|
266 | - $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date'; |
|
267 | - break; |
|
268 | - case 'venue_title': |
|
269 | - $SQL .= ', Venue.post_title AS venue_title'; |
|
270 | - break; |
|
271 | - case 'city': |
|
272 | - $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city'; |
|
273 | - break; |
|
274 | - case 'state': |
|
275 | - $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name'; |
|
276 | - break; |
|
277 | - } |
|
278 | - } |
|
279 | - return $SQL; |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - /** |
|
284 | - * @param string $SQL |
|
285 | - * @param WP_Query $wp_query |
|
286 | - * @return string |
|
287 | - * @throws EE_Error |
|
288 | - * @throws InvalidArgumentException |
|
289 | - * @throws InvalidDataTypeException |
|
290 | - * @throws InvalidInterfaceException |
|
291 | - */ |
|
292 | - public static function posts_join($SQL, WP_Query $wp_query) |
|
293 | - { |
|
294 | - if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
295 | - // Category |
|
296 | - $SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired); |
|
297 | - $SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category); |
|
298 | - $SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby); |
|
299 | - } |
|
300 | - return $SQL; |
|
301 | - } |
|
302 | - |
|
303 | - |
|
304 | - /** |
|
305 | - * @param string $SQL |
|
306 | - * @param boolean $show_expired if TRUE, then displayed past events |
|
307 | - * @return string |
|
308 | - * @throws EE_Error |
|
309 | - * @throws InvalidArgumentException |
|
310 | - * @throws InvalidDataTypeException |
|
311 | - * @throws InvalidInterfaceException |
|
312 | - */ |
|
313 | - public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false) |
|
314 | - { |
|
315 | - if (! $show_expired) { |
|
316 | - $join = EEM_Event::instance()->table() . '.ID = '; |
|
317 | - $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
318 | - // don't add if this is already in the SQL |
|
319 | - if (strpos($SQL, $join) === false) { |
|
320 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) '; |
|
321 | - } |
|
322 | - } |
|
323 | - return $SQL; |
|
324 | - } |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * @param string $SQL |
|
329 | - * @param string $join_terms pass TRUE or term string, doesn't really matter since this value doesn't really get |
|
330 | - * used for anything yet |
|
331 | - * @return string |
|
332 | - */ |
|
333 | - public static function posts_join_sql_for_terms($SQL = '', $join_terms = '') |
|
334 | - { |
|
335 | - if (! empty($join_terms)) { |
|
336 | - global $wpdb; |
|
337 | - $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)"; |
|
338 | - $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)"; |
|
339 | - $SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) "; |
|
340 | - } |
|
341 | - return $SQL; |
|
342 | - } |
|
343 | - |
|
344 | - |
|
345 | - /** |
|
346 | - * usage: $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params ); |
|
347 | - * |
|
348 | - * @param string $SQL |
|
349 | - * @param array $orderby_params |
|
350 | - * @return string |
|
351 | - * @throws EE_Error |
|
352 | - * @throws InvalidArgumentException |
|
353 | - * @throws InvalidDataTypeException |
|
354 | - * @throws InvalidInterfaceException |
|
355 | - */ |
|
356 | - public static function posts_join_for_orderby($SQL = '', array $orderby_params = []) |
|
357 | - { |
|
358 | - foreach ($orderby_params as $orderby) { |
|
359 | - switch ($orderby) { |
|
360 | - case 'ticket_start': |
|
361 | - case 'ticket_end': |
|
362 | - $SQL .= EEH_Event_Query::_posts_join_for_datetime( |
|
363 | - $SQL, |
|
364 | - EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name() |
|
365 | - ); |
|
366 | - $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table(); |
|
367 | - $SQL .= ' ON ('; |
|
368 | - $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
369 | - $SQL .= ' = '; |
|
370 | - $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
371 | - $SQL .= ' )'; |
|
372 | - break; |
|
373 | - case 'venue_title': |
|
374 | - case 'city': |
|
375 | - $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL); |
|
376 | - break; |
|
377 | - case 'state': |
|
378 | - $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL); |
|
379 | - $SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL); |
|
380 | - break; |
|
381 | - case 'start_date': |
|
382 | - default: |
|
383 | - $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID'); |
|
384 | - break; |
|
385 | - } |
|
386 | - } |
|
387 | - return $SQL; |
|
388 | - } |
|
389 | - |
|
390 | - |
|
391 | - /** |
|
392 | - * @param string $SQL |
|
393 | - * @param string $join |
|
394 | - * @return string |
|
395 | - * @throws EE_Error |
|
396 | - * @throws InvalidArgumentException |
|
397 | - * @throws InvalidDataTypeException |
|
398 | - * @throws InvalidInterfaceException |
|
399 | - */ |
|
400 | - protected static function _posts_join_for_datetime($SQL = '', $join = '') |
|
401 | - { |
|
402 | - if (! empty($join)) { |
|
403 | - $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
404 | - if (strpos($SQL, $join) === false) { |
|
405 | - return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )'; |
|
406 | - } |
|
407 | - } |
|
408 | - return ''; |
|
409 | - } |
|
410 | - |
|
411 | - |
|
412 | - /** |
|
413 | - * @param string $SQL |
|
414 | - * @return string |
|
415 | - * @throws EE_Error |
|
416 | - * @throws InvalidArgumentException |
|
417 | - * @throws InvalidDataTypeException |
|
418 | - * @throws InvalidInterfaceException |
|
419 | - */ |
|
420 | - protected static function _posts_join_for_event_venue($SQL = '') |
|
421 | - { |
|
422 | - // Event Venue table name |
|
423 | - $event_venue_table = EEM_Event_Venue::instance()->table(); |
|
424 | - // generate conditions for: Event <=> Event Venue JOIN clause |
|
425 | - $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = '; |
|
426 | - $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name(); |
|
427 | - // don't add joins if they have already been added |
|
428 | - if (strpos($SQL, $event_to_event_venue_join) === false) { |
|
429 | - // Venue table name |
|
430 | - $venue_table = EEM_Venue::instance()->table(); |
|
431 | - // Venue table pk |
|
432 | - $venue_table_pk = EEM_Venue::instance()->primary_key_name(); |
|
433 | - // Venue Meta table name |
|
434 | - $venue_meta_table = EEM_Venue::instance()->second_table(); |
|
435 | - // generate JOIN clause for: Event <=> Event Venue |
|
436 | - $venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )"; |
|
437 | - // generate JOIN clause for: Event Venue <=> Venue |
|
438 | - $venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )"; |
|
439 | - // generate JOIN clause for: Venue <=> Venue Meta |
|
440 | - $venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )"; |
|
441 | - unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table); |
|
442 | - return $venue_SQL; |
|
443 | - } |
|
444 | - unset($event_venue_table, $event_to_event_venue_join); |
|
445 | - return ''; |
|
446 | - } |
|
447 | - |
|
448 | - |
|
449 | - /** |
|
450 | - * @param string $SQL |
|
451 | - * @return string |
|
452 | - * @throws EE_Error |
|
453 | - * @throws InvalidArgumentException |
|
454 | - * @throws InvalidDataTypeException |
|
455 | - * @throws InvalidInterfaceException |
|
456 | - */ |
|
457 | - protected static function _posts_join_for_venue_state($SQL = '') |
|
458 | - { |
|
459 | - // Venue Meta table name |
|
460 | - $venue_meta_table = EEM_Venue::instance()->second_table(); |
|
461 | - // State table name |
|
462 | - $state_table = EEM_State::instance()->table(); |
|
463 | - // State table pk |
|
464 | - $state_table_pk = EEM_State::instance()->primary_key_name(); |
|
465 | - // verify vars |
|
466 | - if ($venue_meta_table && $state_table && $state_table_pk) { |
|
467 | - // like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID |
|
468 | - $join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk"; |
|
469 | - // don't add join if it has already been added |
|
470 | - if (strpos($SQL, $join) === false) { |
|
471 | - unset($state_table_pk, $venue_meta_table, $venue_table_pk); |
|
472 | - return " LEFT JOIN $state_table ON ( $join )"; |
|
473 | - } |
|
474 | - } |
|
475 | - unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk); |
|
476 | - return ''; |
|
477 | - } |
|
478 | - |
|
479 | - |
|
480 | - /** |
|
481 | - * @param string $SQL |
|
482 | - * @param WP_Query $wp_query |
|
483 | - * @return string |
|
484 | - * @throws EE_Error |
|
485 | - * @throws InvalidArgumentException |
|
486 | - * @throws InvalidDataTypeException |
|
487 | - * @throws InvalidInterfaceException |
|
488 | - */ |
|
489 | - public static function posts_where($SQL, WP_Query $wp_query) |
|
490 | - { |
|
491 | - if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
492 | - // Show Expired ? |
|
493 | - $SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired); |
|
494 | - // Category |
|
495 | - $SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category); |
|
496 | - // Start Date |
|
497 | - $SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month); |
|
498 | - } |
|
499 | - return $SQL; |
|
500 | - } |
|
501 | - |
|
502 | - |
|
503 | - /** |
|
504 | - * @param boolean $show_expired if TRUE, then displayed past events |
|
505 | - * @return string |
|
506 | - * @throws EE_Error |
|
507 | - * @throws InvalidArgumentException |
|
508 | - * @throws InvalidDataTypeException |
|
509 | - * @throws InvalidInterfaceException |
|
510 | - */ |
|
511 | - public static function posts_where_sql_for_show_expired($show_expired = false) |
|
512 | - { |
|
513 | - return ! $show_expired |
|
514 | - ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' ' |
|
515 | - : ''; |
|
516 | - } |
|
517 | - |
|
518 | - |
|
519 | - /** |
|
520 | - * @param boolean $event_category_slug |
|
521 | - * @return string |
|
522 | - */ |
|
523 | - public static function posts_where_sql_for_event_category_slug($event_category_slug = null) |
|
524 | - { |
|
525 | - global $wpdb; |
|
526 | - if (! empty($event_category_slug)) { |
|
527 | - $event_category_slugs_array = array_map('trim', explode(',', $event_category_slug)); |
|
528 | - $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s')); |
|
529 | - return $wpdb->prepare( |
|
530 | - " AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ", |
|
531 | - $event_category_slugs_array |
|
532 | - ); |
|
533 | - } |
|
534 | - return ''; |
|
535 | - } |
|
536 | - |
|
537 | - |
|
538 | - /** |
|
539 | - * @param boolean $month |
|
540 | - * @return string |
|
541 | - * @throws EE_Error |
|
542 | - * @throws InvalidArgumentException |
|
543 | - * @throws InvalidDataTypeException |
|
544 | - * @throws InvalidInterfaceException |
|
545 | - */ |
|
546 | - public static function posts_where_sql_for_event_list_month($month = null) |
|
547 | - { |
|
548 | - $SQL = ''; |
|
549 | - if (! empty($month)) { |
|
550 | - $datetime_table = EEM_Datetime::instance()->table(); |
|
551 | - // event start date is LESS than the end of the month ( so nothing that doesn't start until next month ) |
|
552 | - $SQL = " AND {$datetime_table}.DTT_EVT_start <= '"; |
|
553 | - $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'"; |
|
554 | - // event end date is GREATER than the start of the month ( so nothing that ended before this month ) |
|
555 | - $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '"; |
|
556 | - $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' "; |
|
557 | - } |
|
558 | - return $SQL; |
|
559 | - } |
|
560 | - |
|
561 | - |
|
562 | - /** |
|
563 | - * @param string $SQL |
|
564 | - * @param WP_Query $wp_query |
|
565 | - * @return string |
|
566 | - * @throws EE_Error |
|
567 | - * @throws InvalidArgumentException |
|
568 | - * @throws InvalidDataTypeException |
|
569 | - * @throws InvalidInterfaceException |
|
570 | - */ |
|
571 | - public static function posts_orderby($SQL, WP_Query $wp_query) |
|
572 | - { |
|
573 | - if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
574 | - $SQL = EEH_Event_Query::posts_orderby_sql( |
|
575 | - EEH_Event_Query::$_event_query_orderby, |
|
576 | - EEH_Event_Query::$_event_query_sort |
|
577 | - ); |
|
578 | - } |
|
579 | - return $SQL; |
|
580 | - } |
|
581 | - |
|
582 | - |
|
583 | - /** |
|
584 | - * posts_orderby_sql |
|
585 | - * possible parameters: |
|
586 | - * ID |
|
587 | - * start_date |
|
588 | - * end_date |
|
589 | - * event_name |
|
590 | - * category_slug |
|
591 | - * ticket_start |
|
592 | - * ticket_end |
|
593 | - * venue_title |
|
594 | - * city |
|
595 | - * state |
|
596 | - * **IMPORTANT** |
|
597 | - * make sure to also send the $orderby_params array to the posts_join_for_orderby() method |
|
598 | - * or else some of the table references below will result in MySQL errors |
|
599 | - * |
|
600 | - * @param array $orderby_params |
|
601 | - * @param string $sort |
|
602 | - * @return string |
|
603 | - * @throws EE_Error |
|
604 | - * @throws InvalidArgumentException |
|
605 | - * @throws InvalidDataTypeException |
|
606 | - * @throws InvalidInterfaceException |
|
607 | - */ |
|
608 | - public static function posts_orderby_sql(array $orderby_params = [], $sort = 'ASC') |
|
609 | - { |
|
610 | - global $wpdb; |
|
611 | - $SQL = ''; |
|
612 | - $counter = 0; |
|
613 | - $sort = in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true) |
|
614 | - ? strtoupper($sort) |
|
615 | - : 'ASC'; |
|
616 | - // make sure 'orderby' is set in query params |
|
617 | - if (! isset(self::$_query_params['orderby'])) { |
|
618 | - self::$_query_params['orderby'] = []; |
|
619 | - } |
|
620 | - // loop thru $orderby_params (type cast as array) |
|
621 | - foreach ($orderby_params as $orderby) { |
|
622 | - // check if we have already added this param |
|
623 | - if (isset(self::$_query_params['orderby'][ $orderby ])) { |
|
624 | - // if so then remove from the $orderby_params so that the count() method below is accurate |
|
625 | - unset($orderby_params[ $orderby ]); |
|
626 | - // then bump ahead to the next param |
|
627 | - continue; |
|
628 | - } |
|
629 | - // this will ad a comma depending on whether this is the first or last param |
|
630 | - $glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', '; |
|
631 | - // ok what's we dealing with? |
|
632 | - switch ($orderby) { |
|
633 | - case 'id': |
|
634 | - case 'ID': |
|
635 | - $SQL .= $glue . $wpdb->posts . '.ID ' . $sort; |
|
636 | - break; |
|
637 | - case 'end_date': |
|
638 | - $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort; |
|
639 | - break; |
|
640 | - case 'event_name': |
|
641 | - $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort; |
|
642 | - break; |
|
643 | - case 'category_slug': |
|
644 | - $SQL .= $glue . $wpdb->terms . '.slug ' . $sort; |
|
645 | - break; |
|
646 | - case 'ticket_start': |
|
647 | - $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort; |
|
648 | - break; |
|
649 | - case 'ticket_end': |
|
650 | - $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort; |
|
651 | - break; |
|
652 | - case 'venue_title': |
|
653 | - $SQL .= $glue . 'venue_title ' . $sort; |
|
654 | - break; |
|
655 | - case 'city': |
|
656 | - $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort; |
|
657 | - break; |
|
658 | - case 'state': |
|
659 | - $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort; |
|
660 | - break; |
|
661 | - case 'start_date': |
|
662 | - default: |
|
663 | - $SQL .= $glue . ' event_start_date ' . $sort; |
|
664 | - break; |
|
665 | - } |
|
666 | - // add to array of orderby params that have been added |
|
667 | - self::$_query_params['orderby'][ $orderby ] = true; |
|
668 | - $counter++; |
|
669 | - } |
|
670 | - return $SQL; |
|
671 | - } |
|
672 | - |
|
673 | - |
|
674 | - /** |
|
675 | - * @return RequestInterface |
|
676 | - * @since 4.10.14.p |
|
677 | - */ |
|
678 | - private static function getRequest() |
|
679 | - { |
|
680 | - return LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
681 | - } |
|
20 | + /** |
|
21 | + * Start Date |
|
22 | + * |
|
23 | + * @var $_event_query_month |
|
24 | + */ |
|
25 | + protected static $_event_query_month; |
|
26 | + |
|
27 | + /** |
|
28 | + * Category |
|
29 | + * |
|
30 | + * @var $_event_query_category |
|
31 | + */ |
|
32 | + protected static $_event_query_category; |
|
33 | + |
|
34 | + /** |
|
35 | + * whether to display expired events in the event list |
|
36 | + * |
|
37 | + * @var bool $_show_expired |
|
38 | + */ |
|
39 | + protected static $_event_query_show_expired = false; |
|
40 | + |
|
41 | + /** |
|
42 | + * list of params for controlling how the query results are ordered |
|
43 | + * |
|
44 | + * @var array $_event_query_orderby |
|
45 | + */ |
|
46 | + protected static $_event_query_orderby = []; |
|
47 | + |
|
48 | + /** |
|
49 | + * direction list is sorted |
|
50 | + * |
|
51 | + * @var string $_event_query_sort |
|
52 | + */ |
|
53 | + protected static $_event_query_sort; |
|
54 | + |
|
55 | + /** |
|
56 | + * list of params used to build the query's various clauses |
|
57 | + * |
|
58 | + * @var $_query_params |
|
59 | + */ |
|
60 | + protected static $_query_params = []; |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * @return void |
|
65 | + */ |
|
66 | + public static function add_query_filters() |
|
67 | + { |
|
68 | + // add query filters |
|
69 | + add_action('pre_get_posts', ['EEH_Event_Query', 'filter_query_parts'], 10, 1); |
|
70 | + } |
|
71 | + |
|
72 | + |
|
73 | + /** |
|
74 | + * @param WP_Query $WP_Query |
|
75 | + * @return bool |
|
76 | + */ |
|
77 | + public static function apply_query_filters(WP_Query $WP_Query) |
|
78 | + { |
|
79 | + return ( |
|
80 | + isset($WP_Query->query['post_type']) |
|
81 | + && $WP_Query->query['post_type'] === 'espresso_events' |
|
82 | + ) |
|
83 | + || apply_filters('FHEE__EEH_Event_Query__apply_query_filters', false); |
|
84 | + } |
|
85 | + |
|
86 | + |
|
87 | + /** |
|
88 | + * @param WP_Query $WP_Query |
|
89 | + */ |
|
90 | + public static function filter_query_parts(WP_Query $WP_Query) |
|
91 | + { |
|
92 | + // ONLY add our filters if this isn't the main wp_query, |
|
93 | + // because if this is the main wp_query we already have |
|
94 | + // our cpt strategies take care of adding things in. |
|
95 | + if ($WP_Query instanceof WP_Query && ! $WP_Query->is_main_query()) { |
|
96 | + // build event list query |
|
97 | + add_filter('posts_fields', ['EEH_Event_Query', 'posts_fields'], 10, 2); |
|
98 | + add_filter('posts_join', ['EEH_Event_Query', 'posts_join'], 10, 2); |
|
99 | + add_filter('posts_where', ['EEH_Event_Query', 'posts_where'], 10, 2); |
|
100 | + add_filter('posts_orderby', ['EEH_Event_Query', 'posts_orderby'], 10, 2); |
|
101 | + add_filter('posts_clauses_request', ['EEH_Event_Query', 'posts_clauses'], 10, 2); |
|
102 | + } |
|
103 | + } |
|
104 | + |
|
105 | + |
|
106 | + /** |
|
107 | + * @param string $month |
|
108 | + * @param string $category |
|
109 | + * @param bool $show_expired |
|
110 | + * @param array|string $orderby |
|
111 | + * @param string $sort |
|
112 | + * @throws InvalidArgumentException |
|
113 | + * @throws InvalidDataTypeException |
|
114 | + * @throws InvalidInterfaceException |
|
115 | + */ |
|
116 | + public static function set_query_params( |
|
117 | + $month = '', |
|
118 | + $category = '', |
|
119 | + $show_expired = false, |
|
120 | + $orderby = 'start_date', |
|
121 | + $sort = 'ASC' |
|
122 | + ) { |
|
123 | + self::$_query_params = []; |
|
124 | + EEH_Event_Query::$_event_query_month = EEH_Event_Query::_display_month($month); |
|
125 | + EEH_Event_Query::$_event_query_category = EEH_Event_Query::_event_category_slug($category); |
|
126 | + EEH_Event_Query::$_event_query_show_expired = EEH_Event_Query::_show_expired($show_expired); |
|
127 | + EEH_Event_Query::$_event_query_orderby = EEH_Event_Query::_orderby($orderby); |
|
128 | + EEH_Event_Query::$_event_query_sort = EEH_Event_Query::_sort($sort); |
|
129 | + } |
|
130 | + |
|
131 | + |
|
132 | + /** |
|
133 | + * what month should the event list display events for? |
|
134 | + * |
|
135 | + * @param string $month |
|
136 | + * @return string |
|
137 | + * @throws InvalidArgumentException |
|
138 | + * @throws InvalidDataTypeException |
|
139 | + * @throws InvalidInterfaceException |
|
140 | + */ |
|
141 | + private static function _display_month($month = '') |
|
142 | + { |
|
143 | + return self::getRequest()->getRequestParam('event_query_month', $month); |
|
144 | + } |
|
145 | + |
|
146 | + |
|
147 | + /** |
|
148 | + * @param string $category |
|
149 | + * @return string |
|
150 | + * @throws InvalidArgumentException |
|
151 | + * @throws InvalidDataTypeException |
|
152 | + * @throws InvalidInterfaceException |
|
153 | + */ |
|
154 | + private static function _event_category_slug($category = '') |
|
155 | + { |
|
156 | + return self::getRequest()->getRequestParam('event_query_category', $category); |
|
157 | + } |
|
158 | + |
|
159 | + |
|
160 | + /** |
|
161 | + * @param bool $show_expired |
|
162 | + * @return bool |
|
163 | + * @throws InvalidArgumentException |
|
164 | + * @throws InvalidDataTypeException |
|
165 | + * @throws InvalidInterfaceException |
|
166 | + */ |
|
167 | + private static function _show_expired($show_expired = false) |
|
168 | + { |
|
169 | + // override default expired option if set via filter |
|
170 | + return self::getRequest()->getRequestParam('event_query_show_expired', $show_expired, 'bool'); |
|
171 | + } |
|
172 | + |
|
173 | + |
|
174 | + /** |
|
175 | + * @param array|string $orderby |
|
176 | + * @return array |
|
177 | + * @throws InvalidArgumentException |
|
178 | + * @throws InvalidDataTypeException |
|
179 | + * @throws InvalidInterfaceException |
|
180 | + */ |
|
181 | + private static function _orderby($orderby = 'start_date') |
|
182 | + { |
|
183 | + $event_query_orderby = self::getRequest()->getRequestParam( |
|
184 | + 'event_query_orderby', |
|
185 | + (array) $orderby, |
|
186 | + DataType::STRING, |
|
187 | + true |
|
188 | + ); |
|
189 | + $event_query_orderby = is_array($event_query_orderby) |
|
190 | + ? $event_query_orderby |
|
191 | + : explode(',', $event_query_orderby); |
|
192 | + $event_query_orderby = array_map('trim', $event_query_orderby); |
|
193 | + return array_map('sanitize_text_field', $event_query_orderby); |
|
194 | + } |
|
195 | + |
|
196 | + |
|
197 | + /** |
|
198 | + * @param string $sort |
|
199 | + * @return string |
|
200 | + * @throws InvalidArgumentException |
|
201 | + * @throws InvalidDataTypeException |
|
202 | + * @throws InvalidInterfaceException |
|
203 | + */ |
|
204 | + private static function _sort($sort = 'ASC') |
|
205 | + { |
|
206 | + $sort = self::getRequest()->getRequestParam('event_query_sort', $sort); |
|
207 | + return in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true) |
|
208 | + ? strtoupper($sort) |
|
209 | + : 'ASC'; |
|
210 | + } |
|
211 | + |
|
212 | + |
|
213 | + /** |
|
214 | + * Filters the clauses for the WP_Query object |
|
215 | + * |
|
216 | + * @param array $clauses array of clauses |
|
217 | + * @param WP_Query $wp_query |
|
218 | + * @return array array of clauses |
|
219 | + */ |
|
220 | + public static function posts_clauses($clauses, WP_Query $wp_query) |
|
221 | + { |
|
222 | + if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
223 | + global $wpdb; |
|
224 | + $clauses['groupby'] = $wpdb->posts . '.ID '; |
|
225 | + } |
|
226 | + return $clauses; |
|
227 | + } |
|
228 | + |
|
229 | + |
|
230 | + /** |
|
231 | + * @param string $SQL |
|
232 | + * @param WP_Query $wp_query |
|
233 | + * @return string |
|
234 | + * @throws EE_Error |
|
235 | + * @throws InvalidArgumentException |
|
236 | + * @throws InvalidDataTypeException |
|
237 | + * @throws InvalidInterfaceException |
|
238 | + */ |
|
239 | + public static function posts_fields($SQL, WP_Query $wp_query) |
|
240 | + { |
|
241 | + if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
242 | + // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
243 | + $SQL .= EEH_Event_Query::posts_fields_sql_for_orderby(EEH_Event_Query::$_event_query_orderby); |
|
244 | + } |
|
245 | + return $SQL; |
|
246 | + } |
|
247 | + |
|
248 | + |
|
249 | + /** |
|
250 | + * @param array $orderby_params |
|
251 | + * @return string |
|
252 | + * @throws EE_Error |
|
253 | + * @throws InvalidArgumentException |
|
254 | + * @throws InvalidDataTypeException |
|
255 | + * @throws InvalidInterfaceException |
|
256 | + */ |
|
257 | + public static function posts_fields_sql_for_orderby(array $orderby_params = []) |
|
258 | + { |
|
259 | + $SQL = ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
260 | + foreach ($orderby_params as $orderby) { |
|
261 | + switch ($orderby) { |
|
262 | + case 'ticket_start': |
|
263 | + $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_start_date'; |
|
264 | + break; |
|
265 | + case 'ticket_end': |
|
266 | + $SQL .= ', ' . EEM_Ticket::instance()->table() . '.TKT_end_date'; |
|
267 | + break; |
|
268 | + case 'venue_title': |
|
269 | + $SQL .= ', Venue.post_title AS venue_title'; |
|
270 | + break; |
|
271 | + case 'city': |
|
272 | + $SQL .= ', ' . EEM_Venue::instance()->second_table() . '.VNU_city'; |
|
273 | + break; |
|
274 | + case 'state': |
|
275 | + $SQL .= ', ' . EEM_State::instance()->table() . '.STA_name'; |
|
276 | + break; |
|
277 | + } |
|
278 | + } |
|
279 | + return $SQL; |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + /** |
|
284 | + * @param string $SQL |
|
285 | + * @param WP_Query $wp_query |
|
286 | + * @return string |
|
287 | + * @throws EE_Error |
|
288 | + * @throws InvalidArgumentException |
|
289 | + * @throws InvalidDataTypeException |
|
290 | + * @throws InvalidInterfaceException |
|
291 | + */ |
|
292 | + public static function posts_join($SQL, WP_Query $wp_query) |
|
293 | + { |
|
294 | + if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
295 | + // Category |
|
296 | + $SQL = EEH_Event_Query::posts_join_sql_for_show_expired($SQL, EEH_Event_Query::$_event_query_show_expired); |
|
297 | + $SQL = EEH_Event_Query::posts_join_sql_for_terms($SQL, EEH_Event_Query::$_event_query_category); |
|
298 | + $SQL = EEH_Event_Query::posts_join_for_orderby($SQL, EEH_Event_Query::$_event_query_orderby); |
|
299 | + } |
|
300 | + return $SQL; |
|
301 | + } |
|
302 | + |
|
303 | + |
|
304 | + /** |
|
305 | + * @param string $SQL |
|
306 | + * @param boolean $show_expired if TRUE, then displayed past events |
|
307 | + * @return string |
|
308 | + * @throws EE_Error |
|
309 | + * @throws InvalidArgumentException |
|
310 | + * @throws InvalidDataTypeException |
|
311 | + * @throws InvalidInterfaceException |
|
312 | + */ |
|
313 | + public static function posts_join_sql_for_show_expired($SQL = '', $show_expired = false) |
|
314 | + { |
|
315 | + if (! $show_expired) { |
|
316 | + $join = EEM_Event::instance()->table() . '.ID = '; |
|
317 | + $join .= EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
318 | + // don't add if this is already in the SQL |
|
319 | + if (strpos($SQL, $join) === false) { |
|
320 | + $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' ) '; |
|
321 | + } |
|
322 | + } |
|
323 | + return $SQL; |
|
324 | + } |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * @param string $SQL |
|
329 | + * @param string $join_terms pass TRUE or term string, doesn't really matter since this value doesn't really get |
|
330 | + * used for anything yet |
|
331 | + * @return string |
|
332 | + */ |
|
333 | + public static function posts_join_sql_for_terms($SQL = '', $join_terms = '') |
|
334 | + { |
|
335 | + if (! empty($join_terms)) { |
|
336 | + global $wpdb; |
|
337 | + $SQL .= " LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)"; |
|
338 | + $SQL .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)"; |
|
339 | + $SQL .= " LEFT JOIN $wpdb->terms ON ($wpdb->terms.term_id = $wpdb->term_taxonomy.term_id) "; |
|
340 | + } |
|
341 | + return $SQL; |
|
342 | + } |
|
343 | + |
|
344 | + |
|
345 | + /** |
|
346 | + * usage: $SQL .= EEH_Event_Query::posts_join_for_orderby( $orderby_params ); |
|
347 | + * |
|
348 | + * @param string $SQL |
|
349 | + * @param array $orderby_params |
|
350 | + * @return string |
|
351 | + * @throws EE_Error |
|
352 | + * @throws InvalidArgumentException |
|
353 | + * @throws InvalidDataTypeException |
|
354 | + * @throws InvalidInterfaceException |
|
355 | + */ |
|
356 | + public static function posts_join_for_orderby($SQL = '', array $orderby_params = []) |
|
357 | + { |
|
358 | + foreach ($orderby_params as $orderby) { |
|
359 | + switch ($orderby) { |
|
360 | + case 'ticket_start': |
|
361 | + case 'ticket_end': |
|
362 | + $SQL .= EEH_Event_Query::_posts_join_for_datetime( |
|
363 | + $SQL, |
|
364 | + EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Datetime::instance()->primary_key_name() |
|
365 | + ); |
|
366 | + $SQL .= ' LEFT JOIN ' . EEM_Ticket::instance()->table(); |
|
367 | + $SQL .= ' ON ('; |
|
368 | + $SQL .= EEM_Datetime_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
369 | + $SQL .= ' = '; |
|
370 | + $SQL .= EEM_Ticket::instance()->table() . '.' . EEM_Ticket::instance()->primary_key_name(); |
|
371 | + $SQL .= ' )'; |
|
372 | + break; |
|
373 | + case 'venue_title': |
|
374 | + case 'city': |
|
375 | + $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL); |
|
376 | + break; |
|
377 | + case 'state': |
|
378 | + $SQL .= EEH_Event_Query::_posts_join_for_event_venue($SQL); |
|
379 | + $SQL .= EEH_Event_Query::_posts_join_for_venue_state($SQL); |
|
380 | + break; |
|
381 | + case 'start_date': |
|
382 | + default: |
|
383 | + $SQL .= EEH_Event_Query::_posts_join_for_datetime($SQL, EEM_Event::instance()->table() . '.ID'); |
|
384 | + break; |
|
385 | + } |
|
386 | + } |
|
387 | + return $SQL; |
|
388 | + } |
|
389 | + |
|
390 | + |
|
391 | + /** |
|
392 | + * @param string $SQL |
|
393 | + * @param string $join |
|
394 | + * @return string |
|
395 | + * @throws EE_Error |
|
396 | + * @throws InvalidArgumentException |
|
397 | + * @throws InvalidDataTypeException |
|
398 | + * @throws InvalidInterfaceException |
|
399 | + */ |
|
400 | + protected static function _posts_join_for_datetime($SQL = '', $join = '') |
|
401 | + { |
|
402 | + if (! empty($join)) { |
|
403 | + $join .= ' = ' . EEM_Datetime::instance()->table() . '.' . EEM_Event::instance()->primary_key_name(); |
|
404 | + if (strpos($SQL, $join) === false) { |
|
405 | + return ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . $join . ' )'; |
|
406 | + } |
|
407 | + } |
|
408 | + return ''; |
|
409 | + } |
|
410 | + |
|
411 | + |
|
412 | + /** |
|
413 | + * @param string $SQL |
|
414 | + * @return string |
|
415 | + * @throws EE_Error |
|
416 | + * @throws InvalidArgumentException |
|
417 | + * @throws InvalidDataTypeException |
|
418 | + * @throws InvalidInterfaceException |
|
419 | + */ |
|
420 | + protected static function _posts_join_for_event_venue($SQL = '') |
|
421 | + { |
|
422 | + // Event Venue table name |
|
423 | + $event_venue_table = EEM_Event_Venue::instance()->table(); |
|
424 | + // generate conditions for: Event <=> Event Venue JOIN clause |
|
425 | + $event_to_event_venue_join = EEM_Event::instance()->table() . '.ID = '; |
|
426 | + $event_to_event_venue_join .= $event_venue_table . '.' . EEM_Event::instance()->primary_key_name(); |
|
427 | + // don't add joins if they have already been added |
|
428 | + if (strpos($SQL, $event_to_event_venue_join) === false) { |
|
429 | + // Venue table name |
|
430 | + $venue_table = EEM_Venue::instance()->table(); |
|
431 | + // Venue table pk |
|
432 | + $venue_table_pk = EEM_Venue::instance()->primary_key_name(); |
|
433 | + // Venue Meta table name |
|
434 | + $venue_meta_table = EEM_Venue::instance()->second_table(); |
|
435 | + // generate JOIN clause for: Event <=> Event Venue |
|
436 | + $venue_SQL = " LEFT JOIN $event_venue_table ON ( $event_to_event_venue_join )"; |
|
437 | + // generate JOIN clause for: Event Venue <=> Venue |
|
438 | + $venue_SQL .= " LEFT JOIN $venue_table as Venue ON ( $event_venue_table.$venue_table_pk = Venue.ID )"; |
|
439 | + // generate JOIN clause for: Venue <=> Venue Meta |
|
440 | + $venue_SQL .= " LEFT JOIN $venue_meta_table ON ( Venue.ID = $venue_meta_table.$venue_table_pk )"; |
|
441 | + unset($event_venue_table, $event_to_event_venue_join, $venue_table, $venue_table_pk, $venue_meta_table); |
|
442 | + return $venue_SQL; |
|
443 | + } |
|
444 | + unset($event_venue_table, $event_to_event_venue_join); |
|
445 | + return ''; |
|
446 | + } |
|
447 | + |
|
448 | + |
|
449 | + /** |
|
450 | + * @param string $SQL |
|
451 | + * @return string |
|
452 | + * @throws EE_Error |
|
453 | + * @throws InvalidArgumentException |
|
454 | + * @throws InvalidDataTypeException |
|
455 | + * @throws InvalidInterfaceException |
|
456 | + */ |
|
457 | + protected static function _posts_join_for_venue_state($SQL = '') |
|
458 | + { |
|
459 | + // Venue Meta table name |
|
460 | + $venue_meta_table = EEM_Venue::instance()->second_table(); |
|
461 | + // State table name |
|
462 | + $state_table = EEM_State::instance()->table(); |
|
463 | + // State table pk |
|
464 | + $state_table_pk = EEM_State::instance()->primary_key_name(); |
|
465 | + // verify vars |
|
466 | + if ($venue_meta_table && $state_table && $state_table_pk) { |
|
467 | + // like: wp_esp_venue_meta.STA_ID = wp_esp_state.STA_ID |
|
468 | + $join = "$venue_meta_table.$state_table_pk = $state_table.$state_table_pk"; |
|
469 | + // don't add join if it has already been added |
|
470 | + if (strpos($SQL, $join) === false) { |
|
471 | + unset($state_table_pk, $venue_meta_table, $venue_table_pk); |
|
472 | + return " LEFT JOIN $state_table ON ( $join )"; |
|
473 | + } |
|
474 | + } |
|
475 | + unset($join, $state_table, $state_table_pk, $venue_meta_table, $venue_table_pk); |
|
476 | + return ''; |
|
477 | + } |
|
478 | + |
|
479 | + |
|
480 | + /** |
|
481 | + * @param string $SQL |
|
482 | + * @param WP_Query $wp_query |
|
483 | + * @return string |
|
484 | + * @throws EE_Error |
|
485 | + * @throws InvalidArgumentException |
|
486 | + * @throws InvalidDataTypeException |
|
487 | + * @throws InvalidInterfaceException |
|
488 | + */ |
|
489 | + public static function posts_where($SQL, WP_Query $wp_query) |
|
490 | + { |
|
491 | + if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
492 | + // Show Expired ? |
|
493 | + $SQL .= EEH_Event_Query::posts_where_sql_for_show_expired(EEH_Event_Query::$_event_query_show_expired); |
|
494 | + // Category |
|
495 | + $SQL .= EEH_Event_Query::posts_where_sql_for_event_category_slug(EEH_Event_Query::$_event_query_category); |
|
496 | + // Start Date |
|
497 | + $SQL .= EEH_Event_Query::posts_where_sql_for_event_list_month(EEH_Event_Query::$_event_query_month); |
|
498 | + } |
|
499 | + return $SQL; |
|
500 | + } |
|
501 | + |
|
502 | + |
|
503 | + /** |
|
504 | + * @param boolean $show_expired if TRUE, then displayed past events |
|
505 | + * @return string |
|
506 | + * @throws EE_Error |
|
507 | + * @throws InvalidArgumentException |
|
508 | + * @throws InvalidDataTypeException |
|
509 | + * @throws InvalidInterfaceException |
|
510 | + */ |
|
511 | + public static function posts_where_sql_for_show_expired($show_expired = false) |
|
512 | + { |
|
513 | + return ! $show_expired |
|
514 | + ? ' AND ' . EEM_Datetime::instance()->table() . '.DTT_EVT_end > \'' . current_time('mysql', true) . '\' ' |
|
515 | + : ''; |
|
516 | + } |
|
517 | + |
|
518 | + |
|
519 | + /** |
|
520 | + * @param boolean $event_category_slug |
|
521 | + * @return string |
|
522 | + */ |
|
523 | + public static function posts_where_sql_for_event_category_slug($event_category_slug = null) |
|
524 | + { |
|
525 | + global $wpdb; |
|
526 | + if (! empty($event_category_slug)) { |
|
527 | + $event_category_slugs_array = array_map('trim', explode(',', $event_category_slug)); |
|
528 | + $event_category_slugs_prepare = implode(', ', array_fill(0, count($event_category_slugs_array), '%s')); |
|
529 | + return $wpdb->prepare( |
|
530 | + " AND {$wpdb->terms}.slug IN ({$event_category_slugs_prepare}) ", |
|
531 | + $event_category_slugs_array |
|
532 | + ); |
|
533 | + } |
|
534 | + return ''; |
|
535 | + } |
|
536 | + |
|
537 | + |
|
538 | + /** |
|
539 | + * @param boolean $month |
|
540 | + * @return string |
|
541 | + * @throws EE_Error |
|
542 | + * @throws InvalidArgumentException |
|
543 | + * @throws InvalidDataTypeException |
|
544 | + * @throws InvalidInterfaceException |
|
545 | + */ |
|
546 | + public static function posts_where_sql_for_event_list_month($month = null) |
|
547 | + { |
|
548 | + $SQL = ''; |
|
549 | + if (! empty($month)) { |
|
550 | + $datetime_table = EEM_Datetime::instance()->table(); |
|
551 | + // event start date is LESS than the end of the month ( so nothing that doesn't start until next month ) |
|
552 | + $SQL = " AND {$datetime_table}.DTT_EVT_start <= '"; |
|
553 | + $SQL .= date('Y-m-t 23:59:59', EEH_DTT_Helper::first_of_month_timestamp($month)) . "'"; |
|
554 | + // event end date is GREATER than the start of the month ( so nothing that ended before this month ) |
|
555 | + $SQL .= " AND {$datetime_table}.DTT_EVT_end >= '"; |
|
556 | + $SQL .= date('Y-m-01 0:0:00', EEH_DTT_Helper::first_of_month_timestamp($month)) . "' "; |
|
557 | + } |
|
558 | + return $SQL; |
|
559 | + } |
|
560 | + |
|
561 | + |
|
562 | + /** |
|
563 | + * @param string $SQL |
|
564 | + * @param WP_Query $wp_query |
|
565 | + * @return string |
|
566 | + * @throws EE_Error |
|
567 | + * @throws InvalidArgumentException |
|
568 | + * @throws InvalidDataTypeException |
|
569 | + * @throws InvalidInterfaceException |
|
570 | + */ |
|
571 | + public static function posts_orderby($SQL, WP_Query $wp_query) |
|
572 | + { |
|
573 | + if (EEH_Event_Query::apply_query_filters($wp_query)) { |
|
574 | + $SQL = EEH_Event_Query::posts_orderby_sql( |
|
575 | + EEH_Event_Query::$_event_query_orderby, |
|
576 | + EEH_Event_Query::$_event_query_sort |
|
577 | + ); |
|
578 | + } |
|
579 | + return $SQL; |
|
580 | + } |
|
581 | + |
|
582 | + |
|
583 | + /** |
|
584 | + * posts_orderby_sql |
|
585 | + * possible parameters: |
|
586 | + * ID |
|
587 | + * start_date |
|
588 | + * end_date |
|
589 | + * event_name |
|
590 | + * category_slug |
|
591 | + * ticket_start |
|
592 | + * ticket_end |
|
593 | + * venue_title |
|
594 | + * city |
|
595 | + * state |
|
596 | + * **IMPORTANT** |
|
597 | + * make sure to also send the $orderby_params array to the posts_join_for_orderby() method |
|
598 | + * or else some of the table references below will result in MySQL errors |
|
599 | + * |
|
600 | + * @param array $orderby_params |
|
601 | + * @param string $sort |
|
602 | + * @return string |
|
603 | + * @throws EE_Error |
|
604 | + * @throws InvalidArgumentException |
|
605 | + * @throws InvalidDataTypeException |
|
606 | + * @throws InvalidInterfaceException |
|
607 | + */ |
|
608 | + public static function posts_orderby_sql(array $orderby_params = [], $sort = 'ASC') |
|
609 | + { |
|
610 | + global $wpdb; |
|
611 | + $SQL = ''; |
|
612 | + $counter = 0; |
|
613 | + $sort = in_array($sort, ['ASC', 'asc', 'DESC', 'desc'], true) |
|
614 | + ? strtoupper($sort) |
|
615 | + : 'ASC'; |
|
616 | + // make sure 'orderby' is set in query params |
|
617 | + if (! isset(self::$_query_params['orderby'])) { |
|
618 | + self::$_query_params['orderby'] = []; |
|
619 | + } |
|
620 | + // loop thru $orderby_params (type cast as array) |
|
621 | + foreach ($orderby_params as $orderby) { |
|
622 | + // check if we have already added this param |
|
623 | + if (isset(self::$_query_params['orderby'][ $orderby ])) { |
|
624 | + // if so then remove from the $orderby_params so that the count() method below is accurate |
|
625 | + unset($orderby_params[ $orderby ]); |
|
626 | + // then bump ahead to the next param |
|
627 | + continue; |
|
628 | + } |
|
629 | + // this will ad a comma depending on whether this is the first or last param |
|
630 | + $glue = $counter === 0 || $counter === count($orderby_params) ? ' ' : ', '; |
|
631 | + // ok what's we dealing with? |
|
632 | + switch ($orderby) { |
|
633 | + case 'id': |
|
634 | + case 'ID': |
|
635 | + $SQL .= $glue . $wpdb->posts . '.ID ' . $sort; |
|
636 | + break; |
|
637 | + case 'end_date': |
|
638 | + $SQL .= $glue . EEM_Datetime::instance()->table() . '.DTT_EVT_end ' . $sort; |
|
639 | + break; |
|
640 | + case 'event_name': |
|
641 | + $SQL .= $glue . $wpdb->posts . '.post_title ' . $sort; |
|
642 | + break; |
|
643 | + case 'category_slug': |
|
644 | + $SQL .= $glue . $wpdb->terms . '.slug ' . $sort; |
|
645 | + break; |
|
646 | + case 'ticket_start': |
|
647 | + $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_start_date ' . $sort; |
|
648 | + break; |
|
649 | + case 'ticket_end': |
|
650 | + $SQL .= $glue . EEM_Ticket::instance()->table() . '.TKT_end_date ' . $sort; |
|
651 | + break; |
|
652 | + case 'venue_title': |
|
653 | + $SQL .= $glue . 'venue_title ' . $sort; |
|
654 | + break; |
|
655 | + case 'city': |
|
656 | + $SQL .= $glue . EEM_Venue::instance()->second_table() . '.VNU_city ' . $sort; |
|
657 | + break; |
|
658 | + case 'state': |
|
659 | + $SQL .= $glue . EEM_State::instance()->table() . '.STA_name ' . $sort; |
|
660 | + break; |
|
661 | + case 'start_date': |
|
662 | + default: |
|
663 | + $SQL .= $glue . ' event_start_date ' . $sort; |
|
664 | + break; |
|
665 | + } |
|
666 | + // add to array of orderby params that have been added |
|
667 | + self::$_query_params['orderby'][ $orderby ] = true; |
|
668 | + $counter++; |
|
669 | + } |
|
670 | + return $SQL; |
|
671 | + } |
|
672 | + |
|
673 | + |
|
674 | + /** |
|
675 | + * @return RequestInterface |
|
676 | + * @since 4.10.14.p |
|
677 | + */ |
|
678 | + private static function getRequest() |
|
679 | + { |
|
680 | + return LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
681 | + } |
|
682 | 682 | } |
@@ -246,22 +246,22 @@ discard block |
||
246 | 246 | // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
247 | 247 | // (which currently fires on the init hook at priority 9), |
248 | 248 | // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
249 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | + if ( ! apply_filters('FHEE_load_EE_Session', true)) { |
|
250 | 250 | return; |
251 | 251 | } |
252 | 252 | $this->session_start_handler = $session_start_handler; |
253 | 253 | $this->session_lifespan = $lifespan; |
254 | 254 | $this->request = $request; |
255 | - if (! defined('ESPRESSO_SESSION')) { |
|
255 | + if ( ! defined('ESPRESSO_SESSION')) { |
|
256 | 256 | define('ESPRESSO_SESSION', true); |
257 | 257 | } |
258 | 258 | // retrieve session options from db |
259 | 259 | $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
260 | - if (! empty($session_settings)) { |
|
260 | + if ( ! empty($session_settings)) { |
|
261 | 261 | // cycle though existing session options |
262 | 262 | foreach ($session_settings as $var_name => $session_setting) { |
263 | 263 | // set values for class properties |
264 | - $var_name = '_' . $var_name; |
|
264 | + $var_name = '_'.$var_name; |
|
265 | 265 | $this->{$var_name} = $session_setting; |
266 | 266 | } |
267 | 267 | } |
@@ -322,7 +322,7 @@ discard block |
||
322 | 322 | public function open_session() |
323 | 323 | { |
324 | 324 | // check for existing session and retrieve it from db |
325 | - if (! $this->_espresso_session()) { |
|
325 | + if ( ! $this->_espresso_session()) { |
|
326 | 326 | // or just start a new one |
327 | 327 | $this->_create_espresso_session(); |
328 | 328 | } |
@@ -399,7 +399,7 @@ discard block |
||
399 | 399 | EE_Session::SAVE_STATE_CLEAN, |
400 | 400 | EE_Session::SAVE_STATE_DIRTY, |
401 | 401 | ]; |
402 | - if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | + if ( ! in_array($save_state, $valid_save_states, true)) { |
|
403 | 403 | $save_state = EE_Session::SAVE_STATE_DIRTY; |
404 | 404 | } |
405 | 405 | $this->save_state = $save_state; |
@@ -417,9 +417,9 @@ discard block |
||
417 | 417 | // set some defaults |
418 | 418 | foreach ($this->_default_session_vars as $key => $default_var) { |
419 | 419 | if (is_array($default_var)) { |
420 | - $this->_session_data[ $key ] = array(); |
|
420 | + $this->_session_data[$key] = array(); |
|
421 | 421 | } else { |
422 | - $this->_session_data[ $key ] = ''; |
|
422 | + $this->_session_data[$key] = ''; |
|
423 | 423 | } |
424 | 424 | } |
425 | 425 | } |
@@ -555,8 +555,8 @@ discard block |
||
555 | 555 | $this->reset_checkout(); |
556 | 556 | $this->reset_transaction(); |
557 | 557 | } |
558 | - if (! empty($key)) { |
|
559 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
558 | + if ( ! empty($key)) { |
|
559 | + return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null; |
|
560 | 560 | } |
561 | 561 | return $this->_session_data; |
562 | 562 | } |
@@ -584,7 +584,7 @@ discard block |
||
584 | 584 | return false; |
585 | 585 | } |
586 | 586 | foreach ($data as $key => $value) { |
587 | - if (isset($this->_default_session_vars[ $key ])) { |
|
587 | + if (isset($this->_default_session_vars[$key])) { |
|
588 | 588 | EE_Error::add_error( |
589 | 589 | sprintf( |
590 | 590 | esc_html__( |
@@ -599,7 +599,7 @@ discard block |
||
599 | 599 | ); |
600 | 600 | return false; |
601 | 601 | } |
602 | - $this->_session_data[ $key ] = $value; |
|
602 | + $this->_session_data[$key] = $value; |
|
603 | 603 | $this->setSaveState(); |
604 | 604 | } |
605 | 605 | return true; |
@@ -630,7 +630,7 @@ discard block |
||
630 | 630 | $this->_user_agent = $this->request->userAgent(); |
631 | 631 | // now let's retrieve what's in the db |
632 | 632 | $session_data = $this->_retrieve_session_data(); |
633 | - if (! empty($session_data)) { |
|
633 | + if ( ! empty($session_data)) { |
|
634 | 634 | // get the current time in UTC |
635 | 635 | $this->_time = $this->_time !== null ? $this->_time : time(); |
636 | 636 | // and reset the session expiration |
@@ -641,7 +641,7 @@ discard block |
||
641 | 641 | // set initial site access time and the session expiration |
642 | 642 | $this->_set_init_access_and_expiration(); |
643 | 643 | // set referer |
644 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | + $this->_session_data['pages_visited'][$this->_session_data['init_access']] = esc_attr( |
|
645 | 645 | $this->request->getServerParam('HTTP_REFERER') |
646 | 646 | ); |
647 | 647 | // no previous session = go back and create one (on top of the data above) |
@@ -679,7 +679,7 @@ discard block |
||
679 | 679 | */ |
680 | 680 | protected function _retrieve_session_data() |
681 | 681 | { |
682 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | + $ssn_key = EE_Session::session_id_prefix.$this->_sid; |
|
683 | 683 | try { |
684 | 684 | // we're using WP's Transient API to store session data using the PHP session ID as the option name |
685 | 685 | $session_data = $this->cache_storage->get($ssn_key, false); |
@@ -688,7 +688,7 @@ discard block |
||
688 | 688 | } |
689 | 689 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
690 | 690 | $hash_check = $this->cache_storage->get( |
691 | - EE_Session::hash_check_prefix . $this->_sid, |
|
691 | + EE_Session::hash_check_prefix.$this->_sid, |
|
692 | 692 | false |
693 | 693 | ); |
694 | 694 | if ($hash_check && $hash_check !== md5($session_data)) { |
@@ -698,7 +698,7 @@ discard block |
||
698 | 698 | 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
699 | 699 | 'event_espresso' |
700 | 700 | ), |
701 | - EE_Session::session_id_prefix . $this->_sid |
|
701 | + EE_Session::session_id_prefix.$this->_sid |
|
702 | 702 | ), |
703 | 703 | __FILE__, |
704 | 704 | __FUNCTION__, |
@@ -712,17 +712,17 @@ discard block |
||
712 | 712 | $row = $wpdb->get_row( |
713 | 713 | $wpdb->prepare( |
714 | 714 | "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
715 | - '_transient_' . $ssn_key |
|
715 | + '_transient_'.$ssn_key |
|
716 | 716 | ) |
717 | 717 | ); |
718 | 718 | $session_data = is_object($row) ? $row->option_value : null; |
719 | 719 | if ($session_data) { |
720 | 720 | $session_data = preg_replace_callback( |
721 | 721 | '!s:(d+):"(.*?)";!', |
722 | - function ($match) { |
|
722 | + function($match) { |
|
723 | 723 | return $match[1] === strlen($match[2]) |
724 | 724 | ? $match[0] |
725 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | + : 's:'.strlen($match[2]).':"'.$match[2].'";'; |
|
726 | 726 | }, |
727 | 727 | $session_data |
728 | 728 | ); |
@@ -733,7 +733,7 @@ discard block |
||
733 | 733 | $session_data = $this->encryption instanceof EE_Encryption |
734 | 734 | ? $this->encryption->base64_string_decode($session_data) |
735 | 735 | : $session_data; |
736 | - if (! is_array($session_data)) { |
|
736 | + if ( ! is_array($session_data)) { |
|
737 | 737 | try { |
738 | 738 | $session_data = maybe_unserialize($session_data); |
739 | 739 | } catch (Exception $e) { |
@@ -747,21 +747,21 @@ discard block |
||
747 | 747 | . '</pre><br>' |
748 | 748 | . $this->find_serialize_error($session_data) |
749 | 749 | : ''; |
750 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
751 | 751 | throw new InvalidSessionDataException($msg, 0, $e); |
752 | 752 | } |
753 | 753 | } |
754 | 754 | // just a check to make sure the session array is indeed an array |
755 | - if (! is_array($session_data)) { |
|
755 | + if ( ! is_array($session_data)) { |
|
756 | 756 | // no?!?! then something is wrong |
757 | 757 | $msg = esc_html__( |
758 | 758 | 'The session data is missing, invalid, or corrupted.', |
759 | 759 | 'event_espresso' |
760 | 760 | ); |
761 | 761 | $msg .= WP_DEBUG |
762 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | + ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data) |
|
763 | 763 | : ''; |
764 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
765 | 765 | throw new InvalidSessionDataException($msg); |
766 | 766 | } |
767 | 767 | if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
@@ -787,7 +787,7 @@ discard block |
||
787 | 787 | // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
788 | 788 | $session_id = $this->request->requestParamIsSet('EESID') |
789 | 789 | ? $this->request->getRequestParam('EESID') |
790 | - : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | + : md5(session_id().get_current_blog_id().$this->_get_sid_salt()); |
|
791 | 791 | return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
792 | 792 | } |
793 | 793 | |
@@ -889,19 +889,19 @@ discard block |
||
889 | 889 | $page_visit = $this->_get_page_visit(); |
890 | 890 | if ($page_visit) { |
891 | 891 | // set pages visited where the first will be the http referrer |
892 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
892 | + $this->_session_data['pages_visited'][$this->_time] = $page_visit; |
|
893 | 893 | // we'll only save the last 10 page visits. |
894 | 894 | $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
895 | 895 | } |
896 | 896 | break; |
897 | 897 | default: |
898 | 898 | // carry any other data over |
899 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
899 | + $session_data[$key] = $this->_session_data[$key]; |
|
900 | 900 | } |
901 | 901 | } |
902 | 902 | $this->_session_data = $session_data; |
903 | 903 | // creating a new session does not require saving to the db just yet |
904 | - if (! $new_session) { |
|
904 | + if ( ! $new_session) { |
|
905 | 905 | // ready? let's save |
906 | 906 | if ($this->_save_session_to_db()) { |
907 | 907 | return true; |
@@ -979,7 +979,7 @@ discard block |
||
979 | 979 | } |
980 | 980 | $transaction = $this->transaction(); |
981 | 981 | if ($transaction instanceof EE_Transaction) { |
982 | - if (! $transaction->ID()) { |
|
982 | + if ( ! $transaction->ID()) { |
|
983 | 983 | $transaction->save(); |
984 | 984 | } |
985 | 985 | $this->_session_data['transaction'] = $transaction->ID(); |
@@ -993,14 +993,14 @@ discard block |
||
993 | 993 | // maybe save hash check |
994 | 994 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
995 | 995 | $this->cache_storage->add( |
996 | - EE_Session::hash_check_prefix . $this->_sid, |
|
996 | + EE_Session::hash_check_prefix.$this->_sid, |
|
997 | 997 | md5($session_data), |
998 | 998 | $this->session_lifespan->inSeconds() |
999 | 999 | ); |
1000 | 1000 | } |
1001 | 1001 | // we're using the Transient API for storing session data, |
1002 | 1002 | $saved = $this->cache_storage->add( |
1003 | - EE_Session::session_id_prefix . $this->_sid, |
|
1003 | + EE_Session::session_id_prefix.$this->_sid, |
|
1004 | 1004 | $session_data, |
1005 | 1005 | $this->session_lifespan->inSeconds() |
1006 | 1006 | ); |
@@ -1015,7 +1015,7 @@ discard block |
||
1015 | 1015 | */ |
1016 | 1016 | public function _get_page_visit() |
1017 | 1017 | { |
1018 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1018 | + $page_visit = home_url('/').'wp-admin/admin-ajax.php'; |
|
1019 | 1019 | // check for request url |
1020 | 1020 | if ($this->request->serverParamIsSet('REQUEST_URI')) { |
1021 | 1021 | $page_id = '?'; |
@@ -1027,14 +1027,14 @@ discard block |
||
1027 | 1027 | // check for page_id in SERVER REQUEST |
1028 | 1028 | if ($this->request->requestParamIsSet('page_id')) { |
1029 | 1029 | // rebuild $e_reg without any of the extra parameters |
1030 | - $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1030 | + $page_id .= 'page_id='.$this->request->getRequestParam('page_id', 0, 'int').'&'; |
|
1031 | 1031 | } |
1032 | 1032 | // check for $e_reg in SERVER REQUEST |
1033 | 1033 | if ($this->request->requestParamIsSet('ee')) { |
1034 | 1034 | // rebuild $e_reg without any of the extra parameters |
1035 | - $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1035 | + $e_reg = 'ee='.$this->request->getRequestParam('ee'); |
|
1036 | 1036 | } |
1037 | - $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1037 | + $page_visit = esc_url(rtrim($http_host.$request_uri.$page_id.$e_reg, '?')); |
|
1038 | 1038 | } |
1039 | 1039 | return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
1040 | 1040 | } |
@@ -1071,7 +1071,7 @@ discard block |
||
1071 | 1071 | // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/> |
1072 | 1072 | // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b> |
1073 | 1073 | // </h3>'; |
1074 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1074 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()'); |
|
1075 | 1075 | $this->reset_cart(); |
1076 | 1076 | $this->reset_checkout(); |
1077 | 1077 | $this->reset_transaction(); |
@@ -1094,7 +1094,7 @@ discard block |
||
1094 | 1094 | public function reset_data($data_to_reset = array(), $show_all_notices = false) |
1095 | 1095 | { |
1096 | 1096 | // if $data_to_reset is not in an array, then put it in one |
1097 | - if (! is_array($data_to_reset)) { |
|
1097 | + if ( ! is_array($data_to_reset)) { |
|
1098 | 1098 | $data_to_reset = array($data_to_reset); |
1099 | 1099 | } |
1100 | 1100 | // nothing ??? go home! |
@@ -1114,11 +1114,11 @@ discard block |
||
1114 | 1114 | // since $data_to_reset is an array, cycle through the values |
1115 | 1115 | foreach ($data_to_reset as $reset) { |
1116 | 1116 | // first check to make sure it is a valid session var |
1117 | - if (isset($this->_session_data[ $reset ])) { |
|
1117 | + if (isset($this->_session_data[$reset])) { |
|
1118 | 1118 | // then check to make sure it is not a default var |
1119 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1119 | + if ( ! array_key_exists($reset, $this->_default_session_vars)) { |
|
1120 | 1120 | // remove session var |
1121 | - unset($this->_session_data[ $reset ]); |
|
1121 | + unset($this->_session_data[$reset]); |
|
1122 | 1122 | $this->setSaveState(); |
1123 | 1123 | if ($show_all_notices) { |
1124 | 1124 | EE_Error::add_success( |
@@ -1221,7 +1221,7 @@ discard block |
||
1221 | 1221 | // or use that for the new transient cleanup query limit |
1222 | 1222 | add_filter( |
1223 | 1223 | 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
1224 | - function () use ($expired_session_transient_delete_query_limit) { |
|
1224 | + function() use ($expired_session_transient_delete_query_limit) { |
|
1225 | 1225 | return $expired_session_transient_delete_query_limit; |
1226 | 1226 | } |
1227 | 1227 | ); |
@@ -1239,7 +1239,7 @@ discard block |
||
1239 | 1239 | $error = '<pre>'; |
1240 | 1240 | $data2 = preg_replace_callback( |
1241 | 1241 | '!s:(\d+):"(.*?)";!', |
1242 | - function ($match) { |
|
1242 | + function($match) { |
|
1243 | 1243 | return ($match[1] === strlen($match[2])) |
1244 | 1244 | ? $match[0] |
1245 | 1245 | : 's:' |
@@ -1251,13 +1251,13 @@ discard block |
||
1251 | 1251 | $data1 |
1252 | 1252 | ); |
1253 | 1253 | $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
1254 | - $error .= $data1 . PHP_EOL; |
|
1255 | - $error .= $data2 . PHP_EOL; |
|
1254 | + $error .= $data1.PHP_EOL; |
|
1255 | + $error .= $data2.PHP_EOL; |
|
1256 | 1256 | for ($i = 0; $i < $max; $i++) { |
1257 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1258 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1259 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1260 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | + if (@$data1[$i] !== @$data2[$i]) { |
|
1258 | + $error .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL; |
|
1259 | + $error .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL; |
|
1260 | + $error .= "\t-> Line Number = $i".PHP_EOL; |
|
1261 | 1261 | $start = ($i - 20); |
1262 | 1262 | $start = ($start < 0) ? 0 : $start; |
1263 | 1263 | $length = 40; |
@@ -1272,7 +1272,7 @@ discard block |
||
1272 | 1272 | $error .= "\t-> Section Data1 = "; |
1273 | 1273 | $error .= substr_replace( |
1274 | 1274 | substr($data1, $start, $length), |
1275 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1275 | + "<b style=\"color:green\">{$data1[$i]}</b>", |
|
1276 | 1276 | $rpoint, |
1277 | 1277 | $rlength |
1278 | 1278 | ); |
@@ -1280,7 +1280,7 @@ discard block |
||
1280 | 1280 | $error .= "\t-> Section Data2 = "; |
1281 | 1281 | $error .= substr_replace( |
1282 | 1282 | substr($data2, $start, $length), |
1283 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1283 | + "<b style=\"color:red\">{$data2[$i]}</b>", |
|
1284 | 1284 | $rpoint, |
1285 | 1285 | $rlength |
1286 | 1286 | ); |
@@ -1311,7 +1311,7 @@ discard block |
||
1311 | 1311 | public function garbageCollection() |
1312 | 1312 | { |
1313 | 1313 | // only perform during regular requests if last garbage collection was over an hour ago |
1314 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1314 | + if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1315 | 1315 | $this->_last_gc = time(); |
1316 | 1316 | $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
1317 | 1317 | /** @type WPDB $wpdb */ |
@@ -1346,7 +1346,7 @@ discard block |
||
1346 | 1346 | // AND option_value < 1508368198 LIMIT 50 |
1347 | 1347 | $expired_sessions = $wpdb->get_col($SQL); |
1348 | 1348 | // valid results? |
1349 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1349 | + if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1350 | 1350 | $this->cache_storage->deleteMany($expired_sessions, true); |
1351 | 1351 | } |
1352 | 1352 | } |
@@ -23,1310 +23,1310 @@ discard block |
||
23 | 23 | */ |
24 | 24 | class EE_Session implements SessionIdentifierInterface |
25 | 25 | { |
26 | - const session_id_prefix = 'ee_ssn_'; |
|
27 | - |
|
28 | - const hash_check_prefix = 'ee_shc_'; |
|
29 | - |
|
30 | - const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
31 | - |
|
32 | - const STATUS_CLOSED = 0; |
|
33 | - |
|
34 | - const STATUS_OPEN = 1; |
|
35 | - |
|
36 | - const SAVE_STATE_CLEAN = 'clean'; |
|
37 | - const SAVE_STATE_DIRTY = 'dirty'; |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * instance of the EE_Session object |
|
42 | - * |
|
43 | - * @var EE_Session |
|
44 | - */ |
|
45 | - private static $_instance; |
|
46 | - |
|
47 | - /** |
|
48 | - * @var CacheStorageInterface $cache_storage |
|
49 | - */ |
|
50 | - protected $cache_storage; |
|
51 | - |
|
52 | - /** |
|
53 | - * @var EE_Encryption $encryption |
|
54 | - */ |
|
55 | - protected $encryption; |
|
56 | - |
|
57 | - /** |
|
58 | - * @var SessionStartHandler $session_start_handler |
|
59 | - */ |
|
60 | - protected $session_start_handler; |
|
61 | - |
|
62 | - /** |
|
63 | - * the session id |
|
64 | - * |
|
65 | - * @var string |
|
66 | - */ |
|
67 | - private $_sid; |
|
68 | - |
|
69 | - /** |
|
70 | - * session id salt |
|
71 | - * |
|
72 | - * @var string |
|
73 | - */ |
|
74 | - private $_sid_salt; |
|
75 | - |
|
76 | - /** |
|
77 | - * session data |
|
78 | - * |
|
79 | - * @var array |
|
80 | - */ |
|
81 | - private $_session_data = array(); |
|
82 | - |
|
83 | - /** |
|
84 | - * how long an EE session lasts |
|
85 | - * default session lifespan of 1 hour (for not so instant IPNs) |
|
86 | - * |
|
87 | - * @var SessionLifespan $session_lifespan |
|
88 | - */ |
|
89 | - private $session_lifespan; |
|
90 | - |
|
91 | - /** |
|
92 | - * session expiration time as Unix timestamp in GMT |
|
93 | - * |
|
94 | - * @var int |
|
95 | - */ |
|
96 | - private $_expiration; |
|
97 | - |
|
98 | - /** |
|
99 | - * whether or not session has expired at some point |
|
100 | - * |
|
101 | - * @var boolean |
|
102 | - */ |
|
103 | - private $_expired = false; |
|
104 | - |
|
105 | - /** |
|
106 | - * current time as Unix timestamp in GMT |
|
107 | - * |
|
108 | - * @var int |
|
109 | - */ |
|
110 | - private $_time; |
|
111 | - |
|
112 | - /** |
|
113 | - * whether to encrypt session data |
|
114 | - * |
|
115 | - * @var bool |
|
116 | - */ |
|
117 | - private $_use_encryption; |
|
118 | - |
|
119 | - /** |
|
120 | - * well... according to the server... |
|
121 | - * |
|
122 | - * @var null |
|
123 | - */ |
|
124 | - private $_user_agent; |
|
125 | - |
|
126 | - /** |
|
127 | - * do you really trust the server ? |
|
128 | - * |
|
129 | - * @var null |
|
130 | - */ |
|
131 | - private $_ip_address; |
|
132 | - |
|
133 | - /** |
|
134 | - * current WP user_id |
|
135 | - * |
|
136 | - * @var null |
|
137 | - */ |
|
138 | - private $_wp_user_id; |
|
139 | - |
|
140 | - /** |
|
141 | - * array for defining default session vars |
|
142 | - * |
|
143 | - * @var array |
|
144 | - */ |
|
145 | - private $_default_session_vars = array( |
|
146 | - 'id' => null, |
|
147 | - 'user_id' => null, |
|
148 | - 'ip_address' => null, |
|
149 | - 'user_agent' => null, |
|
150 | - 'init_access' => null, |
|
151 | - 'last_access' => null, |
|
152 | - 'expiration' => null, |
|
153 | - 'pages_visited' => array(), |
|
154 | - ); |
|
155 | - |
|
156 | - /** |
|
157 | - * timestamp for when last garbage collection cycle was performed |
|
158 | - * |
|
159 | - * @var int $_last_gc |
|
160 | - */ |
|
161 | - private $_last_gc; |
|
162 | - |
|
163 | - /** |
|
164 | - * @var RequestInterface $request |
|
165 | - */ |
|
166 | - protected $request; |
|
167 | - |
|
168 | - /** |
|
169 | - * whether session is active or not |
|
170 | - * |
|
171 | - * @var int $status |
|
172 | - */ |
|
173 | - private $status = EE_Session::STATUS_CLOSED; |
|
174 | - |
|
175 | - /** |
|
176 | - * whether session data has changed therefore requiring a session save |
|
177 | - * |
|
178 | - * @var string $save_state |
|
179 | - */ |
|
180 | - private $save_state = EE_Session::SAVE_STATE_CLEAN; |
|
181 | - |
|
182 | - |
|
183 | - /** |
|
184 | - * @singleton method used to instantiate class object |
|
185 | - * @param CacheStorageInterface $cache_storage |
|
186 | - * @param SessionLifespan|null $lifespan |
|
187 | - * @param RequestInterface $request |
|
188 | - * @param SessionStartHandler $session_start_handler |
|
189 | - * @param EE_Encryption $encryption |
|
190 | - * @return EE_Session |
|
191 | - * @throws InvalidArgumentException |
|
192 | - * @throws InvalidDataTypeException |
|
193 | - * @throws InvalidInterfaceException |
|
194 | - */ |
|
195 | - public static function instance( |
|
196 | - CacheStorageInterface $cache_storage = null, |
|
197 | - SessionLifespan $lifespan = null, |
|
198 | - RequestInterface $request = null, |
|
199 | - SessionStartHandler $session_start_handler = null, |
|
200 | - EE_Encryption $encryption = null |
|
201 | - ) { |
|
202 | - // check if class object is instantiated |
|
203 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
204 | - // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
205 | - if ( |
|
206 | - ! self::$_instance instanceof EE_Session |
|
207 | - && $cache_storage instanceof CacheStorageInterface |
|
208 | - && $lifespan instanceof SessionLifespan |
|
209 | - && $request instanceof RequestInterface |
|
210 | - && $session_start_handler instanceof SessionStartHandler |
|
211 | - && apply_filters('FHEE_load_EE_Session', true) |
|
212 | - ) { |
|
213 | - self::$_instance = new self( |
|
214 | - $cache_storage, |
|
215 | - $lifespan, |
|
216 | - $request, |
|
217 | - $session_start_handler, |
|
218 | - $encryption |
|
219 | - ); |
|
220 | - } |
|
221 | - return self::$_instance; |
|
222 | - } |
|
223 | - |
|
224 | - |
|
225 | - /** |
|
226 | - * protected constructor to prevent direct creation |
|
227 | - * |
|
228 | - * @param CacheStorageInterface $cache_storage |
|
229 | - * @param SessionLifespan $lifespan |
|
230 | - * @param RequestInterface $request |
|
231 | - * @param SessionStartHandler $session_start_handler |
|
232 | - * @param EE_Encryption $encryption |
|
233 | - * @throws InvalidArgumentException |
|
234 | - * @throws InvalidDataTypeException |
|
235 | - * @throws InvalidInterfaceException |
|
236 | - */ |
|
237 | - protected function __construct( |
|
238 | - CacheStorageInterface $cache_storage, |
|
239 | - SessionLifespan $lifespan, |
|
240 | - RequestInterface $request, |
|
241 | - SessionStartHandler $session_start_handler, |
|
242 | - EE_Encryption $encryption = null |
|
243 | - ) { |
|
244 | - // session loading is turned ON by default, |
|
245 | - // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
|
246 | - // (which currently fires on the init hook at priority 9), |
|
247 | - // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
248 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | - return; |
|
250 | - } |
|
251 | - $this->session_start_handler = $session_start_handler; |
|
252 | - $this->session_lifespan = $lifespan; |
|
253 | - $this->request = $request; |
|
254 | - if (! defined('ESPRESSO_SESSION')) { |
|
255 | - define('ESPRESSO_SESSION', true); |
|
256 | - } |
|
257 | - // retrieve session options from db |
|
258 | - $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
259 | - if (! empty($session_settings)) { |
|
260 | - // cycle though existing session options |
|
261 | - foreach ($session_settings as $var_name => $session_setting) { |
|
262 | - // set values for class properties |
|
263 | - $var_name = '_' . $var_name; |
|
264 | - $this->{$var_name} = $session_setting; |
|
265 | - } |
|
266 | - } |
|
267 | - $this->cache_storage = $cache_storage; |
|
268 | - // are we using encryption? |
|
269 | - $this->_use_encryption = $encryption instanceof EE_Encryption |
|
270 | - && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
271 | - // encrypt data via: $this->encryption->encrypt(); |
|
272 | - $this->encryption = $encryption; |
|
273 | - // filter hook allows outside functions/classes/plugins to change default empty cart |
|
274 | - $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
275 | - array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
276 | - // apply default session vars |
|
277 | - $this->_set_defaults(); |
|
278 | - add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
279 | - // check request for 'clear_session' param |
|
280 | - add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
281 | - // once everything is all said and done, |
|
282 | - add_action('shutdown', array($this, 'update'), 100); |
|
283 | - add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
284 | - $this->configure_garbage_collection_filters(); |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * @return bool |
|
290 | - * @throws InvalidArgumentException |
|
291 | - * @throws InvalidDataTypeException |
|
292 | - * @throws InvalidInterfaceException |
|
293 | - */ |
|
294 | - public static function isLoadedAndActive() |
|
295 | - { |
|
296 | - return did_action('AHEE__EE_System__core_loaded_and_ready') |
|
297 | - && EE_Session::instance() instanceof EE_Session |
|
298 | - && EE_Session::instance()->isActive(); |
|
299 | - } |
|
300 | - |
|
301 | - |
|
302 | - /** |
|
303 | - * @return bool |
|
304 | - */ |
|
305 | - public function isActive() |
|
306 | - { |
|
307 | - return $this->status === EE_Session::STATUS_OPEN; |
|
308 | - } |
|
309 | - |
|
310 | - |
|
311 | - /** |
|
312 | - * @return void |
|
313 | - * @throws EE_Error |
|
314 | - * @throws InvalidArgumentException |
|
315 | - * @throws InvalidDataTypeException |
|
316 | - * @throws InvalidInterfaceException |
|
317 | - * @throws InvalidSessionDataException |
|
318 | - * @throws RuntimeException |
|
319 | - * @throws ReflectionException |
|
320 | - */ |
|
321 | - public function open_session() |
|
322 | - { |
|
323 | - // check for existing session and retrieve it from db |
|
324 | - if (! $this->_espresso_session()) { |
|
325 | - // or just start a new one |
|
326 | - $this->_create_espresso_session(); |
|
327 | - } |
|
328 | - } |
|
329 | - |
|
330 | - |
|
331 | - /** |
|
332 | - * @return bool |
|
333 | - */ |
|
334 | - public function expired() |
|
335 | - { |
|
336 | - return $this->_expired; |
|
337 | - } |
|
338 | - |
|
339 | - |
|
340 | - /** |
|
341 | - * @return void |
|
342 | - */ |
|
343 | - public function reset_expired() |
|
344 | - { |
|
345 | - $this->_expired = false; |
|
346 | - } |
|
347 | - |
|
348 | - |
|
349 | - /** |
|
350 | - * @return int |
|
351 | - */ |
|
352 | - public function expiration() |
|
353 | - { |
|
354 | - return $this->_expiration; |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * @return int |
|
360 | - */ |
|
361 | - public function extension() |
|
362 | - { |
|
363 | - return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - /** |
|
368 | - * @param int $time number of seconds to add to session expiration |
|
369 | - */ |
|
370 | - public function extend_expiration($time = 0) |
|
371 | - { |
|
372 | - $time = $time ? $time : $this->extension(); |
|
373 | - $this->_expiration += absint($time); |
|
374 | - } |
|
375 | - |
|
376 | - |
|
377 | - /** |
|
378 | - * @return int |
|
379 | - */ |
|
380 | - public function lifespan() |
|
381 | - { |
|
382 | - return $this->session_lifespan->inSeconds(); |
|
383 | - } |
|
384 | - |
|
385 | - |
|
386 | - /** |
|
387 | - * Marks whether the session data has been updated or not. |
|
388 | - * Valid options are: |
|
389 | - * EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary |
|
390 | - * EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated |
|
391 | - * default value is EE_Session::SAVE_STATE_DIRTY |
|
392 | - * |
|
393 | - * @param string $save_state |
|
394 | - */ |
|
395 | - public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) |
|
396 | - { |
|
397 | - $valid_save_states = [ |
|
398 | - EE_Session::SAVE_STATE_CLEAN, |
|
399 | - EE_Session::SAVE_STATE_DIRTY, |
|
400 | - ]; |
|
401 | - if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | - $save_state = EE_Session::SAVE_STATE_DIRTY; |
|
403 | - } |
|
404 | - $this->save_state = $save_state; |
|
405 | - } |
|
406 | - |
|
407 | - |
|
408 | - |
|
409 | - /** |
|
410 | - * This just sets some defaults for the _session data property |
|
411 | - * |
|
412 | - * @return void |
|
413 | - */ |
|
414 | - private function _set_defaults() |
|
415 | - { |
|
416 | - // set some defaults |
|
417 | - foreach ($this->_default_session_vars as $key => $default_var) { |
|
418 | - if (is_array($default_var)) { |
|
419 | - $this->_session_data[ $key ] = array(); |
|
420 | - } else { |
|
421 | - $this->_session_data[ $key ] = ''; |
|
422 | - } |
|
423 | - } |
|
424 | - } |
|
425 | - |
|
426 | - |
|
427 | - /** |
|
428 | - * @retrieve session data |
|
429 | - * @return string |
|
430 | - */ |
|
431 | - public function id() |
|
432 | - { |
|
433 | - return $this->_sid; |
|
434 | - } |
|
435 | - |
|
436 | - |
|
437 | - /** |
|
438 | - * @param \EE_Cart $cart |
|
439 | - * @return bool |
|
440 | - */ |
|
441 | - public function set_cart(EE_Cart $cart) |
|
442 | - { |
|
443 | - $this->_session_data['cart'] = $cart; |
|
444 | - $this->setSaveState(); |
|
445 | - return true; |
|
446 | - } |
|
447 | - |
|
448 | - |
|
449 | - /** |
|
450 | - * reset_cart |
|
451 | - */ |
|
452 | - public function reset_cart() |
|
453 | - { |
|
454 | - do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
455 | - $this->_session_data['cart'] = null; |
|
456 | - $this->setSaveState(); |
|
457 | - } |
|
458 | - |
|
459 | - |
|
460 | - /** |
|
461 | - * @return \EE_Cart |
|
462 | - */ |
|
463 | - public function cart() |
|
464 | - { |
|
465 | - return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
466 | - ? $this->_session_data['cart'] |
|
467 | - : null; |
|
468 | - } |
|
469 | - |
|
470 | - |
|
471 | - /** |
|
472 | - * @param \EE_Checkout $checkout |
|
473 | - * @return bool |
|
474 | - */ |
|
475 | - public function set_checkout(EE_Checkout $checkout) |
|
476 | - { |
|
477 | - $this->_session_data['checkout'] = $checkout; |
|
478 | - $this->setSaveState(); |
|
479 | - return true; |
|
480 | - } |
|
481 | - |
|
482 | - |
|
483 | - /** |
|
484 | - * reset_checkout |
|
485 | - */ |
|
486 | - public function reset_checkout() |
|
487 | - { |
|
488 | - do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
489 | - $this->_session_data['checkout'] = null; |
|
490 | - $this->setSaveState(); |
|
491 | - } |
|
492 | - |
|
493 | - |
|
494 | - /** |
|
495 | - * @return \EE_Checkout |
|
496 | - */ |
|
497 | - public function checkout() |
|
498 | - { |
|
499 | - return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
500 | - ? $this->_session_data['checkout'] |
|
501 | - : null; |
|
502 | - } |
|
503 | - |
|
504 | - |
|
505 | - /** |
|
506 | - * @param \EE_Transaction $transaction |
|
507 | - * @return bool |
|
508 | - * @throws EE_Error |
|
509 | - */ |
|
510 | - public function set_transaction(EE_Transaction $transaction) |
|
511 | - { |
|
512 | - // first remove the session from the transaction before we save the transaction in the session |
|
513 | - $transaction->set_txn_session_data(null); |
|
514 | - $this->_session_data['transaction'] = $transaction; |
|
515 | - $this->setSaveState(); |
|
516 | - return true; |
|
517 | - } |
|
518 | - |
|
519 | - |
|
520 | - /** |
|
521 | - * reset_transaction |
|
522 | - */ |
|
523 | - public function reset_transaction() |
|
524 | - { |
|
525 | - do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
526 | - $this->_session_data['transaction'] = null; |
|
527 | - $this->setSaveState(); |
|
528 | - } |
|
529 | - |
|
530 | - |
|
531 | - /** |
|
532 | - * @return \EE_Transaction |
|
533 | - */ |
|
534 | - public function transaction() |
|
535 | - { |
|
536 | - return isset($this->_session_data['transaction']) |
|
537 | - && $this->_session_data['transaction'] instanceof EE_Transaction |
|
538 | - ? $this->_session_data['transaction'] |
|
539 | - : null; |
|
540 | - } |
|
541 | - |
|
542 | - |
|
543 | - /** |
|
544 | - * retrieve session data |
|
545 | - * |
|
546 | - * @param null $key |
|
547 | - * @param bool $reset_cache |
|
548 | - * @return array |
|
549 | - */ |
|
550 | - public function get_session_data($key = null, $reset_cache = false) |
|
551 | - { |
|
552 | - if ($reset_cache) { |
|
553 | - $this->reset_cart(); |
|
554 | - $this->reset_checkout(); |
|
555 | - $this->reset_transaction(); |
|
556 | - } |
|
557 | - if (! empty($key)) { |
|
558 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
559 | - } |
|
560 | - return $this->_session_data; |
|
561 | - } |
|
562 | - |
|
563 | - |
|
564 | - /** |
|
565 | - * Returns TRUE on success, FALSE on fail |
|
566 | - * |
|
567 | - * @param array $data |
|
568 | - * @return bool |
|
569 | - */ |
|
570 | - public function set_session_data($data) |
|
571 | - { |
|
572 | - // nothing ??? bad data ??? go home! |
|
573 | - if (empty($data) || ! is_array($data)) { |
|
574 | - EE_Error::add_error( |
|
575 | - esc_html__( |
|
576 | - 'No session data or invalid session data was provided.', |
|
577 | - 'event_espresso' |
|
578 | - ), |
|
579 | - __FILE__, |
|
580 | - __FUNCTION__, |
|
581 | - __LINE__ |
|
582 | - ); |
|
583 | - return false; |
|
584 | - } |
|
585 | - foreach ($data as $key => $value) { |
|
586 | - if (isset($this->_default_session_vars[ $key ])) { |
|
587 | - EE_Error::add_error( |
|
588 | - sprintf( |
|
589 | - esc_html__( |
|
590 | - 'Sorry! %s is a default session datum and can not be reset.', |
|
591 | - 'event_espresso' |
|
592 | - ), |
|
593 | - $key |
|
594 | - ), |
|
595 | - __FILE__, |
|
596 | - __FUNCTION__, |
|
597 | - __LINE__ |
|
598 | - ); |
|
599 | - return false; |
|
600 | - } |
|
601 | - $this->_session_data[ $key ] = $value; |
|
602 | - $this->setSaveState(); |
|
603 | - } |
|
604 | - return true; |
|
605 | - } |
|
606 | - |
|
607 | - |
|
608 | - /** |
|
609 | - * @initiate session |
|
610 | - * @return bool TRUE on success, FALSE on fail |
|
611 | - * @throws EE_Error |
|
612 | - * @throws InvalidArgumentException |
|
613 | - * @throws InvalidDataTypeException |
|
614 | - * @throws InvalidInterfaceException |
|
615 | - * @throws InvalidSessionDataException |
|
616 | - * @throws RuntimeException |
|
617 | - * @throws ReflectionException |
|
618 | - */ |
|
619 | - private function _espresso_session() |
|
620 | - { |
|
621 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
622 | - $this->session_start_handler->startSession(); |
|
623 | - $this->status = EE_Session::STATUS_OPEN; |
|
624 | - // get our modified session ID |
|
625 | - $this->_sid = $this->_generate_session_id(); |
|
626 | - // and the visitors IP |
|
627 | - $this->_ip_address = $this->request->ipAddress(); |
|
628 | - // set the "user agent" |
|
629 | - $this->_user_agent = $this->request->userAgent(); |
|
630 | - // now let's retrieve what's in the db |
|
631 | - $session_data = $this->_retrieve_session_data(); |
|
632 | - if (! empty($session_data)) { |
|
633 | - // get the current time in UTC |
|
634 | - $this->_time = $this->_time !== null ? $this->_time : time(); |
|
635 | - // and reset the session expiration |
|
636 | - $this->_expiration = isset($session_data['expiration']) |
|
637 | - ? $session_data['expiration'] |
|
638 | - : $this->_time + $this->session_lifespan->inSeconds(); |
|
639 | - } else { |
|
640 | - // set initial site access time and the session expiration |
|
641 | - $this->_set_init_access_and_expiration(); |
|
642 | - // set referer |
|
643 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | - $this->request->getServerParam('HTTP_REFERER') |
|
645 | - ); |
|
646 | - // no previous session = go back and create one (on top of the data above) |
|
647 | - return false; |
|
648 | - } |
|
649 | - // now the user agent |
|
650 | - if ($session_data['user_agent'] !== $this->_user_agent) { |
|
651 | - return false; |
|
652 | - } |
|
653 | - // wait a minute... how old are you? |
|
654 | - if ($this->_time > $this->_expiration) { |
|
655 | - // yer too old fer me! |
|
656 | - $this->_expired = true; |
|
657 | - // wipe out everything that isn't a default session datum |
|
658 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
659 | - } |
|
660 | - // make event espresso session data available to plugin |
|
661 | - $this->_session_data = array_merge($this->_session_data, $session_data); |
|
662 | - return true; |
|
663 | - } |
|
664 | - |
|
665 | - |
|
666 | - /** |
|
667 | - * _get_session_data |
|
668 | - * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
669 | - * databases |
|
670 | - * |
|
671 | - * @return array |
|
672 | - * @throws EE_Error |
|
673 | - * @throws InvalidArgumentException |
|
674 | - * @throws InvalidSessionDataException |
|
675 | - * @throws InvalidDataTypeException |
|
676 | - * @throws InvalidInterfaceException |
|
677 | - * @throws RuntimeException |
|
678 | - */ |
|
679 | - protected function _retrieve_session_data() |
|
680 | - { |
|
681 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | - try { |
|
683 | - // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
684 | - $session_data = $this->cache_storage->get($ssn_key, false); |
|
685 | - if (empty($session_data)) { |
|
686 | - return array(); |
|
687 | - } |
|
688 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
689 | - $hash_check = $this->cache_storage->get( |
|
690 | - EE_Session::hash_check_prefix . $this->_sid, |
|
691 | - false |
|
692 | - ); |
|
693 | - if ($hash_check && $hash_check !== md5($session_data)) { |
|
694 | - EE_Error::add_error( |
|
695 | - sprintf( |
|
696 | - esc_html__( |
|
697 | - 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
698 | - 'event_espresso' |
|
699 | - ), |
|
700 | - EE_Session::session_id_prefix . $this->_sid |
|
701 | - ), |
|
702 | - __FILE__, |
|
703 | - __FUNCTION__, |
|
704 | - __LINE__ |
|
705 | - ); |
|
706 | - } |
|
707 | - } |
|
708 | - } catch (Exception $e) { |
|
709 | - // let's just eat that error for now and attempt to correct any corrupted data |
|
710 | - global $wpdb; |
|
711 | - $row = $wpdb->get_row( |
|
712 | - $wpdb->prepare( |
|
713 | - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
714 | - '_transient_' . $ssn_key |
|
715 | - ) |
|
716 | - ); |
|
717 | - $session_data = is_object($row) ? $row->option_value : null; |
|
718 | - if ($session_data) { |
|
719 | - $session_data = preg_replace_callback( |
|
720 | - '!s:(d+):"(.*?)";!', |
|
721 | - function ($match) { |
|
722 | - return $match[1] === strlen($match[2]) |
|
723 | - ? $match[0] |
|
724 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | - }, |
|
726 | - $session_data |
|
727 | - ); |
|
728 | - } |
|
729 | - $session_data = maybe_unserialize($session_data); |
|
730 | - } |
|
731 | - // in case the data is encoded... try to decode it |
|
732 | - $session_data = $this->encryption instanceof EE_Encryption |
|
733 | - ? $this->encryption->base64_string_decode($session_data) |
|
734 | - : $session_data; |
|
735 | - if (! is_array($session_data)) { |
|
736 | - try { |
|
737 | - $session_data = maybe_unserialize($session_data); |
|
738 | - } catch (Exception $e) { |
|
739 | - $msg = esc_html__( |
|
740 | - 'An error occurred while attempting to unserialize the session data.', |
|
741 | - 'event_espresso' |
|
742 | - ); |
|
743 | - $msg .= WP_DEBUG |
|
744 | - ? '<br><pre>' |
|
745 | - . print_r($session_data, true) |
|
746 | - . '</pre><br>' |
|
747 | - . $this->find_serialize_error($session_data) |
|
748 | - : ''; |
|
749 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | - throw new InvalidSessionDataException($msg, 0, $e); |
|
751 | - } |
|
752 | - } |
|
753 | - // just a check to make sure the session array is indeed an array |
|
754 | - if (! is_array($session_data)) { |
|
755 | - // no?!?! then something is wrong |
|
756 | - $msg = esc_html__( |
|
757 | - 'The session data is missing, invalid, or corrupted.', |
|
758 | - 'event_espresso' |
|
759 | - ); |
|
760 | - $msg .= WP_DEBUG |
|
761 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | - : ''; |
|
763 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | - throw new InvalidSessionDataException($msg); |
|
765 | - } |
|
766 | - if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
767 | - $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
768 | - $session_data['transaction'] |
|
769 | - ); |
|
770 | - } |
|
771 | - return $session_data; |
|
772 | - } |
|
773 | - |
|
774 | - |
|
775 | - /** |
|
776 | - * _generate_session_id |
|
777 | - * Retrieves the PHP session id either directly from the PHP session, |
|
778 | - * or from the request array if it was passed in from an AJAX request. |
|
779 | - * The session id is then salted and hashed (mmm sounds tasty) |
|
780 | - * so that it can be safely used as a request param |
|
781 | - * |
|
782 | - * @return string |
|
783 | - */ |
|
784 | - protected function _generate_session_id() |
|
785 | - { |
|
786 | - // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
787 | - $session_id = $this->request->requestParamIsSet('EESID') |
|
788 | - ? $this->request->getRequestParam('EESID') |
|
789 | - : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | - return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
791 | - } |
|
792 | - |
|
793 | - |
|
794 | - /** |
|
795 | - * _get_sid_salt |
|
796 | - * |
|
797 | - * @return string |
|
798 | - */ |
|
799 | - protected function _get_sid_salt() |
|
800 | - { |
|
801 | - // was session id salt already saved to db ? |
|
802 | - if (empty($this->_sid_salt)) { |
|
803 | - // no? then maybe use WP defined constant |
|
804 | - if (defined('AUTH_SALT')) { |
|
805 | - $this->_sid_salt = AUTH_SALT; |
|
806 | - } |
|
807 | - // if salt doesn't exist or is too short |
|
808 | - if (strlen($this->_sid_salt) < 32) { |
|
809 | - // create a new one |
|
810 | - $this->_sid_salt = wp_generate_password(64); |
|
811 | - } |
|
812 | - // and save it as a permanent session setting |
|
813 | - $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
814 | - } |
|
815 | - return $this->_sid_salt; |
|
816 | - } |
|
817 | - |
|
818 | - |
|
819 | - /** |
|
820 | - * _set_init_access_and_expiration |
|
821 | - * |
|
822 | - * @return void |
|
823 | - */ |
|
824 | - protected function _set_init_access_and_expiration() |
|
825 | - { |
|
826 | - $this->_time = time(); |
|
827 | - $this->_expiration = $this->_time + $this->session_lifespan->inSeconds(); |
|
828 | - // set initial site access time |
|
829 | - $this->_session_data['init_access'] = $this->_time; |
|
830 | - // and the session expiration |
|
831 | - $this->_session_data['expiration'] = $this->_expiration; |
|
832 | - } |
|
833 | - |
|
834 | - |
|
835 | - /** |
|
836 | - * @update session data prior to saving to the db |
|
837 | - * @param bool $new_session |
|
838 | - * @return bool TRUE on success, FALSE on fail |
|
839 | - * @throws EE_Error |
|
840 | - * @throws InvalidArgumentException |
|
841 | - * @throws InvalidDataTypeException |
|
842 | - * @throws InvalidInterfaceException |
|
843 | - * @throws ReflectionException |
|
844 | - */ |
|
845 | - public function update($new_session = false) |
|
846 | - { |
|
847 | - $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id']) |
|
848 | - ? $this->_session_data |
|
849 | - : array(); |
|
850 | - if (empty($this->_session_data)) { |
|
851 | - $this->_set_defaults(); |
|
852 | - } |
|
853 | - $session_data = array(); |
|
854 | - foreach ($this->_session_data as $key => $value) { |
|
855 | - switch ($key) { |
|
856 | - case 'id': |
|
857 | - // session ID |
|
858 | - $session_data['id'] = $this->_sid; |
|
859 | - break; |
|
860 | - case 'ip_address': |
|
861 | - // visitor ip address |
|
862 | - $session_data['ip_address'] = $this->request->ipAddress(); |
|
863 | - break; |
|
864 | - case 'user_agent': |
|
865 | - // visitor user_agent |
|
866 | - $session_data['user_agent'] = $this->_user_agent; |
|
867 | - break; |
|
868 | - case 'init_access': |
|
869 | - $session_data['init_access'] = absint($value); |
|
870 | - break; |
|
871 | - case 'last_access': |
|
872 | - // current access time |
|
873 | - $session_data['last_access'] = $this->_time; |
|
874 | - break; |
|
875 | - case 'expiration': |
|
876 | - // when the session expires |
|
877 | - $session_data['expiration'] = ! empty($this->_expiration) |
|
878 | - ? $this->_expiration |
|
879 | - : $session_data['init_access'] + $this->session_lifespan->inSeconds(); |
|
880 | - break; |
|
881 | - case 'user_id': |
|
882 | - // current user if logged in |
|
883 | - $session_data['user_id'] = $this->_wp_user_id(); |
|
884 | - break; |
|
885 | - case 'pages_visited': |
|
886 | - $page_visit = $this->_get_page_visit(); |
|
887 | - if ($page_visit) { |
|
888 | - // set pages visited where the first will be the http referrer |
|
889 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
890 | - // we'll only save the last 10 page visits. |
|
891 | - $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
892 | - } |
|
893 | - break; |
|
894 | - default: |
|
895 | - // carry any other data over |
|
896 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
897 | - } |
|
898 | - } |
|
899 | - $this->_session_data = $session_data; |
|
900 | - // creating a new session does not require saving to the db just yet |
|
901 | - if (! $new_session) { |
|
902 | - // ready? let's save |
|
903 | - if ($this->_save_session_to_db()) { |
|
904 | - return true; |
|
905 | - } |
|
906 | - return false; |
|
907 | - } |
|
908 | - // meh, why not? |
|
909 | - return true; |
|
910 | - } |
|
911 | - |
|
912 | - |
|
913 | - /** |
|
914 | - * @create session data array |
|
915 | - * @throws EE_Error |
|
916 | - * @throws InvalidArgumentException |
|
917 | - * @throws InvalidDataTypeException |
|
918 | - * @throws InvalidInterfaceException |
|
919 | - * @throws ReflectionException |
|
920 | - */ |
|
921 | - private function _create_espresso_session() |
|
922 | - { |
|
923 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
924 | - // use the update function for now with $new_session arg set to TRUE |
|
925 | - $this->update(true); |
|
926 | - } |
|
927 | - |
|
928 | - /** |
|
929 | - * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good |
|
930 | - * too). This is used when determining if we want to save the session or not. |
|
931 | - * @since 4.9.67.p |
|
932 | - * @return bool |
|
933 | - */ |
|
934 | - private function sessionHasStuffWorthSaving() |
|
935 | - { |
|
936 | - return $this->save_state === EE_Session::SAVE_STATE_DIRTY |
|
937 | - // we may want to eventually remove the following |
|
938 | - // on the assumption that the above check is enough |
|
939 | - || $this->cart() instanceof EE_Cart |
|
940 | - || ( |
|
941 | - isset($this->_session_data['ee_notices']) |
|
942 | - && ( |
|
943 | - ! empty($this->_session_data['ee_notices']['attention']) |
|
944 | - || ! empty($this->_session_data['ee_notices']['errors']) |
|
945 | - || ! empty($this->_session_data['ee_notices']['success']) |
|
946 | - ) |
|
947 | - ); |
|
948 | - } |
|
949 | - |
|
950 | - |
|
951 | - /** |
|
952 | - * _save_session_to_db |
|
953 | - * |
|
954 | - * @param bool $clear_session |
|
955 | - * @return bool |
|
956 | - * @throws EE_Error |
|
957 | - * @throws InvalidArgumentException |
|
958 | - * @throws InvalidDataTypeException |
|
959 | - * @throws InvalidInterfaceException |
|
960 | - * @throws ReflectionException |
|
961 | - */ |
|
962 | - private function _save_session_to_db($clear_session = false) |
|
963 | - { |
|
964 | - // don't save sessions for crawlers |
|
965 | - // and unless we're deleting the session data, don't save anything if there isn't a cart |
|
966 | - if ( |
|
967 | - $this->request->isBot() |
|
968 | - || ( |
|
969 | - ! $clear_session |
|
970 | - && ! $this->sessionHasStuffWorthSaving() |
|
971 | - && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true) |
|
972 | - ) |
|
973 | - ) { |
|
974 | - return false; |
|
975 | - } |
|
976 | - $transaction = $this->transaction(); |
|
977 | - if ($transaction instanceof EE_Transaction) { |
|
978 | - if (! $transaction->ID()) { |
|
979 | - $transaction->save(); |
|
980 | - } |
|
981 | - $this->_session_data['transaction'] = $transaction->ID(); |
|
982 | - } |
|
983 | - // then serialize all of our session data |
|
984 | - $session_data = serialize($this->_session_data); |
|
985 | - // do we need to also encode it to avoid corrupted data when saved to the db? |
|
986 | - $session_data = $this->_use_encryption |
|
987 | - ? $this->encryption->base64_string_encode($session_data) |
|
988 | - : $session_data; |
|
989 | - // maybe save hash check |
|
990 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
991 | - $this->cache_storage->add( |
|
992 | - EE_Session::hash_check_prefix . $this->_sid, |
|
993 | - md5($session_data), |
|
994 | - $this->session_lifespan->inSeconds() |
|
995 | - ); |
|
996 | - } |
|
997 | - // we're using the Transient API for storing session data, |
|
998 | - $saved = $this->cache_storage->add( |
|
999 | - EE_Session::session_id_prefix . $this->_sid, |
|
1000 | - $session_data, |
|
1001 | - $this->session_lifespan->inSeconds() |
|
1002 | - ); |
|
1003 | - $this->setSaveState(EE_Session::SAVE_STATE_CLEAN); |
|
1004 | - return $saved; |
|
1005 | - } |
|
1006 | - |
|
1007 | - |
|
1008 | - /** |
|
1009 | - * @get the full page request the visitor is accessing |
|
1010 | - * @return string |
|
1011 | - */ |
|
1012 | - public function _get_page_visit() |
|
1013 | - { |
|
1014 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1015 | - // check for request url |
|
1016 | - if ($this->request->serverParamIsSet('REQUEST_URI')) { |
|
1017 | - $page_id = '?'; |
|
1018 | - $e_reg = ''; |
|
1019 | - $request_uri = $this->request->getServerParam('REQUEST_URI'); |
|
1020 | - $ru_bits = explode('?', $request_uri); |
|
1021 | - $request_uri = $ru_bits[0]; |
|
1022 | - $http_host = $this->request->getServerParam('HTTP_HOST'); |
|
1023 | - // check for page_id in SERVER REQUEST |
|
1024 | - if ($this->request->requestParamIsSet('page_id')) { |
|
1025 | - // rebuild $e_reg without any of the extra parameters |
|
1026 | - $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1027 | - } |
|
1028 | - // check for $e_reg in SERVER REQUEST |
|
1029 | - if ($this->request->requestParamIsSet('ee')) { |
|
1030 | - // rebuild $e_reg without any of the extra parameters |
|
1031 | - $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1032 | - } |
|
1033 | - $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1034 | - } |
|
1035 | - return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
1036 | - } |
|
1037 | - |
|
1038 | - |
|
1039 | - /** |
|
1040 | - * @the current wp user id |
|
1041 | - * @return int |
|
1042 | - */ |
|
1043 | - public function _wp_user_id() |
|
1044 | - { |
|
1045 | - // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
1046 | - $this->_wp_user_id = get_current_user_id(); |
|
1047 | - return $this->_wp_user_id; |
|
1048 | - } |
|
1049 | - |
|
1050 | - |
|
1051 | - /** |
|
1052 | - * Clear EE_Session data |
|
1053 | - * |
|
1054 | - * @param string $class |
|
1055 | - * @param string $function |
|
1056 | - * @return void |
|
1057 | - * @throws EE_Error |
|
1058 | - * @throws InvalidArgumentException |
|
1059 | - * @throws InvalidDataTypeException |
|
1060 | - * @throws InvalidInterfaceException |
|
1061 | - * @throws ReflectionException |
|
1062 | - */ |
|
1063 | - public function clear_session($class = '', $function = '') |
|
1064 | - { |
|
26 | + const session_id_prefix = 'ee_ssn_'; |
|
27 | + |
|
28 | + const hash_check_prefix = 'ee_shc_'; |
|
29 | + |
|
30 | + const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
31 | + |
|
32 | + const STATUS_CLOSED = 0; |
|
33 | + |
|
34 | + const STATUS_OPEN = 1; |
|
35 | + |
|
36 | + const SAVE_STATE_CLEAN = 'clean'; |
|
37 | + const SAVE_STATE_DIRTY = 'dirty'; |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * instance of the EE_Session object |
|
42 | + * |
|
43 | + * @var EE_Session |
|
44 | + */ |
|
45 | + private static $_instance; |
|
46 | + |
|
47 | + /** |
|
48 | + * @var CacheStorageInterface $cache_storage |
|
49 | + */ |
|
50 | + protected $cache_storage; |
|
51 | + |
|
52 | + /** |
|
53 | + * @var EE_Encryption $encryption |
|
54 | + */ |
|
55 | + protected $encryption; |
|
56 | + |
|
57 | + /** |
|
58 | + * @var SessionStartHandler $session_start_handler |
|
59 | + */ |
|
60 | + protected $session_start_handler; |
|
61 | + |
|
62 | + /** |
|
63 | + * the session id |
|
64 | + * |
|
65 | + * @var string |
|
66 | + */ |
|
67 | + private $_sid; |
|
68 | + |
|
69 | + /** |
|
70 | + * session id salt |
|
71 | + * |
|
72 | + * @var string |
|
73 | + */ |
|
74 | + private $_sid_salt; |
|
75 | + |
|
76 | + /** |
|
77 | + * session data |
|
78 | + * |
|
79 | + * @var array |
|
80 | + */ |
|
81 | + private $_session_data = array(); |
|
82 | + |
|
83 | + /** |
|
84 | + * how long an EE session lasts |
|
85 | + * default session lifespan of 1 hour (for not so instant IPNs) |
|
86 | + * |
|
87 | + * @var SessionLifespan $session_lifespan |
|
88 | + */ |
|
89 | + private $session_lifespan; |
|
90 | + |
|
91 | + /** |
|
92 | + * session expiration time as Unix timestamp in GMT |
|
93 | + * |
|
94 | + * @var int |
|
95 | + */ |
|
96 | + private $_expiration; |
|
97 | + |
|
98 | + /** |
|
99 | + * whether or not session has expired at some point |
|
100 | + * |
|
101 | + * @var boolean |
|
102 | + */ |
|
103 | + private $_expired = false; |
|
104 | + |
|
105 | + /** |
|
106 | + * current time as Unix timestamp in GMT |
|
107 | + * |
|
108 | + * @var int |
|
109 | + */ |
|
110 | + private $_time; |
|
111 | + |
|
112 | + /** |
|
113 | + * whether to encrypt session data |
|
114 | + * |
|
115 | + * @var bool |
|
116 | + */ |
|
117 | + private $_use_encryption; |
|
118 | + |
|
119 | + /** |
|
120 | + * well... according to the server... |
|
121 | + * |
|
122 | + * @var null |
|
123 | + */ |
|
124 | + private $_user_agent; |
|
125 | + |
|
126 | + /** |
|
127 | + * do you really trust the server ? |
|
128 | + * |
|
129 | + * @var null |
|
130 | + */ |
|
131 | + private $_ip_address; |
|
132 | + |
|
133 | + /** |
|
134 | + * current WP user_id |
|
135 | + * |
|
136 | + * @var null |
|
137 | + */ |
|
138 | + private $_wp_user_id; |
|
139 | + |
|
140 | + /** |
|
141 | + * array for defining default session vars |
|
142 | + * |
|
143 | + * @var array |
|
144 | + */ |
|
145 | + private $_default_session_vars = array( |
|
146 | + 'id' => null, |
|
147 | + 'user_id' => null, |
|
148 | + 'ip_address' => null, |
|
149 | + 'user_agent' => null, |
|
150 | + 'init_access' => null, |
|
151 | + 'last_access' => null, |
|
152 | + 'expiration' => null, |
|
153 | + 'pages_visited' => array(), |
|
154 | + ); |
|
155 | + |
|
156 | + /** |
|
157 | + * timestamp for when last garbage collection cycle was performed |
|
158 | + * |
|
159 | + * @var int $_last_gc |
|
160 | + */ |
|
161 | + private $_last_gc; |
|
162 | + |
|
163 | + /** |
|
164 | + * @var RequestInterface $request |
|
165 | + */ |
|
166 | + protected $request; |
|
167 | + |
|
168 | + /** |
|
169 | + * whether session is active or not |
|
170 | + * |
|
171 | + * @var int $status |
|
172 | + */ |
|
173 | + private $status = EE_Session::STATUS_CLOSED; |
|
174 | + |
|
175 | + /** |
|
176 | + * whether session data has changed therefore requiring a session save |
|
177 | + * |
|
178 | + * @var string $save_state |
|
179 | + */ |
|
180 | + private $save_state = EE_Session::SAVE_STATE_CLEAN; |
|
181 | + |
|
182 | + |
|
183 | + /** |
|
184 | + * @singleton method used to instantiate class object |
|
185 | + * @param CacheStorageInterface $cache_storage |
|
186 | + * @param SessionLifespan|null $lifespan |
|
187 | + * @param RequestInterface $request |
|
188 | + * @param SessionStartHandler $session_start_handler |
|
189 | + * @param EE_Encryption $encryption |
|
190 | + * @return EE_Session |
|
191 | + * @throws InvalidArgumentException |
|
192 | + * @throws InvalidDataTypeException |
|
193 | + * @throws InvalidInterfaceException |
|
194 | + */ |
|
195 | + public static function instance( |
|
196 | + CacheStorageInterface $cache_storage = null, |
|
197 | + SessionLifespan $lifespan = null, |
|
198 | + RequestInterface $request = null, |
|
199 | + SessionStartHandler $session_start_handler = null, |
|
200 | + EE_Encryption $encryption = null |
|
201 | + ) { |
|
202 | + // check if class object is instantiated |
|
203 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
204 | + // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
205 | + if ( |
|
206 | + ! self::$_instance instanceof EE_Session |
|
207 | + && $cache_storage instanceof CacheStorageInterface |
|
208 | + && $lifespan instanceof SessionLifespan |
|
209 | + && $request instanceof RequestInterface |
|
210 | + && $session_start_handler instanceof SessionStartHandler |
|
211 | + && apply_filters('FHEE_load_EE_Session', true) |
|
212 | + ) { |
|
213 | + self::$_instance = new self( |
|
214 | + $cache_storage, |
|
215 | + $lifespan, |
|
216 | + $request, |
|
217 | + $session_start_handler, |
|
218 | + $encryption |
|
219 | + ); |
|
220 | + } |
|
221 | + return self::$_instance; |
|
222 | + } |
|
223 | + |
|
224 | + |
|
225 | + /** |
|
226 | + * protected constructor to prevent direct creation |
|
227 | + * |
|
228 | + * @param CacheStorageInterface $cache_storage |
|
229 | + * @param SessionLifespan $lifespan |
|
230 | + * @param RequestInterface $request |
|
231 | + * @param SessionStartHandler $session_start_handler |
|
232 | + * @param EE_Encryption $encryption |
|
233 | + * @throws InvalidArgumentException |
|
234 | + * @throws InvalidDataTypeException |
|
235 | + * @throws InvalidInterfaceException |
|
236 | + */ |
|
237 | + protected function __construct( |
|
238 | + CacheStorageInterface $cache_storage, |
|
239 | + SessionLifespan $lifespan, |
|
240 | + RequestInterface $request, |
|
241 | + SessionStartHandler $session_start_handler, |
|
242 | + EE_Encryption $encryption = null |
|
243 | + ) { |
|
244 | + // session loading is turned ON by default, |
|
245 | + // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
|
246 | + // (which currently fires on the init hook at priority 9), |
|
247 | + // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
248 | + if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | + return; |
|
250 | + } |
|
251 | + $this->session_start_handler = $session_start_handler; |
|
252 | + $this->session_lifespan = $lifespan; |
|
253 | + $this->request = $request; |
|
254 | + if (! defined('ESPRESSO_SESSION')) { |
|
255 | + define('ESPRESSO_SESSION', true); |
|
256 | + } |
|
257 | + // retrieve session options from db |
|
258 | + $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
259 | + if (! empty($session_settings)) { |
|
260 | + // cycle though existing session options |
|
261 | + foreach ($session_settings as $var_name => $session_setting) { |
|
262 | + // set values for class properties |
|
263 | + $var_name = '_' . $var_name; |
|
264 | + $this->{$var_name} = $session_setting; |
|
265 | + } |
|
266 | + } |
|
267 | + $this->cache_storage = $cache_storage; |
|
268 | + // are we using encryption? |
|
269 | + $this->_use_encryption = $encryption instanceof EE_Encryption |
|
270 | + && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
271 | + // encrypt data via: $this->encryption->encrypt(); |
|
272 | + $this->encryption = $encryption; |
|
273 | + // filter hook allows outside functions/classes/plugins to change default empty cart |
|
274 | + $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
275 | + array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
276 | + // apply default session vars |
|
277 | + $this->_set_defaults(); |
|
278 | + add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
279 | + // check request for 'clear_session' param |
|
280 | + add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
281 | + // once everything is all said and done, |
|
282 | + add_action('shutdown', array($this, 'update'), 100); |
|
283 | + add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
284 | + $this->configure_garbage_collection_filters(); |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * @return bool |
|
290 | + * @throws InvalidArgumentException |
|
291 | + * @throws InvalidDataTypeException |
|
292 | + * @throws InvalidInterfaceException |
|
293 | + */ |
|
294 | + public static function isLoadedAndActive() |
|
295 | + { |
|
296 | + return did_action('AHEE__EE_System__core_loaded_and_ready') |
|
297 | + && EE_Session::instance() instanceof EE_Session |
|
298 | + && EE_Session::instance()->isActive(); |
|
299 | + } |
|
300 | + |
|
301 | + |
|
302 | + /** |
|
303 | + * @return bool |
|
304 | + */ |
|
305 | + public function isActive() |
|
306 | + { |
|
307 | + return $this->status === EE_Session::STATUS_OPEN; |
|
308 | + } |
|
309 | + |
|
310 | + |
|
311 | + /** |
|
312 | + * @return void |
|
313 | + * @throws EE_Error |
|
314 | + * @throws InvalidArgumentException |
|
315 | + * @throws InvalidDataTypeException |
|
316 | + * @throws InvalidInterfaceException |
|
317 | + * @throws InvalidSessionDataException |
|
318 | + * @throws RuntimeException |
|
319 | + * @throws ReflectionException |
|
320 | + */ |
|
321 | + public function open_session() |
|
322 | + { |
|
323 | + // check for existing session and retrieve it from db |
|
324 | + if (! $this->_espresso_session()) { |
|
325 | + // or just start a new one |
|
326 | + $this->_create_espresso_session(); |
|
327 | + } |
|
328 | + } |
|
329 | + |
|
330 | + |
|
331 | + /** |
|
332 | + * @return bool |
|
333 | + */ |
|
334 | + public function expired() |
|
335 | + { |
|
336 | + return $this->_expired; |
|
337 | + } |
|
338 | + |
|
339 | + |
|
340 | + /** |
|
341 | + * @return void |
|
342 | + */ |
|
343 | + public function reset_expired() |
|
344 | + { |
|
345 | + $this->_expired = false; |
|
346 | + } |
|
347 | + |
|
348 | + |
|
349 | + /** |
|
350 | + * @return int |
|
351 | + */ |
|
352 | + public function expiration() |
|
353 | + { |
|
354 | + return $this->_expiration; |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * @return int |
|
360 | + */ |
|
361 | + public function extension() |
|
362 | + { |
|
363 | + return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + /** |
|
368 | + * @param int $time number of seconds to add to session expiration |
|
369 | + */ |
|
370 | + public function extend_expiration($time = 0) |
|
371 | + { |
|
372 | + $time = $time ? $time : $this->extension(); |
|
373 | + $this->_expiration += absint($time); |
|
374 | + } |
|
375 | + |
|
376 | + |
|
377 | + /** |
|
378 | + * @return int |
|
379 | + */ |
|
380 | + public function lifespan() |
|
381 | + { |
|
382 | + return $this->session_lifespan->inSeconds(); |
|
383 | + } |
|
384 | + |
|
385 | + |
|
386 | + /** |
|
387 | + * Marks whether the session data has been updated or not. |
|
388 | + * Valid options are: |
|
389 | + * EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary |
|
390 | + * EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated |
|
391 | + * default value is EE_Session::SAVE_STATE_DIRTY |
|
392 | + * |
|
393 | + * @param string $save_state |
|
394 | + */ |
|
395 | + public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) |
|
396 | + { |
|
397 | + $valid_save_states = [ |
|
398 | + EE_Session::SAVE_STATE_CLEAN, |
|
399 | + EE_Session::SAVE_STATE_DIRTY, |
|
400 | + ]; |
|
401 | + if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | + $save_state = EE_Session::SAVE_STATE_DIRTY; |
|
403 | + } |
|
404 | + $this->save_state = $save_state; |
|
405 | + } |
|
406 | + |
|
407 | + |
|
408 | + |
|
409 | + /** |
|
410 | + * This just sets some defaults for the _session data property |
|
411 | + * |
|
412 | + * @return void |
|
413 | + */ |
|
414 | + private function _set_defaults() |
|
415 | + { |
|
416 | + // set some defaults |
|
417 | + foreach ($this->_default_session_vars as $key => $default_var) { |
|
418 | + if (is_array($default_var)) { |
|
419 | + $this->_session_data[ $key ] = array(); |
|
420 | + } else { |
|
421 | + $this->_session_data[ $key ] = ''; |
|
422 | + } |
|
423 | + } |
|
424 | + } |
|
425 | + |
|
426 | + |
|
427 | + /** |
|
428 | + * @retrieve session data |
|
429 | + * @return string |
|
430 | + */ |
|
431 | + public function id() |
|
432 | + { |
|
433 | + return $this->_sid; |
|
434 | + } |
|
435 | + |
|
436 | + |
|
437 | + /** |
|
438 | + * @param \EE_Cart $cart |
|
439 | + * @return bool |
|
440 | + */ |
|
441 | + public function set_cart(EE_Cart $cart) |
|
442 | + { |
|
443 | + $this->_session_data['cart'] = $cart; |
|
444 | + $this->setSaveState(); |
|
445 | + return true; |
|
446 | + } |
|
447 | + |
|
448 | + |
|
449 | + /** |
|
450 | + * reset_cart |
|
451 | + */ |
|
452 | + public function reset_cart() |
|
453 | + { |
|
454 | + do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
455 | + $this->_session_data['cart'] = null; |
|
456 | + $this->setSaveState(); |
|
457 | + } |
|
458 | + |
|
459 | + |
|
460 | + /** |
|
461 | + * @return \EE_Cart |
|
462 | + */ |
|
463 | + public function cart() |
|
464 | + { |
|
465 | + return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
466 | + ? $this->_session_data['cart'] |
|
467 | + : null; |
|
468 | + } |
|
469 | + |
|
470 | + |
|
471 | + /** |
|
472 | + * @param \EE_Checkout $checkout |
|
473 | + * @return bool |
|
474 | + */ |
|
475 | + public function set_checkout(EE_Checkout $checkout) |
|
476 | + { |
|
477 | + $this->_session_data['checkout'] = $checkout; |
|
478 | + $this->setSaveState(); |
|
479 | + return true; |
|
480 | + } |
|
481 | + |
|
482 | + |
|
483 | + /** |
|
484 | + * reset_checkout |
|
485 | + */ |
|
486 | + public function reset_checkout() |
|
487 | + { |
|
488 | + do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
489 | + $this->_session_data['checkout'] = null; |
|
490 | + $this->setSaveState(); |
|
491 | + } |
|
492 | + |
|
493 | + |
|
494 | + /** |
|
495 | + * @return \EE_Checkout |
|
496 | + */ |
|
497 | + public function checkout() |
|
498 | + { |
|
499 | + return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
500 | + ? $this->_session_data['checkout'] |
|
501 | + : null; |
|
502 | + } |
|
503 | + |
|
504 | + |
|
505 | + /** |
|
506 | + * @param \EE_Transaction $transaction |
|
507 | + * @return bool |
|
508 | + * @throws EE_Error |
|
509 | + */ |
|
510 | + public function set_transaction(EE_Transaction $transaction) |
|
511 | + { |
|
512 | + // first remove the session from the transaction before we save the transaction in the session |
|
513 | + $transaction->set_txn_session_data(null); |
|
514 | + $this->_session_data['transaction'] = $transaction; |
|
515 | + $this->setSaveState(); |
|
516 | + return true; |
|
517 | + } |
|
518 | + |
|
519 | + |
|
520 | + /** |
|
521 | + * reset_transaction |
|
522 | + */ |
|
523 | + public function reset_transaction() |
|
524 | + { |
|
525 | + do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
526 | + $this->_session_data['transaction'] = null; |
|
527 | + $this->setSaveState(); |
|
528 | + } |
|
529 | + |
|
530 | + |
|
531 | + /** |
|
532 | + * @return \EE_Transaction |
|
533 | + */ |
|
534 | + public function transaction() |
|
535 | + { |
|
536 | + return isset($this->_session_data['transaction']) |
|
537 | + && $this->_session_data['transaction'] instanceof EE_Transaction |
|
538 | + ? $this->_session_data['transaction'] |
|
539 | + : null; |
|
540 | + } |
|
541 | + |
|
542 | + |
|
543 | + /** |
|
544 | + * retrieve session data |
|
545 | + * |
|
546 | + * @param null $key |
|
547 | + * @param bool $reset_cache |
|
548 | + * @return array |
|
549 | + */ |
|
550 | + public function get_session_data($key = null, $reset_cache = false) |
|
551 | + { |
|
552 | + if ($reset_cache) { |
|
553 | + $this->reset_cart(); |
|
554 | + $this->reset_checkout(); |
|
555 | + $this->reset_transaction(); |
|
556 | + } |
|
557 | + if (! empty($key)) { |
|
558 | + return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
559 | + } |
|
560 | + return $this->_session_data; |
|
561 | + } |
|
562 | + |
|
563 | + |
|
564 | + /** |
|
565 | + * Returns TRUE on success, FALSE on fail |
|
566 | + * |
|
567 | + * @param array $data |
|
568 | + * @return bool |
|
569 | + */ |
|
570 | + public function set_session_data($data) |
|
571 | + { |
|
572 | + // nothing ??? bad data ??? go home! |
|
573 | + if (empty($data) || ! is_array($data)) { |
|
574 | + EE_Error::add_error( |
|
575 | + esc_html__( |
|
576 | + 'No session data or invalid session data was provided.', |
|
577 | + 'event_espresso' |
|
578 | + ), |
|
579 | + __FILE__, |
|
580 | + __FUNCTION__, |
|
581 | + __LINE__ |
|
582 | + ); |
|
583 | + return false; |
|
584 | + } |
|
585 | + foreach ($data as $key => $value) { |
|
586 | + if (isset($this->_default_session_vars[ $key ])) { |
|
587 | + EE_Error::add_error( |
|
588 | + sprintf( |
|
589 | + esc_html__( |
|
590 | + 'Sorry! %s is a default session datum and can not be reset.', |
|
591 | + 'event_espresso' |
|
592 | + ), |
|
593 | + $key |
|
594 | + ), |
|
595 | + __FILE__, |
|
596 | + __FUNCTION__, |
|
597 | + __LINE__ |
|
598 | + ); |
|
599 | + return false; |
|
600 | + } |
|
601 | + $this->_session_data[ $key ] = $value; |
|
602 | + $this->setSaveState(); |
|
603 | + } |
|
604 | + return true; |
|
605 | + } |
|
606 | + |
|
607 | + |
|
608 | + /** |
|
609 | + * @initiate session |
|
610 | + * @return bool TRUE on success, FALSE on fail |
|
611 | + * @throws EE_Error |
|
612 | + * @throws InvalidArgumentException |
|
613 | + * @throws InvalidDataTypeException |
|
614 | + * @throws InvalidInterfaceException |
|
615 | + * @throws InvalidSessionDataException |
|
616 | + * @throws RuntimeException |
|
617 | + * @throws ReflectionException |
|
618 | + */ |
|
619 | + private function _espresso_session() |
|
620 | + { |
|
621 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
622 | + $this->session_start_handler->startSession(); |
|
623 | + $this->status = EE_Session::STATUS_OPEN; |
|
624 | + // get our modified session ID |
|
625 | + $this->_sid = $this->_generate_session_id(); |
|
626 | + // and the visitors IP |
|
627 | + $this->_ip_address = $this->request->ipAddress(); |
|
628 | + // set the "user agent" |
|
629 | + $this->_user_agent = $this->request->userAgent(); |
|
630 | + // now let's retrieve what's in the db |
|
631 | + $session_data = $this->_retrieve_session_data(); |
|
632 | + if (! empty($session_data)) { |
|
633 | + // get the current time in UTC |
|
634 | + $this->_time = $this->_time !== null ? $this->_time : time(); |
|
635 | + // and reset the session expiration |
|
636 | + $this->_expiration = isset($session_data['expiration']) |
|
637 | + ? $session_data['expiration'] |
|
638 | + : $this->_time + $this->session_lifespan->inSeconds(); |
|
639 | + } else { |
|
640 | + // set initial site access time and the session expiration |
|
641 | + $this->_set_init_access_and_expiration(); |
|
642 | + // set referer |
|
643 | + $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | + $this->request->getServerParam('HTTP_REFERER') |
|
645 | + ); |
|
646 | + // no previous session = go back and create one (on top of the data above) |
|
647 | + return false; |
|
648 | + } |
|
649 | + // now the user agent |
|
650 | + if ($session_data['user_agent'] !== $this->_user_agent) { |
|
651 | + return false; |
|
652 | + } |
|
653 | + // wait a minute... how old are you? |
|
654 | + if ($this->_time > $this->_expiration) { |
|
655 | + // yer too old fer me! |
|
656 | + $this->_expired = true; |
|
657 | + // wipe out everything that isn't a default session datum |
|
658 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
659 | + } |
|
660 | + // make event espresso session data available to plugin |
|
661 | + $this->_session_data = array_merge($this->_session_data, $session_data); |
|
662 | + return true; |
|
663 | + } |
|
664 | + |
|
665 | + |
|
666 | + /** |
|
667 | + * _get_session_data |
|
668 | + * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
669 | + * databases |
|
670 | + * |
|
671 | + * @return array |
|
672 | + * @throws EE_Error |
|
673 | + * @throws InvalidArgumentException |
|
674 | + * @throws InvalidSessionDataException |
|
675 | + * @throws InvalidDataTypeException |
|
676 | + * @throws InvalidInterfaceException |
|
677 | + * @throws RuntimeException |
|
678 | + */ |
|
679 | + protected function _retrieve_session_data() |
|
680 | + { |
|
681 | + $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | + try { |
|
683 | + // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
684 | + $session_data = $this->cache_storage->get($ssn_key, false); |
|
685 | + if (empty($session_data)) { |
|
686 | + return array(); |
|
687 | + } |
|
688 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
689 | + $hash_check = $this->cache_storage->get( |
|
690 | + EE_Session::hash_check_prefix . $this->_sid, |
|
691 | + false |
|
692 | + ); |
|
693 | + if ($hash_check && $hash_check !== md5($session_data)) { |
|
694 | + EE_Error::add_error( |
|
695 | + sprintf( |
|
696 | + esc_html__( |
|
697 | + 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
698 | + 'event_espresso' |
|
699 | + ), |
|
700 | + EE_Session::session_id_prefix . $this->_sid |
|
701 | + ), |
|
702 | + __FILE__, |
|
703 | + __FUNCTION__, |
|
704 | + __LINE__ |
|
705 | + ); |
|
706 | + } |
|
707 | + } |
|
708 | + } catch (Exception $e) { |
|
709 | + // let's just eat that error for now and attempt to correct any corrupted data |
|
710 | + global $wpdb; |
|
711 | + $row = $wpdb->get_row( |
|
712 | + $wpdb->prepare( |
|
713 | + "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
714 | + '_transient_' . $ssn_key |
|
715 | + ) |
|
716 | + ); |
|
717 | + $session_data = is_object($row) ? $row->option_value : null; |
|
718 | + if ($session_data) { |
|
719 | + $session_data = preg_replace_callback( |
|
720 | + '!s:(d+):"(.*?)";!', |
|
721 | + function ($match) { |
|
722 | + return $match[1] === strlen($match[2]) |
|
723 | + ? $match[0] |
|
724 | + : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | + }, |
|
726 | + $session_data |
|
727 | + ); |
|
728 | + } |
|
729 | + $session_data = maybe_unserialize($session_data); |
|
730 | + } |
|
731 | + // in case the data is encoded... try to decode it |
|
732 | + $session_data = $this->encryption instanceof EE_Encryption |
|
733 | + ? $this->encryption->base64_string_decode($session_data) |
|
734 | + : $session_data; |
|
735 | + if (! is_array($session_data)) { |
|
736 | + try { |
|
737 | + $session_data = maybe_unserialize($session_data); |
|
738 | + } catch (Exception $e) { |
|
739 | + $msg = esc_html__( |
|
740 | + 'An error occurred while attempting to unserialize the session data.', |
|
741 | + 'event_espresso' |
|
742 | + ); |
|
743 | + $msg .= WP_DEBUG |
|
744 | + ? '<br><pre>' |
|
745 | + . print_r($session_data, true) |
|
746 | + . '</pre><br>' |
|
747 | + . $this->find_serialize_error($session_data) |
|
748 | + : ''; |
|
749 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | + throw new InvalidSessionDataException($msg, 0, $e); |
|
751 | + } |
|
752 | + } |
|
753 | + // just a check to make sure the session array is indeed an array |
|
754 | + if (! is_array($session_data)) { |
|
755 | + // no?!?! then something is wrong |
|
756 | + $msg = esc_html__( |
|
757 | + 'The session data is missing, invalid, or corrupted.', |
|
758 | + 'event_espresso' |
|
759 | + ); |
|
760 | + $msg .= WP_DEBUG |
|
761 | + ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | + : ''; |
|
763 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | + throw new InvalidSessionDataException($msg); |
|
765 | + } |
|
766 | + if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
767 | + $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
768 | + $session_data['transaction'] |
|
769 | + ); |
|
770 | + } |
|
771 | + return $session_data; |
|
772 | + } |
|
773 | + |
|
774 | + |
|
775 | + /** |
|
776 | + * _generate_session_id |
|
777 | + * Retrieves the PHP session id either directly from the PHP session, |
|
778 | + * or from the request array if it was passed in from an AJAX request. |
|
779 | + * The session id is then salted and hashed (mmm sounds tasty) |
|
780 | + * so that it can be safely used as a request param |
|
781 | + * |
|
782 | + * @return string |
|
783 | + */ |
|
784 | + protected function _generate_session_id() |
|
785 | + { |
|
786 | + // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
787 | + $session_id = $this->request->requestParamIsSet('EESID') |
|
788 | + ? $this->request->getRequestParam('EESID') |
|
789 | + : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | + return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
791 | + } |
|
792 | + |
|
793 | + |
|
794 | + /** |
|
795 | + * _get_sid_salt |
|
796 | + * |
|
797 | + * @return string |
|
798 | + */ |
|
799 | + protected function _get_sid_salt() |
|
800 | + { |
|
801 | + // was session id salt already saved to db ? |
|
802 | + if (empty($this->_sid_salt)) { |
|
803 | + // no? then maybe use WP defined constant |
|
804 | + if (defined('AUTH_SALT')) { |
|
805 | + $this->_sid_salt = AUTH_SALT; |
|
806 | + } |
|
807 | + // if salt doesn't exist or is too short |
|
808 | + if (strlen($this->_sid_salt) < 32) { |
|
809 | + // create a new one |
|
810 | + $this->_sid_salt = wp_generate_password(64); |
|
811 | + } |
|
812 | + // and save it as a permanent session setting |
|
813 | + $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
814 | + } |
|
815 | + return $this->_sid_salt; |
|
816 | + } |
|
817 | + |
|
818 | + |
|
819 | + /** |
|
820 | + * _set_init_access_and_expiration |
|
821 | + * |
|
822 | + * @return void |
|
823 | + */ |
|
824 | + protected function _set_init_access_and_expiration() |
|
825 | + { |
|
826 | + $this->_time = time(); |
|
827 | + $this->_expiration = $this->_time + $this->session_lifespan->inSeconds(); |
|
828 | + // set initial site access time |
|
829 | + $this->_session_data['init_access'] = $this->_time; |
|
830 | + // and the session expiration |
|
831 | + $this->_session_data['expiration'] = $this->_expiration; |
|
832 | + } |
|
833 | + |
|
834 | + |
|
835 | + /** |
|
836 | + * @update session data prior to saving to the db |
|
837 | + * @param bool $new_session |
|
838 | + * @return bool TRUE on success, FALSE on fail |
|
839 | + * @throws EE_Error |
|
840 | + * @throws InvalidArgumentException |
|
841 | + * @throws InvalidDataTypeException |
|
842 | + * @throws InvalidInterfaceException |
|
843 | + * @throws ReflectionException |
|
844 | + */ |
|
845 | + public function update($new_session = false) |
|
846 | + { |
|
847 | + $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id']) |
|
848 | + ? $this->_session_data |
|
849 | + : array(); |
|
850 | + if (empty($this->_session_data)) { |
|
851 | + $this->_set_defaults(); |
|
852 | + } |
|
853 | + $session_data = array(); |
|
854 | + foreach ($this->_session_data as $key => $value) { |
|
855 | + switch ($key) { |
|
856 | + case 'id': |
|
857 | + // session ID |
|
858 | + $session_data['id'] = $this->_sid; |
|
859 | + break; |
|
860 | + case 'ip_address': |
|
861 | + // visitor ip address |
|
862 | + $session_data['ip_address'] = $this->request->ipAddress(); |
|
863 | + break; |
|
864 | + case 'user_agent': |
|
865 | + // visitor user_agent |
|
866 | + $session_data['user_agent'] = $this->_user_agent; |
|
867 | + break; |
|
868 | + case 'init_access': |
|
869 | + $session_data['init_access'] = absint($value); |
|
870 | + break; |
|
871 | + case 'last_access': |
|
872 | + // current access time |
|
873 | + $session_data['last_access'] = $this->_time; |
|
874 | + break; |
|
875 | + case 'expiration': |
|
876 | + // when the session expires |
|
877 | + $session_data['expiration'] = ! empty($this->_expiration) |
|
878 | + ? $this->_expiration |
|
879 | + : $session_data['init_access'] + $this->session_lifespan->inSeconds(); |
|
880 | + break; |
|
881 | + case 'user_id': |
|
882 | + // current user if logged in |
|
883 | + $session_data['user_id'] = $this->_wp_user_id(); |
|
884 | + break; |
|
885 | + case 'pages_visited': |
|
886 | + $page_visit = $this->_get_page_visit(); |
|
887 | + if ($page_visit) { |
|
888 | + // set pages visited where the first will be the http referrer |
|
889 | + $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
890 | + // we'll only save the last 10 page visits. |
|
891 | + $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
892 | + } |
|
893 | + break; |
|
894 | + default: |
|
895 | + // carry any other data over |
|
896 | + $session_data[ $key ] = $this->_session_data[ $key ]; |
|
897 | + } |
|
898 | + } |
|
899 | + $this->_session_data = $session_data; |
|
900 | + // creating a new session does not require saving to the db just yet |
|
901 | + if (! $new_session) { |
|
902 | + // ready? let's save |
|
903 | + if ($this->_save_session_to_db()) { |
|
904 | + return true; |
|
905 | + } |
|
906 | + return false; |
|
907 | + } |
|
908 | + // meh, why not? |
|
909 | + return true; |
|
910 | + } |
|
911 | + |
|
912 | + |
|
913 | + /** |
|
914 | + * @create session data array |
|
915 | + * @throws EE_Error |
|
916 | + * @throws InvalidArgumentException |
|
917 | + * @throws InvalidDataTypeException |
|
918 | + * @throws InvalidInterfaceException |
|
919 | + * @throws ReflectionException |
|
920 | + */ |
|
921 | + private function _create_espresso_session() |
|
922 | + { |
|
923 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
924 | + // use the update function for now with $new_session arg set to TRUE |
|
925 | + $this->update(true); |
|
926 | + } |
|
927 | + |
|
928 | + /** |
|
929 | + * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good |
|
930 | + * too). This is used when determining if we want to save the session or not. |
|
931 | + * @since 4.9.67.p |
|
932 | + * @return bool |
|
933 | + */ |
|
934 | + private function sessionHasStuffWorthSaving() |
|
935 | + { |
|
936 | + return $this->save_state === EE_Session::SAVE_STATE_DIRTY |
|
937 | + // we may want to eventually remove the following |
|
938 | + // on the assumption that the above check is enough |
|
939 | + || $this->cart() instanceof EE_Cart |
|
940 | + || ( |
|
941 | + isset($this->_session_data['ee_notices']) |
|
942 | + && ( |
|
943 | + ! empty($this->_session_data['ee_notices']['attention']) |
|
944 | + || ! empty($this->_session_data['ee_notices']['errors']) |
|
945 | + || ! empty($this->_session_data['ee_notices']['success']) |
|
946 | + ) |
|
947 | + ); |
|
948 | + } |
|
949 | + |
|
950 | + |
|
951 | + /** |
|
952 | + * _save_session_to_db |
|
953 | + * |
|
954 | + * @param bool $clear_session |
|
955 | + * @return bool |
|
956 | + * @throws EE_Error |
|
957 | + * @throws InvalidArgumentException |
|
958 | + * @throws InvalidDataTypeException |
|
959 | + * @throws InvalidInterfaceException |
|
960 | + * @throws ReflectionException |
|
961 | + */ |
|
962 | + private function _save_session_to_db($clear_session = false) |
|
963 | + { |
|
964 | + // don't save sessions for crawlers |
|
965 | + // and unless we're deleting the session data, don't save anything if there isn't a cart |
|
966 | + if ( |
|
967 | + $this->request->isBot() |
|
968 | + || ( |
|
969 | + ! $clear_session |
|
970 | + && ! $this->sessionHasStuffWorthSaving() |
|
971 | + && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true) |
|
972 | + ) |
|
973 | + ) { |
|
974 | + return false; |
|
975 | + } |
|
976 | + $transaction = $this->transaction(); |
|
977 | + if ($transaction instanceof EE_Transaction) { |
|
978 | + if (! $transaction->ID()) { |
|
979 | + $transaction->save(); |
|
980 | + } |
|
981 | + $this->_session_data['transaction'] = $transaction->ID(); |
|
982 | + } |
|
983 | + // then serialize all of our session data |
|
984 | + $session_data = serialize($this->_session_data); |
|
985 | + // do we need to also encode it to avoid corrupted data when saved to the db? |
|
986 | + $session_data = $this->_use_encryption |
|
987 | + ? $this->encryption->base64_string_encode($session_data) |
|
988 | + : $session_data; |
|
989 | + // maybe save hash check |
|
990 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
991 | + $this->cache_storage->add( |
|
992 | + EE_Session::hash_check_prefix . $this->_sid, |
|
993 | + md5($session_data), |
|
994 | + $this->session_lifespan->inSeconds() |
|
995 | + ); |
|
996 | + } |
|
997 | + // we're using the Transient API for storing session data, |
|
998 | + $saved = $this->cache_storage->add( |
|
999 | + EE_Session::session_id_prefix . $this->_sid, |
|
1000 | + $session_data, |
|
1001 | + $this->session_lifespan->inSeconds() |
|
1002 | + ); |
|
1003 | + $this->setSaveState(EE_Session::SAVE_STATE_CLEAN); |
|
1004 | + return $saved; |
|
1005 | + } |
|
1006 | + |
|
1007 | + |
|
1008 | + /** |
|
1009 | + * @get the full page request the visitor is accessing |
|
1010 | + * @return string |
|
1011 | + */ |
|
1012 | + public function _get_page_visit() |
|
1013 | + { |
|
1014 | + $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1015 | + // check for request url |
|
1016 | + if ($this->request->serverParamIsSet('REQUEST_URI')) { |
|
1017 | + $page_id = '?'; |
|
1018 | + $e_reg = ''; |
|
1019 | + $request_uri = $this->request->getServerParam('REQUEST_URI'); |
|
1020 | + $ru_bits = explode('?', $request_uri); |
|
1021 | + $request_uri = $ru_bits[0]; |
|
1022 | + $http_host = $this->request->getServerParam('HTTP_HOST'); |
|
1023 | + // check for page_id in SERVER REQUEST |
|
1024 | + if ($this->request->requestParamIsSet('page_id')) { |
|
1025 | + // rebuild $e_reg without any of the extra parameters |
|
1026 | + $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1027 | + } |
|
1028 | + // check for $e_reg in SERVER REQUEST |
|
1029 | + if ($this->request->requestParamIsSet('ee')) { |
|
1030 | + // rebuild $e_reg without any of the extra parameters |
|
1031 | + $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1032 | + } |
|
1033 | + $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1034 | + } |
|
1035 | + return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
1036 | + } |
|
1037 | + |
|
1038 | + |
|
1039 | + /** |
|
1040 | + * @the current wp user id |
|
1041 | + * @return int |
|
1042 | + */ |
|
1043 | + public function _wp_user_id() |
|
1044 | + { |
|
1045 | + // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
1046 | + $this->_wp_user_id = get_current_user_id(); |
|
1047 | + return $this->_wp_user_id; |
|
1048 | + } |
|
1049 | + |
|
1050 | + |
|
1051 | + /** |
|
1052 | + * Clear EE_Session data |
|
1053 | + * |
|
1054 | + * @param string $class |
|
1055 | + * @param string $function |
|
1056 | + * @return void |
|
1057 | + * @throws EE_Error |
|
1058 | + * @throws InvalidArgumentException |
|
1059 | + * @throws InvalidDataTypeException |
|
1060 | + * @throws InvalidInterfaceException |
|
1061 | + * @throws ReflectionException |
|
1062 | + */ |
|
1063 | + public function clear_session($class = '', $function = '') |
|
1064 | + { |
|
1065 | 1065 | // echo ' |
1066 | 1066 | // <h3 style="color:#999;line-height:.9em;"> |
1067 | 1067 | // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/> |
1068 | 1068 | // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b> |
1069 | 1069 | // </h3>'; |
1070 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1071 | - $this->reset_cart(); |
|
1072 | - $this->reset_checkout(); |
|
1073 | - $this->reset_transaction(); |
|
1074 | - // wipe out everything that isn't a default session datum |
|
1075 | - $this->reset_data(array_keys($this->_session_data)); |
|
1076 | - // reset initial site access time and the session expiration |
|
1077 | - $this->_set_init_access_and_expiration(); |
|
1078 | - $this->setSaveState(); |
|
1079 | - $this->_save_session_to_db(true); |
|
1080 | - } |
|
1081 | - |
|
1082 | - |
|
1083 | - /** |
|
1084 | - * resets all non-default session vars. Returns TRUE on success, FALSE on fail |
|
1085 | - * |
|
1086 | - * @param array|mixed $data_to_reset |
|
1087 | - * @param bool $show_all_notices |
|
1088 | - * @return bool |
|
1089 | - */ |
|
1090 | - public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1091 | - { |
|
1092 | - // if $data_to_reset is not in an array, then put it in one |
|
1093 | - if (! is_array($data_to_reset)) { |
|
1094 | - $data_to_reset = array($data_to_reset); |
|
1095 | - } |
|
1096 | - // nothing ??? go home! |
|
1097 | - if (empty($data_to_reset)) { |
|
1098 | - EE_Error::add_error( |
|
1099 | - esc_html__( |
|
1100 | - 'No session data could be reset, because no session var name was provided.', |
|
1101 | - 'event_espresso' |
|
1102 | - ), |
|
1103 | - __FILE__, |
|
1104 | - __FUNCTION__, |
|
1105 | - __LINE__ |
|
1106 | - ); |
|
1107 | - return false; |
|
1108 | - } |
|
1109 | - $return_value = true; |
|
1110 | - // since $data_to_reset is an array, cycle through the values |
|
1111 | - foreach ($data_to_reset as $reset) { |
|
1112 | - // first check to make sure it is a valid session var |
|
1113 | - if (isset($this->_session_data[ $reset ])) { |
|
1114 | - // then check to make sure it is not a default var |
|
1115 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1116 | - // remove session var |
|
1117 | - unset($this->_session_data[ $reset ]); |
|
1118 | - $this->setSaveState(); |
|
1119 | - if ($show_all_notices) { |
|
1120 | - EE_Error::add_success( |
|
1121 | - sprintf( |
|
1122 | - esc_html__('The session variable %s was removed.', 'event_espresso'), |
|
1123 | - $reset |
|
1124 | - ), |
|
1125 | - __FILE__, |
|
1126 | - __FUNCTION__, |
|
1127 | - __LINE__ |
|
1128 | - ); |
|
1129 | - } |
|
1130 | - } else { |
|
1131 | - // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1132 | - if ($show_all_notices) { |
|
1133 | - EE_Error::add_error( |
|
1134 | - sprintf( |
|
1135 | - esc_html__( |
|
1136 | - 'Sorry! %s is a default session datum and can not be reset.', |
|
1137 | - 'event_espresso' |
|
1138 | - ), |
|
1139 | - $reset |
|
1140 | - ), |
|
1141 | - __FILE__, |
|
1142 | - __FUNCTION__, |
|
1143 | - __LINE__ |
|
1144 | - ); |
|
1145 | - } |
|
1146 | - $return_value = false; |
|
1147 | - } |
|
1148 | - } elseif ($show_all_notices) { |
|
1149 | - // oops! that session var does not exist! |
|
1150 | - EE_Error::add_error( |
|
1151 | - sprintf( |
|
1152 | - esc_html__( |
|
1153 | - 'The session item provided, %s, is invalid or does not exist.', |
|
1154 | - 'event_espresso' |
|
1155 | - ), |
|
1156 | - $reset |
|
1157 | - ), |
|
1158 | - __FILE__, |
|
1159 | - __FUNCTION__, |
|
1160 | - __LINE__ |
|
1161 | - ); |
|
1162 | - $return_value = false; |
|
1163 | - } |
|
1164 | - } // end of foreach |
|
1165 | - return $return_value; |
|
1166 | - } |
|
1167 | - |
|
1168 | - |
|
1169 | - /** |
|
1170 | - * wp_loaded |
|
1171 | - * |
|
1172 | - * @throws EE_Error |
|
1173 | - * @throws InvalidDataTypeException |
|
1174 | - * @throws InvalidInterfaceException |
|
1175 | - * @throws InvalidArgumentException |
|
1176 | - * @throws ReflectionException |
|
1177 | - */ |
|
1178 | - public function wp_loaded() |
|
1179 | - { |
|
1180 | - if ($this->request->requestParamIsSet('clear_session')) { |
|
1181 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
1182 | - } |
|
1183 | - } |
|
1184 | - |
|
1185 | - |
|
1186 | - /** |
|
1187 | - * Used to reset the entire object (for tests). |
|
1188 | - * |
|
1189 | - * @since 4.3.0 |
|
1190 | - * @throws EE_Error |
|
1191 | - * @throws InvalidDataTypeException |
|
1192 | - * @throws InvalidInterfaceException |
|
1193 | - * @throws InvalidArgumentException |
|
1194 | - * @throws ReflectionException |
|
1195 | - */ |
|
1196 | - public function reset_instance() |
|
1197 | - { |
|
1198 | - $this->clear_session(); |
|
1199 | - self::$_instance = null; |
|
1200 | - } |
|
1201 | - |
|
1202 | - |
|
1203 | - public function configure_garbage_collection_filters() |
|
1204 | - { |
|
1205 | - // run old filter we had for controlling session cleanup |
|
1206 | - $expired_session_transient_delete_query_limit = absint( |
|
1207 | - apply_filters( |
|
1208 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1209 | - 50 |
|
1210 | - ) |
|
1211 | - ); |
|
1212 | - // is there a value? or one that is different than the default 50 records? |
|
1213 | - if ($expired_session_transient_delete_query_limit === 0) { |
|
1214 | - // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1215 | - add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1216 | - } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1217 | - // or use that for the new transient cleanup query limit |
|
1218 | - add_filter( |
|
1219 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1220 | - function () use ($expired_session_transient_delete_query_limit) { |
|
1221 | - return $expired_session_transient_delete_query_limit; |
|
1222 | - } |
|
1223 | - ); |
|
1224 | - } |
|
1225 | - } |
|
1226 | - |
|
1227 | - |
|
1228 | - /** |
|
1229 | - * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1230 | - * @param $data1 |
|
1231 | - * @return string |
|
1232 | - */ |
|
1233 | - private function find_serialize_error($data1) |
|
1234 | - { |
|
1235 | - $error = '<pre>'; |
|
1236 | - $data2 = preg_replace_callback( |
|
1237 | - '!s:(\d+):"(.*?)";!', |
|
1238 | - function ($match) { |
|
1239 | - return ($match[1] === strlen($match[2])) |
|
1240 | - ? $match[0] |
|
1241 | - : 's:' |
|
1242 | - . strlen($match[2]) |
|
1243 | - . ':"' |
|
1244 | - . $match[2] |
|
1245 | - . '";'; |
|
1246 | - }, |
|
1247 | - $data1 |
|
1248 | - ); |
|
1249 | - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1250 | - $error .= $data1 . PHP_EOL; |
|
1251 | - $error .= $data2 . PHP_EOL; |
|
1252 | - for ($i = 0; $i < $max; $i++) { |
|
1253 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1254 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1255 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1256 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | - $start = ($i - 20); |
|
1258 | - $start = ($start < 0) ? 0 : $start; |
|
1259 | - $length = 40; |
|
1260 | - $point = $max - $i; |
|
1261 | - if ($point < 20) { |
|
1262 | - $rlength = 1; |
|
1263 | - $rpoint = -$point; |
|
1264 | - } else { |
|
1265 | - $rpoint = $length - 20; |
|
1266 | - $rlength = 1; |
|
1267 | - } |
|
1268 | - $error .= "\t-> Section Data1 = "; |
|
1269 | - $error .= substr_replace( |
|
1270 | - substr($data1, $start, $length), |
|
1271 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1272 | - $rpoint, |
|
1273 | - $rlength |
|
1274 | - ); |
|
1275 | - $error .= PHP_EOL; |
|
1276 | - $error .= "\t-> Section Data2 = "; |
|
1277 | - $error .= substr_replace( |
|
1278 | - substr($data2, $start, $length), |
|
1279 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1280 | - $rpoint, |
|
1281 | - $rlength |
|
1282 | - ); |
|
1283 | - $error .= PHP_EOL; |
|
1284 | - } |
|
1285 | - } |
|
1286 | - $error .= '</pre>'; |
|
1287 | - return $error; |
|
1288 | - } |
|
1289 | - |
|
1290 | - |
|
1291 | - /** |
|
1292 | - * Saves an array of settings used for configuring aspects of session behaviour |
|
1293 | - * |
|
1294 | - * @param array $updated_settings |
|
1295 | - */ |
|
1296 | - private function updateSessionSettings(array $updated_settings = array()) |
|
1297 | - { |
|
1298 | - // add existing settings, but only if not included in incoming $updated_settings array |
|
1299 | - $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1300 | - update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1301 | - } |
|
1302 | - |
|
1303 | - |
|
1304 | - /** |
|
1305 | - * garbage_collection |
|
1306 | - */ |
|
1307 | - public function garbageCollection() |
|
1308 | - { |
|
1309 | - // only perform during regular requests if last garbage collection was over an hour ago |
|
1310 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1311 | - $this->_last_gc = time(); |
|
1312 | - $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1313 | - /** @type WPDB $wpdb */ |
|
1314 | - global $wpdb; |
|
1315 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
1316 | - $expired_session_transient_delete_query_limit = absint( |
|
1317 | - apply_filters( |
|
1318 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1319 | - 50 |
|
1320 | - ) |
|
1321 | - ); |
|
1322 | - // non-zero LIMIT means take out the trash |
|
1323 | - if ($expired_session_transient_delete_query_limit) { |
|
1324 | - $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1325 | - $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1326 | - // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1327 | - // but we only want to pick up any trash that's been around for more than a day |
|
1328 | - $expiration = time() - DAY_IN_SECONDS; |
|
1329 | - $SQL = " |
|
1070 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1071 | + $this->reset_cart(); |
|
1072 | + $this->reset_checkout(); |
|
1073 | + $this->reset_transaction(); |
|
1074 | + // wipe out everything that isn't a default session datum |
|
1075 | + $this->reset_data(array_keys($this->_session_data)); |
|
1076 | + // reset initial site access time and the session expiration |
|
1077 | + $this->_set_init_access_and_expiration(); |
|
1078 | + $this->setSaveState(); |
|
1079 | + $this->_save_session_to_db(true); |
|
1080 | + } |
|
1081 | + |
|
1082 | + |
|
1083 | + /** |
|
1084 | + * resets all non-default session vars. Returns TRUE on success, FALSE on fail |
|
1085 | + * |
|
1086 | + * @param array|mixed $data_to_reset |
|
1087 | + * @param bool $show_all_notices |
|
1088 | + * @return bool |
|
1089 | + */ |
|
1090 | + public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1091 | + { |
|
1092 | + // if $data_to_reset is not in an array, then put it in one |
|
1093 | + if (! is_array($data_to_reset)) { |
|
1094 | + $data_to_reset = array($data_to_reset); |
|
1095 | + } |
|
1096 | + // nothing ??? go home! |
|
1097 | + if (empty($data_to_reset)) { |
|
1098 | + EE_Error::add_error( |
|
1099 | + esc_html__( |
|
1100 | + 'No session data could be reset, because no session var name was provided.', |
|
1101 | + 'event_espresso' |
|
1102 | + ), |
|
1103 | + __FILE__, |
|
1104 | + __FUNCTION__, |
|
1105 | + __LINE__ |
|
1106 | + ); |
|
1107 | + return false; |
|
1108 | + } |
|
1109 | + $return_value = true; |
|
1110 | + // since $data_to_reset is an array, cycle through the values |
|
1111 | + foreach ($data_to_reset as $reset) { |
|
1112 | + // first check to make sure it is a valid session var |
|
1113 | + if (isset($this->_session_data[ $reset ])) { |
|
1114 | + // then check to make sure it is not a default var |
|
1115 | + if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1116 | + // remove session var |
|
1117 | + unset($this->_session_data[ $reset ]); |
|
1118 | + $this->setSaveState(); |
|
1119 | + if ($show_all_notices) { |
|
1120 | + EE_Error::add_success( |
|
1121 | + sprintf( |
|
1122 | + esc_html__('The session variable %s was removed.', 'event_espresso'), |
|
1123 | + $reset |
|
1124 | + ), |
|
1125 | + __FILE__, |
|
1126 | + __FUNCTION__, |
|
1127 | + __LINE__ |
|
1128 | + ); |
|
1129 | + } |
|
1130 | + } else { |
|
1131 | + // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1132 | + if ($show_all_notices) { |
|
1133 | + EE_Error::add_error( |
|
1134 | + sprintf( |
|
1135 | + esc_html__( |
|
1136 | + 'Sorry! %s is a default session datum and can not be reset.', |
|
1137 | + 'event_espresso' |
|
1138 | + ), |
|
1139 | + $reset |
|
1140 | + ), |
|
1141 | + __FILE__, |
|
1142 | + __FUNCTION__, |
|
1143 | + __LINE__ |
|
1144 | + ); |
|
1145 | + } |
|
1146 | + $return_value = false; |
|
1147 | + } |
|
1148 | + } elseif ($show_all_notices) { |
|
1149 | + // oops! that session var does not exist! |
|
1150 | + EE_Error::add_error( |
|
1151 | + sprintf( |
|
1152 | + esc_html__( |
|
1153 | + 'The session item provided, %s, is invalid or does not exist.', |
|
1154 | + 'event_espresso' |
|
1155 | + ), |
|
1156 | + $reset |
|
1157 | + ), |
|
1158 | + __FILE__, |
|
1159 | + __FUNCTION__, |
|
1160 | + __LINE__ |
|
1161 | + ); |
|
1162 | + $return_value = false; |
|
1163 | + } |
|
1164 | + } // end of foreach |
|
1165 | + return $return_value; |
|
1166 | + } |
|
1167 | + |
|
1168 | + |
|
1169 | + /** |
|
1170 | + * wp_loaded |
|
1171 | + * |
|
1172 | + * @throws EE_Error |
|
1173 | + * @throws InvalidDataTypeException |
|
1174 | + * @throws InvalidInterfaceException |
|
1175 | + * @throws InvalidArgumentException |
|
1176 | + * @throws ReflectionException |
|
1177 | + */ |
|
1178 | + public function wp_loaded() |
|
1179 | + { |
|
1180 | + if ($this->request->requestParamIsSet('clear_session')) { |
|
1181 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
1182 | + } |
|
1183 | + } |
|
1184 | + |
|
1185 | + |
|
1186 | + /** |
|
1187 | + * Used to reset the entire object (for tests). |
|
1188 | + * |
|
1189 | + * @since 4.3.0 |
|
1190 | + * @throws EE_Error |
|
1191 | + * @throws InvalidDataTypeException |
|
1192 | + * @throws InvalidInterfaceException |
|
1193 | + * @throws InvalidArgumentException |
|
1194 | + * @throws ReflectionException |
|
1195 | + */ |
|
1196 | + public function reset_instance() |
|
1197 | + { |
|
1198 | + $this->clear_session(); |
|
1199 | + self::$_instance = null; |
|
1200 | + } |
|
1201 | + |
|
1202 | + |
|
1203 | + public function configure_garbage_collection_filters() |
|
1204 | + { |
|
1205 | + // run old filter we had for controlling session cleanup |
|
1206 | + $expired_session_transient_delete_query_limit = absint( |
|
1207 | + apply_filters( |
|
1208 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1209 | + 50 |
|
1210 | + ) |
|
1211 | + ); |
|
1212 | + // is there a value? or one that is different than the default 50 records? |
|
1213 | + if ($expired_session_transient_delete_query_limit === 0) { |
|
1214 | + // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1215 | + add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1216 | + } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1217 | + // or use that for the new transient cleanup query limit |
|
1218 | + add_filter( |
|
1219 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1220 | + function () use ($expired_session_transient_delete_query_limit) { |
|
1221 | + return $expired_session_transient_delete_query_limit; |
|
1222 | + } |
|
1223 | + ); |
|
1224 | + } |
|
1225 | + } |
|
1226 | + |
|
1227 | + |
|
1228 | + /** |
|
1229 | + * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1230 | + * @param $data1 |
|
1231 | + * @return string |
|
1232 | + */ |
|
1233 | + private function find_serialize_error($data1) |
|
1234 | + { |
|
1235 | + $error = '<pre>'; |
|
1236 | + $data2 = preg_replace_callback( |
|
1237 | + '!s:(\d+):"(.*?)";!', |
|
1238 | + function ($match) { |
|
1239 | + return ($match[1] === strlen($match[2])) |
|
1240 | + ? $match[0] |
|
1241 | + : 's:' |
|
1242 | + . strlen($match[2]) |
|
1243 | + . ':"' |
|
1244 | + . $match[2] |
|
1245 | + . '";'; |
|
1246 | + }, |
|
1247 | + $data1 |
|
1248 | + ); |
|
1249 | + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1250 | + $error .= $data1 . PHP_EOL; |
|
1251 | + $error .= $data2 . PHP_EOL; |
|
1252 | + for ($i = 0; $i < $max; $i++) { |
|
1253 | + if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1254 | + $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1255 | + $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1256 | + $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | + $start = ($i - 20); |
|
1258 | + $start = ($start < 0) ? 0 : $start; |
|
1259 | + $length = 40; |
|
1260 | + $point = $max - $i; |
|
1261 | + if ($point < 20) { |
|
1262 | + $rlength = 1; |
|
1263 | + $rpoint = -$point; |
|
1264 | + } else { |
|
1265 | + $rpoint = $length - 20; |
|
1266 | + $rlength = 1; |
|
1267 | + } |
|
1268 | + $error .= "\t-> Section Data1 = "; |
|
1269 | + $error .= substr_replace( |
|
1270 | + substr($data1, $start, $length), |
|
1271 | + "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1272 | + $rpoint, |
|
1273 | + $rlength |
|
1274 | + ); |
|
1275 | + $error .= PHP_EOL; |
|
1276 | + $error .= "\t-> Section Data2 = "; |
|
1277 | + $error .= substr_replace( |
|
1278 | + substr($data2, $start, $length), |
|
1279 | + "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1280 | + $rpoint, |
|
1281 | + $rlength |
|
1282 | + ); |
|
1283 | + $error .= PHP_EOL; |
|
1284 | + } |
|
1285 | + } |
|
1286 | + $error .= '</pre>'; |
|
1287 | + return $error; |
|
1288 | + } |
|
1289 | + |
|
1290 | + |
|
1291 | + /** |
|
1292 | + * Saves an array of settings used for configuring aspects of session behaviour |
|
1293 | + * |
|
1294 | + * @param array $updated_settings |
|
1295 | + */ |
|
1296 | + private function updateSessionSettings(array $updated_settings = array()) |
|
1297 | + { |
|
1298 | + // add existing settings, but only if not included in incoming $updated_settings array |
|
1299 | + $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1300 | + update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1301 | + } |
|
1302 | + |
|
1303 | + |
|
1304 | + /** |
|
1305 | + * garbage_collection |
|
1306 | + */ |
|
1307 | + public function garbageCollection() |
|
1308 | + { |
|
1309 | + // only perform during regular requests if last garbage collection was over an hour ago |
|
1310 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1311 | + $this->_last_gc = time(); |
|
1312 | + $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1313 | + /** @type WPDB $wpdb */ |
|
1314 | + global $wpdb; |
|
1315 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
1316 | + $expired_session_transient_delete_query_limit = absint( |
|
1317 | + apply_filters( |
|
1318 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1319 | + 50 |
|
1320 | + ) |
|
1321 | + ); |
|
1322 | + // non-zero LIMIT means take out the trash |
|
1323 | + if ($expired_session_transient_delete_query_limit) { |
|
1324 | + $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1325 | + $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1326 | + // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1327 | + // but we only want to pick up any trash that's been around for more than a day |
|
1328 | + $expiration = time() - DAY_IN_SECONDS; |
|
1329 | + $SQL = " |
|
1330 | 1330 | SELECT option_name |
1331 | 1331 | FROM {$wpdb->options} |
1332 | 1332 | WHERE |
@@ -1335,17 +1335,17 @@ discard block |
||
1335 | 1335 | AND option_value < {$expiration} |
1336 | 1336 | LIMIT {$expired_session_transient_delete_query_limit} |
1337 | 1337 | "; |
1338 | - // produces something like: |
|
1339 | - // SELECT option_name FROM wp_options |
|
1340 | - // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1341 | - // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1342 | - // AND option_value < 1508368198 LIMIT 50 |
|
1343 | - $expired_sessions = $wpdb->get_col($SQL); |
|
1344 | - // valid results? |
|
1345 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1346 | - $this->cache_storage->deleteMany($expired_sessions, true); |
|
1347 | - } |
|
1348 | - } |
|
1349 | - } |
|
1350 | - } |
|
1338 | + // produces something like: |
|
1339 | + // SELECT option_name FROM wp_options |
|
1340 | + // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1341 | + // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1342 | + // AND option_value < 1508368198 LIMIT 50 |
|
1343 | + $expired_sessions = $wpdb->get_col($SQL); |
|
1344 | + // valid results? |
|
1345 | + if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1346 | + $this->cache_storage->deleteMany($expired_sessions, true); |
|
1347 | + } |
|
1348 | + } |
|
1349 | + } |
|
1350 | + } |
|
1351 | 1351 | } |
@@ -22,206 +22,206 @@ |
||
22 | 22 | */ |
23 | 23 | class ModelObjNode extends BaseNode |
24 | 24 | { |
25 | - /** |
|
26 | - * @var int|string |
|
27 | - */ |
|
28 | - protected $id; |
|
25 | + /** |
|
26 | + * @var int|string |
|
27 | + */ |
|
28 | + protected $id; |
|
29 | 29 | |
30 | - /** |
|
31 | - * @var EEM_Base |
|
32 | - */ |
|
33 | - protected $model; |
|
30 | + /** |
|
31 | + * @var EEM_Base |
|
32 | + */ |
|
33 | + protected $model; |
|
34 | 34 | |
35 | - /** |
|
36 | - * @var RelationNode[] |
|
37 | - */ |
|
38 | - protected $nodes; |
|
35 | + /** |
|
36 | + * @var RelationNode[] |
|
37 | + */ |
|
38 | + protected $nodes; |
|
39 | 39 | |
40 | - /** |
|
41 | - * We don't pass the model objects because this needs to serialize to something tiny for effiency. |
|
42 | - * @param $model_obj_id |
|
43 | - * @param EEM_Base $model |
|
44 | - * @param array $dont_traverse_models array of model names we DON'T want to traverse. |
|
45 | - */ |
|
46 | - public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = []) |
|
47 | - { |
|
48 | - $this->id = $model_obj_id; |
|
49 | - $this->model = $model; |
|
50 | - $this->dont_traverse_models = $dont_traverse_models; |
|
51 | - } |
|
40 | + /** |
|
41 | + * We don't pass the model objects because this needs to serialize to something tiny for effiency. |
|
42 | + * @param $model_obj_id |
|
43 | + * @param EEM_Base $model |
|
44 | + * @param array $dont_traverse_models array of model names we DON'T want to traverse. |
|
45 | + */ |
|
46 | + public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = []) |
|
47 | + { |
|
48 | + $this->id = $model_obj_id; |
|
49 | + $this->model = $model; |
|
50 | + $this->dont_traverse_models = $dont_traverse_models; |
|
51 | + } |
|
52 | 52 | |
53 | - /** |
|
54 | - * Creates a relation node for each relation of this model's relations. |
|
55 | - * Does NOT call `discover` on them yet though. |
|
56 | - * @since 4.10.12.p |
|
57 | - * @throws \EE_Error |
|
58 | - * @throws InvalidDataTypeException |
|
59 | - * @throws InvalidInterfaceException |
|
60 | - * @throws InvalidArgumentException |
|
61 | - * @throws ReflectionException |
|
62 | - */ |
|
63 | - protected function discover() |
|
64 | - { |
|
65 | - $this->nodes = []; |
|
66 | - foreach ($this->model->relation_settings() as $relationName => $relation) { |
|
67 | - // Make sure this isn't one of the models we were told to not traverse into. |
|
68 | - if (in_array($relationName, $this->dont_traverse_models)) { |
|
69 | - continue; |
|
70 | - } |
|
71 | - if ($relation instanceof EE_Has_Many_Relation) { |
|
72 | - $this->nodes[ $relationName ] = new RelationNode( |
|
73 | - $this->id, |
|
74 | - $this->model, |
|
75 | - $relation->get_other_model(), |
|
76 | - $this->dont_traverse_models |
|
77 | - ); |
|
78 | - } elseif ( |
|
79 | - $relation instanceof EE_HABTM_Relation && |
|
80 | - ! in_array( |
|
81 | - $relation->get_join_model()->get_this_model_name(), |
|
82 | - $this->dont_traverse_models |
|
83 | - ) |
|
84 | - ) { |
|
85 | - $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
86 | - $this->id, |
|
87 | - $this->model, |
|
88 | - $relation->get_join_model(), |
|
89 | - $this->dont_traverse_models |
|
90 | - ); |
|
91 | - } |
|
92 | - } |
|
93 | - ksort($this->nodes); |
|
94 | - } |
|
53 | + /** |
|
54 | + * Creates a relation node for each relation of this model's relations. |
|
55 | + * Does NOT call `discover` on them yet though. |
|
56 | + * @since 4.10.12.p |
|
57 | + * @throws \EE_Error |
|
58 | + * @throws InvalidDataTypeException |
|
59 | + * @throws InvalidInterfaceException |
|
60 | + * @throws InvalidArgumentException |
|
61 | + * @throws ReflectionException |
|
62 | + */ |
|
63 | + protected function discover() |
|
64 | + { |
|
65 | + $this->nodes = []; |
|
66 | + foreach ($this->model->relation_settings() as $relationName => $relation) { |
|
67 | + // Make sure this isn't one of the models we were told to not traverse into. |
|
68 | + if (in_array($relationName, $this->dont_traverse_models)) { |
|
69 | + continue; |
|
70 | + } |
|
71 | + if ($relation instanceof EE_Has_Many_Relation) { |
|
72 | + $this->nodes[ $relationName ] = new RelationNode( |
|
73 | + $this->id, |
|
74 | + $this->model, |
|
75 | + $relation->get_other_model(), |
|
76 | + $this->dont_traverse_models |
|
77 | + ); |
|
78 | + } elseif ( |
|
79 | + $relation instanceof EE_HABTM_Relation && |
|
80 | + ! in_array( |
|
81 | + $relation->get_join_model()->get_this_model_name(), |
|
82 | + $this->dont_traverse_models |
|
83 | + ) |
|
84 | + ) { |
|
85 | + $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
86 | + $this->id, |
|
87 | + $this->model, |
|
88 | + $relation->get_join_model(), |
|
89 | + $this->dont_traverse_models |
|
90 | + ); |
|
91 | + } |
|
92 | + } |
|
93 | + ksort($this->nodes); |
|
94 | + } |
|
95 | 95 | |
96 | 96 | |
97 | - /** |
|
98 | - * Whether this item has already been initialized |
|
99 | - */ |
|
100 | - protected function isDiscovered() |
|
101 | - { |
|
102 | - return $this->nodes !== null && is_array($this->nodes); |
|
103 | - } |
|
97 | + /** |
|
98 | + * Whether this item has already been initialized |
|
99 | + */ |
|
100 | + protected function isDiscovered() |
|
101 | + { |
|
102 | + return $this->nodes !== null && is_array($this->nodes); |
|
103 | + } |
|
104 | 104 | |
105 | - /** |
|
106 | - * @since 4.10.12.p |
|
107 | - * @return boolean |
|
108 | - */ |
|
109 | - public function isComplete() |
|
110 | - { |
|
111 | - if ($this->complete === null) { |
|
112 | - $this->complete = false; |
|
113 | - } |
|
114 | - return $this->complete; |
|
115 | - } |
|
105 | + /** |
|
106 | + * @since 4.10.12.p |
|
107 | + * @return boolean |
|
108 | + */ |
|
109 | + public function isComplete() |
|
110 | + { |
|
111 | + if ($this->complete === null) { |
|
112 | + $this->complete = false; |
|
113 | + } |
|
114 | + return $this->complete; |
|
115 | + } |
|
116 | 116 | |
117 | - /** |
|
118 | - * Triggers working on each child relation node that has work to do. |
|
119 | - * @since 4.10.12.p |
|
120 | - * @param $model_objects_to_identify |
|
121 | - * @return int units of work done |
|
122 | - */ |
|
123 | - protected function work($model_objects_to_identify) |
|
124 | - { |
|
125 | - $num_identified = 0; |
|
126 | - // Begin assuming we'll finish all the work on this node and its children... |
|
127 | - $this->complete = true; |
|
128 | - foreach ($this->nodes as $model_name => $relation_node) { |
|
129 | - $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified); |
|
130 | - // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
|
131 | - // related model objects. |
|
132 | - if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
|
133 | - unset($this->nodes[ $model_name ]); |
|
134 | - } |
|
135 | - if ($num_identified >= $model_objects_to_identify) { |
|
136 | - // ...but admit we're wrong if the work exceeded the budget. |
|
137 | - $this->complete = false; |
|
138 | - break; |
|
139 | - } |
|
140 | - } |
|
141 | - return $num_identified; |
|
142 | - } |
|
117 | + /** |
|
118 | + * Triggers working on each child relation node that has work to do. |
|
119 | + * @since 4.10.12.p |
|
120 | + * @param $model_objects_to_identify |
|
121 | + * @return int units of work done |
|
122 | + */ |
|
123 | + protected function work($model_objects_to_identify) |
|
124 | + { |
|
125 | + $num_identified = 0; |
|
126 | + // Begin assuming we'll finish all the work on this node and its children... |
|
127 | + $this->complete = true; |
|
128 | + foreach ($this->nodes as $model_name => $relation_node) { |
|
129 | + $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified); |
|
130 | + // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
|
131 | + // related model objects. |
|
132 | + if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
|
133 | + unset($this->nodes[ $model_name ]); |
|
134 | + } |
|
135 | + if ($num_identified >= $model_objects_to_identify) { |
|
136 | + // ...but admit we're wrong if the work exceeded the budget. |
|
137 | + $this->complete = false; |
|
138 | + break; |
|
139 | + } |
|
140 | + } |
|
141 | + return $num_identified; |
|
142 | + } |
|
143 | 143 | |
144 | - /** |
|
145 | - * @since 4.10.12.p |
|
146 | - * @return array |
|
147 | - * @throws \EE_Error |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws InvalidInterfaceException |
|
150 | - * @throws InvalidArgumentException |
|
151 | - * @throws ReflectionException |
|
152 | - */ |
|
153 | - public function toArray() |
|
154 | - { |
|
155 | - $tree = [ |
|
156 | - 'id' => $this->id, |
|
157 | - 'complete' => $this->isComplete(), |
|
158 | - 'rels' => [] |
|
159 | - ]; |
|
160 | - if ($this->nodes === null) { |
|
161 | - $tree['rels'] = null; |
|
162 | - } else { |
|
163 | - foreach ($this->nodes as $relation_name => $relation_node) { |
|
164 | - $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
165 | - } |
|
166 | - } |
|
167 | - return $tree; |
|
168 | - } |
|
144 | + /** |
|
145 | + * @since 4.10.12.p |
|
146 | + * @return array |
|
147 | + * @throws \EE_Error |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws InvalidInterfaceException |
|
150 | + * @throws InvalidArgumentException |
|
151 | + * @throws ReflectionException |
|
152 | + */ |
|
153 | + public function toArray() |
|
154 | + { |
|
155 | + $tree = [ |
|
156 | + 'id' => $this->id, |
|
157 | + 'complete' => $this->isComplete(), |
|
158 | + 'rels' => [] |
|
159 | + ]; |
|
160 | + if ($this->nodes === null) { |
|
161 | + $tree['rels'] = null; |
|
162 | + } else { |
|
163 | + foreach ($this->nodes as $relation_name => $relation_node) { |
|
164 | + $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
165 | + } |
|
166 | + } |
|
167 | + return $tree; |
|
168 | + } |
|
169 | 169 | |
170 | - /** |
|
171 | - * @since 4.10.12.p |
|
172 | - * @return array|mixed |
|
173 | - * @throws InvalidArgumentException |
|
174 | - * @throws InvalidDataTypeException |
|
175 | - * @throws InvalidInterfaceException |
|
176 | - * @throws ReflectionException |
|
177 | - * @throws \EE_Error |
|
178 | - */ |
|
179 | - public function getIds() |
|
180 | - { |
|
181 | - $ids = [ |
|
182 | - $this->model->get_this_model_name() => [ |
|
183 | - $this->id => $this->id |
|
184 | - ] |
|
185 | - ]; |
|
186 | - if ($this->nodes && is_array($this->nodes)) { |
|
187 | - foreach ($this->nodes as $relation_node) { |
|
188 | - $ids = array_replace_recursive($ids, $relation_node->getIds()); |
|
189 | - } |
|
190 | - } |
|
191 | - return $ids; |
|
192 | - } |
|
170 | + /** |
|
171 | + * @since 4.10.12.p |
|
172 | + * @return array|mixed |
|
173 | + * @throws InvalidArgumentException |
|
174 | + * @throws InvalidDataTypeException |
|
175 | + * @throws InvalidInterfaceException |
|
176 | + * @throws ReflectionException |
|
177 | + * @throws \EE_Error |
|
178 | + */ |
|
179 | + public function getIds() |
|
180 | + { |
|
181 | + $ids = [ |
|
182 | + $this->model->get_this_model_name() => [ |
|
183 | + $this->id => $this->id |
|
184 | + ] |
|
185 | + ]; |
|
186 | + if ($this->nodes && is_array($this->nodes)) { |
|
187 | + foreach ($this->nodes as $relation_node) { |
|
188 | + $ids = array_replace_recursive($ids, $relation_node->getIds()); |
|
189 | + } |
|
190 | + } |
|
191 | + return $ids; |
|
192 | + } |
|
193 | 193 | |
194 | - /** |
|
195 | - * Don't serialize the models. Just record their names on some dynamic properties. |
|
196 | - * @since 4.10.12.p |
|
197 | - */ |
|
198 | - public function __sleep() |
|
199 | - { |
|
200 | - $this->m = $this->model->get_this_model_name(); |
|
201 | - return array_merge( |
|
202 | - [ |
|
203 | - 'm', |
|
204 | - 'id', |
|
205 | - 'nodes', |
|
206 | - ], |
|
207 | - parent::__sleep() |
|
208 | - ); |
|
209 | - } |
|
194 | + /** |
|
195 | + * Don't serialize the models. Just record their names on some dynamic properties. |
|
196 | + * @since 4.10.12.p |
|
197 | + */ |
|
198 | + public function __sleep() |
|
199 | + { |
|
200 | + $this->m = $this->model->get_this_model_name(); |
|
201 | + return array_merge( |
|
202 | + [ |
|
203 | + 'm', |
|
204 | + 'id', |
|
205 | + 'nodes', |
|
206 | + ], |
|
207 | + parent::__sleep() |
|
208 | + ); |
|
209 | + } |
|
210 | 210 | |
211 | - /** |
|
212 | - * Use the dynamic properties to instantiate the models we use. |
|
213 | - * @since 4.10.12.p |
|
214 | - * @throws EE_Error |
|
215 | - * @throws InvalidArgumentException |
|
216 | - * @throws InvalidDataTypeException |
|
217 | - * @throws InvalidInterfaceException |
|
218 | - * @throws ReflectionException |
|
219 | - */ |
|
220 | - public function __wakeup() |
|
221 | - { |
|
222 | - $this->model = EE_Registry::instance()->load_model($this->m); |
|
223 | - parent::__wakeup(); |
|
224 | - } |
|
211 | + /** |
|
212 | + * Use the dynamic properties to instantiate the models we use. |
|
213 | + * @since 4.10.12.p |
|
214 | + * @throws EE_Error |
|
215 | + * @throws InvalidArgumentException |
|
216 | + * @throws InvalidDataTypeException |
|
217 | + * @throws InvalidInterfaceException |
|
218 | + * @throws ReflectionException |
|
219 | + */ |
|
220 | + public function __wakeup() |
|
221 | + { |
|
222 | + $this->model = EE_Registry::instance()->load_model($this->m); |
|
223 | + parent::__wakeup(); |
|
224 | + } |
|
225 | 225 | } |
226 | 226 | // End of file Visitor.php |
227 | 227 | // Location: EventEspresso\core\services\orm\tree_traversal/Visitor.php |
@@ -69,7 +69,7 @@ discard block |
||
69 | 69 | continue; |
70 | 70 | } |
71 | 71 | if ($relation instanceof EE_Has_Many_Relation) { |
72 | - $this->nodes[ $relationName ] = new RelationNode( |
|
72 | + $this->nodes[$relationName] = new RelationNode( |
|
73 | 73 | $this->id, |
74 | 74 | $this->model, |
75 | 75 | $relation->get_other_model(), |
@@ -82,7 +82,7 @@ discard block |
||
82 | 82 | $this->dont_traverse_models |
83 | 83 | ) |
84 | 84 | ) { |
85 | - $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
85 | + $this->nodes[$relation->get_join_model()->get_this_model_name()] = new RelationNode( |
|
86 | 86 | $this->id, |
87 | 87 | $this->model, |
88 | 88 | $relation->get_join_model(), |
@@ -130,7 +130,7 @@ discard block |
||
130 | 130 | // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
131 | 131 | // related model objects. |
132 | 132 | if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
133 | - unset($this->nodes[ $model_name ]); |
|
133 | + unset($this->nodes[$model_name]); |
|
134 | 134 | } |
135 | 135 | if ($num_identified >= $model_objects_to_identify) { |
136 | 136 | // ...but admit we're wrong if the work exceeded the budget. |
@@ -161,7 +161,7 @@ discard block |
||
161 | 161 | $tree['rels'] = null; |
162 | 162 | } else { |
163 | 163 | foreach ($this->nodes as $relation_name => $relation_node) { |
164 | - $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
164 | + $tree['rels'][$relation_name] = $relation_node->toArray(); |
|
165 | 165 | } |
166 | 166 | } |
167 | 167 | return $tree; |
@@ -68,11 +68,11 @@ discard block |
||
68 | 68 | } |
69 | 69 | |
70 | 70 | // make sure we don't register twice |
71 | - if (isset(self::$_registry[ $identifier ])) { |
|
71 | + if (isset(self::$_registry[$identifier])) { |
|
72 | 72 | return; |
73 | 73 | } |
74 | 74 | // check correct loading |
75 | - if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
75 | + if ( ! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
76 | 76 | EE_Error::doing_it_wrong( |
77 | 77 | __METHOD__, |
78 | 78 | sprintf( |
@@ -89,30 +89,30 @@ discard block |
||
89 | 89 | ); |
90 | 90 | } |
91 | 91 | |
92 | - self::$_registry[ $identifier ] = $setup_args; |
|
93 | - self::$_extensions[ $identifier ] = []; |
|
92 | + self::$_registry[$identifier] = $setup_args; |
|
93 | + self::$_extensions[$identifier] = []; |
|
94 | 94 | |
95 | 95 | if (isset($setup_args['model_extension_paths'])) { |
96 | - require_once(EE_LIBRARIES . 'plugin_api/db/EEME_Base.lib.php'); |
|
96 | + require_once(EE_LIBRARIES.'plugin_api/db/EEME_Base.lib.php'); |
|
97 | 97 | $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['model_extension_paths']); |
98 | 98 | // remove all files that are not PHP |
99 | 99 | foreach ($class_to_filepath_map as $class => $path) { |
100 | 100 | if (substr($path, strlen($path) - 3) !== 'php') { |
101 | - unset($class_to_filepath_map[ $class ]); |
|
101 | + unset($class_to_filepath_map[$class]); |
|
102 | 102 | } |
103 | 103 | } |
104 | 104 | EEH_Autoloader::register_autoloader($class_to_filepath_map); |
105 | 105 | foreach (array_keys($class_to_filepath_map) as $classname) { |
106 | - self::$_extensions[ $identifier ]['models'][ $classname ] = new $classname(); |
|
106 | + self::$_extensions[$identifier]['models'][$classname] = new $classname(); |
|
107 | 107 | } |
108 | 108 | unset($setup_args['model_extension_paths']); |
109 | 109 | } |
110 | 110 | if (isset($setup_args['class_extension_paths'])) { |
111 | - require_once(EE_LIBRARIES . 'plugin_api/db/EEE_Base_Class.lib.php'); |
|
111 | + require_once(EE_LIBRARIES.'plugin_api/db/EEE_Base_Class.lib.php'); |
|
112 | 112 | $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['class_extension_paths']); |
113 | 113 | EEH_Autoloader::register_autoloader($class_to_filepath_map); |
114 | 114 | foreach (array_keys($class_to_filepath_map) as $classname) { |
115 | - self::$_extensions[ $identifier ]['classes'][ $classname ] = new $classname(); |
|
115 | + self::$_extensions[$identifier]['classes'][$classname] = new $classname(); |
|
116 | 116 | } |
117 | 117 | unset($setup_args['class_extension_paths']); |
118 | 118 | } |
@@ -131,9 +131,9 @@ discard block |
||
131 | 131 | */ |
132 | 132 | public static function deregister($identifier = '') |
133 | 133 | { |
134 | - if (isset(self::$_registry[ $identifier ])) { |
|
135 | - unset(self::$_registry[ $identifier ]); |
|
136 | - foreach (self::$_extensions[ $identifier ] as $extension_of_type) { |
|
134 | + if (isset(self::$_registry[$identifier])) { |
|
135 | + unset(self::$_registry[$identifier]); |
|
136 | + foreach (self::$_extensions[$identifier] as $extension_of_type) { |
|
137 | 137 | foreach ($extension_of_type as $extension) { |
138 | 138 | $extension->deregister(); |
139 | 139 | } |
@@ -11,132 +11,132 @@ |
||
11 | 11 | */ |
12 | 12 | class EE_Register_Model_Extensions implements EEI_Plugin_API |
13 | 13 | { |
14 | - protected static $_registry; |
|
14 | + protected static $_registry; |
|
15 | 15 | |
16 | - protected static $_extensions = []; |
|
16 | + protected static $_extensions = []; |
|
17 | 17 | |
18 | 18 | |
19 | - /** |
|
20 | - * register method for setting up model extensions |
|
21 | - * |
|
22 | - * @param string $identifier unique id for the extensions being setup |
|
23 | - * @param array $setup_args { |
|
24 | - * @return void |
|
25 | - * @throws EE_Error |
|
26 | - * @type array $model_extension_paths array of folders containing DB model extensions, where each file follows |
|
27 | - * the models naming convention, which is: |
|
28 | - * EEME_{your_plugin_slug}_model_name_extended}.model_ext.php. |
|
29 | - * Where {your_plugin_slug} is really anything you want (but something having |
|
30 | - * to do with your addon, like 'Calendar' or '3D_View') and |
|
31 | - * model_name_extended} is the model extended. |
|
32 | - * The class contained in teh file should extend |
|
33 | - * EEME_Base_{model_name_extended}.model_ext.php. |
|
34 | - * Where {your_plugin_slug} is really anything you want (but something |
|
35 | - * having to do with your addon, like 'Calendar' or '3D_View') and |
|
36 | - * {model_name_extended} is the model extended. The class contained in teh |
|
37 | - * file should extend EEME_Base |
|
38 | - * @type array $class_extension_paths array of folders containing DB class extensions, where each file follows |
|
39 | - * the model class extension naming convention, which is: |
|
40 | - * EEE_{your_plugin_slug}_model_name_extended}.class_ext.php. |
|
41 | - * Where {your_plugin_slug} is something like 'Calendar','MailChimp',etc, |
|
42 | - * and model_name_extended} is the name of the model extended, eg |
|
43 | - * 'Attendee','Event',etc. |
|
44 | - * The class contained in the file should extend EEE_Base_Class |
|
45 | - * ._{model_name_extended}.class_ext.php. |
|
46 | - * Where {your_plugin_slug} is something like 'Calendar','MailChimp',etc, |
|
47 | - * and {model_name_extended} is the name of the model extended, eg |
|
48 | - * 'Attendee','Event',etc. The class contained in the file should extend |
|
49 | - * EEE_Base_Class. |
|
50 | - * } |
|
51 | - * |
|
52 | - */ |
|
53 | - public static function register($identifier = '', array $setup_args = []) |
|
54 | - { |
|
55 | - // required fields MUST be present, so let's make sure they are. |
|
56 | - if ( |
|
57 | - empty($identifier) |
|
58 | - || ! is_array($setup_args) |
|
59 | - || (empty($setup_args['model_extension_paths']) && empty($setup_args['class_extension_paths'])) |
|
60 | - ) { |
|
61 | - throw new EE_Error( |
|
62 | - esc_html__( |
|
63 | - 'In order to register Model extensions with EE_Register_Model_Extensions::register(), you must include a "model_id" (a unique identifier for this set of models), and an array containing the following keys: "model_extension_paths" (an array of full server paths to folders that contain model extensions), and "class_extension_paths" (an array of full server paths to folders that contain class extensions)', |
|
64 | - 'event_espresso' |
|
65 | - ) |
|
66 | - ); |
|
67 | - } |
|
19 | + /** |
|
20 | + * register method for setting up model extensions |
|
21 | + * |
|
22 | + * @param string $identifier unique id for the extensions being setup |
|
23 | + * @param array $setup_args { |
|
24 | + * @return void |
|
25 | + * @throws EE_Error |
|
26 | + * @type array $model_extension_paths array of folders containing DB model extensions, where each file follows |
|
27 | + * the models naming convention, which is: |
|
28 | + * EEME_{your_plugin_slug}_model_name_extended}.model_ext.php. |
|
29 | + * Where {your_plugin_slug} is really anything you want (but something having |
|
30 | + * to do with your addon, like 'Calendar' or '3D_View') and |
|
31 | + * model_name_extended} is the model extended. |
|
32 | + * The class contained in teh file should extend |
|
33 | + * EEME_Base_{model_name_extended}.model_ext.php. |
|
34 | + * Where {your_plugin_slug} is really anything you want (but something |
|
35 | + * having to do with your addon, like 'Calendar' or '3D_View') and |
|
36 | + * {model_name_extended} is the model extended. The class contained in teh |
|
37 | + * file should extend EEME_Base |
|
38 | + * @type array $class_extension_paths array of folders containing DB class extensions, where each file follows |
|
39 | + * the model class extension naming convention, which is: |
|
40 | + * EEE_{your_plugin_slug}_model_name_extended}.class_ext.php. |
|
41 | + * Where {your_plugin_slug} is something like 'Calendar','MailChimp',etc, |
|
42 | + * and model_name_extended} is the name of the model extended, eg |
|
43 | + * 'Attendee','Event',etc. |
|
44 | + * The class contained in the file should extend EEE_Base_Class |
|
45 | + * ._{model_name_extended}.class_ext.php. |
|
46 | + * Where {your_plugin_slug} is something like 'Calendar','MailChimp',etc, |
|
47 | + * and {model_name_extended} is the name of the model extended, eg |
|
48 | + * 'Attendee','Event',etc. The class contained in the file should extend |
|
49 | + * EEE_Base_Class. |
|
50 | + * } |
|
51 | + * |
|
52 | + */ |
|
53 | + public static function register($identifier = '', array $setup_args = []) |
|
54 | + { |
|
55 | + // required fields MUST be present, so let's make sure they are. |
|
56 | + if ( |
|
57 | + empty($identifier) |
|
58 | + || ! is_array($setup_args) |
|
59 | + || (empty($setup_args['model_extension_paths']) && empty($setup_args['class_extension_paths'])) |
|
60 | + ) { |
|
61 | + throw new EE_Error( |
|
62 | + esc_html__( |
|
63 | + 'In order to register Model extensions with EE_Register_Model_Extensions::register(), you must include a "model_id" (a unique identifier for this set of models), and an array containing the following keys: "model_extension_paths" (an array of full server paths to folders that contain model extensions), and "class_extension_paths" (an array of full server paths to folders that contain class extensions)', |
|
64 | + 'event_espresso' |
|
65 | + ) |
|
66 | + ); |
|
67 | + } |
|
68 | 68 | |
69 | - // make sure we don't register twice |
|
70 | - if (isset(self::$_registry[ $identifier ])) { |
|
71 | - return; |
|
72 | - } |
|
73 | - // check correct loading |
|
74 | - if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
75 | - EE_Error::doing_it_wrong( |
|
76 | - __METHOD__, |
|
77 | - sprintf( |
|
78 | - esc_html__( |
|
79 | - 'An attempt was made to register "%1$s" as a Model extension has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__load_espresso_addons" hook to register models.%2$s Hook Status: %2$s "AHEE__EE_System__load_espresso_addons" : %3$s %2$s "AHEE__EE_Admin__loaded" : %4$s%2$s', |
|
80 | - 'event_espresso' |
|
81 | - ), |
|
82 | - $identifier, |
|
83 | - '<br />', |
|
84 | - did_action('AHEE__EE_System__load_espresso_addons') ? 'action done' : 'action NOT done', |
|
85 | - did_action('AHEE__EE_Admin__loaded') ? 'action done' : 'action NOT done' |
|
86 | - ), |
|
87 | - '4.3' |
|
88 | - ); |
|
89 | - } |
|
69 | + // make sure we don't register twice |
|
70 | + if (isset(self::$_registry[ $identifier ])) { |
|
71 | + return; |
|
72 | + } |
|
73 | + // check correct loading |
|
74 | + if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
75 | + EE_Error::doing_it_wrong( |
|
76 | + __METHOD__, |
|
77 | + sprintf( |
|
78 | + esc_html__( |
|
79 | + 'An attempt was made to register "%1$s" as a Model extension has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__load_espresso_addons" hook to register models.%2$s Hook Status: %2$s "AHEE__EE_System__load_espresso_addons" : %3$s %2$s "AHEE__EE_Admin__loaded" : %4$s%2$s', |
|
80 | + 'event_espresso' |
|
81 | + ), |
|
82 | + $identifier, |
|
83 | + '<br />', |
|
84 | + did_action('AHEE__EE_System__load_espresso_addons') ? 'action done' : 'action NOT done', |
|
85 | + did_action('AHEE__EE_Admin__loaded') ? 'action done' : 'action NOT done' |
|
86 | + ), |
|
87 | + '4.3' |
|
88 | + ); |
|
89 | + } |
|
90 | 90 | |
91 | - self::$_registry[ $identifier ] = $setup_args; |
|
92 | - self::$_extensions[ $identifier ] = []; |
|
91 | + self::$_registry[ $identifier ] = $setup_args; |
|
92 | + self::$_extensions[ $identifier ] = []; |
|
93 | 93 | |
94 | - if (isset($setup_args['model_extension_paths'])) { |
|
95 | - require_once(EE_LIBRARIES . 'plugin_api/db/EEME_Base.lib.php'); |
|
96 | - $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['model_extension_paths']); |
|
97 | - // remove all files that are not PHP |
|
98 | - foreach ($class_to_filepath_map as $class => $path) { |
|
99 | - if (substr($path, strlen($path) - 3) !== 'php') { |
|
100 | - unset($class_to_filepath_map[ $class ]); |
|
101 | - } |
|
102 | - } |
|
103 | - EEH_Autoloader::register_autoloader($class_to_filepath_map); |
|
104 | - foreach (array_keys($class_to_filepath_map) as $classname) { |
|
105 | - self::$_extensions[ $identifier ]['models'][ $classname ] = new $classname(); |
|
106 | - } |
|
107 | - unset($setup_args['model_extension_paths']); |
|
108 | - } |
|
109 | - if (isset($setup_args['class_extension_paths'])) { |
|
110 | - require_once(EE_LIBRARIES . 'plugin_api/db/EEE_Base_Class.lib.php'); |
|
111 | - $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['class_extension_paths']); |
|
112 | - EEH_Autoloader::register_autoloader($class_to_filepath_map); |
|
113 | - foreach (array_keys($class_to_filepath_map) as $classname) { |
|
114 | - self::$_extensions[ $identifier ]['classes'][ $classname ] = new $classname(); |
|
115 | - } |
|
116 | - unset($setup_args['class_extension_paths']); |
|
117 | - } |
|
118 | - foreach ($setup_args as $unknown_key => $unknown_config) { |
|
119 | - throw new EE_Error( |
|
120 | - sprintf(esc_html__("The key '%s' is not a known key for registering a model", "event_espresso"), $unknown_key) |
|
121 | - ); |
|
122 | - } |
|
123 | - } |
|
94 | + if (isset($setup_args['model_extension_paths'])) { |
|
95 | + require_once(EE_LIBRARIES . 'plugin_api/db/EEME_Base.lib.php'); |
|
96 | + $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['model_extension_paths']); |
|
97 | + // remove all files that are not PHP |
|
98 | + foreach ($class_to_filepath_map as $class => $path) { |
|
99 | + if (substr($path, strlen($path) - 3) !== 'php') { |
|
100 | + unset($class_to_filepath_map[ $class ]); |
|
101 | + } |
|
102 | + } |
|
103 | + EEH_Autoloader::register_autoloader($class_to_filepath_map); |
|
104 | + foreach (array_keys($class_to_filepath_map) as $classname) { |
|
105 | + self::$_extensions[ $identifier ]['models'][ $classname ] = new $classname(); |
|
106 | + } |
|
107 | + unset($setup_args['model_extension_paths']); |
|
108 | + } |
|
109 | + if (isset($setup_args['class_extension_paths'])) { |
|
110 | + require_once(EE_LIBRARIES . 'plugin_api/db/EEE_Base_Class.lib.php'); |
|
111 | + $class_to_filepath_map = EEH_File::get_contents_of_folders($setup_args['class_extension_paths']); |
|
112 | + EEH_Autoloader::register_autoloader($class_to_filepath_map); |
|
113 | + foreach (array_keys($class_to_filepath_map) as $classname) { |
|
114 | + self::$_extensions[ $identifier ]['classes'][ $classname ] = new $classname(); |
|
115 | + } |
|
116 | + unset($setup_args['class_extension_paths']); |
|
117 | + } |
|
118 | + foreach ($setup_args as $unknown_key => $unknown_config) { |
|
119 | + throw new EE_Error( |
|
120 | + sprintf(esc_html__("The key '%s' is not a known key for registering a model", "event_espresso"), $unknown_key) |
|
121 | + ); |
|
122 | + } |
|
123 | + } |
|
124 | 124 | |
125 | 125 | |
126 | - /** |
|
127 | - * deregister |
|
128 | - * |
|
129 | - * @param string $identifier |
|
130 | - */ |
|
131 | - public static function deregister($identifier = '') |
|
132 | - { |
|
133 | - if (isset(self::$_registry[ $identifier ])) { |
|
134 | - unset(self::$_registry[ $identifier ]); |
|
135 | - foreach (self::$_extensions[ $identifier ] as $extension_of_type) { |
|
136 | - foreach ($extension_of_type as $extension) { |
|
137 | - $extension->deregister(); |
|
138 | - } |
|
139 | - } |
|
140 | - } |
|
141 | - } |
|
126 | + /** |
|
127 | + * deregister |
|
128 | + * |
|
129 | + * @param string $identifier |
|
130 | + */ |
|
131 | + public static function deregister($identifier = '') |
|
132 | + { |
|
133 | + if (isset(self::$_registry[ $identifier ])) { |
|
134 | + unset(self::$_registry[ $identifier ]); |
|
135 | + foreach (self::$_extensions[ $identifier ] as $extension_of_type) { |
|
136 | + foreach ($extension_of_type as $extension) { |
|
137 | + $extension->deregister(); |
|
138 | + } |
|
139 | + } |
|
140 | + } |
|
141 | + } |
|
142 | 142 | } |
@@ -59,7 +59,7 @@ discard block |
||
59 | 59 | ); |
60 | 60 | } |
61 | 61 | // make sure we don't register twice |
62 | - if (isset(self::$_settings[ $identifier ])) { |
|
62 | + if (isset(self::$_settings[$identifier])) { |
|
63 | 63 | return; |
64 | 64 | } |
65 | 65 | // make sure this was called in the right place! |
@@ -77,7 +77,7 @@ discard block |
||
77 | 77 | ); |
78 | 78 | } |
79 | 79 | // setup $_settings array from incoming values. |
80 | - self::$_settings[ $identifier ] = [ |
|
80 | + self::$_settings[$identifier] = [ |
|
81 | 81 | // array of full server paths to any EE_PMT_Base children used |
82 | 82 | 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
83 | 83 | ? (array) $setup_args['payment_method_paths'] |
@@ -93,12 +93,12 @@ discard block |
||
93 | 93 | if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) { |
94 | 94 | $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
95 | 95 | // register payment methods directly |
96 | - foreach (self::$_settings[ $identifier ]['payment_method_paths'] as $payment_method_path) { |
|
96 | + foreach (self::$_settings[$identifier]['payment_method_paths'] as $payment_method_path) { |
|
97 | 97 | $payment_method_manager->register_payment_method($payment_method_path); |
98 | 98 | } |
99 | 99 | $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
100 | 100 | $capabilities->addCaps( |
101 | - self::getPaymentMethodCapabilities(self::$_settings[ $identifier ]) |
|
101 | + self::getPaymentMethodCapabilities(self::$_settings[$identifier]) |
|
102 | 102 | ); |
103 | 103 | } |
104 | 104 | } |
@@ -135,13 +135,13 @@ discard block |
||
135 | 135 | */ |
136 | 136 | public static function deregister($identifier = '') |
137 | 137 | { |
138 | - if (isset(self::$_settings[ $identifier ])) { |
|
138 | + if (isset(self::$_settings[$identifier])) { |
|
139 | 139 | // set action for just this module id to delay deregistration until core is loaded and ready. |
140 | - $module_settings = self::$_settings[ $identifier ]; |
|
141 | - unset(self::$_settings[ $identifier ]); |
|
140 | + $module_settings = self::$_settings[$identifier]; |
|
141 | + unset(self::$_settings[$identifier]); |
|
142 | 142 | add_action( |
143 | 143 | 'AHEE__EE_System__core_loaded_and_ready', |
144 | - function () use ($module_settings) { |
|
144 | + function() use ($module_settings) { |
|
145 | 145 | $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
146 | 146 | $capabilities->removeCaps( |
147 | 147 | EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
@@ -18,163 +18,163 @@ |
||
18 | 18 | */ |
19 | 19 | class EE_Register_Payment_Method implements EEI_Plugin_API |
20 | 20 | { |
21 | - /** |
|
22 | - * Holds values for registered payment methods |
|
23 | - * |
|
24 | - * @var array |
|
25 | - */ |
|
26 | - protected static $_settings = []; |
|
21 | + /** |
|
22 | + * Holds values for registered payment methods |
|
23 | + * |
|
24 | + * @var array |
|
25 | + */ |
|
26 | + protected static $_settings = []; |
|
27 | 27 | |
28 | 28 | |
29 | - /** |
|
30 | - * Method for registering new EE_PMT_Base children |
|
31 | - * |
|
32 | - * @param string $identifier a unique identifier for this set of modules Required. |
|
33 | - * @param array $setup_args an array of arguments provided for registering modules Required.{ |
|
34 | - * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class |
|
35 | - * (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains |
|
36 | - * the files EE_PMT_Payomatic.pm.php) |
|
37 | - * } |
|
38 | - * @return void |
|
39 | - * @throws EE_Error |
|
40 | - * @type array payment_method_paths an array of full server paths to folders containing any EE_PMT_Base |
|
41 | - * children, or to the EED_Module files themselves |
|
42 | - * @throws InvalidDataTypeException |
|
43 | - * @throws DomainException |
|
44 | - * @throws InvalidArgumentException |
|
45 | - * @throws InvalidInterfaceException |
|
46 | - * @throws InvalidDataTypeException |
|
47 | - * @since 4.5.0 |
|
48 | - */ |
|
49 | - public static function register($identifier = '', array $setup_args = []) |
|
50 | - { |
|
51 | - // required fields MUST be present, so let's make sure they are. |
|
52 | - if (empty($identifier) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) { |
|
53 | - throw new EE_Error( |
|
54 | - esc_html__( |
|
55 | - 'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)', |
|
56 | - 'event_espresso' |
|
57 | - ) |
|
58 | - ); |
|
59 | - } |
|
60 | - // make sure we don't register twice |
|
61 | - if (isset(self::$_settings[ $identifier ])) { |
|
62 | - return; |
|
63 | - } |
|
64 | - // make sure this was called in the right place! |
|
65 | - if ( |
|
66 | - ! did_action('AHEE__EE_System__load_espresso_addons') |
|
67 | - || did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets') |
|
68 | - ) { |
|
69 | - EE_Error::doing_it_wrong( |
|
70 | - __METHOD__, |
|
71 | - esc_html__( |
|
72 | - 'An attempt to register modules has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.', |
|
73 | - 'event_espresso' |
|
74 | - ), |
|
75 | - '4.3.0' |
|
76 | - ); |
|
77 | - } |
|
78 | - // setup $_settings array from incoming values. |
|
79 | - self::$_settings[ $identifier ] = [ |
|
80 | - // array of full server paths to any EE_PMT_Base children used |
|
81 | - 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
|
82 | - ? (array) $setup_args['payment_method_paths'] |
|
83 | - : [], |
|
84 | - ]; |
|
85 | - // add to list of modules to be registered |
|
86 | - add_filter( |
|
87 | - 'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register', |
|
88 | - ['EE_Register_Payment_Method', 'add_payment_methods'] |
|
89 | - ); |
|
90 | - // If EE_Payment_Method_Manager::register_payment_methods has already been called, |
|
91 | - // then we need to add our caps for this payment method manually |
|
92 | - if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) { |
|
93 | - $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
94 | - // register payment methods directly |
|
95 | - foreach (self::$_settings[ $identifier ]['payment_method_paths'] as $payment_method_path) { |
|
96 | - $payment_method_manager->register_payment_method($payment_method_path); |
|
97 | - } |
|
98 | - $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
99 | - $capabilities->addCaps( |
|
100 | - self::getPaymentMethodCapabilities(self::$_settings[ $identifier ]) |
|
101 | - ); |
|
102 | - } |
|
103 | - } |
|
29 | + /** |
|
30 | + * Method for registering new EE_PMT_Base children |
|
31 | + * |
|
32 | + * @param string $identifier a unique identifier for this set of modules Required. |
|
33 | + * @param array $setup_args an array of arguments provided for registering modules Required.{ |
|
34 | + * @type string[] $payment_method_paths each element is the folder containing the EE_PMT_Base child class |
|
35 | + * (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains |
|
36 | + * the files EE_PMT_Payomatic.pm.php) |
|
37 | + * } |
|
38 | + * @return void |
|
39 | + * @throws EE_Error |
|
40 | + * @type array payment_method_paths an array of full server paths to folders containing any EE_PMT_Base |
|
41 | + * children, or to the EED_Module files themselves |
|
42 | + * @throws InvalidDataTypeException |
|
43 | + * @throws DomainException |
|
44 | + * @throws InvalidArgumentException |
|
45 | + * @throws InvalidInterfaceException |
|
46 | + * @throws InvalidDataTypeException |
|
47 | + * @since 4.5.0 |
|
48 | + */ |
|
49 | + public static function register($identifier = '', array $setup_args = []) |
|
50 | + { |
|
51 | + // required fields MUST be present, so let's make sure they are. |
|
52 | + if (empty($identifier) || ! is_array($setup_args) || empty($setup_args['payment_method_paths'])) { |
|
53 | + throw new EE_Error( |
|
54 | + esc_html__( |
|
55 | + 'In order to register Payment Methods with EE_Register_Payment_Method::register(), you must include a "payment_method_id" (a unique identifier for this set of modules), and an array containing the following keys: "payment_method_paths" (an array of full server paths to folders that contain modules, or to the module files themselves)', |
|
56 | + 'event_espresso' |
|
57 | + ) |
|
58 | + ); |
|
59 | + } |
|
60 | + // make sure we don't register twice |
|
61 | + if (isset(self::$_settings[ $identifier ])) { |
|
62 | + return; |
|
63 | + } |
|
64 | + // make sure this was called in the right place! |
|
65 | + if ( |
|
66 | + ! did_action('AHEE__EE_System__load_espresso_addons') |
|
67 | + || did_action('AHEE__EE_System__register_shortcodes_modules_and_widgets') |
|
68 | + ) { |
|
69 | + EE_Error::doing_it_wrong( |
|
70 | + __METHOD__, |
|
71 | + esc_html__( |
|
72 | + 'An attempt to register modules has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__register_shortcodes_modules_and_widgets" hook to register modules.', |
|
73 | + 'event_espresso' |
|
74 | + ), |
|
75 | + '4.3.0' |
|
76 | + ); |
|
77 | + } |
|
78 | + // setup $_settings array from incoming values. |
|
79 | + self::$_settings[ $identifier ] = [ |
|
80 | + // array of full server paths to any EE_PMT_Base children used |
|
81 | + 'payment_method_paths' => isset($setup_args['payment_method_paths']) |
|
82 | + ? (array) $setup_args['payment_method_paths'] |
|
83 | + : [], |
|
84 | + ]; |
|
85 | + // add to list of modules to be registered |
|
86 | + add_filter( |
|
87 | + 'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register', |
|
88 | + ['EE_Register_Payment_Method', 'add_payment_methods'] |
|
89 | + ); |
|
90 | + // If EE_Payment_Method_Manager::register_payment_methods has already been called, |
|
91 | + // then we need to add our caps for this payment method manually |
|
92 | + if (did_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods')) { |
|
93 | + $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
94 | + // register payment methods directly |
|
95 | + foreach (self::$_settings[ $identifier ]['payment_method_paths'] as $payment_method_path) { |
|
96 | + $payment_method_manager->register_payment_method($payment_method_path); |
|
97 | + } |
|
98 | + $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
99 | + $capabilities->addCaps( |
|
100 | + self::getPaymentMethodCapabilities(self::$_settings[ $identifier ]) |
|
101 | + ); |
|
102 | + } |
|
103 | + } |
|
104 | 104 | |
105 | 105 | |
106 | - /** |
|
107 | - * Filters the list of payment methods to add ours. |
|
108 | - * and they're just full filepaths to FOLDERS containing a payment method class file. Eg. |
|
109 | - * |
|
110 | - * @param array $payment_method_folders array of paths to all payment methods that require registering |
|
111 | - * @return array |
|
112 | - */ |
|
113 | - public static function add_payment_methods(array $payment_method_folders) |
|
114 | - { |
|
115 | - foreach (self::$_settings as $settings) { |
|
116 | - foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
117 | - $payment_method_folders[] = $payment_method_path; |
|
118 | - } |
|
119 | - } |
|
120 | - return $payment_method_folders; |
|
121 | - } |
|
106 | + /** |
|
107 | + * Filters the list of payment methods to add ours. |
|
108 | + * and they're just full filepaths to FOLDERS containing a payment method class file. Eg. |
|
109 | + * |
|
110 | + * @param array $payment_method_folders array of paths to all payment methods that require registering |
|
111 | + * @return array |
|
112 | + */ |
|
113 | + public static function add_payment_methods(array $payment_method_folders) |
|
114 | + { |
|
115 | + foreach (self::$_settings as $settings) { |
|
116 | + foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
117 | + $payment_method_folders[] = $payment_method_path; |
|
118 | + } |
|
119 | + } |
|
120 | + return $payment_method_folders; |
|
121 | + } |
|
122 | 122 | |
123 | 123 | |
124 | - /** |
|
125 | - * This deregisters a module that was previously registered with a specific $identifier. |
|
126 | - * |
|
127 | - * @param string $identifier the name for the module that was previously registered |
|
128 | - * @return void |
|
129 | - * @throws DomainException |
|
130 | - * @throws InvalidArgumentException |
|
131 | - * @throws InvalidInterfaceException |
|
132 | - * @throws InvalidDataTypeException |
|
133 | - * @since 4.3.0 |
|
134 | - */ |
|
135 | - public static function deregister($identifier = '') |
|
136 | - { |
|
137 | - if (isset(self::$_settings[ $identifier ])) { |
|
138 | - // set action for just this module id to delay deregistration until core is loaded and ready. |
|
139 | - $module_settings = self::$_settings[ $identifier ]; |
|
140 | - unset(self::$_settings[ $identifier ]); |
|
141 | - add_action( |
|
142 | - 'AHEE__EE_System__core_loaded_and_ready', |
|
143 | - function () use ($module_settings) { |
|
144 | - $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
145 | - $capabilities->removeCaps( |
|
146 | - EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
|
147 | - ); |
|
148 | - } |
|
149 | - ); |
|
150 | - } |
|
151 | - } |
|
124 | + /** |
|
125 | + * This deregisters a module that was previously registered with a specific $identifier. |
|
126 | + * |
|
127 | + * @param string $identifier the name for the module that was previously registered |
|
128 | + * @return void |
|
129 | + * @throws DomainException |
|
130 | + * @throws InvalidArgumentException |
|
131 | + * @throws InvalidInterfaceException |
|
132 | + * @throws InvalidDataTypeException |
|
133 | + * @since 4.3.0 |
|
134 | + */ |
|
135 | + public static function deregister($identifier = '') |
|
136 | + { |
|
137 | + if (isset(self::$_settings[ $identifier ])) { |
|
138 | + // set action for just this module id to delay deregistration until core is loaded and ready. |
|
139 | + $module_settings = self::$_settings[ $identifier ]; |
|
140 | + unset(self::$_settings[ $identifier ]); |
|
141 | + add_action( |
|
142 | + 'AHEE__EE_System__core_loaded_and_ready', |
|
143 | + function () use ($module_settings) { |
|
144 | + $capabilities = LoaderFactory::getLoader()->getShared('EE_Capabilities'); |
|
145 | + $capabilities->removeCaps( |
|
146 | + EE_Register_Payment_Method::getPaymentMethodCapabilities($module_settings) |
|
147 | + ); |
|
148 | + } |
|
149 | + ); |
|
150 | + } |
|
151 | + } |
|
152 | 152 | |
153 | 153 | |
154 | - /** |
|
155 | - * returns an array of the caps that get added when a Payment Method is registered |
|
156 | - * |
|
157 | - * @param array $settings |
|
158 | - * @return array |
|
159 | - * @throws DomainException |
|
160 | - * @throws InvalidArgumentException |
|
161 | - * @throws InvalidInterfaceException |
|
162 | - * @throws InvalidDataTypeException |
|
163 | - * @access private Developers do NOT use this method. It's only public for PHP5.3 closure support (see deregister) |
|
164 | - * When we drop support for PHP5.3 this will be made private again. You have been warned. |
|
165 | - */ |
|
166 | - public static function getPaymentMethodCapabilities(array $settings) |
|
167 | - { |
|
168 | - $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
169 | - $payment_method_caps = ['administrator' => []]; |
|
170 | - if (isset($settings['payment_method_paths'])) { |
|
171 | - foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
172 | - $payment_method_caps = $payment_method_manager->addPaymentMethodCap( |
|
173 | - strtolower(basename($payment_method_path)), |
|
174 | - $payment_method_caps |
|
175 | - ); |
|
176 | - } |
|
177 | - } |
|
178 | - return $payment_method_caps; |
|
179 | - } |
|
154 | + /** |
|
155 | + * returns an array of the caps that get added when a Payment Method is registered |
|
156 | + * |
|
157 | + * @param array $settings |
|
158 | + * @return array |
|
159 | + * @throws DomainException |
|
160 | + * @throws InvalidArgumentException |
|
161 | + * @throws InvalidInterfaceException |
|
162 | + * @throws InvalidDataTypeException |
|
163 | + * @access private Developers do NOT use this method. It's only public for PHP5.3 closure support (see deregister) |
|
164 | + * When we drop support for PHP5.3 this will be made private again. You have been warned. |
|
165 | + */ |
|
166 | + public static function getPaymentMethodCapabilities(array $settings) |
|
167 | + { |
|
168 | + $payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); |
|
169 | + $payment_method_caps = ['administrator' => []]; |
|
170 | + if (isset($settings['payment_method_paths'])) { |
|
171 | + foreach ($settings['payment_method_paths'] as $payment_method_path) { |
|
172 | + $payment_method_caps = $payment_method_manager->addPaymentMethodCap( |
|
173 | + strtolower(basename($payment_method_path)), |
|
174 | + $payment_method_caps |
|
175 | + ); |
|
176 | + } |
|
177 | + } |
|
178 | + return $payment_method_caps; |
|
179 | + } |
|
180 | 180 | } |
@@ -70,13 +70,13 @@ discard block |
||
70 | 70 | } |
71 | 71 | |
72 | 72 | // make sure we don't register twice |
73 | - if (isset(self::$_registry[ $identifier ])) { |
|
73 | + if (isset(self::$_registry[$identifier])) { |
|
74 | 74 | return; |
75 | 75 | } |
76 | 76 | |
77 | 77 | // check that incoming $identifier doesn't already exist. If it does then we'll create a unique reference for this template pack. |
78 | - if (isset(self::$_registry[ $identifier ])) { |
|
79 | - $identifier = uniqid() . '_' . $identifier; |
|
78 | + if (isset(self::$_registry[$identifier])) { |
|
79 | + $identifier = uniqid().'_'.$identifier; |
|
80 | 80 | } |
81 | 81 | |
82 | 82 | |
@@ -99,7 +99,7 @@ discard block |
||
99 | 99 | } |
100 | 100 | |
101 | 101 | if (self::_verify_class_not_exist($setup_args['classname'])) { |
102 | - self::$_registry[ $identifier ] = [ |
|
102 | + self::$_registry[$identifier] = [ |
|
103 | 103 | 'path' => (string) $setup_args['path'], |
104 | 104 | 'classname' => (string) $setup_args['classname'], |
105 | 105 | ]; |
@@ -151,14 +151,14 @@ discard block |
||
151 | 151 | { |
152 | 152 | foreach (self::$_registry as $args) { |
153 | 153 | // verify class_exists |
154 | - if (! class_exists($args['classname'])) { |
|
155 | - require_once($args['path'] . '/' . $args['classname'] . '.class.php'); |
|
154 | + if ( ! class_exists($args['classname'])) { |
|
155 | + require_once($args['path'].'/'.$args['classname'].'.class.php'); |
|
156 | 156 | } |
157 | 157 | |
158 | 158 | // check again! |
159 | 159 | if (class_exists($args['classname'])) { |
160 | 160 | $template_pack = new $args['classname'](); |
161 | - $template_packs[ $template_pack->dbref ] = $template_pack; |
|
161 | + $template_packs[$template_pack->dbref] = $template_pack; |
|
162 | 162 | } |
163 | 163 | } |
164 | 164 | |
@@ -208,6 +208,6 @@ discard block |
||
208 | 208 | */ |
209 | 209 | public static function deregister($identifier = '') |
210 | 210 | { |
211 | - unset(self::$_registry[ $identifier ]); |
|
211 | + unset(self::$_registry[$identifier]); |
|
212 | 212 | } |
213 | 213 | } |
@@ -10,202 +10,202 @@ |
||
10 | 10 | */ |
11 | 11 | class EE_Register_Messages_Template_Pack implements EEI_Plugin_API |
12 | 12 | { |
13 | - /** |
|
14 | - * Holds values for registered template pack |
|
15 | - * |
|
16 | - * @since 4.5.0 |
|
17 | - * |
|
18 | - * @var array |
|
19 | - */ |
|
20 | - protected static $_registry = []; |
|
21 | - |
|
22 | - |
|
23 | - /** |
|
24 | - * Used to register a new template pack with the messages system. |
|
25 | - * |
|
26 | - * Template packs are primarily defined via class extending EE_Messages_Template_Pack and are typically used to |
|
27 | - * change entire layouts for a set of message templates. This method is used to register the new template pack and |
|
28 | - * automatically have it loaded in the appropriate places. |
|
29 | - * |
|
30 | - * This registry also verifies that there isn't already a template pack registered with the same name and if there |
|
31 | - * is then it will add an EE_Error notice. |
|
32 | - * |
|
33 | - * Note that this only handles registering the your Template Pack class with the message template pack system. |
|
34 | - * However, there is also a naming schema you must follow for templates you are providing with your template pack. |
|
35 | - * |
|
36 | - * @param string $identifier The internal reference used to refer to this template pack. Note, this is first come, |
|
37 | - * first serve. If there is already a template pack registered with this name then the |
|
38 | - * registry will assign a unique reference for it so it can still be activated (but this |
|
39 | - * makes it harder to deregister as it will be unique per load - so its best to try to |
|
40 | - * make this a unique string!) |
|
41 | - * @param array $setup_args array { |
|
42 | - * An array of required values for registering the template pack. |
|
43 | - * @type string $path The path for the new template pack class. |
|
44 | - * @type string $classname The name of the new Template Pack Class. |
|
45 | - * } |
|
46 | - * |
|
47 | - * @return void |
|
48 | - * @throws EE_Error |
|
49 | - * |
|
50 | - * @see core/libraries/messages/defaults/default/* for all the example templates the default template pack |
|
51 | - * supports. |
|
52 | - * |
|
53 | - * |
|
54 | - * @since 4.5.0 |
|
55 | - * @see EE_Messages_Template_Pack_Default for an example class |
|
56 | - */ |
|
57 | - public static function register($identifier = '', array $setup_args = []) |
|
58 | - { |
|
59 | - |
|
60 | - // check for required params |
|
61 | - if (empty($identifier) || empty($setup_args['path']) || empty($setup_args['classname'])) { |
|
62 | - throw new EE_Error( |
|
63 | - esc_html__( |
|
64 | - 'In order to register a new template pack for the EE Messages system, you must include a value to reference the template pack being registered and the setup_args must have the path for the new template pack class as well as the classname for the new Template Pack Class. ', |
|
65 | - 'event_espresso' |
|
66 | - ) |
|
67 | - ); |
|
68 | - } |
|
69 | - |
|
70 | - // make sure we don't register twice |
|
71 | - if (isset(self::$_registry[ $identifier ])) { |
|
72 | - return; |
|
73 | - } |
|
74 | - |
|
75 | - // check that incoming $identifier doesn't already exist. If it does then we'll create a unique reference for this template pack. |
|
76 | - if (isset(self::$_registry[ $identifier ])) { |
|
77 | - $identifier = uniqid() . '_' . $identifier; |
|
78 | - } |
|
79 | - |
|
80 | - |
|
81 | - // make sure this was called in the right place! |
|
82 | - if ( |
|
83 | - ! did_action('EE_Brewing_Regular___messages_caf') |
|
84 | - || did_action('AHEE__EE_System__perform_activations_upgrades_and_migrations') |
|
85 | - ) { |
|
86 | - EE_Error::doing_it_wrong( |
|
87 | - __METHOD__, |
|
88 | - sprintf( |
|
89 | - esc_html__( |
|
90 | - 'A EE Messages Template Pack given the reference "%s" has been attempted to be registered with the EE Messages System. It may or may not work because it should be only called on the "EE_Brewing_Regular__messages_caf" hook.', |
|
91 | - 'event_espresso' |
|
92 | - ), |
|
93 | - $identifier |
|
94 | - ), |
|
95 | - '4.5.0' |
|
96 | - ); |
|
97 | - } |
|
98 | - |
|
99 | - if (self::_verify_class_not_exist($setup_args['classname'])) { |
|
100 | - self::$_registry[ $identifier ] = [ |
|
101 | - 'path' => (string) $setup_args['path'], |
|
102 | - 'classname' => (string) $setup_args['classname'], |
|
103 | - ]; |
|
104 | - } |
|
105 | - |
|
106 | - // hook into the system |
|
107 | - add_filter( |
|
108 | - 'FHEE__EED_Messages___set_messages_paths___MSG_PATHS', |
|
109 | - ['EE_Register_Messages_Template_Pack', 'set_template_pack_path'], |
|
110 | - 10 |
|
111 | - ); |
|
112 | - add_filter( |
|
113 | - 'FHEE__EED_Messages__get_template_packs__template_packs', |
|
114 | - ['EE_Register_Messages_Template_Pack', 'set_template_pack'], |
|
115 | - 10 |
|
116 | - ); |
|
117 | - } |
|
118 | - |
|
119 | - |
|
120 | - /** |
|
121 | - * Callback for the FHEE__EED_Messages___set_messages_paths___MSG_PATHS filter. This adds this template packs path |
|
122 | - * to the messages autoloader paths. |
|
123 | - * |
|
124 | - * @param array $paths Array of paths already registered with the messages autoloader |
|
125 | - * |
|
126 | - * @return array |
|
127 | - * @since 4.5.0 |
|
128 | - * |
|
129 | - */ |
|
130 | - public static function set_template_pack_path(array $paths) |
|
131 | - { |
|
132 | - foreach (self::$_registry as $args) { |
|
133 | - $paths[] = $args['path']; |
|
134 | - } |
|
135 | - return $paths; |
|
136 | - } |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * Callback for the FHEE__EED_Messages__get_template_packs__template_packs filter. This adds the instantiated, |
|
141 | - * registered template pack to the template packs array when requested by client code. |
|
142 | - * |
|
143 | - * @param EE_Messages_Template_Pack[] $template_packs |
|
144 | - * @return EE_Messages_Template_Pack[] |
|
145 | - * @since 4.5.0 |
|
146 | - * |
|
147 | - */ |
|
148 | - public static function set_template_pack(array $template_packs) |
|
149 | - { |
|
150 | - foreach (self::$_registry as $args) { |
|
151 | - // verify class_exists |
|
152 | - if (! class_exists($args['classname'])) { |
|
153 | - require_once($args['path'] . '/' . $args['classname'] . '.class.php'); |
|
154 | - } |
|
155 | - |
|
156 | - // check again! |
|
157 | - if (class_exists($args['classname'])) { |
|
158 | - $template_pack = new $args['classname'](); |
|
159 | - $template_packs[ $template_pack->dbref ] = $template_pack; |
|
160 | - } |
|
161 | - } |
|
162 | - |
|
163 | - return $template_packs; |
|
164 | - } |
|
165 | - |
|
166 | - |
|
167 | - /** |
|
168 | - * This verifies that the classes for each registered template pack are unique names. |
|
169 | - * |
|
170 | - * @param string $classname The classname being checked |
|
171 | - * |
|
172 | - * @return bool |
|
173 | - */ |
|
174 | - private static function _verify_class_not_exist($classname) |
|
175 | - { |
|
176 | - // loop through the existing registry and see if the classname is already present. |
|
177 | - foreach (self::$_registry as $args) { |
|
178 | - if ($args['classname'] == $classname) { |
|
179 | - EE_Error::add_error( |
|
180 | - sprintf( |
|
181 | - esc_html__( |
|
182 | - 'The %s template pack that you just activated cannot be registered with the messages system because there is already a template pack active using the same classname. Contact the author of this template pack to let them know of the conflict. To stop seeing this message you will need to deactivate this template pack.', |
|
183 | - 'event_espresso' |
|
184 | - ), |
|
185 | - $classname |
|
186 | - ), |
|
187 | - __FILE__, |
|
188 | - __LINE__, |
|
189 | - __FUNCTION__ |
|
190 | - ); |
|
191 | - return false; |
|
192 | - } |
|
193 | - } |
|
194 | - return true; |
|
195 | - } |
|
196 | - |
|
197 | - |
|
198 | - /** |
|
199 | - * This deregisters a variation set that was previously registered with the given slug. |
|
200 | - * |
|
201 | - * @param string $identifier The name for the variation set that was previously registered. |
|
202 | - * |
|
203 | - * @return void |
|
204 | - * @since 4.5.0 |
|
205 | - * |
|
206 | - */ |
|
207 | - public static function deregister($identifier = '') |
|
208 | - { |
|
209 | - unset(self::$_registry[ $identifier ]); |
|
210 | - } |
|
13 | + /** |
|
14 | + * Holds values for registered template pack |
|
15 | + * |
|
16 | + * @since 4.5.0 |
|
17 | + * |
|
18 | + * @var array |
|
19 | + */ |
|
20 | + protected static $_registry = []; |
|
21 | + |
|
22 | + |
|
23 | + /** |
|
24 | + * Used to register a new template pack with the messages system. |
|
25 | + * |
|
26 | + * Template packs are primarily defined via class extending EE_Messages_Template_Pack and are typically used to |
|
27 | + * change entire layouts for a set of message templates. This method is used to register the new template pack and |
|
28 | + * automatically have it loaded in the appropriate places. |
|
29 | + * |
|
30 | + * This registry also verifies that there isn't already a template pack registered with the same name and if there |
|
31 | + * is then it will add an EE_Error notice. |
|
32 | + * |
|
33 | + * Note that this only handles registering the your Template Pack class with the message template pack system. |
|
34 | + * However, there is also a naming schema you must follow for templates you are providing with your template pack. |
|
35 | + * |
|
36 | + * @param string $identifier The internal reference used to refer to this template pack. Note, this is first come, |
|
37 | + * first serve. If there is already a template pack registered with this name then the |
|
38 | + * registry will assign a unique reference for it so it can still be activated (but this |
|
39 | + * makes it harder to deregister as it will be unique per load - so its best to try to |
|
40 | + * make this a unique string!) |
|
41 | + * @param array $setup_args array { |
|
42 | + * An array of required values for registering the template pack. |
|
43 | + * @type string $path The path for the new template pack class. |
|
44 | + * @type string $classname The name of the new Template Pack Class. |
|
45 | + * } |
|
46 | + * |
|
47 | + * @return void |
|
48 | + * @throws EE_Error |
|
49 | + * |
|
50 | + * @see core/libraries/messages/defaults/default/* for all the example templates the default template pack |
|
51 | + * supports. |
|
52 | + * |
|
53 | + * |
|
54 | + * @since 4.5.0 |
|
55 | + * @see EE_Messages_Template_Pack_Default for an example class |
|
56 | + */ |
|
57 | + public static function register($identifier = '', array $setup_args = []) |
|
58 | + { |
|
59 | + |
|
60 | + // check for required params |
|
61 | + if (empty($identifier) || empty($setup_args['path']) || empty($setup_args['classname'])) { |
|
62 | + throw new EE_Error( |
|
63 | + esc_html__( |
|
64 | + 'In order to register a new template pack for the EE Messages system, you must include a value to reference the template pack being registered and the setup_args must have the path for the new template pack class as well as the classname for the new Template Pack Class. ', |
|
65 | + 'event_espresso' |
|
66 | + ) |
|
67 | + ); |
|
68 | + } |
|
69 | + |
|
70 | + // make sure we don't register twice |
|
71 | + if (isset(self::$_registry[ $identifier ])) { |
|
72 | + return; |
|
73 | + } |
|
74 | + |
|
75 | + // check that incoming $identifier doesn't already exist. If it does then we'll create a unique reference for this template pack. |
|
76 | + if (isset(self::$_registry[ $identifier ])) { |
|
77 | + $identifier = uniqid() . '_' . $identifier; |
|
78 | + } |
|
79 | + |
|
80 | + |
|
81 | + // make sure this was called in the right place! |
|
82 | + if ( |
|
83 | + ! did_action('EE_Brewing_Regular___messages_caf') |
|
84 | + || did_action('AHEE__EE_System__perform_activations_upgrades_and_migrations') |
|
85 | + ) { |
|
86 | + EE_Error::doing_it_wrong( |
|
87 | + __METHOD__, |
|
88 | + sprintf( |
|
89 | + esc_html__( |
|
90 | + 'A EE Messages Template Pack given the reference "%s" has been attempted to be registered with the EE Messages System. It may or may not work because it should be only called on the "EE_Brewing_Regular__messages_caf" hook.', |
|
91 | + 'event_espresso' |
|
92 | + ), |
|
93 | + $identifier |
|
94 | + ), |
|
95 | + '4.5.0' |
|
96 | + ); |
|
97 | + } |
|
98 | + |
|
99 | + if (self::_verify_class_not_exist($setup_args['classname'])) { |
|
100 | + self::$_registry[ $identifier ] = [ |
|
101 | + 'path' => (string) $setup_args['path'], |
|
102 | + 'classname' => (string) $setup_args['classname'], |
|
103 | + ]; |
|
104 | + } |
|
105 | + |
|
106 | + // hook into the system |
|
107 | + add_filter( |
|
108 | + 'FHEE__EED_Messages___set_messages_paths___MSG_PATHS', |
|
109 | + ['EE_Register_Messages_Template_Pack', 'set_template_pack_path'], |
|
110 | + 10 |
|
111 | + ); |
|
112 | + add_filter( |
|
113 | + 'FHEE__EED_Messages__get_template_packs__template_packs', |
|
114 | + ['EE_Register_Messages_Template_Pack', 'set_template_pack'], |
|
115 | + 10 |
|
116 | + ); |
|
117 | + } |
|
118 | + |
|
119 | + |
|
120 | + /** |
|
121 | + * Callback for the FHEE__EED_Messages___set_messages_paths___MSG_PATHS filter. This adds this template packs path |
|
122 | + * to the messages autoloader paths. |
|
123 | + * |
|
124 | + * @param array $paths Array of paths already registered with the messages autoloader |
|
125 | + * |
|
126 | + * @return array |
|
127 | + * @since 4.5.0 |
|
128 | + * |
|
129 | + */ |
|
130 | + public static function set_template_pack_path(array $paths) |
|
131 | + { |
|
132 | + foreach (self::$_registry as $args) { |
|
133 | + $paths[] = $args['path']; |
|
134 | + } |
|
135 | + return $paths; |
|
136 | + } |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * Callback for the FHEE__EED_Messages__get_template_packs__template_packs filter. This adds the instantiated, |
|
141 | + * registered template pack to the template packs array when requested by client code. |
|
142 | + * |
|
143 | + * @param EE_Messages_Template_Pack[] $template_packs |
|
144 | + * @return EE_Messages_Template_Pack[] |
|
145 | + * @since 4.5.0 |
|
146 | + * |
|
147 | + */ |
|
148 | + public static function set_template_pack(array $template_packs) |
|
149 | + { |
|
150 | + foreach (self::$_registry as $args) { |
|
151 | + // verify class_exists |
|
152 | + if (! class_exists($args['classname'])) { |
|
153 | + require_once($args['path'] . '/' . $args['classname'] . '.class.php'); |
|
154 | + } |
|
155 | + |
|
156 | + // check again! |
|
157 | + if (class_exists($args['classname'])) { |
|
158 | + $template_pack = new $args['classname'](); |
|
159 | + $template_packs[ $template_pack->dbref ] = $template_pack; |
|
160 | + } |
|
161 | + } |
|
162 | + |
|
163 | + return $template_packs; |
|
164 | + } |
|
165 | + |
|
166 | + |
|
167 | + /** |
|
168 | + * This verifies that the classes for each registered template pack are unique names. |
|
169 | + * |
|
170 | + * @param string $classname The classname being checked |
|
171 | + * |
|
172 | + * @return bool |
|
173 | + */ |
|
174 | + private static function _verify_class_not_exist($classname) |
|
175 | + { |
|
176 | + // loop through the existing registry and see if the classname is already present. |
|
177 | + foreach (self::$_registry as $args) { |
|
178 | + if ($args['classname'] == $classname) { |
|
179 | + EE_Error::add_error( |
|
180 | + sprintf( |
|
181 | + esc_html__( |
|
182 | + 'The %s template pack that you just activated cannot be registered with the messages system because there is already a template pack active using the same classname. Contact the author of this template pack to let them know of the conflict. To stop seeing this message you will need to deactivate this template pack.', |
|
183 | + 'event_espresso' |
|
184 | + ), |
|
185 | + $classname |
|
186 | + ), |
|
187 | + __FILE__, |
|
188 | + __LINE__, |
|
189 | + __FUNCTION__ |
|
190 | + ); |
|
191 | + return false; |
|
192 | + } |
|
193 | + } |
|
194 | + return true; |
|
195 | + } |
|
196 | + |
|
197 | + |
|
198 | + /** |
|
199 | + * This deregisters a variation set that was previously registered with the given slug. |
|
200 | + * |
|
201 | + * @param string $identifier The name for the variation set that was previously registered. |
|
202 | + * |
|
203 | + * @return void |
|
204 | + * @since 4.5.0 |
|
205 | + * |
|
206 | + */ |
|
207 | + public static function deregister($identifier = '') |
|
208 | + { |
|
209 | + unset(self::$_registry[ $identifier ]); |
|
210 | + } |
|
211 | 211 | } |