@@ -20,692 +20,692 @@ |
||
20 | 20 | */ |
21 | 21 | abstract class EE_Model_Field_Base implements HasSchemaInterface |
22 | 22 | { |
23 | - /** |
|
24 | - * The alias for the table the column belongs to. |
|
25 | - * |
|
26 | - * @var string |
|
27 | - */ |
|
28 | - protected $_table_alias; |
|
29 | - |
|
30 | - /** |
|
31 | - * The actual db column name for the table |
|
32 | - * |
|
33 | - * @var string |
|
34 | - */ |
|
35 | - protected $_table_column; |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * The authoritative name for the table column (used by client code to reference the field). |
|
40 | - * |
|
41 | - * @var string |
|
42 | - */ |
|
43 | - protected $_name; |
|
44 | - |
|
45 | - |
|
46 | - /** |
|
47 | - * A description for the field. |
|
48 | - * |
|
49 | - * @var string |
|
50 | - */ |
|
51 | - protected $_nicename; |
|
52 | - |
|
53 | - |
|
54 | - /** |
|
55 | - * Whether the field is nullable or not |
|
56 | - * |
|
57 | - * @var bool |
|
58 | - */ |
|
59 | - protected $_nullable; |
|
60 | - |
|
61 | - |
|
62 | - /** |
|
63 | - * What the default value for the field should be. |
|
64 | - * |
|
65 | - * @var mixed |
|
66 | - */ |
|
67 | - protected $_default_value; |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * Other configuration for the field |
|
72 | - * |
|
73 | - * @var mixed |
|
74 | - */ |
|
75 | - protected $_other_config; |
|
76 | - |
|
77 | - |
|
78 | - /** |
|
79 | - * The name of the model this field is instantiated for. |
|
80 | - * |
|
81 | - * @var string |
|
82 | - */ |
|
83 | - protected $_model_name; |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * This should be a json-schema valid data type for the field. |
|
88 | - * |
|
89 | - * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2 |
|
90 | - * @var string |
|
91 | - */ |
|
92 | - private $_schema_type = 'string'; |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * If the schema has a defined format then it should be defined via this property. |
|
97 | - * |
|
98 | - * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7 |
|
99 | - * @var string |
|
100 | - */ |
|
101 | - private $_schema_format = ''; |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * Indicates that the value of the field is managed exclusively by the server/model and not something |
|
106 | - * settable by client code. |
|
107 | - * |
|
108 | - * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4 |
|
109 | - * @var bool |
|
110 | - */ |
|
111 | - private $_schema_readonly = false; |
|
112 | - |
|
113 | - |
|
114 | - /** |
|
115 | - * @param string $table_column |
|
116 | - * @param string $nicename |
|
117 | - * @param bool $nullable |
|
118 | - * @param null $default_value |
|
119 | - */ |
|
120 | - public function __construct($table_column, $nicename, $nullable, $default_value = null) |
|
121 | - { |
|
122 | - $this->_table_column = $table_column; |
|
123 | - $this->_nicename = $nicename; |
|
124 | - $this->_nullable = $nullable; |
|
125 | - $this->_default_value = $default_value; |
|
126 | - } |
|
127 | - |
|
128 | - |
|
129 | - /** |
|
130 | - * @param $table_alias |
|
131 | - * @param $name |
|
132 | - * @param $model_name |
|
133 | - */ |
|
134 | - public function _construct_finalize($table_alias, $name, $model_name) |
|
135 | - { |
|
136 | - $this->_table_alias = $table_alias; |
|
137 | - $this->_name = $name; |
|
138 | - $this->_model_name = $model_name; |
|
139 | - /** |
|
140 | - * allow for changing the defaults |
|
141 | - */ |
|
142 | - $this->_nicename = apply_filters( |
|
143 | - 'FHEE__EE_Model_Field_Base___construct_finalize___nicename', |
|
144 | - $this->_nicename, |
|
145 | - $this |
|
146 | - ); |
|
147 | - $this->_default_value = apply_filters( |
|
148 | - 'FHEE__EE_Model_Field_Base___construct_finalize___default_value', |
|
149 | - $this->_default_value, |
|
150 | - $this |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - public function get_table_alias() |
|
156 | - { |
|
157 | - return $this->_table_alias; |
|
158 | - } |
|
159 | - |
|
160 | - |
|
161 | - public function get_table_column() |
|
162 | - { |
|
163 | - return $this->_table_column; |
|
164 | - } |
|
165 | - |
|
166 | - |
|
167 | - /** |
|
168 | - * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime' |
|
169 | - * |
|
170 | - * @return string |
|
171 | - */ |
|
172 | - public function get_model_name() |
|
173 | - { |
|
174 | - return $this->_model_name; |
|
175 | - } |
|
176 | - |
|
177 | - |
|
178 | - /** |
|
179 | - * @return string |
|
180 | - * @throws EE_Error |
|
181 | - */ |
|
182 | - public function get_name() |
|
183 | - { |
|
184 | - if ($this->_name) { |
|
185 | - return $this->_name; |
|
186 | - } else { |
|
187 | - throw new EE_Error( |
|
188 | - sprintf( |
|
189 | - esc_html__( |
|
190 | - "Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?", |
|
191 | - "event_espresso" |
|
192 | - ), |
|
193 | - get_class($this) |
|
194 | - ) |
|
195 | - ); |
|
196 | - } |
|
197 | - } |
|
198 | - |
|
199 | - |
|
200 | - public function get_nicename() |
|
201 | - { |
|
202 | - return $this->_nicename; |
|
203 | - } |
|
204 | - |
|
205 | - |
|
206 | - public function is_nullable() |
|
207 | - { |
|
208 | - return $this->_nullable; |
|
209 | - } |
|
210 | - |
|
211 | - |
|
212 | - /** |
|
213 | - * returns whether this field is an auto-increment field or not. If it is, then |
|
214 | - * on insertion it can be null. However, on updates it must be present. |
|
215 | - * |
|
216 | - * @return boolean |
|
217 | - */ |
|
218 | - public function is_auto_increment() |
|
219 | - { |
|
220 | - return false; |
|
221 | - } |
|
222 | - |
|
223 | - |
|
224 | - /** |
|
225 | - * The default value in the model object's value domain. See lengthy comment about |
|
226 | - * value domains at the top of EEM_Base |
|
227 | - * |
|
228 | - * @return mixed |
|
229 | - */ |
|
230 | - public function get_default_value() |
|
231 | - { |
|
232 | - return $this->_default_value; |
|
233 | - } |
|
234 | - |
|
235 | - |
|
236 | - /** |
|
237 | - * Returns the table alias joined to the table column, however this isn't the right |
|
238 | - * table alias if the aliased table is being joined to. In that case, you can use |
|
239 | - * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias |
|
240 | - * in the current query |
|
241 | - * |
|
242 | - * @return string |
|
243 | - */ |
|
244 | - public function get_qualified_column() |
|
245 | - { |
|
246 | - return $this->get_table_alias() . "." . $this->get_table_column(); |
|
247 | - } |
|
248 | - |
|
249 | - |
|
250 | - /** |
|
251 | - * When get() is called on a model object (eg EE_Event), before returning its value, |
|
252 | - * call this function on it, allowing us to customize the returned value based on |
|
253 | - * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default, |
|
254 | - * we simply return it. |
|
255 | - * |
|
256 | - * @param mixed $value_of_field_on_model_object |
|
257 | - * @return mixed |
|
258 | - */ |
|
259 | - public function prepare_for_get($value_of_field_on_model_object) |
|
260 | - { |
|
261 | - return $value_of_field_on_model_object; |
|
262 | - } |
|
263 | - |
|
264 | - |
|
265 | - /** |
|
266 | - * When inserting or updating a field on a model object, run this function on each |
|
267 | - * value to prepare it for insertion into the db. Generally this converts |
|
268 | - * the validated input on the model object into the format used in the DB. |
|
269 | - * |
|
270 | - * @param mixed $value_of_field_on_model_object |
|
271 | - * @return mixed |
|
272 | - */ |
|
273 | - public function prepare_for_use_in_db($value_of_field_on_model_object) |
|
274 | - { |
|
275 | - return $value_of_field_on_model_object; |
|
276 | - } |
|
277 | - |
|
278 | - |
|
279 | - /** |
|
280 | - * When creating a brand-new model object, or setting a particular value for one of its fields, this function |
|
281 | - * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc. |
|
282 | - * By default, we do nothing. |
|
283 | - * |
|
284 | - * If the model field is going to perform any validation on the input, this is where it should be done |
|
285 | - * (once the value is on the model object, it may be used in other ways besides putting it into the DB |
|
286 | - * so it's best to validate it right away). |
|
287 | - * |
|
288 | - * @param mixed $value_inputted_for_field_on_model_object |
|
289 | - * @return mixed |
|
290 | - */ |
|
291 | - public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
292 | - { |
|
293 | - return $value_inputted_for_field_on_model_object; |
|
294 | - } |
|
295 | - |
|
296 | - |
|
297 | - /** |
|
298 | - * When instantiating a model object from DB results, this function is called before setting each field. |
|
299 | - * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that |
|
300 | - * is the one child classes will most often define. |
|
301 | - * |
|
302 | - * @param mixed $value_found_in_db_for_model_object |
|
303 | - * @return mixed |
|
304 | - */ |
|
305 | - public function prepare_for_set_from_db($value_found_in_db_for_model_object) |
|
306 | - { |
|
307 | - return $this->prepare_for_set($value_found_in_db_for_model_object); |
|
308 | - } |
|
309 | - |
|
310 | - |
|
311 | - /** |
|
312 | - * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a |
|
313 | - * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12, |
|
314 | - * 2013, at 3:23pm" instead of |
|
315 | - * "8765678632", or any other modifications to how the value should be displayed, but not modified itself. |
|
316 | - * |
|
317 | - * @param mixed $value_on_field_to_be_outputted |
|
318 | - * @return mixed |
|
319 | - */ |
|
320 | - public function prepare_for_pretty_echoing($value_on_field_to_be_outputted) |
|
321 | - { |
|
322 | - return $value_on_field_to_be_outputted; |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - /** |
|
327 | - * Returns whatever is set as the nicename for the object. |
|
328 | - * |
|
329 | - * @return string |
|
330 | - */ |
|
331 | - public function getSchemaDescription() |
|
332 | - { |
|
333 | - return $this->get_nicename(); |
|
334 | - } |
|
335 | - |
|
336 | - |
|
337 | - /** |
|
338 | - * Returns whatever is set as the $_schema_type property for the object. |
|
339 | - * Note: this will automatically add 'null' to the schema if the object is_nullable() |
|
340 | - * |
|
341 | - * @return string|array |
|
342 | - */ |
|
343 | - public function getSchemaType() |
|
344 | - { |
|
345 | - if ($this->is_nullable()) { |
|
346 | - $this->_schema_type = (array) $this->_schema_type; |
|
347 | - if (! in_array('null', $this->_schema_type)) { |
|
348 | - $this->_schema_type[] = 'null'; |
|
349 | - } |
|
350 | - } |
|
351 | - return $this->_schema_type; |
|
352 | - } |
|
353 | - |
|
354 | - |
|
355 | - /** |
|
356 | - * Sets the _schema_type property. Child classes should call this in their constructors to override the default |
|
357 | - * state for this property. |
|
358 | - * |
|
359 | - * @param string|array $type |
|
360 | - * @throws InvalidArgumentException |
|
361 | - */ |
|
362 | - protected function setSchemaType($type) |
|
363 | - { |
|
364 | - $this->validateSchemaType($type); |
|
365 | - $this->_schema_type = $type; |
|
366 | - } |
|
367 | - |
|
368 | - |
|
369 | - /** |
|
370 | - * This is usually present when the $_schema_type property is 'object'. Any child classes will need to override |
|
371 | - * this method and return the properties for the schema. |
|
372 | - * |
|
373 | - * The reason this is not a property on the class is because there may be filters set on the values for the property |
|
374 | - * that won't be exposed on construct. For example enum type schemas may have the enum values filtered. |
|
375 | - * |
|
376 | - * @return array |
|
377 | - */ |
|
378 | - public function getSchemaProperties() |
|
379 | - { |
|
380 | - return []; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * By default this returns the scalar default value that was sent in on the class prepped according to the class |
|
386 | - * type as the default. However, when there are schema properties, then the default property is setup to mirror |
|
387 | - * the property keys and correctly prepare the default according to that expected property value. The getSchema |
|
388 | - * method validates whether the schema for default is setup correctly or not according to the schema type |
|
389 | - * |
|
390 | - * @return mixed |
|
391 | - */ |
|
392 | - public function getSchemaDefault() |
|
393 | - { |
|
394 | - $default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value())); |
|
395 | - $schema_properties = $this->getSchemaProperties(); |
|
396 | - |
|
397 | - // if this schema has properties than shape the default value to match the properties shape. |
|
398 | - if ($schema_properties) { |
|
399 | - $value_to_return = []; |
|
400 | - foreach ($schema_properties as $property_key => $property_schema) { |
|
401 | - switch ($property_key) { |
|
402 | - case 'pretty': |
|
403 | - case 'rendered': |
|
404 | - $value_to_return[ $property_key ] = |
|
405 | - $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value)); |
|
406 | - break; |
|
407 | - default: |
|
408 | - $value_to_return[ $property_key ] = $default_value; |
|
409 | - break; |
|
410 | - } |
|
411 | - } |
|
412 | - $default_value = $value_to_return; |
|
413 | - } |
|
414 | - return $default_value; |
|
415 | - } |
|
416 | - |
|
417 | - |
|
418 | - /** |
|
419 | - * If a child class has enum values, they should override this method and provide a simple array |
|
420 | - * of the enum values. |
|
421 | - * The reason this is not a property on the class is because there may be filterable enum values that |
|
422 | - * are set on the instantiated object that could be filtered after construct. |
|
423 | - * |
|
424 | - * @return array |
|
425 | - */ |
|
426 | - public function getSchemaEnum() |
|
427 | - { |
|
428 | - return []; |
|
429 | - } |
|
430 | - |
|
431 | - |
|
432 | - /** |
|
433 | - * This returns the value of the $_schema_format property on the object. |
|
434 | - * |
|
435 | - * @return string |
|
436 | - */ |
|
437 | - public function getSchemaFormat() |
|
438 | - { |
|
439 | - return $this->_schema_format; |
|
440 | - } |
|
441 | - |
|
442 | - |
|
443 | - /** |
|
444 | - * Sets the schema format property. |
|
445 | - * |
|
446 | - * @param string $format |
|
447 | - * @throws InvalidArgumentException |
|
448 | - */ |
|
449 | - protected function setSchemaFormat($format) |
|
450 | - { |
|
451 | - $this->validateSchemaFormat($format); |
|
452 | - $this->_schema_format = $format; |
|
453 | - } |
|
454 | - |
|
455 | - |
|
456 | - /** |
|
457 | - * This returns the value of the $_schema_readonly property on the object. |
|
458 | - * |
|
459 | - * @return bool |
|
460 | - */ |
|
461 | - public function getSchemaReadonly() |
|
462 | - { |
|
463 | - return $this->_schema_readonly; |
|
464 | - } |
|
465 | - |
|
466 | - |
|
467 | - /** |
|
468 | - * This sets the value for the $_schema_readonly property. |
|
469 | - * |
|
470 | - * @param bool $readonly (only explicit boolean values are accepted) |
|
471 | - */ |
|
472 | - protected function setSchemaReadOnly($readonly) |
|
473 | - { |
|
474 | - if (! is_bool($readonly)) { |
|
475 | - throw new InvalidArgumentException( |
|
476 | - sprintf( |
|
477 | - esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'), |
|
478 | - print_r($readonly, true) |
|
479 | - ) |
|
480 | - ); |
|
481 | - } |
|
482 | - |
|
483 | - $this->_schema_readonly = $readonly; |
|
484 | - } |
|
485 | - |
|
486 | - |
|
487 | - /** |
|
488 | - * Return `%d`, `%s` or `%f` to indicate the data type for the field. |
|
489 | - * |
|
490 | - * @return string |
|
491 | - * @uses _get_wpdb_data_type() |
|
492 | - * |
|
493 | - */ |
|
494 | - public function get_wpdb_data_type() |
|
495 | - { |
|
496 | - return $this->_get_wpdb_data_type(); |
|
497 | - } |
|
498 | - |
|
499 | - |
|
500 | - /** |
|
501 | - * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries. |
|
502 | - * |
|
503 | - * @param string $type Included if a specific type is requested. |
|
504 | - * @return string |
|
505 | - * @uses get_schema_type() |
|
506 | - */ |
|
507 | - protected function _get_wpdb_data_type($type = '') |
|
508 | - { |
|
509 | - $type = empty($type) ? $this->getSchemaType() : $type; |
|
510 | - |
|
511 | - // if type is an array, then different parsing is required. |
|
512 | - if (is_array($type)) { |
|
513 | - return $this->_get_wpdb_data_type_for_type_array($type); |
|
514 | - } |
|
515 | - |
|
516 | - $wpdb_type = '%s'; |
|
517 | - switch ($type) { |
|
518 | - case 'number': |
|
519 | - $wpdb_type = '%f'; |
|
520 | - break; |
|
521 | - case 'integer': |
|
522 | - case 'boolean': |
|
523 | - $wpdb_type = '%d'; |
|
524 | - break; |
|
525 | - case 'object': |
|
526 | - $properties = $this->getSchemaProperties(); |
|
527 | - if (isset($properties['raw'], $properties['raw']['type'])) { |
|
528 | - $wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']); |
|
529 | - } |
|
530 | - break; // leave at default |
|
531 | - } |
|
532 | - return $wpdb_type; |
|
533 | - } |
|
534 | - |
|
535 | - |
|
536 | - protected function _get_wpdb_data_type_for_type_array($type) |
|
537 | - { |
|
538 | - $type = (array) $type; |
|
539 | - // first let's flip because then we can do a faster key check |
|
540 | - $type = array_flip($type); |
|
541 | - |
|
542 | - // check for things that mean '%s' |
|
543 | - if (isset($type['string'], $type['object'], $type['array'])) { |
|
544 | - return '%s'; |
|
545 | - } |
|
546 | - |
|
547 | - // if makes it past the above condition and there's float in the array |
|
548 | - // then the type is %f |
|
549 | - if (isset($type['number'])) { |
|
550 | - return '%f'; |
|
551 | - } |
|
552 | - |
|
553 | - // if it makes it above the above conditions and there is an integer in the array |
|
554 | - // then the type is %d |
|
555 | - if (isset($type['integer'])) { |
|
556 | - return '%d'; |
|
557 | - } |
|
558 | - |
|
559 | - // anything else is a string |
|
560 | - return '%s'; |
|
561 | - } |
|
562 | - |
|
563 | - |
|
564 | - /** |
|
565 | - * This returns elements used to represent this field in the json schema. |
|
566 | - * |
|
567 | - * @link http://json-schema.org/ |
|
568 | - * @return array |
|
569 | - */ |
|
570 | - public function getSchema() |
|
571 | - { |
|
572 | - $schema = [ |
|
573 | - 'description' => $this->getSchemaDescription(), |
|
574 | - 'type' => $this->getSchemaType(), |
|
575 | - 'readonly' => $this->getSchemaReadonly(), |
|
576 | - 'default' => $this->getSchemaDefault(), |
|
577 | - ]; |
|
578 | - |
|
579 | - // optional properties of the schema |
|
580 | - $enum = $this->getSchemaEnum(); |
|
581 | - $properties = $this->getSchemaProperties(); |
|
582 | - $format = $this->getSchemaFormat(); |
|
583 | - if ($enum) { |
|
584 | - $schema['enum'] = $enum; |
|
585 | - } |
|
586 | - |
|
587 | - if ($properties) { |
|
588 | - $schema['properties'] = $properties; |
|
589 | - } |
|
590 | - |
|
591 | - if ($format) { |
|
592 | - $schema['format'] = $format; |
|
593 | - } |
|
594 | - return $schema; |
|
595 | - } |
|
596 | - |
|
597 | - |
|
598 | - /** |
|
599 | - * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part |
|
600 | - * of the model objects (ie, client code shouldn't care to ever see their value... if client code does |
|
601 | - * want to see their value, then they shouldn't be db-only fields!) |
|
602 | - * Eg, when doing events as custom post types, querying the post_type is essential, but |
|
603 | - * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event'). |
|
604 | - * By default, all fields aren't db-only. |
|
605 | - * |
|
606 | - * @return boolean |
|
607 | - */ |
|
608 | - public function is_db_only_field() |
|
609 | - { |
|
610 | - return false; |
|
611 | - } |
|
612 | - |
|
613 | - |
|
614 | - /** |
|
615 | - * Validates the incoming string|array to ensure its an allowable type. |
|
616 | - * |
|
617 | - * @param string|array $type |
|
618 | - * @throws InvalidArgumentException |
|
619 | - */ |
|
620 | - private function validateSchemaType($type) |
|
621 | - { |
|
622 | - if (! (is_string($type) || is_array($type))) { |
|
623 | - throw new InvalidArgumentException( |
|
624 | - sprintf( |
|
625 | - esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'), |
|
626 | - print_r($type, true) |
|
627 | - ) |
|
628 | - ); |
|
629 | - } |
|
630 | - |
|
631 | - // validate allowable types. |
|
632 | - // @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2 |
|
633 | - $allowable_types = array_flip( |
|
634 | - [ |
|
635 | - 'string', |
|
636 | - 'number', |
|
637 | - 'null', |
|
638 | - 'object', |
|
639 | - 'array', |
|
640 | - 'boolean', |
|
641 | - 'integer', |
|
642 | - ] |
|
643 | - ); |
|
644 | - |
|
645 | - if (is_array($type)) { |
|
646 | - foreach ($type as $item_in_type) { |
|
647 | - $this->validateSchemaType($item_in_type); |
|
648 | - } |
|
649 | - return; |
|
650 | - } |
|
651 | - |
|
652 | - if (! isset($allowable_types[ $type ])) { |
|
653 | - throw new InvalidArgumentException( |
|
654 | - sprintf( |
|
655 | - esc_html__( |
|
656 | - 'The incoming argument (%1$s) must be one of the allowable types: %2$s', |
|
657 | - 'event_espresso' |
|
658 | - ), |
|
659 | - $type, |
|
660 | - implode(',', array_flip($allowable_types)) |
|
661 | - ) |
|
662 | - ); |
|
663 | - } |
|
664 | - } |
|
665 | - |
|
666 | - |
|
667 | - /** |
|
668 | - * Validates that the incoming format is an allowable string to use for the _schema_format property |
|
669 | - * |
|
670 | - * @param $format |
|
671 | - * @throws InvalidArgumentException |
|
672 | - */ |
|
673 | - private function validateSchemaFormat($format) |
|
674 | - { |
|
675 | - if (! is_string($format)) { |
|
676 | - throw new InvalidArgumentException( |
|
677 | - sprintf( |
|
678 | - esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'), |
|
679 | - print_r($format, true) |
|
680 | - ) |
|
681 | - ); |
|
682 | - } |
|
683 | - |
|
684 | - // validate allowable format values |
|
685 | - // @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7 |
|
686 | - $allowable_formats = array_flip( |
|
687 | - [ |
|
688 | - 'date-time', |
|
689 | - 'email', |
|
690 | - 'hostname', |
|
691 | - 'ipv4', |
|
692 | - 'ipv6', |
|
693 | - 'uri', |
|
694 | - 'uriref', |
|
695 | - ] |
|
696 | - ); |
|
697 | - |
|
698 | - if (! isset($allowable_formats[ $format ])) { |
|
699 | - throw new InvalidArgumentException( |
|
700 | - sprintf( |
|
701 | - esc_html__( |
|
702 | - 'The incoming argument (%1$s) must be one of the allowable formats: %2$s', |
|
703 | - 'event_espresso' |
|
704 | - ), |
|
705 | - $format, |
|
706 | - implode(',', array_flip($allowable_formats)) |
|
707 | - ) |
|
708 | - ); |
|
709 | - } |
|
710 | - } |
|
23 | + /** |
|
24 | + * The alias for the table the column belongs to. |
|
25 | + * |
|
26 | + * @var string |
|
27 | + */ |
|
28 | + protected $_table_alias; |
|
29 | + |
|
30 | + /** |
|
31 | + * The actual db column name for the table |
|
32 | + * |
|
33 | + * @var string |
|
34 | + */ |
|
35 | + protected $_table_column; |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * The authoritative name for the table column (used by client code to reference the field). |
|
40 | + * |
|
41 | + * @var string |
|
42 | + */ |
|
43 | + protected $_name; |
|
44 | + |
|
45 | + |
|
46 | + /** |
|
47 | + * A description for the field. |
|
48 | + * |
|
49 | + * @var string |
|
50 | + */ |
|
51 | + protected $_nicename; |
|
52 | + |
|
53 | + |
|
54 | + /** |
|
55 | + * Whether the field is nullable or not |
|
56 | + * |
|
57 | + * @var bool |
|
58 | + */ |
|
59 | + protected $_nullable; |
|
60 | + |
|
61 | + |
|
62 | + /** |
|
63 | + * What the default value for the field should be. |
|
64 | + * |
|
65 | + * @var mixed |
|
66 | + */ |
|
67 | + protected $_default_value; |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * Other configuration for the field |
|
72 | + * |
|
73 | + * @var mixed |
|
74 | + */ |
|
75 | + protected $_other_config; |
|
76 | + |
|
77 | + |
|
78 | + /** |
|
79 | + * The name of the model this field is instantiated for. |
|
80 | + * |
|
81 | + * @var string |
|
82 | + */ |
|
83 | + protected $_model_name; |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * This should be a json-schema valid data type for the field. |
|
88 | + * |
|
89 | + * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2 |
|
90 | + * @var string |
|
91 | + */ |
|
92 | + private $_schema_type = 'string'; |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * If the schema has a defined format then it should be defined via this property. |
|
97 | + * |
|
98 | + * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7 |
|
99 | + * @var string |
|
100 | + */ |
|
101 | + private $_schema_format = ''; |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * Indicates that the value of the field is managed exclusively by the server/model and not something |
|
106 | + * settable by client code. |
|
107 | + * |
|
108 | + * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4 |
|
109 | + * @var bool |
|
110 | + */ |
|
111 | + private $_schema_readonly = false; |
|
112 | + |
|
113 | + |
|
114 | + /** |
|
115 | + * @param string $table_column |
|
116 | + * @param string $nicename |
|
117 | + * @param bool $nullable |
|
118 | + * @param null $default_value |
|
119 | + */ |
|
120 | + public function __construct($table_column, $nicename, $nullable, $default_value = null) |
|
121 | + { |
|
122 | + $this->_table_column = $table_column; |
|
123 | + $this->_nicename = $nicename; |
|
124 | + $this->_nullable = $nullable; |
|
125 | + $this->_default_value = $default_value; |
|
126 | + } |
|
127 | + |
|
128 | + |
|
129 | + /** |
|
130 | + * @param $table_alias |
|
131 | + * @param $name |
|
132 | + * @param $model_name |
|
133 | + */ |
|
134 | + public function _construct_finalize($table_alias, $name, $model_name) |
|
135 | + { |
|
136 | + $this->_table_alias = $table_alias; |
|
137 | + $this->_name = $name; |
|
138 | + $this->_model_name = $model_name; |
|
139 | + /** |
|
140 | + * allow for changing the defaults |
|
141 | + */ |
|
142 | + $this->_nicename = apply_filters( |
|
143 | + 'FHEE__EE_Model_Field_Base___construct_finalize___nicename', |
|
144 | + $this->_nicename, |
|
145 | + $this |
|
146 | + ); |
|
147 | + $this->_default_value = apply_filters( |
|
148 | + 'FHEE__EE_Model_Field_Base___construct_finalize___default_value', |
|
149 | + $this->_default_value, |
|
150 | + $this |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + public function get_table_alias() |
|
156 | + { |
|
157 | + return $this->_table_alias; |
|
158 | + } |
|
159 | + |
|
160 | + |
|
161 | + public function get_table_column() |
|
162 | + { |
|
163 | + return $this->_table_column; |
|
164 | + } |
|
165 | + |
|
166 | + |
|
167 | + /** |
|
168 | + * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime' |
|
169 | + * |
|
170 | + * @return string |
|
171 | + */ |
|
172 | + public function get_model_name() |
|
173 | + { |
|
174 | + return $this->_model_name; |
|
175 | + } |
|
176 | + |
|
177 | + |
|
178 | + /** |
|
179 | + * @return string |
|
180 | + * @throws EE_Error |
|
181 | + */ |
|
182 | + public function get_name() |
|
183 | + { |
|
184 | + if ($this->_name) { |
|
185 | + return $this->_name; |
|
186 | + } else { |
|
187 | + throw new EE_Error( |
|
188 | + sprintf( |
|
189 | + esc_html__( |
|
190 | + "Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?", |
|
191 | + "event_espresso" |
|
192 | + ), |
|
193 | + get_class($this) |
|
194 | + ) |
|
195 | + ); |
|
196 | + } |
|
197 | + } |
|
198 | + |
|
199 | + |
|
200 | + public function get_nicename() |
|
201 | + { |
|
202 | + return $this->_nicename; |
|
203 | + } |
|
204 | + |
|
205 | + |
|
206 | + public function is_nullable() |
|
207 | + { |
|
208 | + return $this->_nullable; |
|
209 | + } |
|
210 | + |
|
211 | + |
|
212 | + /** |
|
213 | + * returns whether this field is an auto-increment field or not. If it is, then |
|
214 | + * on insertion it can be null. However, on updates it must be present. |
|
215 | + * |
|
216 | + * @return boolean |
|
217 | + */ |
|
218 | + public function is_auto_increment() |
|
219 | + { |
|
220 | + return false; |
|
221 | + } |
|
222 | + |
|
223 | + |
|
224 | + /** |
|
225 | + * The default value in the model object's value domain. See lengthy comment about |
|
226 | + * value domains at the top of EEM_Base |
|
227 | + * |
|
228 | + * @return mixed |
|
229 | + */ |
|
230 | + public function get_default_value() |
|
231 | + { |
|
232 | + return $this->_default_value; |
|
233 | + } |
|
234 | + |
|
235 | + |
|
236 | + /** |
|
237 | + * Returns the table alias joined to the table column, however this isn't the right |
|
238 | + * table alias if the aliased table is being joined to. In that case, you can use |
|
239 | + * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias |
|
240 | + * in the current query |
|
241 | + * |
|
242 | + * @return string |
|
243 | + */ |
|
244 | + public function get_qualified_column() |
|
245 | + { |
|
246 | + return $this->get_table_alias() . "." . $this->get_table_column(); |
|
247 | + } |
|
248 | + |
|
249 | + |
|
250 | + /** |
|
251 | + * When get() is called on a model object (eg EE_Event), before returning its value, |
|
252 | + * call this function on it, allowing us to customize the returned value based on |
|
253 | + * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default, |
|
254 | + * we simply return it. |
|
255 | + * |
|
256 | + * @param mixed $value_of_field_on_model_object |
|
257 | + * @return mixed |
|
258 | + */ |
|
259 | + public function prepare_for_get($value_of_field_on_model_object) |
|
260 | + { |
|
261 | + return $value_of_field_on_model_object; |
|
262 | + } |
|
263 | + |
|
264 | + |
|
265 | + /** |
|
266 | + * When inserting or updating a field on a model object, run this function on each |
|
267 | + * value to prepare it for insertion into the db. Generally this converts |
|
268 | + * the validated input on the model object into the format used in the DB. |
|
269 | + * |
|
270 | + * @param mixed $value_of_field_on_model_object |
|
271 | + * @return mixed |
|
272 | + */ |
|
273 | + public function prepare_for_use_in_db($value_of_field_on_model_object) |
|
274 | + { |
|
275 | + return $value_of_field_on_model_object; |
|
276 | + } |
|
277 | + |
|
278 | + |
|
279 | + /** |
|
280 | + * When creating a brand-new model object, or setting a particular value for one of its fields, this function |
|
281 | + * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc. |
|
282 | + * By default, we do nothing. |
|
283 | + * |
|
284 | + * If the model field is going to perform any validation on the input, this is where it should be done |
|
285 | + * (once the value is on the model object, it may be used in other ways besides putting it into the DB |
|
286 | + * so it's best to validate it right away). |
|
287 | + * |
|
288 | + * @param mixed $value_inputted_for_field_on_model_object |
|
289 | + * @return mixed |
|
290 | + */ |
|
291 | + public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
292 | + { |
|
293 | + return $value_inputted_for_field_on_model_object; |
|
294 | + } |
|
295 | + |
|
296 | + |
|
297 | + /** |
|
298 | + * When instantiating a model object from DB results, this function is called before setting each field. |
|
299 | + * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that |
|
300 | + * is the one child classes will most often define. |
|
301 | + * |
|
302 | + * @param mixed $value_found_in_db_for_model_object |
|
303 | + * @return mixed |
|
304 | + */ |
|
305 | + public function prepare_for_set_from_db($value_found_in_db_for_model_object) |
|
306 | + { |
|
307 | + return $this->prepare_for_set($value_found_in_db_for_model_object); |
|
308 | + } |
|
309 | + |
|
310 | + |
|
311 | + /** |
|
312 | + * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a |
|
313 | + * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12, |
|
314 | + * 2013, at 3:23pm" instead of |
|
315 | + * "8765678632", or any other modifications to how the value should be displayed, but not modified itself. |
|
316 | + * |
|
317 | + * @param mixed $value_on_field_to_be_outputted |
|
318 | + * @return mixed |
|
319 | + */ |
|
320 | + public function prepare_for_pretty_echoing($value_on_field_to_be_outputted) |
|
321 | + { |
|
322 | + return $value_on_field_to_be_outputted; |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + /** |
|
327 | + * Returns whatever is set as the nicename for the object. |
|
328 | + * |
|
329 | + * @return string |
|
330 | + */ |
|
331 | + public function getSchemaDescription() |
|
332 | + { |
|
333 | + return $this->get_nicename(); |
|
334 | + } |
|
335 | + |
|
336 | + |
|
337 | + /** |
|
338 | + * Returns whatever is set as the $_schema_type property for the object. |
|
339 | + * Note: this will automatically add 'null' to the schema if the object is_nullable() |
|
340 | + * |
|
341 | + * @return string|array |
|
342 | + */ |
|
343 | + public function getSchemaType() |
|
344 | + { |
|
345 | + if ($this->is_nullable()) { |
|
346 | + $this->_schema_type = (array) $this->_schema_type; |
|
347 | + if (! in_array('null', $this->_schema_type)) { |
|
348 | + $this->_schema_type[] = 'null'; |
|
349 | + } |
|
350 | + } |
|
351 | + return $this->_schema_type; |
|
352 | + } |
|
353 | + |
|
354 | + |
|
355 | + /** |
|
356 | + * Sets the _schema_type property. Child classes should call this in their constructors to override the default |
|
357 | + * state for this property. |
|
358 | + * |
|
359 | + * @param string|array $type |
|
360 | + * @throws InvalidArgumentException |
|
361 | + */ |
|
362 | + protected function setSchemaType($type) |
|
363 | + { |
|
364 | + $this->validateSchemaType($type); |
|
365 | + $this->_schema_type = $type; |
|
366 | + } |
|
367 | + |
|
368 | + |
|
369 | + /** |
|
370 | + * This is usually present when the $_schema_type property is 'object'. Any child classes will need to override |
|
371 | + * this method and return the properties for the schema. |
|
372 | + * |
|
373 | + * The reason this is not a property on the class is because there may be filters set on the values for the property |
|
374 | + * that won't be exposed on construct. For example enum type schemas may have the enum values filtered. |
|
375 | + * |
|
376 | + * @return array |
|
377 | + */ |
|
378 | + public function getSchemaProperties() |
|
379 | + { |
|
380 | + return []; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * By default this returns the scalar default value that was sent in on the class prepped according to the class |
|
386 | + * type as the default. However, when there are schema properties, then the default property is setup to mirror |
|
387 | + * the property keys and correctly prepare the default according to that expected property value. The getSchema |
|
388 | + * method validates whether the schema for default is setup correctly or not according to the schema type |
|
389 | + * |
|
390 | + * @return mixed |
|
391 | + */ |
|
392 | + public function getSchemaDefault() |
|
393 | + { |
|
394 | + $default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value())); |
|
395 | + $schema_properties = $this->getSchemaProperties(); |
|
396 | + |
|
397 | + // if this schema has properties than shape the default value to match the properties shape. |
|
398 | + if ($schema_properties) { |
|
399 | + $value_to_return = []; |
|
400 | + foreach ($schema_properties as $property_key => $property_schema) { |
|
401 | + switch ($property_key) { |
|
402 | + case 'pretty': |
|
403 | + case 'rendered': |
|
404 | + $value_to_return[ $property_key ] = |
|
405 | + $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value)); |
|
406 | + break; |
|
407 | + default: |
|
408 | + $value_to_return[ $property_key ] = $default_value; |
|
409 | + break; |
|
410 | + } |
|
411 | + } |
|
412 | + $default_value = $value_to_return; |
|
413 | + } |
|
414 | + return $default_value; |
|
415 | + } |
|
416 | + |
|
417 | + |
|
418 | + /** |
|
419 | + * If a child class has enum values, they should override this method and provide a simple array |
|
420 | + * of the enum values. |
|
421 | + * The reason this is not a property on the class is because there may be filterable enum values that |
|
422 | + * are set on the instantiated object that could be filtered after construct. |
|
423 | + * |
|
424 | + * @return array |
|
425 | + */ |
|
426 | + public function getSchemaEnum() |
|
427 | + { |
|
428 | + return []; |
|
429 | + } |
|
430 | + |
|
431 | + |
|
432 | + /** |
|
433 | + * This returns the value of the $_schema_format property on the object. |
|
434 | + * |
|
435 | + * @return string |
|
436 | + */ |
|
437 | + public function getSchemaFormat() |
|
438 | + { |
|
439 | + return $this->_schema_format; |
|
440 | + } |
|
441 | + |
|
442 | + |
|
443 | + /** |
|
444 | + * Sets the schema format property. |
|
445 | + * |
|
446 | + * @param string $format |
|
447 | + * @throws InvalidArgumentException |
|
448 | + */ |
|
449 | + protected function setSchemaFormat($format) |
|
450 | + { |
|
451 | + $this->validateSchemaFormat($format); |
|
452 | + $this->_schema_format = $format; |
|
453 | + } |
|
454 | + |
|
455 | + |
|
456 | + /** |
|
457 | + * This returns the value of the $_schema_readonly property on the object. |
|
458 | + * |
|
459 | + * @return bool |
|
460 | + */ |
|
461 | + public function getSchemaReadonly() |
|
462 | + { |
|
463 | + return $this->_schema_readonly; |
|
464 | + } |
|
465 | + |
|
466 | + |
|
467 | + /** |
|
468 | + * This sets the value for the $_schema_readonly property. |
|
469 | + * |
|
470 | + * @param bool $readonly (only explicit boolean values are accepted) |
|
471 | + */ |
|
472 | + protected function setSchemaReadOnly($readonly) |
|
473 | + { |
|
474 | + if (! is_bool($readonly)) { |
|
475 | + throw new InvalidArgumentException( |
|
476 | + sprintf( |
|
477 | + esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'), |
|
478 | + print_r($readonly, true) |
|
479 | + ) |
|
480 | + ); |
|
481 | + } |
|
482 | + |
|
483 | + $this->_schema_readonly = $readonly; |
|
484 | + } |
|
485 | + |
|
486 | + |
|
487 | + /** |
|
488 | + * Return `%d`, `%s` or `%f` to indicate the data type for the field. |
|
489 | + * |
|
490 | + * @return string |
|
491 | + * @uses _get_wpdb_data_type() |
|
492 | + * |
|
493 | + */ |
|
494 | + public function get_wpdb_data_type() |
|
495 | + { |
|
496 | + return $this->_get_wpdb_data_type(); |
|
497 | + } |
|
498 | + |
|
499 | + |
|
500 | + /** |
|
501 | + * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries. |
|
502 | + * |
|
503 | + * @param string $type Included if a specific type is requested. |
|
504 | + * @return string |
|
505 | + * @uses get_schema_type() |
|
506 | + */ |
|
507 | + protected function _get_wpdb_data_type($type = '') |
|
508 | + { |
|
509 | + $type = empty($type) ? $this->getSchemaType() : $type; |
|
510 | + |
|
511 | + // if type is an array, then different parsing is required. |
|
512 | + if (is_array($type)) { |
|
513 | + return $this->_get_wpdb_data_type_for_type_array($type); |
|
514 | + } |
|
515 | + |
|
516 | + $wpdb_type = '%s'; |
|
517 | + switch ($type) { |
|
518 | + case 'number': |
|
519 | + $wpdb_type = '%f'; |
|
520 | + break; |
|
521 | + case 'integer': |
|
522 | + case 'boolean': |
|
523 | + $wpdb_type = '%d'; |
|
524 | + break; |
|
525 | + case 'object': |
|
526 | + $properties = $this->getSchemaProperties(); |
|
527 | + if (isset($properties['raw'], $properties['raw']['type'])) { |
|
528 | + $wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']); |
|
529 | + } |
|
530 | + break; // leave at default |
|
531 | + } |
|
532 | + return $wpdb_type; |
|
533 | + } |
|
534 | + |
|
535 | + |
|
536 | + protected function _get_wpdb_data_type_for_type_array($type) |
|
537 | + { |
|
538 | + $type = (array) $type; |
|
539 | + // first let's flip because then we can do a faster key check |
|
540 | + $type = array_flip($type); |
|
541 | + |
|
542 | + // check for things that mean '%s' |
|
543 | + if (isset($type['string'], $type['object'], $type['array'])) { |
|
544 | + return '%s'; |
|
545 | + } |
|
546 | + |
|
547 | + // if makes it past the above condition and there's float in the array |
|
548 | + // then the type is %f |
|
549 | + if (isset($type['number'])) { |
|
550 | + return '%f'; |
|
551 | + } |
|
552 | + |
|
553 | + // if it makes it above the above conditions and there is an integer in the array |
|
554 | + // then the type is %d |
|
555 | + if (isset($type['integer'])) { |
|
556 | + return '%d'; |
|
557 | + } |
|
558 | + |
|
559 | + // anything else is a string |
|
560 | + return '%s'; |
|
561 | + } |
|
562 | + |
|
563 | + |
|
564 | + /** |
|
565 | + * This returns elements used to represent this field in the json schema. |
|
566 | + * |
|
567 | + * @link http://json-schema.org/ |
|
568 | + * @return array |
|
569 | + */ |
|
570 | + public function getSchema() |
|
571 | + { |
|
572 | + $schema = [ |
|
573 | + 'description' => $this->getSchemaDescription(), |
|
574 | + 'type' => $this->getSchemaType(), |
|
575 | + 'readonly' => $this->getSchemaReadonly(), |
|
576 | + 'default' => $this->getSchemaDefault(), |
|
577 | + ]; |
|
578 | + |
|
579 | + // optional properties of the schema |
|
580 | + $enum = $this->getSchemaEnum(); |
|
581 | + $properties = $this->getSchemaProperties(); |
|
582 | + $format = $this->getSchemaFormat(); |
|
583 | + if ($enum) { |
|
584 | + $schema['enum'] = $enum; |
|
585 | + } |
|
586 | + |
|
587 | + if ($properties) { |
|
588 | + $schema['properties'] = $properties; |
|
589 | + } |
|
590 | + |
|
591 | + if ($format) { |
|
592 | + $schema['format'] = $format; |
|
593 | + } |
|
594 | + return $schema; |
|
595 | + } |
|
596 | + |
|
597 | + |
|
598 | + /** |
|
599 | + * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part |
|
600 | + * of the model objects (ie, client code shouldn't care to ever see their value... if client code does |
|
601 | + * want to see their value, then they shouldn't be db-only fields!) |
|
602 | + * Eg, when doing events as custom post types, querying the post_type is essential, but |
|
603 | + * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event'). |
|
604 | + * By default, all fields aren't db-only. |
|
605 | + * |
|
606 | + * @return boolean |
|
607 | + */ |
|
608 | + public function is_db_only_field() |
|
609 | + { |
|
610 | + return false; |
|
611 | + } |
|
612 | + |
|
613 | + |
|
614 | + /** |
|
615 | + * Validates the incoming string|array to ensure its an allowable type. |
|
616 | + * |
|
617 | + * @param string|array $type |
|
618 | + * @throws InvalidArgumentException |
|
619 | + */ |
|
620 | + private function validateSchemaType($type) |
|
621 | + { |
|
622 | + if (! (is_string($type) || is_array($type))) { |
|
623 | + throw new InvalidArgumentException( |
|
624 | + sprintf( |
|
625 | + esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'), |
|
626 | + print_r($type, true) |
|
627 | + ) |
|
628 | + ); |
|
629 | + } |
|
630 | + |
|
631 | + // validate allowable types. |
|
632 | + // @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2 |
|
633 | + $allowable_types = array_flip( |
|
634 | + [ |
|
635 | + 'string', |
|
636 | + 'number', |
|
637 | + 'null', |
|
638 | + 'object', |
|
639 | + 'array', |
|
640 | + 'boolean', |
|
641 | + 'integer', |
|
642 | + ] |
|
643 | + ); |
|
644 | + |
|
645 | + if (is_array($type)) { |
|
646 | + foreach ($type as $item_in_type) { |
|
647 | + $this->validateSchemaType($item_in_type); |
|
648 | + } |
|
649 | + return; |
|
650 | + } |
|
651 | + |
|
652 | + if (! isset($allowable_types[ $type ])) { |
|
653 | + throw new InvalidArgumentException( |
|
654 | + sprintf( |
|
655 | + esc_html__( |
|
656 | + 'The incoming argument (%1$s) must be one of the allowable types: %2$s', |
|
657 | + 'event_espresso' |
|
658 | + ), |
|
659 | + $type, |
|
660 | + implode(',', array_flip($allowable_types)) |
|
661 | + ) |
|
662 | + ); |
|
663 | + } |
|
664 | + } |
|
665 | + |
|
666 | + |
|
667 | + /** |
|
668 | + * Validates that the incoming format is an allowable string to use for the _schema_format property |
|
669 | + * |
|
670 | + * @param $format |
|
671 | + * @throws InvalidArgumentException |
|
672 | + */ |
|
673 | + private function validateSchemaFormat($format) |
|
674 | + { |
|
675 | + if (! is_string($format)) { |
|
676 | + throw new InvalidArgumentException( |
|
677 | + sprintf( |
|
678 | + esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'), |
|
679 | + print_r($format, true) |
|
680 | + ) |
|
681 | + ); |
|
682 | + } |
|
683 | + |
|
684 | + // validate allowable format values |
|
685 | + // @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7 |
|
686 | + $allowable_formats = array_flip( |
|
687 | + [ |
|
688 | + 'date-time', |
|
689 | + 'email', |
|
690 | + 'hostname', |
|
691 | + 'ipv4', |
|
692 | + 'ipv6', |
|
693 | + 'uri', |
|
694 | + 'uriref', |
|
695 | + ] |
|
696 | + ); |
|
697 | + |
|
698 | + if (! isset($allowable_formats[ $format ])) { |
|
699 | + throw new InvalidArgumentException( |
|
700 | + sprintf( |
|
701 | + esc_html__( |
|
702 | + 'The incoming argument (%1$s) must be one of the allowable formats: %2$s', |
|
703 | + 'event_espresso' |
|
704 | + ), |
|
705 | + $format, |
|
706 | + implode(',', array_flip($allowable_formats)) |
|
707 | + ) |
|
708 | + ); |
|
709 | + } |
|
710 | + } |
|
711 | 711 | } |
@@ -139,7 +139,7 @@ discard block |
||
139 | 139 | /** |
140 | 140 | * allow for changing the defaults |
141 | 141 | */ |
142 | - $this->_nicename = apply_filters( |
|
142 | + $this->_nicename = apply_filters( |
|
143 | 143 | 'FHEE__EE_Model_Field_Base___construct_finalize___nicename', |
144 | 144 | $this->_nicename, |
145 | 145 | $this |
@@ -243,7 +243,7 @@ discard block |
||
243 | 243 | */ |
244 | 244 | public function get_qualified_column() |
245 | 245 | { |
246 | - return $this->get_table_alias() . "." . $this->get_table_column(); |
|
246 | + return $this->get_table_alias().".".$this->get_table_column(); |
|
247 | 247 | } |
248 | 248 | |
249 | 249 | |
@@ -344,7 +344,7 @@ discard block |
||
344 | 344 | { |
345 | 345 | if ($this->is_nullable()) { |
346 | 346 | $this->_schema_type = (array) $this->_schema_type; |
347 | - if (! in_array('null', $this->_schema_type)) { |
|
347 | + if ( ! in_array('null', $this->_schema_type)) { |
|
348 | 348 | $this->_schema_type[] = 'null'; |
349 | 349 | } |
350 | 350 | } |
@@ -401,11 +401,11 @@ discard block |
||
401 | 401 | switch ($property_key) { |
402 | 402 | case 'pretty': |
403 | 403 | case 'rendered': |
404 | - $value_to_return[ $property_key ] = |
|
404 | + $value_to_return[$property_key] = |
|
405 | 405 | $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value)); |
406 | 406 | break; |
407 | 407 | default: |
408 | - $value_to_return[ $property_key ] = $default_value; |
|
408 | + $value_to_return[$property_key] = $default_value; |
|
409 | 409 | break; |
410 | 410 | } |
411 | 411 | } |
@@ -471,7 +471,7 @@ discard block |
||
471 | 471 | */ |
472 | 472 | protected function setSchemaReadOnly($readonly) |
473 | 473 | { |
474 | - if (! is_bool($readonly)) { |
|
474 | + if ( ! is_bool($readonly)) { |
|
475 | 475 | throw new InvalidArgumentException( |
476 | 476 | sprintf( |
477 | 477 | esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'), |
@@ -619,7 +619,7 @@ discard block |
||
619 | 619 | */ |
620 | 620 | private function validateSchemaType($type) |
621 | 621 | { |
622 | - if (! (is_string($type) || is_array($type))) { |
|
622 | + if ( ! (is_string($type) || is_array($type))) { |
|
623 | 623 | throw new InvalidArgumentException( |
624 | 624 | sprintf( |
625 | 625 | esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'), |
@@ -649,7 +649,7 @@ discard block |
||
649 | 649 | return; |
650 | 650 | } |
651 | 651 | |
652 | - if (! isset($allowable_types[ $type ])) { |
|
652 | + if ( ! isset($allowable_types[$type])) { |
|
653 | 653 | throw new InvalidArgumentException( |
654 | 654 | sprintf( |
655 | 655 | esc_html__( |
@@ -672,7 +672,7 @@ discard block |
||
672 | 672 | */ |
673 | 673 | private function validateSchemaFormat($format) |
674 | 674 | { |
675 | - if (! is_string($format)) { |
|
675 | + if ( ! is_string($format)) { |
|
676 | 676 | throw new InvalidArgumentException( |
677 | 677 | sprintf( |
678 | 678 | esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'), |
@@ -695,7 +695,7 @@ discard block |
||
695 | 695 | ] |
696 | 696 | ); |
697 | 697 | |
698 | - if (! isset($allowable_formats[ $format ])) { |
|
698 | + if ( ! isset($allowable_formats[$format])) { |
|
699 | 699 | throw new InvalidArgumentException( |
700 | 700 | sprintf( |
701 | 701 | esc_html__( |
@@ -69,14 +69,14 @@ discard block |
||
69 | 69 | self::$_instance = new self($grand_total, $session); |
70 | 70 | } |
71 | 71 | // or maybe retrieve an existing one ? |
72 | - if (! self::$_instance instanceof EE_Cart) { |
|
72 | + if ( ! self::$_instance instanceof EE_Cart) { |
|
73 | 73 | // try getting the cart out of the session |
74 | 74 | $saved_cart = $session instanceof EE_Session ? $session->cart() : null; |
75 | 75 | self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session); |
76 | 76 | unset($saved_cart); |
77 | 77 | } |
78 | 78 | // verify that cart is ok and grand total line item exists |
79 | - if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) { |
|
79 | + if ( ! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) { |
|
80 | 80 | self::$_instance = new self($grand_total, $session); |
81 | 81 | } |
82 | 82 | self::$_instance->get_grand_total(); |
@@ -132,7 +132,7 @@ discard block |
||
132 | 132 | */ |
133 | 133 | public function session() |
134 | 134 | { |
135 | - if (! $this->_session instanceof EE_Session) { |
|
135 | + if ( ! $this->_session instanceof EE_Session) { |
|
136 | 136 | $this->set_session(); |
137 | 137 | } |
138 | 138 | return $this->_session; |
@@ -277,7 +277,7 @@ discard block |
||
277 | 277 | */ |
278 | 278 | public function hasTickets() |
279 | 279 | { |
280 | - if (! $this->has_tickets) { |
|
280 | + if ( ! $this->has_tickets) { |
|
281 | 281 | $tickets = EEH_Line_Item::get_ticket_line_items($this->get_grand_total()); |
282 | 282 | $this->has_tickets = is_array($tickets) && count($tickets) > 0; |
283 | 283 | } |
@@ -293,7 +293,7 @@ discard block |
||
293 | 293 | */ |
294 | 294 | public function get_cart_total_before_tax() |
295 | 295 | { |
296 | - if (! $this->hasTickets()) { |
|
296 | + if ( ! $this->hasTickets()) { |
|
297 | 297 | return 0.00; |
298 | 298 | } |
299 | 299 | return $this->get_grand_total()->recalculate_pre_tax_total(); |
@@ -308,7 +308,7 @@ discard block |
||
308 | 308 | */ |
309 | 309 | public function get_applied_taxes() |
310 | 310 | { |
311 | - if (! $this->hasTickets()) { |
|
311 | + if ( ! $this->hasTickets()) { |
|
312 | 312 | return 0.00; |
313 | 313 | } |
314 | 314 | return EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
@@ -323,7 +323,7 @@ discard block |
||
323 | 323 | */ |
324 | 324 | public function get_cart_grand_total() |
325 | 325 | { |
326 | - if (! $this->hasTickets()) { |
|
326 | + if ( ! $this->hasTickets()) { |
|
327 | 327 | return 0.00; |
328 | 328 | } |
329 | 329 | EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
@@ -339,7 +339,7 @@ discard block |
||
339 | 339 | */ |
340 | 340 | public function recalculate_all_cart_totals() |
341 | 341 | { |
342 | - if (! $this->hasTickets()) { |
|
342 | + if ( ! $this->hasTickets()) { |
|
343 | 343 | return 0.00; |
344 | 344 | } |
345 | 345 | $pre_tax_total = $this->get_cart_total_before_tax(); |
@@ -427,7 +427,7 @@ discard block |
||
427 | 427 | */ |
428 | 428 | public function __wakeup() |
429 | 429 | { |
430 | - if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) { |
|
430 | + if ( ! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) { |
|
431 | 431 | // $this->_grand_total is actually just an ID, so use it to get the object from the db |
432 | 432 | $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total); |
433 | 433 | } |
@@ -16,434 +16,434 @@ |
||
16 | 16 | */ |
17 | 17 | class EE_Cart implements ResettableInterface |
18 | 18 | { |
19 | - /** |
|
20 | - * TRUE if tickets have been added to cart |
|
21 | - * |
|
22 | - * @var bool |
|
23 | - */ |
|
24 | - private $has_tickets; |
|
25 | - |
|
26 | - /** |
|
27 | - * instance of the EE_Cart object |
|
28 | - * |
|
29 | - * @var EE_Cart $_instance |
|
30 | - */ |
|
31 | - private static $_instance; |
|
32 | - |
|
33 | - /** |
|
34 | - * instance of the EE_Session object |
|
35 | - * |
|
36 | - * @var EE_Session $_session |
|
37 | - */ |
|
38 | - protected $_session; |
|
39 | - |
|
40 | - /** |
|
41 | - * The total Line item which comprises all the children line-item subtotals, |
|
42 | - * which in turn each have their line items. |
|
43 | - * Typically, the line item structure will look like: |
|
44 | - * grand total |
|
45 | - * -tickets-sub-total |
|
46 | - * --ticket1 |
|
47 | - * --ticket2 |
|
48 | - * --... |
|
49 | - * -taxes-sub-total |
|
50 | - * --tax1 |
|
51 | - * --tax2 |
|
52 | - * |
|
53 | - * @var EE_Line_Item |
|
54 | - */ |
|
55 | - private $_grand_total; |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * @singleton method used to instantiate class object |
|
60 | - * @access public |
|
61 | - * @param EE_Line_Item $grand_total |
|
62 | - * @param EE_Session $session |
|
63 | - * @return EE_Cart |
|
64 | - * @throws EE_Error|ReflectionException |
|
65 | - */ |
|
66 | - public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
67 | - { |
|
68 | - if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) { |
|
69 | - self::$_instance = new self($grand_total, $session); |
|
70 | - } |
|
71 | - // or maybe retrieve an existing one ? |
|
72 | - if (! self::$_instance instanceof EE_Cart) { |
|
73 | - // try getting the cart out of the session |
|
74 | - $saved_cart = $session instanceof EE_Session ? $session->cart() : null; |
|
75 | - self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session); |
|
76 | - unset($saved_cart); |
|
77 | - } |
|
78 | - // verify that cart is ok and grand total line item exists |
|
79 | - if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) { |
|
80 | - self::$_instance = new self($grand_total, $session); |
|
81 | - } |
|
82 | - self::$_instance->get_grand_total(); |
|
83 | - // once everything is all said and done, save the cart to the EE_Session |
|
84 | - add_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
|
85 | - return self::$_instance; |
|
86 | - } |
|
87 | - |
|
88 | - |
|
89 | - /** |
|
90 | - * private constructor to prevent direct creation |
|
91 | - * |
|
92 | - * @Constructor |
|
93 | - * @access private |
|
94 | - * @param EE_Line_Item $grand_total |
|
95 | - * @param EE_Session $session |
|
96 | - * @throws EE_Error |
|
97 | - * @throws ReflectionException |
|
98 | - */ |
|
99 | - private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
100 | - { |
|
101 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
102 | - $this->set_session($session); |
|
103 | - if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) { |
|
104 | - $this->set_grand_total_line_item($grand_total); |
|
105 | - } |
|
106 | - } |
|
107 | - |
|
108 | - |
|
109 | - /** |
|
110 | - * Resets the cart completely (whereas empty_cart |
|
111 | - * |
|
112 | - * @param EE_Line_Item $grand_total |
|
113 | - * @param EE_Session $session |
|
114 | - * @return EE_Cart |
|
115 | - * @throws EE_Error|ReflectionException |
|
116 | - */ |
|
117 | - public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
118 | - { |
|
119 | - remove_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
|
120 | - if ($session instanceof EE_Session) { |
|
121 | - $session->reset_cart(); |
|
122 | - } |
|
123 | - self::$_instance = null; |
|
124 | - return self::instance($grand_total, $session); |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - /** |
|
129 | - * @return EE_Session |
|
130 | - * @throws EE_Error |
|
131 | - * @throws ReflectionException |
|
132 | - */ |
|
133 | - public function session() |
|
134 | - { |
|
135 | - if (! $this->_session instanceof EE_Session) { |
|
136 | - $this->set_session(); |
|
137 | - } |
|
138 | - return $this->_session; |
|
139 | - } |
|
140 | - |
|
141 | - |
|
142 | - /** |
|
143 | - * @param EE_Session $session |
|
144 | - * @throws EE_Error |
|
145 | - * @throws ReflectionException |
|
146 | - */ |
|
147 | - public function set_session(EE_Session $session = null) |
|
148 | - { |
|
149 | - $this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session'); |
|
150 | - } |
|
151 | - |
|
152 | - |
|
153 | - /** |
|
154 | - * Sets the cart to match the line item. Especially handy for loading an old cart where you |
|
155 | - * know the grand total line item on it |
|
156 | - * |
|
157 | - * @param EE_Line_Item $line_item |
|
158 | - */ |
|
159 | - public function set_grand_total_line_item(EE_Line_Item $line_item) |
|
160 | - { |
|
161 | - $this->_grand_total = $line_item; |
|
162 | - } |
|
163 | - |
|
164 | - |
|
165 | - /** |
|
166 | - * get_cart_from_reg_url_link |
|
167 | - * |
|
168 | - * @param EE_Transaction $transaction |
|
169 | - * @param EE_Session $session |
|
170 | - * @return EE_Cart |
|
171 | - * @throws EE_Error|ReflectionException |
|
172 | - */ |
|
173 | - public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null) |
|
174 | - { |
|
175 | - $grand_total = $transaction->total_line_item(); |
|
176 | - $grand_total->get_items(); |
|
177 | - $grand_total->tax_descendants(); |
|
178 | - return EE_Cart::instance($grand_total, $session); |
|
179 | - } |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items |
|
184 | - * |
|
185 | - * @return EE_Line_Item |
|
186 | - * @throws EE_Error|ReflectionException |
|
187 | - */ |
|
188 | - private function _create_grand_total() |
|
189 | - { |
|
190 | - $this->_grand_total = EEH_Line_Item::create_total_line_item(); |
|
191 | - return $this->_grand_total; |
|
192 | - } |
|
193 | - |
|
194 | - |
|
195 | - /** |
|
196 | - * Gets all the line items of object type Ticket |
|
197 | - * |
|
198 | - * @return EE_Line_Item[] |
|
199 | - * @throws EE_Error |
|
200 | - * @throws ReflectionException |
|
201 | - */ |
|
202 | - public function get_tickets() |
|
203 | - { |
|
204 | - if ($this->_grand_total === null) { |
|
205 | - return array(); |
|
206 | - } |
|
207 | - return EEH_Line_Item::get_ticket_line_items($this->_grand_total); |
|
208 | - } |
|
209 | - |
|
210 | - |
|
211 | - /** |
|
212 | - * returns the total quantity of tickets in the cart |
|
213 | - * |
|
214 | - * @return int |
|
215 | - * @throws EE_Error|ReflectionException |
|
216 | - */ |
|
217 | - public function all_ticket_quantity_count() |
|
218 | - { |
|
219 | - $tickets = $this->get_tickets(); |
|
220 | - if (empty($tickets)) { |
|
221 | - return 0; |
|
222 | - } |
|
223 | - $count = 0; |
|
224 | - foreach ($tickets as $ticket) { |
|
225 | - $count += $ticket->get('LIN_quantity'); |
|
226 | - } |
|
227 | - $this->has_tickets = $count > 0; |
|
228 | - return $count; |
|
229 | - } |
|
230 | - |
|
231 | - |
|
232 | - /** |
|
233 | - * Gets all the tax line items |
|
234 | - * |
|
235 | - * @return EE_Line_Item[] |
|
236 | - * @throws EE_Error|ReflectionException |
|
237 | - */ |
|
238 | - public function get_taxes() |
|
239 | - { |
|
240 | - return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children(); |
|
241 | - } |
|
242 | - |
|
243 | - |
|
244 | - /** |
|
245 | - * Gets the total line item (which is a parent of all other line items) on this cart |
|
246 | - * |
|
247 | - * @return EE_Line_Item |
|
248 | - * @throws EE_Error|ReflectionException |
|
249 | - */ |
|
250 | - public function get_grand_total() |
|
251 | - { |
|
252 | - return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total(); |
|
253 | - } |
|
254 | - |
|
255 | - |
|
256 | - /** |
|
257 | - * @process items for adding to cart |
|
258 | - * @access public |
|
259 | - * @param EE_Ticket $ticket |
|
260 | - * @param int $qty |
|
261 | - * @return TRUE on success, FALSE on fail |
|
262 | - * @throws EE_Error|ReflectionException |
|
263 | - */ |
|
264 | - public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1) |
|
265 | - { |
|
266 | - EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty); |
|
267 | - $this->has_tickets = true; |
|
268 | - return $this->save_cart(); |
|
269 | - } |
|
270 | - |
|
271 | - |
|
272 | - /** |
|
273 | - * @return bool |
|
274 | - * @throws EE_Error |
|
275 | - * @throws ReflectionException |
|
276 | - * @since $VID:$ |
|
277 | - */ |
|
278 | - public function hasTickets() |
|
279 | - { |
|
280 | - if (! $this->has_tickets) { |
|
281 | - $tickets = EEH_Line_Item::get_ticket_line_items($this->get_grand_total()); |
|
282 | - $this->has_tickets = is_array($tickets) && count($tickets) > 0; |
|
283 | - } |
|
284 | - return $this->has_tickets; |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * get_cart_total_before_tax |
|
290 | - * |
|
291 | - * @return float |
|
292 | - * @throws EE_Error|ReflectionException |
|
293 | - */ |
|
294 | - public function get_cart_total_before_tax() |
|
295 | - { |
|
296 | - if (! $this->hasTickets()) { |
|
297 | - return 0.00; |
|
298 | - } |
|
299 | - return $this->get_grand_total()->recalculate_pre_tax_total(); |
|
300 | - } |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * gets the total amount of tax paid for items in this cart |
|
305 | - * |
|
306 | - * @return float |
|
307 | - * @throws EE_Error|ReflectionException |
|
308 | - */ |
|
309 | - public function get_applied_taxes() |
|
310 | - { |
|
311 | - if (! $this->hasTickets()) { |
|
312 | - return 0.00; |
|
313 | - } |
|
314 | - return EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
|
320 | - * |
|
321 | - * @return float |
|
322 | - * @throws EE_Error|ReflectionException |
|
323 | - */ |
|
324 | - public function get_cart_grand_total() |
|
325 | - { |
|
326 | - if (! $this->hasTickets()) { |
|
327 | - return 0.00; |
|
328 | - } |
|
329 | - EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
330 | - return $this->get_grand_total()->total(); |
|
331 | - } |
|
332 | - |
|
333 | - |
|
334 | - /** |
|
335 | - * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
|
336 | - * |
|
337 | - * @return float |
|
338 | - * @throws EE_Error|ReflectionException |
|
339 | - */ |
|
340 | - public function recalculate_all_cart_totals() |
|
341 | - { |
|
342 | - if (! $this->hasTickets()) { |
|
343 | - return 0.00; |
|
344 | - } |
|
345 | - $pre_tax_total = $this->get_cart_total_before_tax(); |
|
346 | - $taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
347 | - $this->_grand_total->set_total($pre_tax_total + $taxes_total); |
|
348 | - $this->_grand_total->save_this_and_descendants_to_txn(); |
|
349 | - return $this->get_grand_total()->total(); |
|
350 | - } |
|
351 | - |
|
352 | - |
|
353 | - /** |
|
354 | - * deletes an item from the cart |
|
355 | - * |
|
356 | - * @param array|bool|string $line_item_codes |
|
357 | - * @return int on success, FALSE on fail |
|
358 | - * @throws EE_Error|ReflectionException |
|
359 | - */ |
|
360 | - public function delete_items($line_item_codes = false) |
|
361 | - { |
|
362 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
363 | - return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - /** |
|
368 | - * @remove ALL items from cart and zero ALL totals |
|
369 | - * @return bool |
|
370 | - * @throws EE_Error|ReflectionException |
|
371 | - */ |
|
372 | - public function empty_cart() |
|
373 | - { |
|
374 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
375 | - $this->_grand_total = $this->_create_grand_total(); |
|
376 | - $this->has_tickets = false; |
|
377 | - return $this->save_cart(); |
|
378 | - } |
|
379 | - |
|
380 | - |
|
381 | - /** |
|
382 | - * @remove ALL items from cart and delete total as well |
|
383 | - * @return bool |
|
384 | - * @throws EE_Error|ReflectionException |
|
385 | - */ |
|
386 | - public function delete_cart() |
|
387 | - { |
|
388 | - if ($this->_grand_total instanceof EE_Line_Item) { |
|
389 | - $deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total); |
|
390 | - if ($deleted) { |
|
391 | - $deleted += $this->_grand_total->delete(); |
|
392 | - $this->_grand_total = null; |
|
393 | - $this->has_tickets = null; |
|
394 | - return $deleted > 0; |
|
395 | - } |
|
396 | - } |
|
397 | - return false; |
|
398 | - } |
|
399 | - |
|
400 | - |
|
401 | - /** |
|
402 | - * @save cart to session |
|
403 | - * @param bool $apply_taxes |
|
404 | - * @return bool TRUE on success, FALSE on fail |
|
405 | - * @throws EE_Error|ReflectionException |
|
406 | - */ |
|
407 | - public function save_cart($apply_taxes = true) |
|
408 | - { |
|
409 | - if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) { |
|
410 | - EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
411 | - // make sure we don't cache the transaction because it can get stale |
|
412 | - if ( |
|
413 | - $this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction |
|
414 | - && $this->_grand_total->get_one_from_cache('Transaction')->ID() |
|
415 | - ) { |
|
416 | - $this->_grand_total->clear_cache('Transaction', null, true); |
|
417 | - } |
|
418 | - } |
|
419 | - if ($this->session() instanceof EE_Session) { |
|
420 | - return $this->session()->set_cart($this); |
|
421 | - } |
|
422 | - return false; |
|
423 | - } |
|
424 | - |
|
425 | - |
|
426 | - /** |
|
427 | - * @throws EE_Error |
|
428 | - */ |
|
429 | - public function __wakeup() |
|
430 | - { |
|
431 | - if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) { |
|
432 | - // $this->_grand_total is actually just an ID, so use it to get the object from the db |
|
433 | - $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total); |
|
434 | - } |
|
435 | - } |
|
436 | - |
|
437 | - |
|
438 | - /** |
|
439 | - * @return array |
|
440 | - * @throws EE_Error|ReflectionException |
|
441 | - */ |
|
442 | - public function __sleep() |
|
443 | - { |
|
444 | - if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) { |
|
445 | - $this->_grand_total = $this->_grand_total->ID(); |
|
446 | - } |
|
447 | - return array('_grand_total'); |
|
448 | - } |
|
19 | + /** |
|
20 | + * TRUE if tickets have been added to cart |
|
21 | + * |
|
22 | + * @var bool |
|
23 | + */ |
|
24 | + private $has_tickets; |
|
25 | + |
|
26 | + /** |
|
27 | + * instance of the EE_Cart object |
|
28 | + * |
|
29 | + * @var EE_Cart $_instance |
|
30 | + */ |
|
31 | + private static $_instance; |
|
32 | + |
|
33 | + /** |
|
34 | + * instance of the EE_Session object |
|
35 | + * |
|
36 | + * @var EE_Session $_session |
|
37 | + */ |
|
38 | + protected $_session; |
|
39 | + |
|
40 | + /** |
|
41 | + * The total Line item which comprises all the children line-item subtotals, |
|
42 | + * which in turn each have their line items. |
|
43 | + * Typically, the line item structure will look like: |
|
44 | + * grand total |
|
45 | + * -tickets-sub-total |
|
46 | + * --ticket1 |
|
47 | + * --ticket2 |
|
48 | + * --... |
|
49 | + * -taxes-sub-total |
|
50 | + * --tax1 |
|
51 | + * --tax2 |
|
52 | + * |
|
53 | + * @var EE_Line_Item |
|
54 | + */ |
|
55 | + private $_grand_total; |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * @singleton method used to instantiate class object |
|
60 | + * @access public |
|
61 | + * @param EE_Line_Item $grand_total |
|
62 | + * @param EE_Session $session |
|
63 | + * @return EE_Cart |
|
64 | + * @throws EE_Error|ReflectionException |
|
65 | + */ |
|
66 | + public static function instance(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
67 | + { |
|
68 | + if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) { |
|
69 | + self::$_instance = new self($grand_total, $session); |
|
70 | + } |
|
71 | + // or maybe retrieve an existing one ? |
|
72 | + if (! self::$_instance instanceof EE_Cart) { |
|
73 | + // try getting the cart out of the session |
|
74 | + $saved_cart = $session instanceof EE_Session ? $session->cart() : null; |
|
75 | + self::$_instance = $saved_cart instanceof EE_Cart ? $saved_cart : new self($grand_total, $session); |
|
76 | + unset($saved_cart); |
|
77 | + } |
|
78 | + // verify that cart is ok and grand total line item exists |
|
79 | + if (! self::$_instance instanceof EE_Cart || ! self::$_instance->_grand_total instanceof EE_Line_Item) { |
|
80 | + self::$_instance = new self($grand_total, $session); |
|
81 | + } |
|
82 | + self::$_instance->get_grand_total(); |
|
83 | + // once everything is all said and done, save the cart to the EE_Session |
|
84 | + add_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
|
85 | + return self::$_instance; |
|
86 | + } |
|
87 | + |
|
88 | + |
|
89 | + /** |
|
90 | + * private constructor to prevent direct creation |
|
91 | + * |
|
92 | + * @Constructor |
|
93 | + * @access private |
|
94 | + * @param EE_Line_Item $grand_total |
|
95 | + * @param EE_Session $session |
|
96 | + * @throws EE_Error |
|
97 | + * @throws ReflectionException |
|
98 | + */ |
|
99 | + private function __construct(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
100 | + { |
|
101 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
102 | + $this->set_session($session); |
|
103 | + if ($grand_total instanceof EE_Line_Item && $grand_total->is_total()) { |
|
104 | + $this->set_grand_total_line_item($grand_total); |
|
105 | + } |
|
106 | + } |
|
107 | + |
|
108 | + |
|
109 | + /** |
|
110 | + * Resets the cart completely (whereas empty_cart |
|
111 | + * |
|
112 | + * @param EE_Line_Item $grand_total |
|
113 | + * @param EE_Session $session |
|
114 | + * @return EE_Cart |
|
115 | + * @throws EE_Error|ReflectionException |
|
116 | + */ |
|
117 | + public static function reset(EE_Line_Item $grand_total = null, EE_Session $session = null) |
|
118 | + { |
|
119 | + remove_action('shutdown', array(self::$_instance, 'save_cart'), 90); |
|
120 | + if ($session instanceof EE_Session) { |
|
121 | + $session->reset_cart(); |
|
122 | + } |
|
123 | + self::$_instance = null; |
|
124 | + return self::instance($grand_total, $session); |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + /** |
|
129 | + * @return EE_Session |
|
130 | + * @throws EE_Error |
|
131 | + * @throws ReflectionException |
|
132 | + */ |
|
133 | + public function session() |
|
134 | + { |
|
135 | + if (! $this->_session instanceof EE_Session) { |
|
136 | + $this->set_session(); |
|
137 | + } |
|
138 | + return $this->_session; |
|
139 | + } |
|
140 | + |
|
141 | + |
|
142 | + /** |
|
143 | + * @param EE_Session $session |
|
144 | + * @throws EE_Error |
|
145 | + * @throws ReflectionException |
|
146 | + */ |
|
147 | + public function set_session(EE_Session $session = null) |
|
148 | + { |
|
149 | + $this->_session = $session instanceof EE_Session ? $session : EE_Registry::instance()->load_core('Session'); |
|
150 | + } |
|
151 | + |
|
152 | + |
|
153 | + /** |
|
154 | + * Sets the cart to match the line item. Especially handy for loading an old cart where you |
|
155 | + * know the grand total line item on it |
|
156 | + * |
|
157 | + * @param EE_Line_Item $line_item |
|
158 | + */ |
|
159 | + public function set_grand_total_line_item(EE_Line_Item $line_item) |
|
160 | + { |
|
161 | + $this->_grand_total = $line_item; |
|
162 | + } |
|
163 | + |
|
164 | + |
|
165 | + /** |
|
166 | + * get_cart_from_reg_url_link |
|
167 | + * |
|
168 | + * @param EE_Transaction $transaction |
|
169 | + * @param EE_Session $session |
|
170 | + * @return EE_Cart |
|
171 | + * @throws EE_Error|ReflectionException |
|
172 | + */ |
|
173 | + public static function get_cart_from_txn(EE_Transaction $transaction, EE_Session $session = null) |
|
174 | + { |
|
175 | + $grand_total = $transaction->total_line_item(); |
|
176 | + $grand_total->get_items(); |
|
177 | + $grand_total->tax_descendants(); |
|
178 | + return EE_Cart::instance($grand_total, $session); |
|
179 | + } |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * Creates the total line item, and ensures it has its 'tickets' and 'taxes' sub-items |
|
184 | + * |
|
185 | + * @return EE_Line_Item |
|
186 | + * @throws EE_Error|ReflectionException |
|
187 | + */ |
|
188 | + private function _create_grand_total() |
|
189 | + { |
|
190 | + $this->_grand_total = EEH_Line_Item::create_total_line_item(); |
|
191 | + return $this->_grand_total; |
|
192 | + } |
|
193 | + |
|
194 | + |
|
195 | + /** |
|
196 | + * Gets all the line items of object type Ticket |
|
197 | + * |
|
198 | + * @return EE_Line_Item[] |
|
199 | + * @throws EE_Error |
|
200 | + * @throws ReflectionException |
|
201 | + */ |
|
202 | + public function get_tickets() |
|
203 | + { |
|
204 | + if ($this->_grand_total === null) { |
|
205 | + return array(); |
|
206 | + } |
|
207 | + return EEH_Line_Item::get_ticket_line_items($this->_grand_total); |
|
208 | + } |
|
209 | + |
|
210 | + |
|
211 | + /** |
|
212 | + * returns the total quantity of tickets in the cart |
|
213 | + * |
|
214 | + * @return int |
|
215 | + * @throws EE_Error|ReflectionException |
|
216 | + */ |
|
217 | + public function all_ticket_quantity_count() |
|
218 | + { |
|
219 | + $tickets = $this->get_tickets(); |
|
220 | + if (empty($tickets)) { |
|
221 | + return 0; |
|
222 | + } |
|
223 | + $count = 0; |
|
224 | + foreach ($tickets as $ticket) { |
|
225 | + $count += $ticket->get('LIN_quantity'); |
|
226 | + } |
|
227 | + $this->has_tickets = $count > 0; |
|
228 | + return $count; |
|
229 | + } |
|
230 | + |
|
231 | + |
|
232 | + /** |
|
233 | + * Gets all the tax line items |
|
234 | + * |
|
235 | + * @return EE_Line_Item[] |
|
236 | + * @throws EE_Error|ReflectionException |
|
237 | + */ |
|
238 | + public function get_taxes() |
|
239 | + { |
|
240 | + return EEH_Line_Item::get_taxes_subtotal($this->_grand_total)->children(); |
|
241 | + } |
|
242 | + |
|
243 | + |
|
244 | + /** |
|
245 | + * Gets the total line item (which is a parent of all other line items) on this cart |
|
246 | + * |
|
247 | + * @return EE_Line_Item |
|
248 | + * @throws EE_Error|ReflectionException |
|
249 | + */ |
|
250 | + public function get_grand_total() |
|
251 | + { |
|
252 | + return $this->_grand_total instanceof EE_Line_Item ? $this->_grand_total : $this->_create_grand_total(); |
|
253 | + } |
|
254 | + |
|
255 | + |
|
256 | + /** |
|
257 | + * @process items for adding to cart |
|
258 | + * @access public |
|
259 | + * @param EE_Ticket $ticket |
|
260 | + * @param int $qty |
|
261 | + * @return TRUE on success, FALSE on fail |
|
262 | + * @throws EE_Error|ReflectionException |
|
263 | + */ |
|
264 | + public function add_ticket_to_cart(EE_Ticket $ticket, $qty = 1) |
|
265 | + { |
|
266 | + EEH_Line_Item::add_ticket_purchase($this->get_grand_total(), $ticket, $qty); |
|
267 | + $this->has_tickets = true; |
|
268 | + return $this->save_cart(); |
|
269 | + } |
|
270 | + |
|
271 | + |
|
272 | + /** |
|
273 | + * @return bool |
|
274 | + * @throws EE_Error |
|
275 | + * @throws ReflectionException |
|
276 | + * @since $VID:$ |
|
277 | + */ |
|
278 | + public function hasTickets() |
|
279 | + { |
|
280 | + if (! $this->has_tickets) { |
|
281 | + $tickets = EEH_Line_Item::get_ticket_line_items($this->get_grand_total()); |
|
282 | + $this->has_tickets = is_array($tickets) && count($tickets) > 0; |
|
283 | + } |
|
284 | + return $this->has_tickets; |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * get_cart_total_before_tax |
|
290 | + * |
|
291 | + * @return float |
|
292 | + * @throws EE_Error|ReflectionException |
|
293 | + */ |
|
294 | + public function get_cart_total_before_tax() |
|
295 | + { |
|
296 | + if (! $this->hasTickets()) { |
|
297 | + return 0.00; |
|
298 | + } |
|
299 | + return $this->get_grand_total()->recalculate_pre_tax_total(); |
|
300 | + } |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * gets the total amount of tax paid for items in this cart |
|
305 | + * |
|
306 | + * @return float |
|
307 | + * @throws EE_Error|ReflectionException |
|
308 | + */ |
|
309 | + public function get_applied_taxes() |
|
310 | + { |
|
311 | + if (! $this->hasTickets()) { |
|
312 | + return 0.00; |
|
313 | + } |
|
314 | + return EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
|
320 | + * |
|
321 | + * @return float |
|
322 | + * @throws EE_Error|ReflectionException |
|
323 | + */ |
|
324 | + public function get_cart_grand_total() |
|
325 | + { |
|
326 | + if (! $this->hasTickets()) { |
|
327 | + return 0.00; |
|
328 | + } |
|
329 | + EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
330 | + return $this->get_grand_total()->total(); |
|
331 | + } |
|
332 | + |
|
333 | + |
|
334 | + /** |
|
335 | + * Gets the total amount to be paid for the items in the cart, including taxes and other modifiers |
|
336 | + * |
|
337 | + * @return float |
|
338 | + * @throws EE_Error|ReflectionException |
|
339 | + */ |
|
340 | + public function recalculate_all_cart_totals() |
|
341 | + { |
|
342 | + if (! $this->hasTickets()) { |
|
343 | + return 0.00; |
|
344 | + } |
|
345 | + $pre_tax_total = $this->get_cart_total_before_tax(); |
|
346 | + $taxes_total = EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
347 | + $this->_grand_total->set_total($pre_tax_total + $taxes_total); |
|
348 | + $this->_grand_total->save_this_and_descendants_to_txn(); |
|
349 | + return $this->get_grand_total()->total(); |
|
350 | + } |
|
351 | + |
|
352 | + |
|
353 | + /** |
|
354 | + * deletes an item from the cart |
|
355 | + * |
|
356 | + * @param array|bool|string $line_item_codes |
|
357 | + * @return int on success, FALSE on fail |
|
358 | + * @throws EE_Error|ReflectionException |
|
359 | + */ |
|
360 | + public function delete_items($line_item_codes = false) |
|
361 | + { |
|
362 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
363 | + return EEH_Line_Item::delete_items($this->get_grand_total(), $line_item_codes); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + /** |
|
368 | + * @remove ALL items from cart and zero ALL totals |
|
369 | + * @return bool |
|
370 | + * @throws EE_Error|ReflectionException |
|
371 | + */ |
|
372 | + public function empty_cart() |
|
373 | + { |
|
374 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
375 | + $this->_grand_total = $this->_create_grand_total(); |
|
376 | + $this->has_tickets = false; |
|
377 | + return $this->save_cart(); |
|
378 | + } |
|
379 | + |
|
380 | + |
|
381 | + /** |
|
382 | + * @remove ALL items from cart and delete total as well |
|
383 | + * @return bool |
|
384 | + * @throws EE_Error|ReflectionException |
|
385 | + */ |
|
386 | + public function delete_cart() |
|
387 | + { |
|
388 | + if ($this->_grand_total instanceof EE_Line_Item) { |
|
389 | + $deleted = EEH_Line_Item::delete_all_child_items($this->_grand_total); |
|
390 | + if ($deleted) { |
|
391 | + $deleted += $this->_grand_total->delete(); |
|
392 | + $this->_grand_total = null; |
|
393 | + $this->has_tickets = null; |
|
394 | + return $deleted > 0; |
|
395 | + } |
|
396 | + } |
|
397 | + return false; |
|
398 | + } |
|
399 | + |
|
400 | + |
|
401 | + /** |
|
402 | + * @save cart to session |
|
403 | + * @param bool $apply_taxes |
|
404 | + * @return bool TRUE on success, FALSE on fail |
|
405 | + * @throws EE_Error|ReflectionException |
|
406 | + */ |
|
407 | + public function save_cart($apply_taxes = true) |
|
408 | + { |
|
409 | + if ($apply_taxes && $this->_grand_total instanceof EE_Line_Item) { |
|
410 | + EEH_Line_Item::ensure_taxes_applied($this->_grand_total); |
|
411 | + // make sure we don't cache the transaction because it can get stale |
|
412 | + if ( |
|
413 | + $this->_grand_total->get_one_from_cache('Transaction') instanceof EE_Transaction |
|
414 | + && $this->_grand_total->get_one_from_cache('Transaction')->ID() |
|
415 | + ) { |
|
416 | + $this->_grand_total->clear_cache('Transaction', null, true); |
|
417 | + } |
|
418 | + } |
|
419 | + if ($this->session() instanceof EE_Session) { |
|
420 | + return $this->session()->set_cart($this); |
|
421 | + } |
|
422 | + return false; |
|
423 | + } |
|
424 | + |
|
425 | + |
|
426 | + /** |
|
427 | + * @throws EE_Error |
|
428 | + */ |
|
429 | + public function __wakeup() |
|
430 | + { |
|
431 | + if (! $this->_grand_total instanceof EE_Line_Item && absint($this->_grand_total) !== 0) { |
|
432 | + // $this->_grand_total is actually just an ID, so use it to get the object from the db |
|
433 | + $this->_grand_total = EEM_Line_Item::instance()->get_one_by_ID($this->_grand_total); |
|
434 | + } |
|
435 | + } |
|
436 | + |
|
437 | + |
|
438 | + /** |
|
439 | + * @return array |
|
440 | + * @throws EE_Error|ReflectionException |
|
441 | + */ |
|
442 | + public function __sleep() |
|
443 | + { |
|
444 | + if ($this->_grand_total instanceof EE_Line_Item && $this->_grand_total->ID()) { |
|
445 | + $this->_grand_total = $this->_grand_total->ID(); |
|
446 | + } |
|
447 | + return array('_grand_total'); |
|
448 | + } |
|
449 | 449 | } |
@@ -93,7 +93,7 @@ |
||
93 | 93 | // now add any extra zeros to the correct precision |
94 | 94 | $decimal = str_pad($decimal, $precision, '0'); |
95 | 95 | // the final fully formatted result is as simple as stringing it all together |
96 | - return $formatted_number . $decimal_point . $decimal; |
|
96 | + return $formatted_number.$decimal_point.$decimal; |
|
97 | 97 | } |
98 | 98 | |
99 | 99 |
@@ -15,159 +15,159 @@ |
||
15 | 15 | */ |
16 | 16 | abstract class LocaleFloatFormatter implements LocaleFloatFormatterInterface, InterminableInterface |
17 | 17 | { |
18 | - /** |
|
19 | - * number of decimal places used for high precision internal calculations and storage |
|
20 | - */ |
|
21 | - const DECIMAL_PRECISION = 6; |
|
18 | + /** |
|
19 | + * number of decimal places used for high precision internal calculations and storage |
|
20 | + */ |
|
21 | + const DECIMAL_PRECISION = 6; |
|
22 | 22 | |
23 | - /* |
|
23 | + /* |
|
24 | 24 | * the following constants represent the values returned for 'n_sign_posn' && 'p_sign_posn' |
25 | 25 | */ |
26 | 26 | |
27 | - /** |
|
28 | - * 0 - Parentheses surround the quantity and currency_symbol |
|
29 | - */ |
|
30 | - const PARENTHESES = 0; |
|
31 | - |
|
32 | - /** |
|
33 | - * 1 - The sign string precedes the quantity and currency_symbol |
|
34 | - */ |
|
35 | - const SIGN_BEFORE_ALL = 1; |
|
36 | - |
|
37 | - /** |
|
38 | - * 2 - The sign string follows the quantity and currency_symbol |
|
39 | - */ |
|
40 | - const SIGN_AFTER_ALL = 2; |
|
41 | - |
|
42 | - /** |
|
43 | - * 3 - The sign string immediately precedes the currency_symbol |
|
44 | - */ |
|
45 | - const SIGN_BEFORE_CURRENCY = 3; |
|
46 | - |
|
47 | - /** |
|
48 | - * 4 - The sign string immediately follows the currency_symbol |
|
49 | - */ |
|
50 | - const SIGN_AFTER_CURRENCY = 4; |
|
51 | - |
|
52 | - /** |
|
53 | - * @var Locales |
|
54 | - */ |
|
55 | - protected $locales; |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * LocaleFloatFormatter constructor. |
|
60 | - * |
|
61 | - * @param Locales $locales |
|
62 | - */ |
|
63 | - public function __construct(Locales $locales) |
|
64 | - { |
|
65 | - $this->locales = $locales; |
|
66 | - } |
|
67 | - |
|
68 | - |
|
69 | - /** |
|
70 | - * inserts symbols for the locale's decimal and thousands separator at the appropriate places |
|
71 | - * |
|
72 | - * @param float $number |
|
73 | - * @param int $precision |
|
74 | - * @param string $decimal_point |
|
75 | - * @param int $grouping |
|
76 | - * @param string $thousands_separator |
|
77 | - * @return string |
|
78 | - */ |
|
79 | - protected function formatGroupings( |
|
80 | - float $number, |
|
81 | - int $precision, |
|
82 | - string $decimal_point, |
|
83 | - int $grouping, |
|
84 | - string $thousands_separator |
|
85 | - ): string { |
|
86 | - // remove sign (+-), cast to string, then break apart at the decimal place |
|
87 | - $parts = explode('.', (string) abs($number)); |
|
88 | - // separate the integer and decimal portions of the number into separate variables |
|
89 | - [$integer, $decimal] = $parts + [0, 0]; |
|
90 | - // ok this gets a bit crazy, but we need to insert the locale's thousand separator |
|
91 | - // at the correct intervals for the locale, so 123456789 can be something like "123,456,879" or "1.23.45.67.89" |
|
92 | - // so we're first going to reverse the string, then use chunk_split() to give us something like "987,654,321" |
|
93 | - // why reverse the number first? cuz otherwise something like "1234" would become "123,4" not "1,234" |
|
94 | - $formatted_number = chunk_split(strrev($integer), $grouping, $thousands_separator); |
|
95 | - // so THEN we reverse the string again and remove any extra separators |
|
96 | - $formatted_number = ltrim(strrev($formatted_number), $thousands_separator); |
|
97 | - if ($precision === 0) { |
|
98 | - return $formatted_number; |
|
99 | - } |
|
100 | - // now let's deal with the decimal places, by first adding a decimal to an otherwise non-decimal number |
|
101 | - $decimal = "0.$decimal"; |
|
102 | - // then type cast the string to a float and round to the appropriate precision for the locale |
|
103 | - $decimal = round((float) $decimal, $precision); |
|
104 | - // now type cast back to a string, and remove the first two characters ( the "0." added earlier ) |
|
105 | - $decimal = substr((string) $decimal, 2, $precision); |
|
106 | - // now add any extra zeros to the correct precision |
|
107 | - $decimal = str_pad($decimal, $precision, '0'); |
|
108 | - // the final fully formatted result is as simple as stringing it all together |
|
109 | - return $formatted_number . $decimal_point . $decimal; |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * Removes all characters except digits, +- and . |
|
115 | - * |
|
116 | - * @param float|int|string $number |
|
117 | - * @return float |
|
118 | - */ |
|
119 | - public function filterNumericValue($number): float |
|
120 | - { |
|
121 | - return (float) filter_var($number, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
|
122 | - } |
|
123 | - |
|
124 | - |
|
125 | - /** |
|
126 | - * formats the provided number to 6 decimal places using the site locale and returns a string |
|
127 | - * |
|
128 | - * @param float|int|string $number unformatted float, ex: 1.23456789 |
|
129 | - * @return string formatted number value, ex: '1.234568' |
|
130 | - */ |
|
131 | - public function precisionFormat($number): string |
|
132 | - { |
|
133 | - $locale = $this->locales->getLocale($this->locales->getSiteLocaleName()); |
|
134 | - return $this->format($locale, $number, LocaleFloatFormatter::DECIMAL_PRECISION); |
|
135 | - } |
|
136 | - |
|
137 | - |
|
138 | - /** |
|
139 | - * strips formatting using the site locale, then rounds the provided number to 6 decimal places and returns a float |
|
140 | - * |
|
141 | - * @param float|int|string $number unformatted number value, ex: 1234.5678956789 |
|
142 | - * @param int|null $precision the number of decimal places to round to |
|
143 | - * @param int $mode one of the PHP_ROUND_* constants for round up, round down, etc |
|
144 | - * @return float rounded value, ex: 1,234.567896 |
|
145 | - */ |
|
146 | - public function precisionRound( |
|
147 | - $number, |
|
148 | - ?int $precision = LocaleFloatFormatter::DECIMAL_PRECISION, |
|
149 | - int $mode = PHP_ROUND_HALF_UP |
|
150 | - ): float { |
|
151 | - return round( |
|
152 | - $this->filterNumericValue($number), |
|
153 | - $precision, |
|
154 | - $mode |
|
155 | - ); |
|
156 | - } |
|
157 | - |
|
158 | - |
|
159 | - /** |
|
160 | - * strips formatting for the provided locale (defaults to site locale), |
|
161 | - * then rounds the provided number and returns a float |
|
162 | - * |
|
163 | - * @param float|int|string $number unformatted number value, ex: 1234.56789 |
|
164 | - * @param string|Locale $locale ex: 'en_US' or Locale object |
|
165 | - * @param int $mode one of the PHP_ROUND_* constants for round up, round down, etc |
|
166 | - * @return float rounded value, ex: 1,234.57 |
|
167 | - */ |
|
168 | - public function roundForLocale($number, $locale = '', int $mode = PHP_ROUND_HALF_UP): float |
|
169 | - { |
|
170 | - $locale = $this->locales->getLocale($locale); |
|
171 | - return round($this->filterNumericValue($number), $locale->decimalPrecision(), $mode); |
|
172 | - } |
|
27 | + /** |
|
28 | + * 0 - Parentheses surround the quantity and currency_symbol |
|
29 | + */ |
|
30 | + const PARENTHESES = 0; |
|
31 | + |
|
32 | + /** |
|
33 | + * 1 - The sign string precedes the quantity and currency_symbol |
|
34 | + */ |
|
35 | + const SIGN_BEFORE_ALL = 1; |
|
36 | + |
|
37 | + /** |
|
38 | + * 2 - The sign string follows the quantity and currency_symbol |
|
39 | + */ |
|
40 | + const SIGN_AFTER_ALL = 2; |
|
41 | + |
|
42 | + /** |
|
43 | + * 3 - The sign string immediately precedes the currency_symbol |
|
44 | + */ |
|
45 | + const SIGN_BEFORE_CURRENCY = 3; |
|
46 | + |
|
47 | + /** |
|
48 | + * 4 - The sign string immediately follows the currency_symbol |
|
49 | + */ |
|
50 | + const SIGN_AFTER_CURRENCY = 4; |
|
51 | + |
|
52 | + /** |
|
53 | + * @var Locales |
|
54 | + */ |
|
55 | + protected $locales; |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * LocaleFloatFormatter constructor. |
|
60 | + * |
|
61 | + * @param Locales $locales |
|
62 | + */ |
|
63 | + public function __construct(Locales $locales) |
|
64 | + { |
|
65 | + $this->locales = $locales; |
|
66 | + } |
|
67 | + |
|
68 | + |
|
69 | + /** |
|
70 | + * inserts symbols for the locale's decimal and thousands separator at the appropriate places |
|
71 | + * |
|
72 | + * @param float $number |
|
73 | + * @param int $precision |
|
74 | + * @param string $decimal_point |
|
75 | + * @param int $grouping |
|
76 | + * @param string $thousands_separator |
|
77 | + * @return string |
|
78 | + */ |
|
79 | + protected function formatGroupings( |
|
80 | + float $number, |
|
81 | + int $precision, |
|
82 | + string $decimal_point, |
|
83 | + int $grouping, |
|
84 | + string $thousands_separator |
|
85 | + ): string { |
|
86 | + // remove sign (+-), cast to string, then break apart at the decimal place |
|
87 | + $parts = explode('.', (string) abs($number)); |
|
88 | + // separate the integer and decimal portions of the number into separate variables |
|
89 | + [$integer, $decimal] = $parts + [0, 0]; |
|
90 | + // ok this gets a bit crazy, but we need to insert the locale's thousand separator |
|
91 | + // at the correct intervals for the locale, so 123456789 can be something like "123,456,879" or "1.23.45.67.89" |
|
92 | + // so we're first going to reverse the string, then use chunk_split() to give us something like "987,654,321" |
|
93 | + // why reverse the number first? cuz otherwise something like "1234" would become "123,4" not "1,234" |
|
94 | + $formatted_number = chunk_split(strrev($integer), $grouping, $thousands_separator); |
|
95 | + // so THEN we reverse the string again and remove any extra separators |
|
96 | + $formatted_number = ltrim(strrev($formatted_number), $thousands_separator); |
|
97 | + if ($precision === 0) { |
|
98 | + return $formatted_number; |
|
99 | + } |
|
100 | + // now let's deal with the decimal places, by first adding a decimal to an otherwise non-decimal number |
|
101 | + $decimal = "0.$decimal"; |
|
102 | + // then type cast the string to a float and round to the appropriate precision for the locale |
|
103 | + $decimal = round((float) $decimal, $precision); |
|
104 | + // now type cast back to a string, and remove the first two characters ( the "0." added earlier ) |
|
105 | + $decimal = substr((string) $decimal, 2, $precision); |
|
106 | + // now add any extra zeros to the correct precision |
|
107 | + $decimal = str_pad($decimal, $precision, '0'); |
|
108 | + // the final fully formatted result is as simple as stringing it all together |
|
109 | + return $formatted_number . $decimal_point . $decimal; |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * Removes all characters except digits, +- and . |
|
115 | + * |
|
116 | + * @param float|int|string $number |
|
117 | + * @return float |
|
118 | + */ |
|
119 | + public function filterNumericValue($number): float |
|
120 | + { |
|
121 | + return (float) filter_var($number, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
|
122 | + } |
|
123 | + |
|
124 | + |
|
125 | + /** |
|
126 | + * formats the provided number to 6 decimal places using the site locale and returns a string |
|
127 | + * |
|
128 | + * @param float|int|string $number unformatted float, ex: 1.23456789 |
|
129 | + * @return string formatted number value, ex: '1.234568' |
|
130 | + */ |
|
131 | + public function precisionFormat($number): string |
|
132 | + { |
|
133 | + $locale = $this->locales->getLocale($this->locales->getSiteLocaleName()); |
|
134 | + return $this->format($locale, $number, LocaleFloatFormatter::DECIMAL_PRECISION); |
|
135 | + } |
|
136 | + |
|
137 | + |
|
138 | + /** |
|
139 | + * strips formatting using the site locale, then rounds the provided number to 6 decimal places and returns a float |
|
140 | + * |
|
141 | + * @param float|int|string $number unformatted number value, ex: 1234.5678956789 |
|
142 | + * @param int|null $precision the number of decimal places to round to |
|
143 | + * @param int $mode one of the PHP_ROUND_* constants for round up, round down, etc |
|
144 | + * @return float rounded value, ex: 1,234.567896 |
|
145 | + */ |
|
146 | + public function precisionRound( |
|
147 | + $number, |
|
148 | + ?int $precision = LocaleFloatFormatter::DECIMAL_PRECISION, |
|
149 | + int $mode = PHP_ROUND_HALF_UP |
|
150 | + ): float { |
|
151 | + return round( |
|
152 | + $this->filterNumericValue($number), |
|
153 | + $precision, |
|
154 | + $mode |
|
155 | + ); |
|
156 | + } |
|
157 | + |
|
158 | + |
|
159 | + /** |
|
160 | + * strips formatting for the provided locale (defaults to site locale), |
|
161 | + * then rounds the provided number and returns a float |
|
162 | + * |
|
163 | + * @param float|int|string $number unformatted number value, ex: 1234.56789 |
|
164 | + * @param string|Locale $locale ex: 'en_US' or Locale object |
|
165 | + * @param int $mode one of the PHP_ROUND_* constants for round up, round down, etc |
|
166 | + * @return float rounded value, ex: 1,234.57 |
|
167 | + */ |
|
168 | + public function roundForLocale($number, $locale = '', int $mode = PHP_ROUND_HALF_UP): float |
|
169 | + { |
|
170 | + $locale = $this->locales->getLocale($locale); |
|
171 | + return round($this->filterNumericValue($number), $locale->decimalPrecision(), $mode); |
|
172 | + } |
|
173 | 173 | } |
@@ -85,13 +85,13 @@ |
||
85 | 85 | if ($locale instanceof Locale) { |
86 | 86 | return $locale; |
87 | 87 | } |
88 | - if (isset($this->locales[ $locale ])) { |
|
89 | - return $this->locales[ $locale ]; |
|
88 | + if (isset($this->locales[$locale])) { |
|
89 | + return $this->locales[$locale]; |
|
90 | 90 | } |
91 | 91 | $locale_info = $this->locale_switcher->getLocale($locale); |
92 | - if (! empty($locale_info)) { |
|
93 | - $this->locales[ $locale ] = new Locale($locale, $locale_info, $this->default_data->getDefaults()); |
|
94 | - return $this->locales[ $locale ]; |
|
92 | + if ( ! empty($locale_info)) { |
|
93 | + $this->locales[$locale] = new Locale($locale, $locale_info, $this->default_data->getDefaults()); |
|
94 | + return $this->locales[$locale]; |
|
95 | 95 | } |
96 | 96 | throw new DomainException( |
97 | 97 | sprintf( |
@@ -15,175 +15,175 @@ |
||
15 | 15 | */ |
16 | 16 | class Locales implements InterminableInterface |
17 | 17 | { |
18 | - /** |
|
19 | - * Locale string for the site as set in the WP Settings admin |
|
20 | - */ |
|
21 | - const SITE = 'site'; |
|
22 | - |
|
23 | - /** |
|
24 | - * Locale string for the current user |
|
25 | - */ |
|
26 | - const USER = 'user'; |
|
27 | - |
|
28 | - /** |
|
29 | - * @var DefaultLocaleData |
|
30 | - */ |
|
31 | - protected $default_data; |
|
32 | - |
|
33 | - /** |
|
34 | - * @var Locale[] |
|
35 | - */ |
|
36 | - protected $locales; |
|
37 | - |
|
38 | - /** |
|
39 | - * @var LocaleSwitcher |
|
40 | - */ |
|
41 | - protected $locale_switcher; |
|
42 | - |
|
43 | - /** |
|
44 | - * @var string |
|
45 | - */ |
|
46 | - protected $site_locale; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var string |
|
50 | - */ |
|
51 | - protected $user_locale; |
|
52 | - |
|
53 | - |
|
54 | - /** |
|
55 | - * LocaleFloatFormatter constructor. |
|
56 | - * |
|
57 | - * @param DefaultLocaleData $default_data |
|
58 | - * @param LocaleSwitcher $locale_switcher |
|
59 | - */ |
|
60 | - public function __construct(DefaultLocaleData $default_data, LocaleSwitcher $locale_switcher) |
|
61 | - { |
|
62 | - $this->default_data = $default_data; |
|
63 | - $this->locale_switcher = $locale_switcher; |
|
64 | - $this->site_locale = $this->default_data->getDefaultLocale(); |
|
65 | - // give site owners a chance to change the locale for the site |
|
66 | - // ex: some of the WordPress language locales, like "ja" (Japan) do not specify a country |
|
67 | - // but the locale data on teh server might require it, like "ja_JP" |
|
68 | - $this->site_locale = sanitize_text_field( |
|
69 | - apply_filters( |
|
70 | - 'FHEE__EventEspresso_core_services_locale_Locales__construct__site_locale', |
|
71 | - ! empty($this->site_locale) ? $this->site_locale : get_locale() |
|
72 | - ) |
|
73 | - ); |
|
74 | - $this->user_locale = get_user_locale(); |
|
75 | - } |
|
76 | - |
|
77 | - |
|
78 | - /** |
|
79 | - * @param string|Locale $locale locale name ex: en_US or Locale object |
|
80 | - * @return Locale |
|
81 | - */ |
|
82 | - public function getLocale($locale): Locale |
|
83 | - { |
|
84 | - $locale = ! empty($locale) ? $locale : $this->site_locale; |
|
85 | - if ($locale instanceof Locale) { |
|
86 | - return $locale; |
|
87 | - } |
|
88 | - if (isset($this->locales[ $locale ])) { |
|
89 | - return $this->locales[ $locale ]; |
|
90 | - } |
|
91 | - $locale_info = $this->locale_switcher->getLocale($locale); |
|
92 | - if (! empty($locale_info)) { |
|
93 | - $this->locales[ $locale ] = new Locale($locale, $locale_info, $this->default_data->getDefaults()); |
|
94 | - return $this->locales[ $locale ]; |
|
95 | - } |
|
96 | - throw new DomainException( |
|
97 | - sprintf( |
|
98 | - esc_html__( |
|
99 | - 'The "%1$s" locale is either missing or invalid. Please contact your hosting provider about having it enabled on the server', |
|
100 | - 'event_espresso' |
|
101 | - ), |
|
102 | - $locale |
|
103 | - ) |
|
104 | - ); |
|
105 | - } |
|
106 | - |
|
107 | - |
|
108 | - /** |
|
109 | - * @param string $currency_ISO ex: "USD" |
|
110 | - * @param bool $fallback_to_site_locale [optional] if true, will return the site locale |
|
111 | - * if a locale can not be identified for the supplied currency ISO |
|
112 | - * @return Locale |
|
113 | - */ |
|
114 | - public function getLocaleForCurrencyISO(string $currency_ISO, bool $fallback_to_site_locale = false): Locale |
|
115 | - { |
|
116 | - $locale_name = ''; |
|
117 | - // first try to find a matching currency in the current list of locales |
|
118 | - foreach ($this->locales as $locale) { |
|
119 | - if ($locale instanceof Locale) { |
|
120 | - if ($locale->currencyIsoCode() === $currency_ISO) { |
|
121 | - $locale_name = $locale->name(); |
|
122 | - break; |
|
123 | - } |
|
124 | - } |
|
125 | - } |
|
126 | - // give site owners a chance to specify the appropriate locale for the provided currency ISO code |
|
127 | - // ex: the Canadian Dollar "CAD" could be for the locale "en_CA" or "fr_CA" |
|
128 | - // and the Euro (EUR) could be one of ~20 or so countries that use it, many of which have multiple locales |
|
129 | - $locale_name = sanitize_text_field( |
|
130 | - apply_filters( |
|
131 | - 'FHEE__EventEspresso_core_services_locale_Locales__getLocaleForCurrencyISO__locale_name', |
|
132 | - $locale_name, |
|
133 | - $currency_ISO |
|
134 | - ) |
|
135 | - ); |
|
136 | - if ($locale_name) { |
|
137 | - return $this->getLocale($locale_name); |
|
138 | - } |
|
139 | - if ($fallback_to_site_locale) { |
|
140 | - return $this->getSiteLocale(); |
|
141 | - } |
|
142 | - throw new DomainException( |
|
143 | - sprintf( |
|
144 | - esc_html__( |
|
145 | - 'The "%1$s" locale corresponding to the "%2$s" currency is either missing or invalid. Please contact your hosting provider about having it enabled on the server', |
|
146 | - 'event_espresso' |
|
147 | - ), |
|
148 | - $locale_name, |
|
149 | - $currency_ISO |
|
150 | - ) |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - /** |
|
156 | - * @return Locale |
|
157 | - */ |
|
158 | - public function getSiteLocale(): Locale |
|
159 | - { |
|
160 | - return $this->getLocale($this->site_locale); |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * @return string |
|
166 | - */ |
|
167 | - public function getSiteLocaleName(): string |
|
168 | - { |
|
169 | - return $this->site_locale; |
|
170 | - } |
|
171 | - |
|
172 | - |
|
173 | - /** |
|
174 | - * @return Locale |
|
175 | - */ |
|
176 | - public function getUserLocale(): Locale |
|
177 | - { |
|
178 | - return $this->getLocale($this->user_locale); |
|
179 | - } |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * @return string |
|
184 | - */ |
|
185 | - public function getUserLocaleName(): string |
|
186 | - { |
|
187 | - return $this->user_locale; |
|
188 | - } |
|
18 | + /** |
|
19 | + * Locale string for the site as set in the WP Settings admin |
|
20 | + */ |
|
21 | + const SITE = 'site'; |
|
22 | + |
|
23 | + /** |
|
24 | + * Locale string for the current user |
|
25 | + */ |
|
26 | + const USER = 'user'; |
|
27 | + |
|
28 | + /** |
|
29 | + * @var DefaultLocaleData |
|
30 | + */ |
|
31 | + protected $default_data; |
|
32 | + |
|
33 | + /** |
|
34 | + * @var Locale[] |
|
35 | + */ |
|
36 | + protected $locales; |
|
37 | + |
|
38 | + /** |
|
39 | + * @var LocaleSwitcher |
|
40 | + */ |
|
41 | + protected $locale_switcher; |
|
42 | + |
|
43 | + /** |
|
44 | + * @var string |
|
45 | + */ |
|
46 | + protected $site_locale; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var string |
|
50 | + */ |
|
51 | + protected $user_locale; |
|
52 | + |
|
53 | + |
|
54 | + /** |
|
55 | + * LocaleFloatFormatter constructor. |
|
56 | + * |
|
57 | + * @param DefaultLocaleData $default_data |
|
58 | + * @param LocaleSwitcher $locale_switcher |
|
59 | + */ |
|
60 | + public function __construct(DefaultLocaleData $default_data, LocaleSwitcher $locale_switcher) |
|
61 | + { |
|
62 | + $this->default_data = $default_data; |
|
63 | + $this->locale_switcher = $locale_switcher; |
|
64 | + $this->site_locale = $this->default_data->getDefaultLocale(); |
|
65 | + // give site owners a chance to change the locale for the site |
|
66 | + // ex: some of the WordPress language locales, like "ja" (Japan) do not specify a country |
|
67 | + // but the locale data on teh server might require it, like "ja_JP" |
|
68 | + $this->site_locale = sanitize_text_field( |
|
69 | + apply_filters( |
|
70 | + 'FHEE__EventEspresso_core_services_locale_Locales__construct__site_locale', |
|
71 | + ! empty($this->site_locale) ? $this->site_locale : get_locale() |
|
72 | + ) |
|
73 | + ); |
|
74 | + $this->user_locale = get_user_locale(); |
|
75 | + } |
|
76 | + |
|
77 | + |
|
78 | + /** |
|
79 | + * @param string|Locale $locale locale name ex: en_US or Locale object |
|
80 | + * @return Locale |
|
81 | + */ |
|
82 | + public function getLocale($locale): Locale |
|
83 | + { |
|
84 | + $locale = ! empty($locale) ? $locale : $this->site_locale; |
|
85 | + if ($locale instanceof Locale) { |
|
86 | + return $locale; |
|
87 | + } |
|
88 | + if (isset($this->locales[ $locale ])) { |
|
89 | + return $this->locales[ $locale ]; |
|
90 | + } |
|
91 | + $locale_info = $this->locale_switcher->getLocale($locale); |
|
92 | + if (! empty($locale_info)) { |
|
93 | + $this->locales[ $locale ] = new Locale($locale, $locale_info, $this->default_data->getDefaults()); |
|
94 | + return $this->locales[ $locale ]; |
|
95 | + } |
|
96 | + throw new DomainException( |
|
97 | + sprintf( |
|
98 | + esc_html__( |
|
99 | + 'The "%1$s" locale is either missing or invalid. Please contact your hosting provider about having it enabled on the server', |
|
100 | + 'event_espresso' |
|
101 | + ), |
|
102 | + $locale |
|
103 | + ) |
|
104 | + ); |
|
105 | + } |
|
106 | + |
|
107 | + |
|
108 | + /** |
|
109 | + * @param string $currency_ISO ex: "USD" |
|
110 | + * @param bool $fallback_to_site_locale [optional] if true, will return the site locale |
|
111 | + * if a locale can not be identified for the supplied currency ISO |
|
112 | + * @return Locale |
|
113 | + */ |
|
114 | + public function getLocaleForCurrencyISO(string $currency_ISO, bool $fallback_to_site_locale = false): Locale |
|
115 | + { |
|
116 | + $locale_name = ''; |
|
117 | + // first try to find a matching currency in the current list of locales |
|
118 | + foreach ($this->locales as $locale) { |
|
119 | + if ($locale instanceof Locale) { |
|
120 | + if ($locale->currencyIsoCode() === $currency_ISO) { |
|
121 | + $locale_name = $locale->name(); |
|
122 | + break; |
|
123 | + } |
|
124 | + } |
|
125 | + } |
|
126 | + // give site owners a chance to specify the appropriate locale for the provided currency ISO code |
|
127 | + // ex: the Canadian Dollar "CAD" could be for the locale "en_CA" or "fr_CA" |
|
128 | + // and the Euro (EUR) could be one of ~20 or so countries that use it, many of which have multiple locales |
|
129 | + $locale_name = sanitize_text_field( |
|
130 | + apply_filters( |
|
131 | + 'FHEE__EventEspresso_core_services_locale_Locales__getLocaleForCurrencyISO__locale_name', |
|
132 | + $locale_name, |
|
133 | + $currency_ISO |
|
134 | + ) |
|
135 | + ); |
|
136 | + if ($locale_name) { |
|
137 | + return $this->getLocale($locale_name); |
|
138 | + } |
|
139 | + if ($fallback_to_site_locale) { |
|
140 | + return $this->getSiteLocale(); |
|
141 | + } |
|
142 | + throw new DomainException( |
|
143 | + sprintf( |
|
144 | + esc_html__( |
|
145 | + 'The "%1$s" locale corresponding to the "%2$s" currency is either missing or invalid. Please contact your hosting provider about having it enabled on the server', |
|
146 | + 'event_espresso' |
|
147 | + ), |
|
148 | + $locale_name, |
|
149 | + $currency_ISO |
|
150 | + ) |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + /** |
|
156 | + * @return Locale |
|
157 | + */ |
|
158 | + public function getSiteLocale(): Locale |
|
159 | + { |
|
160 | + return $this->getLocale($this->site_locale); |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * @return string |
|
166 | + */ |
|
167 | + public function getSiteLocaleName(): string |
|
168 | + { |
|
169 | + return $this->site_locale; |
|
170 | + } |
|
171 | + |
|
172 | + |
|
173 | + /** |
|
174 | + * @return Locale |
|
175 | + */ |
|
176 | + public function getUserLocale(): Locale |
|
177 | + { |
|
178 | + return $this->getLocale($this->user_locale); |
|
179 | + } |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * @return string |
|
184 | + */ |
|
185 | + public function getUserLocaleName(): string |
|
186 | + { |
|
187 | + return $this->user_locale; |
|
188 | + } |
|
189 | 189 | } |
@@ -112,7 +112,7 @@ discard block |
||
112 | 112 | // price td |
113 | 113 | $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_r'); |
114 | 114 | // total td |
115 | - $total = $line_item->is_taxable() ? $line_item->prettyTotal() . '*' : $line_item->prettyTotal(); |
|
115 | + $total = $line_item->is_taxable() ? $line_item->prettyTotal().'*' : $line_item->prettyTotal(); |
|
116 | 116 | $html .= EEH_HTML::td($total, '', 'item_r'); |
117 | 117 | // end of row |
118 | 118 | $html .= EEH_HTML::trx(); |
@@ -137,7 +137,7 @@ discard block |
||
137 | 137 | $html .= EEH_HTML::td($line_item->name(), '', 'item_l sub-item'); |
138 | 138 | // desc td |
139 | 139 | $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
140 | - $html .= EEH_HTML::td() . EEH_HTML::tdx(); |
|
140 | + $html .= EEH_HTML::td().EEH_HTML::tdx(); |
|
141 | 141 | // discount/surcharge td |
142 | 142 | if ($line_item->is_percent()) { |
143 | 143 | $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'item_r'); |
@@ -14,221 +14,221 @@ |
||
14 | 14 | */ |
15 | 15 | class EE_Invoice_Line_Item_Display_Strategy extends LineItemDisplayStrategy |
16 | 16 | { |
17 | - /** |
|
18 | - * @param EE_Line_Item $line_item |
|
19 | - * @param array $options |
|
20 | - * @return mixed |
|
21 | - * @throws EE_Error |
|
22 | - * @throws ReflectionException |
|
23 | - */ |
|
24 | - public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
25 | - { |
|
26 | - |
|
27 | - $html = ''; |
|
28 | - // set some default options and merge with incoming |
|
29 | - $default_options = array( |
|
30 | - 'show_desc' => true, |
|
31 | - 'odd' => false |
|
32 | - ); |
|
33 | - $options = array_merge($default_options, (array) $options); |
|
34 | - |
|
35 | - switch ($line_item->type()) { |
|
36 | - case EEM_Line_Item::type_total: |
|
37 | - // loop thru children |
|
38 | - foreach ($line_item->children() as $child_line_item) { |
|
39 | - // recursively feed children back into this method |
|
40 | - $html .= $this->display_line_item($child_line_item, $options); |
|
41 | - } |
|
42 | - $html .= $this->_separator_row($options); |
|
43 | - $html .= $this->_total_row($line_item, esc_html__('Total', 'event_espresso'), $options); |
|
44 | - break; |
|
45 | - |
|
46 | - |
|
47 | - case EEM_Line_Item::type_sub_total: |
|
48 | - // loop thru children |
|
49 | - foreach ($line_item->children() as $child_line_item) { |
|
50 | - // recursively feed children back into this method |
|
51 | - $html .= $this->display_line_item($child_line_item, $options); |
|
52 | - } |
|
53 | - $html .= $this->_total_row($line_item, esc_html__('Sub-Total', 'event_espresso'), $options); |
|
54 | - break; |
|
55 | - |
|
56 | - |
|
57 | - case EEM_Line_Item::type_tax_sub_total: |
|
58 | - // loop thru children |
|
59 | - foreach ($line_item->children() as $child_line_item) { |
|
60 | - // recursively feed children back into this method |
|
61 | - $html .= $this->display_line_item($child_line_item, $options); |
|
62 | - } |
|
63 | - $html .= $this->_total_row($line_item, esc_html__('Tax Total', 'event_espresso'), $options); |
|
64 | - break; |
|
65 | - |
|
66 | - |
|
67 | - case EEM_Line_Item::type_line_item: |
|
68 | - // item row |
|
69 | - $html .= $this->_item_row($line_item, $options); |
|
70 | - // got any kids? |
|
71 | - foreach ($line_item->children() as $child_line_item) { |
|
72 | - $this->display_line_item($child_line_item, $options); |
|
73 | - } |
|
74 | - break; |
|
75 | - |
|
76 | - |
|
77 | - case EEM_Line_Item::type_sub_line_item: |
|
78 | - $html .= $this->_sub_item_row($line_item, $options); |
|
79 | - break; |
|
80 | - |
|
81 | - |
|
82 | - case EEM_Line_Item::type_tax: |
|
83 | - $html .= $this->_tax_row($line_item, $options); |
|
84 | - break; |
|
85 | - } |
|
86 | - |
|
87 | - return $html; |
|
88 | - } |
|
89 | - |
|
90 | - |
|
91 | - /** |
|
92 | - * _total_row |
|
93 | - * |
|
94 | - * @param EE_Line_Item $line_item |
|
95 | - * @param array $options |
|
96 | - * @return mixed |
|
97 | - * @throws EE_Error |
|
98 | - * @throws ReflectionException |
|
99 | - */ |
|
100 | - private function _item_row(EE_Line_Item $line_item, $options = array()) |
|
101 | - { |
|
102 | - // start of row |
|
103 | - $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
104 | - $html = EEH_HTML::tr('', $row_class); |
|
105 | - // name td |
|
106 | - $html .= EEH_HTML::td($line_item->name(), '', 'item_l'); |
|
107 | - // desc td |
|
108 | - $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
109 | - // quantity td |
|
110 | - $html .= EEH_HTML::td($line_item->quantity(), '', 'item_r'); |
|
111 | - // price td |
|
112 | - $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_r'); |
|
113 | - // total td |
|
114 | - $total = $line_item->is_taxable() ? $line_item->prettyTotal() . '*' : $line_item->prettyTotal(); |
|
115 | - $html .= EEH_HTML::td($total, '', 'item_r'); |
|
116 | - // end of row |
|
117 | - $html .= EEH_HTML::trx(); |
|
118 | - return $html; |
|
119 | - } |
|
120 | - |
|
121 | - |
|
122 | - /** |
|
123 | - * _sub_item_row |
|
124 | - * |
|
125 | - * @param EE_Line_Item $line_item |
|
126 | - * @param array $options |
|
127 | - * @return mixed |
|
128 | - * @throws EE_Error |
|
129 | - * @throws ReflectionException |
|
130 | - */ |
|
131 | - private function _sub_item_row(EE_Line_Item $line_item, $options = array()) |
|
132 | - { |
|
133 | - // start of row |
|
134 | - $html = EEH_HTML::tr('', 'item sub-item-row'); |
|
135 | - // name td |
|
136 | - $html .= EEH_HTML::td($line_item->name(), '', 'item_l sub-item'); |
|
137 | - // desc td |
|
138 | - $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
139 | - $html .= EEH_HTML::td() . EEH_HTML::tdx(); |
|
140 | - // discount/surcharge td |
|
141 | - if ($line_item->is_percent()) { |
|
142 | - $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'item_r'); |
|
143 | - } else { |
|
144 | - $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_r'); |
|
145 | - } |
|
146 | - // total td |
|
147 | - $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r'); |
|
148 | - // end of row |
|
149 | - $html .= EEH_HTML::trx(); |
|
150 | - return $html; |
|
151 | - } |
|
152 | - |
|
153 | - |
|
154 | - /** |
|
155 | - * _tax_row |
|
156 | - * |
|
157 | - * @param EE_Line_Item $line_item |
|
158 | - * @param array $options |
|
159 | - * @return mixed |
|
160 | - * @throws EE_Error |
|
161 | - * @throws ReflectionException |
|
162 | - */ |
|
163 | - private function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
164 | - { |
|
165 | - // start of row |
|
166 | - $html = EEH_HTML::tr('', 'item sub-item tax-total'); |
|
167 | - // name td |
|
168 | - $html .= EEH_HTML::td($line_item->name(), '', 'item_l sub-item'); |
|
169 | - // desc td |
|
170 | - $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
171 | - // percent td |
|
172 | - $html .= EEH_HTML::td( |
|
173 | - $line_item->prettyPercent(), |
|
174 | - '', |
|
175 | - 'item_r', |
|
176 | - '', |
|
177 | - ' colspan="2"' |
|
178 | - ); |
|
179 | - // total td |
|
180 | - $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r'); |
|
181 | - // end of row |
|
182 | - $html .= EEH_HTML::trx(); |
|
183 | - return $html; |
|
184 | - } |
|
185 | - |
|
186 | - |
|
187 | - /** |
|
188 | - * _total_row |
|
189 | - * |
|
190 | - * @param EE_Line_Item $line_item |
|
191 | - * @param string $text |
|
192 | - * @param array $options |
|
193 | - * @return mixed |
|
194 | - * @throws EE_Error |
|
195 | - * @throws ReflectionException |
|
196 | - */ |
|
197 | - private function _total_row(EE_Line_Item $line_item, $text = '', $options = array()) |
|
198 | - { |
|
199 | - // colspan |
|
200 | - $colspan = $options['show_desc'] ? ' colspan="2"' : ''; |
|
201 | - // start of row |
|
202 | - $html = EEH_HTML::tr('', '', 'total_tr odd'); |
|
203 | - // empty td |
|
204 | - $html .= EEH_HTML::td(EEH_HTML::nbsp(), '', '', '', $colspan); |
|
205 | - // total td |
|
206 | - $html .= EEH_HTML::td($text, '', 'total_currency total', '', $colspan); |
|
207 | - // total td |
|
208 | - $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'total'); |
|
209 | - // end of row |
|
210 | - $html .= EEH_HTML::trx(); |
|
211 | - return $html; |
|
212 | - } |
|
213 | - |
|
214 | - |
|
215 | - |
|
216 | - /** |
|
217 | - * _separator_row |
|
218 | - * |
|
219 | - * @param array $options |
|
220 | - * @return mixed |
|
221 | - */ |
|
222 | - private function _separator_row($options = array()) |
|
223 | - { |
|
224 | - // colspan |
|
225 | - $colspan = $options['show_desc'] ? ' colspan="5"' : ' colspan="4"'; |
|
226 | - // start of row |
|
227 | - $html = EEH_HTML::tr(EEH_HTML::td('<hr>', '', '', '', $colspan)); |
|
17 | + /** |
|
18 | + * @param EE_Line_Item $line_item |
|
19 | + * @param array $options |
|
20 | + * @return mixed |
|
21 | + * @throws EE_Error |
|
22 | + * @throws ReflectionException |
|
23 | + */ |
|
24 | + public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
25 | + { |
|
26 | + |
|
27 | + $html = ''; |
|
28 | + // set some default options and merge with incoming |
|
29 | + $default_options = array( |
|
30 | + 'show_desc' => true, |
|
31 | + 'odd' => false |
|
32 | + ); |
|
33 | + $options = array_merge($default_options, (array) $options); |
|
34 | + |
|
35 | + switch ($line_item->type()) { |
|
36 | + case EEM_Line_Item::type_total: |
|
37 | + // loop thru children |
|
38 | + foreach ($line_item->children() as $child_line_item) { |
|
39 | + // recursively feed children back into this method |
|
40 | + $html .= $this->display_line_item($child_line_item, $options); |
|
41 | + } |
|
42 | + $html .= $this->_separator_row($options); |
|
43 | + $html .= $this->_total_row($line_item, esc_html__('Total', 'event_espresso'), $options); |
|
44 | + break; |
|
45 | + |
|
46 | + |
|
47 | + case EEM_Line_Item::type_sub_total: |
|
48 | + // loop thru children |
|
49 | + foreach ($line_item->children() as $child_line_item) { |
|
50 | + // recursively feed children back into this method |
|
51 | + $html .= $this->display_line_item($child_line_item, $options); |
|
52 | + } |
|
53 | + $html .= $this->_total_row($line_item, esc_html__('Sub-Total', 'event_espresso'), $options); |
|
54 | + break; |
|
55 | + |
|
56 | + |
|
57 | + case EEM_Line_Item::type_tax_sub_total: |
|
58 | + // loop thru children |
|
59 | + foreach ($line_item->children() as $child_line_item) { |
|
60 | + // recursively feed children back into this method |
|
61 | + $html .= $this->display_line_item($child_line_item, $options); |
|
62 | + } |
|
63 | + $html .= $this->_total_row($line_item, esc_html__('Tax Total', 'event_espresso'), $options); |
|
64 | + break; |
|
65 | + |
|
66 | + |
|
67 | + case EEM_Line_Item::type_line_item: |
|
68 | + // item row |
|
69 | + $html .= $this->_item_row($line_item, $options); |
|
70 | + // got any kids? |
|
71 | + foreach ($line_item->children() as $child_line_item) { |
|
72 | + $this->display_line_item($child_line_item, $options); |
|
73 | + } |
|
74 | + break; |
|
75 | + |
|
76 | + |
|
77 | + case EEM_Line_Item::type_sub_line_item: |
|
78 | + $html .= $this->_sub_item_row($line_item, $options); |
|
79 | + break; |
|
80 | + |
|
81 | + |
|
82 | + case EEM_Line_Item::type_tax: |
|
83 | + $html .= $this->_tax_row($line_item, $options); |
|
84 | + break; |
|
85 | + } |
|
86 | + |
|
87 | + return $html; |
|
88 | + } |
|
89 | + |
|
90 | + |
|
91 | + /** |
|
92 | + * _total_row |
|
93 | + * |
|
94 | + * @param EE_Line_Item $line_item |
|
95 | + * @param array $options |
|
96 | + * @return mixed |
|
97 | + * @throws EE_Error |
|
98 | + * @throws ReflectionException |
|
99 | + */ |
|
100 | + private function _item_row(EE_Line_Item $line_item, $options = array()) |
|
101 | + { |
|
102 | + // start of row |
|
103 | + $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
104 | + $html = EEH_HTML::tr('', $row_class); |
|
105 | + // name td |
|
106 | + $html .= EEH_HTML::td($line_item->name(), '', 'item_l'); |
|
107 | + // desc td |
|
108 | + $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
109 | + // quantity td |
|
110 | + $html .= EEH_HTML::td($line_item->quantity(), '', 'item_r'); |
|
111 | + // price td |
|
112 | + $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_r'); |
|
113 | + // total td |
|
114 | + $total = $line_item->is_taxable() ? $line_item->prettyTotal() . '*' : $line_item->prettyTotal(); |
|
115 | + $html .= EEH_HTML::td($total, '', 'item_r'); |
|
116 | + // end of row |
|
117 | + $html .= EEH_HTML::trx(); |
|
118 | + return $html; |
|
119 | + } |
|
120 | + |
|
121 | + |
|
122 | + /** |
|
123 | + * _sub_item_row |
|
124 | + * |
|
125 | + * @param EE_Line_Item $line_item |
|
126 | + * @param array $options |
|
127 | + * @return mixed |
|
128 | + * @throws EE_Error |
|
129 | + * @throws ReflectionException |
|
130 | + */ |
|
131 | + private function _sub_item_row(EE_Line_Item $line_item, $options = array()) |
|
132 | + { |
|
133 | + // start of row |
|
134 | + $html = EEH_HTML::tr('', 'item sub-item-row'); |
|
135 | + // name td |
|
136 | + $html .= EEH_HTML::td($line_item->name(), '', 'item_l sub-item'); |
|
137 | + // desc td |
|
138 | + $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
139 | + $html .= EEH_HTML::td() . EEH_HTML::tdx(); |
|
140 | + // discount/surcharge td |
|
141 | + if ($line_item->is_percent()) { |
|
142 | + $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'item_r'); |
|
143 | + } else { |
|
144 | + $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_r'); |
|
145 | + } |
|
146 | + // total td |
|
147 | + $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r'); |
|
148 | + // end of row |
|
149 | + $html .= EEH_HTML::trx(); |
|
150 | + return $html; |
|
151 | + } |
|
152 | + |
|
153 | + |
|
154 | + /** |
|
155 | + * _tax_row |
|
156 | + * |
|
157 | + * @param EE_Line_Item $line_item |
|
158 | + * @param array $options |
|
159 | + * @return mixed |
|
160 | + * @throws EE_Error |
|
161 | + * @throws ReflectionException |
|
162 | + */ |
|
163 | + private function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
164 | + { |
|
165 | + // start of row |
|
166 | + $html = EEH_HTML::tr('', 'item sub-item tax-total'); |
|
167 | + // name td |
|
168 | + $html .= EEH_HTML::td($line_item->name(), '', 'item_l sub-item'); |
|
169 | + // desc td |
|
170 | + $html .= $options['show_desc'] ? EEH_HTML::td($line_item->desc(), '', 'item_l') : ''; |
|
171 | + // percent td |
|
172 | + $html .= EEH_HTML::td( |
|
173 | + $line_item->prettyPercent(), |
|
174 | + '', |
|
175 | + 'item_r', |
|
176 | + '', |
|
177 | + ' colspan="2"' |
|
178 | + ); |
|
179 | + // total td |
|
180 | + $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r'); |
|
181 | + // end of row |
|
182 | + $html .= EEH_HTML::trx(); |
|
183 | + return $html; |
|
184 | + } |
|
185 | + |
|
186 | + |
|
187 | + /** |
|
188 | + * _total_row |
|
189 | + * |
|
190 | + * @param EE_Line_Item $line_item |
|
191 | + * @param string $text |
|
192 | + * @param array $options |
|
193 | + * @return mixed |
|
194 | + * @throws EE_Error |
|
195 | + * @throws ReflectionException |
|
196 | + */ |
|
197 | + private function _total_row(EE_Line_Item $line_item, $text = '', $options = array()) |
|
198 | + { |
|
199 | + // colspan |
|
200 | + $colspan = $options['show_desc'] ? ' colspan="2"' : ''; |
|
201 | + // start of row |
|
202 | + $html = EEH_HTML::tr('', '', 'total_tr odd'); |
|
203 | + // empty td |
|
204 | + $html .= EEH_HTML::td(EEH_HTML::nbsp(), '', '', '', $colspan); |
|
205 | + // total td |
|
206 | + $html .= EEH_HTML::td($text, '', 'total_currency total', '', $colspan); |
|
207 | + // total td |
|
208 | + $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'total'); |
|
209 | + // end of row |
|
210 | + $html .= EEH_HTML::trx(); |
|
211 | + return $html; |
|
212 | + } |
|
213 | + |
|
214 | + |
|
215 | + |
|
216 | + /** |
|
217 | + * _separator_row |
|
218 | + * |
|
219 | + * @param array $options |
|
220 | + * @return mixed |
|
221 | + */ |
|
222 | + private function _separator_row($options = array()) |
|
223 | + { |
|
224 | + // colspan |
|
225 | + $colspan = $options['show_desc'] ? ' colspan="5"' : ' colspan="4"'; |
|
226 | + // start of row |
|
227 | + $html = EEH_HTML::tr(EEH_HTML::td('<hr>', '', '', '', $colspan)); |
|
228 | 228 | // // separator td |
229 | 229 | // $html .= EEH_HTML::td( '<hr>', '', '', '', $colspan ); |
230 | 230 | // // end of row |
231 | 231 | // $html .= EEH_HTML::trx(); |
232 | - return $html; |
|
233 | - } |
|
232 | + return $html; |
|
233 | + } |
|
234 | 234 | } |
@@ -10,28 +10,28 @@ |
||
10 | 10 | abstract class LineItemDisplayStrategy implements EEI_Line_Item_Display |
11 | 11 | { |
12 | 12 | |
13 | - /** |
|
14 | - * @var CurrencyFormatter |
|
15 | - * @since $VID:$ |
|
16 | - */ |
|
17 | - protected $currency_formatter; |
|
13 | + /** |
|
14 | + * @var CurrencyFormatter |
|
15 | + * @since $VID:$ |
|
16 | + */ |
|
17 | + protected $currency_formatter; |
|
18 | 18 | |
19 | - /** |
|
20 | - * @var NumberFormatter |
|
21 | - */ |
|
22 | - protected $decimal_formatter; |
|
19 | + /** |
|
20 | + * @var NumberFormatter |
|
21 | + */ |
|
22 | + protected $decimal_formatter; |
|
23 | 23 | |
24 | 24 | |
25 | - /** |
|
26 | - * LineItemDisplayStrategy constructor. |
|
27 | - * |
|
28 | - * @param CurrencyFormatter $currency_formatter |
|
29 | - */ |
|
30 | - public function __construct(CurrencyFormatter $currency_formatter = null) |
|
31 | - { |
|
32 | - if (! $currency_formatter instanceof CurrencyFormatter) { |
|
33 | - $currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class); |
|
34 | - } |
|
35 | - $this->currency_formatter = $currency_formatter; |
|
36 | - } |
|
25 | + /** |
|
26 | + * LineItemDisplayStrategy constructor. |
|
27 | + * |
|
28 | + * @param CurrencyFormatter $currency_formatter |
|
29 | + */ |
|
30 | + public function __construct(CurrencyFormatter $currency_formatter = null) |
|
31 | + { |
|
32 | + if (! $currency_formatter instanceof CurrencyFormatter) { |
|
33 | + $currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class); |
|
34 | + } |
|
35 | + $this->currency_formatter = $currency_formatter; |
|
36 | + } |
|
37 | 37 | } |
@@ -29,7 +29,7 @@ |
||
29 | 29 | */ |
30 | 30 | public function __construct(CurrencyFormatter $currency_formatter = null) |
31 | 31 | { |
32 | - if (! $currency_formatter instanceof CurrencyFormatter) { |
|
32 | + if ( ! $currency_formatter instanceof CurrencyFormatter) { |
|
33 | 33 | $currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class); |
34 | 34 | } |
35 | 35 | $this->currency_formatter = $currency_formatter; |
@@ -13,219 +13,219 @@ |
||
13 | 13 | class EE_Default_Line_Item_Display_Strategy extends LineItemDisplayStrategy |
14 | 14 | { |
15 | 15 | |
16 | - /** |
|
17 | - * total amount of tax to apply |
|
18 | - * |
|
19 | - * @type float $_tax_rate |
|
20 | - */ |
|
21 | - private $_tax_rate = 0; |
|
22 | - |
|
23 | - /** |
|
24 | - * total amount including tax we can bill for at this time |
|
25 | - * |
|
26 | - * @type float $_grand_total |
|
27 | - */ |
|
28 | - private $_grand_total = 0.00; |
|
29 | - |
|
30 | - /** |
|
31 | - * total number of items being billed for |
|
32 | - * |
|
33 | - * @type int $_total_items |
|
34 | - */ |
|
35 | - private $_total_items = 0; |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * @return float |
|
40 | - */ |
|
41 | - public function grand_total() |
|
42 | - { |
|
43 | - return $this->_grand_total; |
|
44 | - } |
|
45 | - |
|
46 | - |
|
47 | - /** |
|
48 | - * @return int |
|
49 | - */ |
|
50 | - public function total_items() |
|
51 | - { |
|
52 | - return $this->_total_items; |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - /** |
|
57 | - * @param EE_Line_Item $line_item |
|
58 | - * @param array $options |
|
59 | - * @return mixed |
|
60 | - * @throws EE_Error |
|
61 | - * @throws ReflectionException |
|
62 | - */ |
|
63 | - public function display_line_item(EE_Line_Item $line_item, $options = []) |
|
64 | - { |
|
65 | - $html = ''; |
|
66 | - // set some default options and merge with incoming |
|
67 | - $default_options = [ |
|
68 | - 'show_desc' => true, // TRUE FALSE |
|
69 | - 'odd' => false, |
|
70 | - ]; |
|
71 | - $options = array_merge($default_options, (array) $options); |
|
72 | - |
|
73 | - switch ($line_item->type()) { |
|
74 | - case EEM_Line_Item::type_line_item: |
|
75 | - // item row |
|
76 | - $html .= $this->_item_row($line_item, $options); |
|
77 | - // got any kids? |
|
78 | - foreach ($line_item->children() as $child_line_item) { |
|
79 | - $this->display_line_item($child_line_item, $options); |
|
80 | - } |
|
81 | - break; |
|
82 | - |
|
83 | - case EEM_Line_Item::type_sub_line_item: |
|
84 | - $html .= $this->_sub_item_row($line_item, $options); |
|
85 | - break; |
|
86 | - |
|
87 | - case EEM_Line_Item::type_sub_total: |
|
88 | - break; |
|
89 | - |
|
90 | - case EEM_Line_Item::type_tax: |
|
91 | - $this->_tax_rate += $line_item->percent(); |
|
92 | - break; |
|
93 | - |
|
94 | - case EEM_Line_Item::type_tax_sub_total: |
|
95 | - foreach ($line_item->children() as $child_line_item) { |
|
96 | - if ($child_line_item->type() == EEM_Line_Item::type_tax) { |
|
97 | - // recursively feed children back into this method |
|
98 | - $this->display_line_item($child_line_item, $options); |
|
99 | - } |
|
100 | - } |
|
101 | - break; |
|
102 | - |
|
103 | - case EEM_Line_Item::type_total: |
|
104 | - // get all child line items |
|
105 | - $children = $line_item->children(); |
|
106 | - if ($options['set_tax_rate'] === true) { |
|
107 | - // loop thru tax child line items just to determine tax rate |
|
108 | - foreach ($children as $child_line_item) { |
|
109 | - if ($child_line_item->type() == EEM_Line_Item::type_tax_sub_total) { |
|
110 | - // recursively feed children back into this method |
|
111 | - $this->display_line_item($child_line_item, $options); |
|
112 | - } |
|
113 | - } |
|
114 | - } else { |
|
115 | - // now loop thru all non-tax child line items |
|
116 | - foreach ($children as $child_line_item) { |
|
117 | - if ($child_line_item->type() != EEM_Line_Item::type_tax_sub_total) { |
|
118 | - // recursively feed children back into this method |
|
119 | - $html .= $this->display_line_item($child_line_item, $options); |
|
120 | - } |
|
121 | - } |
|
122 | - } |
|
123 | - break; |
|
124 | - } |
|
125 | - |
|
126 | - return $html; |
|
127 | - } |
|
128 | - |
|
129 | - |
|
130 | - /** |
|
131 | - * _total_row |
|
132 | - * |
|
133 | - * @param EE_Line_Item $line_item |
|
134 | - * @param array $options |
|
135 | - * @return mixed |
|
136 | - * @throws EE_Error |
|
137 | - * @throws ReflectionException |
|
138 | - */ |
|
139 | - private function _item_row(EE_Line_Item $line_item, $options = []) |
|
140 | - { |
|
141 | - // start of row |
|
142 | - $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
143 | - $html = EEH_HTML::tr('', '', $row_class); |
|
144 | - // name && desc |
|
145 | - $name_and_desc = apply_filters( |
|
146 | - 'FHEE__EE_Default_Line_Item_Display_Strategy__item_row__name', |
|
147 | - $line_item->name(), |
|
148 | - $line_item |
|
149 | - ); |
|
150 | - $name_and_desc .= apply_filters( |
|
151 | - 'FHEE__EE_Default_Line_Item_Display_Strategy__item_row__desc', |
|
152 | - ($options['show_desc'] ? '<span class="line-item-desc-spn smaller-text">: ' . $line_item->desc() . '</span>' |
|
153 | - : ''), |
|
154 | - $line_item, |
|
155 | - $options |
|
156 | - ); |
|
157 | - if ($line_item->is_taxable()) { |
|
158 | - $ticket_price_includes_taxes = EE_Registry::instance()->CFG->tax_settings->prices_displayed_including_taxes |
|
159 | - ? esc_html__('* price includes taxes', 'event_espresso') |
|
160 | - : esc_html__('* price does not include taxes', 'event_espresso'); |
|
161 | - $name_and_desc .= '<span class="smaller-text lt-grey-text" style="margin:0 0 0 2em;">' |
|
162 | - . $ticket_price_includes_taxes |
|
163 | - . '</span>'; |
|
164 | - } |
|
165 | - |
|
166 | - // name td |
|
167 | - $html .= EEH_HTML::td($name_and_desc, '', 'item_l'); |
|
168 | - // quantity td |
|
169 | - $html .= EEH_HTML::td($line_item->quantity(), '', 'item_l jst-rght'); |
|
170 | - $tax_rate = $line_item->is_taxable() |
|
171 | - && EE_Registry::instance()->CFG->tax_settings->prices_displayed_including_taxes |
|
172 | - ? 1 + ($this->_tax_rate / 100) |
|
173 | - : 1; |
|
174 | - // price td |
|
175 | - // FIRST get the correctly rounded price per ticket including taxes |
|
176 | - $raw_unit_price = $this->currency_formatter->roundForLocale($line_item->unit_price() * $tax_rate); |
|
177 | - $unit_price = apply_filters( |
|
178 | - 'FHEE__EE_Default_Line_Item_Display_Strategy___item_row__unit_price', |
|
179 | - $this->currency_formatter->formatForLocale($raw_unit_price), |
|
180 | - $line_item, |
|
181 | - $tax_rate |
|
182 | - ); |
|
183 | - $html .= EEH_HTML::td($unit_price, '', 'item_c jst-rght'); |
|
184 | - // total td |
|
185 | - $total = apply_filters( |
|
186 | - 'FHEE__EE_Default_Line_Item_Display_Strategy___item_row__total', |
|
187 | - $this->currency_formatter->formatForLocale($raw_unit_price * $line_item->quantity()), |
|
188 | - $line_item, |
|
189 | - $tax_rate |
|
190 | - ); |
|
191 | - $html .= EEH_HTML::td($total, '', 'item_r jst-rght'); |
|
192 | - // end of row |
|
193 | - $html .= EEH_HTML::trx(); |
|
194 | - |
|
195 | - return $html; |
|
196 | - } |
|
197 | - |
|
198 | - |
|
199 | - /** |
|
200 | - * _sub_item_row |
|
201 | - * |
|
202 | - * @param EE_Line_Item $line_item |
|
203 | - * @param array $options |
|
204 | - * @return mixed |
|
205 | - * @throws EE_Error |
|
206 | - * @throws ReflectionException |
|
207 | - */ |
|
208 | - private function _sub_item_row(EE_Line_Item $line_item, $options = []) |
|
209 | - { |
|
210 | - // start of row |
|
211 | - $html = EEH_HTML::tr('', 'item sub-item-row'); |
|
212 | - // name && desc |
|
213 | - $name_and_desc = $line_item->name(); |
|
214 | - $name_and_desc .= $options['show_desc'] ? '<span class="line-sub-item-desc-spn smaller-text">: ' |
|
215 | - . $line_item->desc() |
|
216 | - . '</span>' : ''; |
|
217 | - // name td |
|
218 | - $html .= EEH_HTML::td(/*__FUNCTION__ .*/ $name_and_desc, '', 'item_l sub-item'); |
|
219 | - // discount/surcharge td |
|
220 | - if ($line_item->is_percent()) { |
|
221 | - $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'item_c'); |
|
222 | - } else { |
|
223 | - $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_c jst-rght'); |
|
224 | - } |
|
225 | - // total td |
|
226 | - $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r jst-rght'); |
|
227 | - // end of row |
|
228 | - $html .= EEH_HTML::trx(); |
|
229 | - return $html; |
|
230 | - } |
|
16 | + /** |
|
17 | + * total amount of tax to apply |
|
18 | + * |
|
19 | + * @type float $_tax_rate |
|
20 | + */ |
|
21 | + private $_tax_rate = 0; |
|
22 | + |
|
23 | + /** |
|
24 | + * total amount including tax we can bill for at this time |
|
25 | + * |
|
26 | + * @type float $_grand_total |
|
27 | + */ |
|
28 | + private $_grand_total = 0.00; |
|
29 | + |
|
30 | + /** |
|
31 | + * total number of items being billed for |
|
32 | + * |
|
33 | + * @type int $_total_items |
|
34 | + */ |
|
35 | + private $_total_items = 0; |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * @return float |
|
40 | + */ |
|
41 | + public function grand_total() |
|
42 | + { |
|
43 | + return $this->_grand_total; |
|
44 | + } |
|
45 | + |
|
46 | + |
|
47 | + /** |
|
48 | + * @return int |
|
49 | + */ |
|
50 | + public function total_items() |
|
51 | + { |
|
52 | + return $this->_total_items; |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + /** |
|
57 | + * @param EE_Line_Item $line_item |
|
58 | + * @param array $options |
|
59 | + * @return mixed |
|
60 | + * @throws EE_Error |
|
61 | + * @throws ReflectionException |
|
62 | + */ |
|
63 | + public function display_line_item(EE_Line_Item $line_item, $options = []) |
|
64 | + { |
|
65 | + $html = ''; |
|
66 | + // set some default options and merge with incoming |
|
67 | + $default_options = [ |
|
68 | + 'show_desc' => true, // TRUE FALSE |
|
69 | + 'odd' => false, |
|
70 | + ]; |
|
71 | + $options = array_merge($default_options, (array) $options); |
|
72 | + |
|
73 | + switch ($line_item->type()) { |
|
74 | + case EEM_Line_Item::type_line_item: |
|
75 | + // item row |
|
76 | + $html .= $this->_item_row($line_item, $options); |
|
77 | + // got any kids? |
|
78 | + foreach ($line_item->children() as $child_line_item) { |
|
79 | + $this->display_line_item($child_line_item, $options); |
|
80 | + } |
|
81 | + break; |
|
82 | + |
|
83 | + case EEM_Line_Item::type_sub_line_item: |
|
84 | + $html .= $this->_sub_item_row($line_item, $options); |
|
85 | + break; |
|
86 | + |
|
87 | + case EEM_Line_Item::type_sub_total: |
|
88 | + break; |
|
89 | + |
|
90 | + case EEM_Line_Item::type_tax: |
|
91 | + $this->_tax_rate += $line_item->percent(); |
|
92 | + break; |
|
93 | + |
|
94 | + case EEM_Line_Item::type_tax_sub_total: |
|
95 | + foreach ($line_item->children() as $child_line_item) { |
|
96 | + if ($child_line_item->type() == EEM_Line_Item::type_tax) { |
|
97 | + // recursively feed children back into this method |
|
98 | + $this->display_line_item($child_line_item, $options); |
|
99 | + } |
|
100 | + } |
|
101 | + break; |
|
102 | + |
|
103 | + case EEM_Line_Item::type_total: |
|
104 | + // get all child line items |
|
105 | + $children = $line_item->children(); |
|
106 | + if ($options['set_tax_rate'] === true) { |
|
107 | + // loop thru tax child line items just to determine tax rate |
|
108 | + foreach ($children as $child_line_item) { |
|
109 | + if ($child_line_item->type() == EEM_Line_Item::type_tax_sub_total) { |
|
110 | + // recursively feed children back into this method |
|
111 | + $this->display_line_item($child_line_item, $options); |
|
112 | + } |
|
113 | + } |
|
114 | + } else { |
|
115 | + // now loop thru all non-tax child line items |
|
116 | + foreach ($children as $child_line_item) { |
|
117 | + if ($child_line_item->type() != EEM_Line_Item::type_tax_sub_total) { |
|
118 | + // recursively feed children back into this method |
|
119 | + $html .= $this->display_line_item($child_line_item, $options); |
|
120 | + } |
|
121 | + } |
|
122 | + } |
|
123 | + break; |
|
124 | + } |
|
125 | + |
|
126 | + return $html; |
|
127 | + } |
|
128 | + |
|
129 | + |
|
130 | + /** |
|
131 | + * _total_row |
|
132 | + * |
|
133 | + * @param EE_Line_Item $line_item |
|
134 | + * @param array $options |
|
135 | + * @return mixed |
|
136 | + * @throws EE_Error |
|
137 | + * @throws ReflectionException |
|
138 | + */ |
|
139 | + private function _item_row(EE_Line_Item $line_item, $options = []) |
|
140 | + { |
|
141 | + // start of row |
|
142 | + $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
143 | + $html = EEH_HTML::tr('', '', $row_class); |
|
144 | + // name && desc |
|
145 | + $name_and_desc = apply_filters( |
|
146 | + 'FHEE__EE_Default_Line_Item_Display_Strategy__item_row__name', |
|
147 | + $line_item->name(), |
|
148 | + $line_item |
|
149 | + ); |
|
150 | + $name_and_desc .= apply_filters( |
|
151 | + 'FHEE__EE_Default_Line_Item_Display_Strategy__item_row__desc', |
|
152 | + ($options['show_desc'] ? '<span class="line-item-desc-spn smaller-text">: ' . $line_item->desc() . '</span>' |
|
153 | + : ''), |
|
154 | + $line_item, |
|
155 | + $options |
|
156 | + ); |
|
157 | + if ($line_item->is_taxable()) { |
|
158 | + $ticket_price_includes_taxes = EE_Registry::instance()->CFG->tax_settings->prices_displayed_including_taxes |
|
159 | + ? esc_html__('* price includes taxes', 'event_espresso') |
|
160 | + : esc_html__('* price does not include taxes', 'event_espresso'); |
|
161 | + $name_and_desc .= '<span class="smaller-text lt-grey-text" style="margin:0 0 0 2em;">' |
|
162 | + . $ticket_price_includes_taxes |
|
163 | + . '</span>'; |
|
164 | + } |
|
165 | + |
|
166 | + // name td |
|
167 | + $html .= EEH_HTML::td($name_and_desc, '', 'item_l'); |
|
168 | + // quantity td |
|
169 | + $html .= EEH_HTML::td($line_item->quantity(), '', 'item_l jst-rght'); |
|
170 | + $tax_rate = $line_item->is_taxable() |
|
171 | + && EE_Registry::instance()->CFG->tax_settings->prices_displayed_including_taxes |
|
172 | + ? 1 + ($this->_tax_rate / 100) |
|
173 | + : 1; |
|
174 | + // price td |
|
175 | + // FIRST get the correctly rounded price per ticket including taxes |
|
176 | + $raw_unit_price = $this->currency_formatter->roundForLocale($line_item->unit_price() * $tax_rate); |
|
177 | + $unit_price = apply_filters( |
|
178 | + 'FHEE__EE_Default_Line_Item_Display_Strategy___item_row__unit_price', |
|
179 | + $this->currency_formatter->formatForLocale($raw_unit_price), |
|
180 | + $line_item, |
|
181 | + $tax_rate |
|
182 | + ); |
|
183 | + $html .= EEH_HTML::td($unit_price, '', 'item_c jst-rght'); |
|
184 | + // total td |
|
185 | + $total = apply_filters( |
|
186 | + 'FHEE__EE_Default_Line_Item_Display_Strategy___item_row__total', |
|
187 | + $this->currency_formatter->formatForLocale($raw_unit_price * $line_item->quantity()), |
|
188 | + $line_item, |
|
189 | + $tax_rate |
|
190 | + ); |
|
191 | + $html .= EEH_HTML::td($total, '', 'item_r jst-rght'); |
|
192 | + // end of row |
|
193 | + $html .= EEH_HTML::trx(); |
|
194 | + |
|
195 | + return $html; |
|
196 | + } |
|
197 | + |
|
198 | + |
|
199 | + /** |
|
200 | + * _sub_item_row |
|
201 | + * |
|
202 | + * @param EE_Line_Item $line_item |
|
203 | + * @param array $options |
|
204 | + * @return mixed |
|
205 | + * @throws EE_Error |
|
206 | + * @throws ReflectionException |
|
207 | + */ |
|
208 | + private function _sub_item_row(EE_Line_Item $line_item, $options = []) |
|
209 | + { |
|
210 | + // start of row |
|
211 | + $html = EEH_HTML::tr('', 'item sub-item-row'); |
|
212 | + // name && desc |
|
213 | + $name_and_desc = $line_item->name(); |
|
214 | + $name_and_desc .= $options['show_desc'] ? '<span class="line-sub-item-desc-spn smaller-text">: ' |
|
215 | + . $line_item->desc() |
|
216 | + . '</span>' : ''; |
|
217 | + // name td |
|
218 | + $html .= EEH_HTML::td(/*__FUNCTION__ .*/ $name_and_desc, '', 'item_l sub-item'); |
|
219 | + // discount/surcharge td |
|
220 | + if ($line_item->is_percent()) { |
|
221 | + $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'item_c'); |
|
222 | + } else { |
|
223 | + $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'item_c jst-rght'); |
|
224 | + } |
|
225 | + // total td |
|
226 | + $html .= EEH_HTML::td($line_item->prettyTotal(), '', 'item_r jst-rght'); |
|
227 | + // end of row |
|
228 | + $html .= EEH_HTML::trx(); |
|
229 | + return $html; |
|
230 | + } |
|
231 | 231 | } |
@@ -65,10 +65,10 @@ discard block |
||
65 | 65 | $html = ''; |
66 | 66 | // set some default options and merge with incoming |
67 | 67 | $default_options = [ |
68 | - 'show_desc' => true, // TRUE FALSE |
|
68 | + 'show_desc' => true, // TRUE FALSE |
|
69 | 69 | 'odd' => false, |
70 | 70 | ]; |
71 | - $options = array_merge($default_options, (array) $options); |
|
71 | + $options = array_merge($default_options, (array) $options); |
|
72 | 72 | |
73 | 73 | switch ($line_item->type()) { |
74 | 74 | case EEM_Line_Item::type_line_item: |
@@ -149,7 +149,7 @@ discard block |
||
149 | 149 | ); |
150 | 150 | $name_and_desc .= apply_filters( |
151 | 151 | 'FHEE__EE_Default_Line_Item_Display_Strategy__item_row__desc', |
152 | - ($options['show_desc'] ? '<span class="line-item-desc-spn smaller-text">: ' . $line_item->desc() . '</span>' |
|
152 | + ($options['show_desc'] ? '<span class="line-item-desc-spn smaller-text">: '.$line_item->desc().'</span>' |
|
153 | 153 | : ''), |
154 | 154 | $line_item, |
155 | 155 | $options |
@@ -166,7 +166,7 @@ discard block |
||
166 | 166 | // name td |
167 | 167 | $html .= EEH_HTML::td($name_and_desc, '', 'item_l'); |
168 | 168 | // quantity td |
169 | - $html .= EEH_HTML::td($line_item->quantity(), '', 'item_l jst-rght'); |
|
169 | + $html .= EEH_HTML::td($line_item->quantity(), '', 'item_l jst-rght'); |
|
170 | 170 | $tax_rate = $line_item->is_taxable() |
171 | 171 | && EE_Registry::instance()->CFG->tax_settings->prices_displayed_including_taxes |
172 | 172 | ? 1 + ($this->_tax_rate / 100) |
@@ -180,7 +180,7 @@ discard block |
||
180 | 180 | $line_item, |
181 | 181 | $tax_rate |
182 | 182 | ); |
183 | - $html .= EEH_HTML::td($unit_price, '', 'item_c jst-rght'); |
|
183 | + $html .= EEH_HTML::td($unit_price, '', 'item_c jst-rght'); |
|
184 | 184 | // total td |
185 | 185 | $total = apply_filters( |
186 | 186 | 'FHEE__EE_Default_Line_Item_Display_Strategy___item_row__total', |
@@ -188,7 +188,7 @@ discard block |
||
188 | 188 | $line_item, |
189 | 189 | $tax_rate |
190 | 190 | ); |
191 | - $html .= EEH_HTML::td($total, '', 'item_r jst-rght'); |
|
191 | + $html .= EEH_HTML::td($total, '', 'item_r jst-rght'); |
|
192 | 192 | // end of row |
193 | 193 | $html .= EEH_HTML::trx(); |
194 | 194 |
@@ -75,15 +75,15 @@ discard block |
||
75 | 75 | : $line_item->name(); |
76 | 76 | |
77 | 77 | $name_html = $name_link |
78 | - ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
78 | + ? '<a href="'.$name_link.'">'.$name_html.'</a>' |
|
79 | 79 | : $name_html; |
80 | 80 | |
81 | 81 | $name_html .= $line_item->is_taxable() ? ' *' : ''; |
82 | 82 | // maybe preface with icon? |
83 | 83 | $name_html = $line_item_related_object instanceof EEI_Has_Icon |
84 | - ? $line_item_related_object->get_icon() . $name_html |
|
84 | + ? $line_item_related_object->get_icon().$name_html |
|
85 | 85 | : $name_html; |
86 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
86 | + $name_html = '<span class="ee-line-item-name linked">'.$name_html.'</span><br>'; |
|
87 | 87 | $name_html .= sprintf( |
88 | 88 | _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
89 | 89 | '<span class="ee-line-item-related-parent-object">', |
@@ -91,7 +91,7 @@ discard block |
||
91 | 91 | ? $line_item->parent()->OBJ_type_i18n() |
92 | 92 | : esc_html__('Item:', 'event_espresso'), |
93 | 93 | $parent_related_object_link |
94 | - ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
94 | + ? '<a href="'.$parent_related_object_link.'">'.$parent_related_object_name.'</a>' |
|
95 | 95 | : $parent_related_object_name, |
96 | 96 | '</span>' |
97 | 97 | ); |
@@ -110,7 +110,7 @@ discard block |
||
110 | 110 | $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
111 | 111 | $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
112 | 112 | $type_html .= ! empty($code) |
113 | - ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' |
|
113 | + ? '<span class="ee-line-item-id">'.sprintf(esc_html__('Code: %s', 'event_espresso'), $code).'</span>' |
|
114 | 114 | : ''; |
115 | 115 | $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
116 | 116 | |
@@ -120,7 +120,7 @@ discard block |
||
120 | 120 | $datetimes = $line_item_related_object->datetimes(); |
121 | 121 | foreach ($datetimes as $datetime) { |
122 | 122 | if ($datetime instanceof EE_Datetime) { |
123 | - $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
123 | + $datetime_content .= $datetime->get_dtt_display_name().'<br>'; |
|
124 | 124 | } |
125 | 125 | } |
126 | 126 | } |
@@ -154,7 +154,7 @@ discard block |
||
154 | 154 | $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
155 | 155 | // name th |
156 | 156 | $html .= EEH_HTML::th( |
157 | - $line_item->name() . '(' . $line_item->prettyPercent() . ')', |
|
157 | + $line_item->name().'('.$line_item->prettyPercent().')', |
|
158 | 158 | '', |
159 | 159 | 'jst-rght', |
160 | 160 | '', |
@@ -193,12 +193,12 @@ discard block |
||
193 | 193 | if ($total_match) { |
194 | 194 | $total_label = sprintf( |
195 | 195 | esc_html__('This registration\'s total %s:', 'event_espresso'), |
196 | - '(' . $currency_code . ')' |
|
196 | + '('.$currency_code.')' |
|
197 | 197 | ); |
198 | 198 | } else { |
199 | 199 | $total_label = sprintf( |
200 | 200 | esc_html__('This registration\'s approximate total %s', 'event_espresso'), |
201 | - '(' . $currency_code . ')' |
|
201 | + '('.$currency_code.')' |
|
202 | 202 | ); |
203 | 203 | $total_label .= '<br>'; |
204 | 204 | $total_label .= '<p class="ee-footnote-text">' |
@@ -14,212 +14,212 @@ |
||
14 | 14 | class EE_Admin_Table_Registration_Line_Item_Display_Strategy extends EE_Admin_Table_Line_Item_Display_Strategy |
15 | 15 | { |
16 | 16 | |
17 | - /** |
|
18 | - * Table header for display. |
|
19 | - * |
|
20 | - * @param array $options |
|
21 | - * @return string |
|
22 | - * @since 4.8 |
|
23 | - */ |
|
24 | - protected function _table_header($options) |
|
25 | - { |
|
26 | - $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
27 | - $html .= EEH_HTML::thead(); |
|
28 | - $html .= EEH_HTML::tr(); |
|
29 | - $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
30 | - $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
31 | - $html .= EEH_HTML::th(esc_html__('Date(s)', 'event_espresso'), '', 'jst-left'); |
|
32 | - $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
33 | - $html .= EEH_HTML::tbody(); |
|
34 | - return $html; |
|
35 | - } |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * _item_row |
|
40 | - * |
|
41 | - * @param EE_Line_Item $line_item |
|
42 | - * @param array $options |
|
43 | - * @return mixed |
|
44 | - * @throws EE_Error |
|
45 | - * @throws ReflectionException |
|
46 | - */ |
|
47 | - protected function _item_row(EE_Line_Item $line_item, $options = []) |
|
48 | - { |
|
49 | - $line_item_related_object = $line_item->get_object(); |
|
50 | - $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item |
|
51 | - ? $line_item->parent()->get_object() |
|
52 | - : null; |
|
53 | - // start of row |
|
54 | - $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
55 | - $html = EEH_HTML::tr('', '', $row_class); |
|
56 | - |
|
57 | - |
|
58 | - // Name Column |
|
59 | - $name_link = $line_item_related_object instanceof EEI_Admin_Links |
|
60 | - ? $line_item_related_object->get_admin_details_link() |
|
61 | - : ''; |
|
62 | - |
|
63 | - // related object scope. |
|
64 | - $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object |
|
65 | - ? $parent_line_item_related_object->name() |
|
66 | - : ''; |
|
67 | - $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item |
|
68 | - ? $line_item->parent()->name() |
|
69 | - : $parent_related_object_name; |
|
70 | - $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links |
|
71 | - ? $parent_line_item_related_object->get_admin_details_link() |
|
72 | - : ''; |
|
73 | - |
|
74 | - $name_html = $line_item_related_object instanceof EEI_Line_Item_Object |
|
75 | - ? $line_item_related_object->name() |
|
76 | - : $line_item->name(); |
|
77 | - |
|
78 | - $name_html = $name_link |
|
79 | - ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
80 | - : $name_html; |
|
81 | - |
|
82 | - $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
83 | - // maybe preface with icon? |
|
84 | - $name_html = $line_item_related_object instanceof EEI_Has_Icon |
|
85 | - ? $line_item_related_object->get_icon() . $name_html |
|
86 | - : $name_html; |
|
87 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
88 | - $name_html .= sprintf( |
|
89 | - _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
90 | - '<span class="ee-line-item-related-parent-object">', |
|
91 | - $line_item->parent() instanceof EE_Line_Item |
|
92 | - ? $line_item->parent()->OBJ_type_i18n() |
|
93 | - : esc_html__('Item:', 'event_espresso'), |
|
94 | - $parent_related_object_link |
|
95 | - ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
96 | - : $parent_related_object_name, |
|
97 | - '</span>' |
|
98 | - ); |
|
99 | - |
|
100 | - $name_html = apply_filters( |
|
101 | - 'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html', |
|
102 | - $name_html, |
|
103 | - $line_item, |
|
104 | - $options |
|
105 | - ); |
|
106 | - |
|
107 | - $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
108 | - // Type Column |
|
109 | - $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
110 | - $type_html .= $this->_get_cancellations($line_item); |
|
111 | - $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
112 | - $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
113 | - $type_html .= ! empty($code) |
|
114 | - ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' |
|
115 | - : ''; |
|
116 | - $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
117 | - |
|
118 | - // Date column |
|
119 | - $datetime_content = ''; |
|
120 | - if ($line_item_related_object instanceof EE_Ticket) { |
|
121 | - $datetimes = $line_item_related_object->datetimes(); |
|
122 | - foreach ($datetimes as $datetime) { |
|
123 | - if ($datetime instanceof EE_Datetime) { |
|
124 | - $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
125 | - } |
|
126 | - } |
|
127 | - } |
|
128 | - $html .= EEH_HTML::td($datetime_content, '', 'jst-left'); |
|
129 | - |
|
130 | - // Amount Column |
|
131 | - if ($line_item->is_percent()) { |
|
132 | - $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'jst-rght'); |
|
133 | - } else { |
|
134 | - $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'jst-rght'); |
|
135 | - } |
|
136 | - |
|
137 | - // finish things off and return |
|
138 | - $html .= EEH_HTML::trx(); |
|
139 | - return $html; |
|
140 | - } |
|
141 | - |
|
142 | - |
|
143 | - /** |
|
144 | - * _tax_row |
|
145 | - * |
|
146 | - * @param EE_Line_Item $line_item |
|
147 | - * @param array $options |
|
148 | - * @return mixed |
|
149 | - * @throws EE_Error |
|
150 | - * @throws ReflectionException |
|
151 | - */ |
|
152 | - protected function _tax_row(EE_Line_Item $line_item, $options = []) |
|
153 | - { |
|
154 | - // start of row |
|
155 | - $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
156 | - // name th |
|
157 | - $html .= EEH_HTML::th( |
|
158 | - $line_item->name() . '(' . $line_item->prettyPercent() . ')', |
|
159 | - '', |
|
160 | - 'jst-rght', |
|
161 | - '', |
|
162 | - ' colspan="3"' |
|
163 | - ); |
|
164 | - // total th |
|
165 | - $html .= EEH_HTML::th($line_item->prettyTotal(), '', 'jst-rght'); |
|
166 | - // end of row |
|
167 | - $html .= EEH_HTML::trx(); |
|
168 | - return $html; |
|
169 | - } |
|
170 | - |
|
171 | - |
|
172 | - /** |
|
173 | - * _total_row |
|
174 | - * |
|
175 | - * @param EE_Line_Item $line_item |
|
176 | - * @param array $options |
|
177 | - * @return mixed |
|
178 | - * @throws EE_Error |
|
179 | - * @throws ReflectionException |
|
180 | - */ |
|
181 | - protected function _total_row(EE_Line_Item $line_item, $options = []) |
|
182 | - { |
|
183 | - $currency_code = $this->currency_formatter->getCurrencyIsoCodeForLocale(); |
|
184 | - $registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null; |
|
185 | - $registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0; |
|
186 | - // if no valid registration object then we're not going to show the approximate text. |
|
187 | - $total_match = $registration instanceof EE_Registration |
|
188 | - ? $registration->final_price() === $line_item->total() |
|
189 | - : true; |
|
190 | - |
|
191 | - // start of row |
|
192 | - $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
193 | - // Total th label |
|
194 | - if ($total_match) { |
|
195 | - $total_label = sprintf( |
|
196 | - esc_html__('This registration\'s total %s:', 'event_espresso'), |
|
197 | - '(' . $currency_code . ')' |
|
198 | - ); |
|
199 | - } else { |
|
200 | - $total_label = sprintf( |
|
201 | - esc_html__('This registration\'s approximate total %s', 'event_espresso'), |
|
202 | - '(' . $currency_code . ')' |
|
203 | - ); |
|
204 | - $total_label .= '<br>'; |
|
205 | - $total_label .= '<p class="ee-footnote-text">' |
|
206 | - . sprintf( |
|
207 | - esc_html__( |
|
208 | - 'The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others. This registration\'s final share is actually %1$s%2$s%3$s.', |
|
209 | - 'event_espresso' |
|
210 | - ), |
|
211 | - '<strong>', |
|
212 | - $registration_total, |
|
213 | - '</strong>' |
|
214 | - ) |
|
215 | - . '</p>'; |
|
216 | - } |
|
217 | - $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"'); |
|
218 | - // total th |
|
219 | - |
|
220 | - $html .= EEH_HTML::th($line_item->prettyTotal(), '', 'jst-rght'); |
|
221 | - // end of row |
|
222 | - $html .= EEH_HTML::trx(); |
|
223 | - return $html; |
|
224 | - } |
|
17 | + /** |
|
18 | + * Table header for display. |
|
19 | + * |
|
20 | + * @param array $options |
|
21 | + * @return string |
|
22 | + * @since 4.8 |
|
23 | + */ |
|
24 | + protected function _table_header($options) |
|
25 | + { |
|
26 | + $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
27 | + $html .= EEH_HTML::thead(); |
|
28 | + $html .= EEH_HTML::tr(); |
|
29 | + $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
30 | + $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
31 | + $html .= EEH_HTML::th(esc_html__('Date(s)', 'event_espresso'), '', 'jst-left'); |
|
32 | + $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
33 | + $html .= EEH_HTML::tbody(); |
|
34 | + return $html; |
|
35 | + } |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * _item_row |
|
40 | + * |
|
41 | + * @param EE_Line_Item $line_item |
|
42 | + * @param array $options |
|
43 | + * @return mixed |
|
44 | + * @throws EE_Error |
|
45 | + * @throws ReflectionException |
|
46 | + */ |
|
47 | + protected function _item_row(EE_Line_Item $line_item, $options = []) |
|
48 | + { |
|
49 | + $line_item_related_object = $line_item->get_object(); |
|
50 | + $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item |
|
51 | + ? $line_item->parent()->get_object() |
|
52 | + : null; |
|
53 | + // start of row |
|
54 | + $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
55 | + $html = EEH_HTML::tr('', '', $row_class); |
|
56 | + |
|
57 | + |
|
58 | + // Name Column |
|
59 | + $name_link = $line_item_related_object instanceof EEI_Admin_Links |
|
60 | + ? $line_item_related_object->get_admin_details_link() |
|
61 | + : ''; |
|
62 | + |
|
63 | + // related object scope. |
|
64 | + $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object |
|
65 | + ? $parent_line_item_related_object->name() |
|
66 | + : ''; |
|
67 | + $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item |
|
68 | + ? $line_item->parent()->name() |
|
69 | + : $parent_related_object_name; |
|
70 | + $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links |
|
71 | + ? $parent_line_item_related_object->get_admin_details_link() |
|
72 | + : ''; |
|
73 | + |
|
74 | + $name_html = $line_item_related_object instanceof EEI_Line_Item_Object |
|
75 | + ? $line_item_related_object->name() |
|
76 | + : $line_item->name(); |
|
77 | + |
|
78 | + $name_html = $name_link |
|
79 | + ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
80 | + : $name_html; |
|
81 | + |
|
82 | + $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
83 | + // maybe preface with icon? |
|
84 | + $name_html = $line_item_related_object instanceof EEI_Has_Icon |
|
85 | + ? $line_item_related_object->get_icon() . $name_html |
|
86 | + : $name_html; |
|
87 | + $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
88 | + $name_html .= sprintf( |
|
89 | + _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
90 | + '<span class="ee-line-item-related-parent-object">', |
|
91 | + $line_item->parent() instanceof EE_Line_Item |
|
92 | + ? $line_item->parent()->OBJ_type_i18n() |
|
93 | + : esc_html__('Item:', 'event_espresso'), |
|
94 | + $parent_related_object_link |
|
95 | + ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
96 | + : $parent_related_object_name, |
|
97 | + '</span>' |
|
98 | + ); |
|
99 | + |
|
100 | + $name_html = apply_filters( |
|
101 | + 'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html', |
|
102 | + $name_html, |
|
103 | + $line_item, |
|
104 | + $options |
|
105 | + ); |
|
106 | + |
|
107 | + $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
108 | + // Type Column |
|
109 | + $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
110 | + $type_html .= $this->_get_cancellations($line_item); |
|
111 | + $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
112 | + $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
113 | + $type_html .= ! empty($code) |
|
114 | + ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' |
|
115 | + : ''; |
|
116 | + $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
117 | + |
|
118 | + // Date column |
|
119 | + $datetime_content = ''; |
|
120 | + if ($line_item_related_object instanceof EE_Ticket) { |
|
121 | + $datetimes = $line_item_related_object->datetimes(); |
|
122 | + foreach ($datetimes as $datetime) { |
|
123 | + if ($datetime instanceof EE_Datetime) { |
|
124 | + $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
125 | + } |
|
126 | + } |
|
127 | + } |
|
128 | + $html .= EEH_HTML::td($datetime_content, '', 'jst-left'); |
|
129 | + |
|
130 | + // Amount Column |
|
131 | + if ($line_item->is_percent()) { |
|
132 | + $html .= EEH_HTML::td($line_item->prettyPercent(), '', 'jst-rght'); |
|
133 | + } else { |
|
134 | + $html .= EEH_HTML::td($line_item->prettyUnitPrice(), '', 'jst-rght'); |
|
135 | + } |
|
136 | + |
|
137 | + // finish things off and return |
|
138 | + $html .= EEH_HTML::trx(); |
|
139 | + return $html; |
|
140 | + } |
|
141 | + |
|
142 | + |
|
143 | + /** |
|
144 | + * _tax_row |
|
145 | + * |
|
146 | + * @param EE_Line_Item $line_item |
|
147 | + * @param array $options |
|
148 | + * @return mixed |
|
149 | + * @throws EE_Error |
|
150 | + * @throws ReflectionException |
|
151 | + */ |
|
152 | + protected function _tax_row(EE_Line_Item $line_item, $options = []) |
|
153 | + { |
|
154 | + // start of row |
|
155 | + $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
156 | + // name th |
|
157 | + $html .= EEH_HTML::th( |
|
158 | + $line_item->name() . '(' . $line_item->prettyPercent() . ')', |
|
159 | + '', |
|
160 | + 'jst-rght', |
|
161 | + '', |
|
162 | + ' colspan="3"' |
|
163 | + ); |
|
164 | + // total th |
|
165 | + $html .= EEH_HTML::th($line_item->prettyTotal(), '', 'jst-rght'); |
|
166 | + // end of row |
|
167 | + $html .= EEH_HTML::trx(); |
|
168 | + return $html; |
|
169 | + } |
|
170 | + |
|
171 | + |
|
172 | + /** |
|
173 | + * _total_row |
|
174 | + * |
|
175 | + * @param EE_Line_Item $line_item |
|
176 | + * @param array $options |
|
177 | + * @return mixed |
|
178 | + * @throws EE_Error |
|
179 | + * @throws ReflectionException |
|
180 | + */ |
|
181 | + protected function _total_row(EE_Line_Item $line_item, $options = []) |
|
182 | + { |
|
183 | + $currency_code = $this->currency_formatter->getCurrencyIsoCodeForLocale(); |
|
184 | + $registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null; |
|
185 | + $registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0; |
|
186 | + // if no valid registration object then we're not going to show the approximate text. |
|
187 | + $total_match = $registration instanceof EE_Registration |
|
188 | + ? $registration->final_price() === $line_item->total() |
|
189 | + : true; |
|
190 | + |
|
191 | + // start of row |
|
192 | + $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
193 | + // Total th label |
|
194 | + if ($total_match) { |
|
195 | + $total_label = sprintf( |
|
196 | + esc_html__('This registration\'s total %s:', 'event_espresso'), |
|
197 | + '(' . $currency_code . ')' |
|
198 | + ); |
|
199 | + } else { |
|
200 | + $total_label = sprintf( |
|
201 | + esc_html__('This registration\'s approximate total %s', 'event_espresso'), |
|
202 | + '(' . $currency_code . ')' |
|
203 | + ); |
|
204 | + $total_label .= '<br>'; |
|
205 | + $total_label .= '<p class="ee-footnote-text">' |
|
206 | + . sprintf( |
|
207 | + esc_html__( |
|
208 | + 'The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others. This registration\'s final share is actually %1$s%2$s%3$s.', |
|
209 | + 'event_espresso' |
|
210 | + ), |
|
211 | + '<strong>', |
|
212 | + $registration_total, |
|
213 | + '</strong>' |
|
214 | + ) |
|
215 | + . '</p>'; |
|
216 | + } |
|
217 | + $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"'); |
|
218 | + // total th |
|
219 | + |
|
220 | + $html .= EEH_HTML::th($line_item->prettyTotal(), '', 'jst-rght'); |
|
221 | + // end of row |
|
222 | + $html .= EEH_HTML::trx(); |
|
223 | + return $html; |
|
224 | + } |
|
225 | 225 | } |
@@ -126,7 +126,7 @@ discard block |
||
126 | 126 | self::priority_low => esc_html__('low', 'event_espresso'), |
127 | 127 | ); |
128 | 128 | |
129 | - $this->_fields = array( |
|
129 | + $this->_fields = array( |
|
130 | 130 | 'Message' => array( |
131 | 131 | 'MSG_ID' => new EE_Primary_Key_Int_Field('MSG_ID', esc_html__('Message ID', 'event_espresso')), |
132 | 132 | 'MSG_token' => new EE_Plain_Text_Field( |
@@ -436,7 +436,7 @@ discard block |
||
436 | 436 | ); |
437 | 437 | break; |
438 | 438 | default: |
439 | - $query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value; |
|
439 | + $query_params[0]['AND**filter_by']['OR**filter_by_'.$request_key][$model_name.'.'.$request_key] = $request_value; |
|
440 | 440 | break; |
441 | 441 | } |
442 | 442 | } |
@@ -499,8 +499,8 @@ discard block |
||
499 | 499 | if ($label_parts) { |
500 | 500 | // prepend to the last element of $label_parts an "and". |
501 | 501 | if (count($label_parts) > 1) { |
502 | - $label_parts_index_to_prepend = count($label_parts) - 1; |
|
503 | - $label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ]; |
|
502 | + $label_parts_index_to_prepend = count($label_parts) - 1; |
|
503 | + $label_parts[$label_parts_index_to_prepend] = 'and'.$label_parts[$label_parts_index_to_prepend]; |
|
504 | 504 | } |
505 | 505 | |
506 | 506 | $pretty_label .= sprintf( |
@@ -560,7 +560,7 @@ discard block |
||
560 | 560 | $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES; |
561 | 561 | } |
562 | 562 | |
563 | - if (! is_null($set_debug)) { |
|
563 | + if ( ! is_null($set_debug)) { |
|
564 | 564 | $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN); |
565 | 565 | } |
566 | 566 | |
@@ -627,13 +627,13 @@ discard block |
||
627 | 627 | ) |
628 | 628 | ); |
629 | 629 | |
630 | - if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) { |
|
630 | + if ( ! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) { |
|
631 | 631 | global $wpdb; |
632 | 632 | $number_deleted = $wpdb->query(' |
633 | 633 | DELETE |
634 | - FROM ' . $this->table() . ' |
|
634 | + FROM ' . $this->table().' |
|
635 | 635 | WHERE |
636 | - MSG_ID IN (' . implode(",", $message_ids_to_delete) . ') |
|
636 | + MSG_ID IN (' . implode(",", $message_ids_to_delete).') |
|
637 | 637 | '); |
638 | 638 | } |
639 | 639 |
@@ -12,649 +12,649 @@ |
||
12 | 12 | */ |
13 | 13 | class EEM_Message extends EEM_Base implements EEI_Query_Filter |
14 | 14 | { |
15 | - // private instance of the Message object |
|
16 | - protected static $_instance = null; |
|
17 | - |
|
18 | - |
|
19 | - /** |
|
20 | - * This priority indicates a message should be generated and sent ASAP |
|
21 | - * |
|
22 | - * @type int |
|
23 | - */ |
|
24 | - const priority_high = 10; |
|
25 | - |
|
26 | - |
|
27 | - /** |
|
28 | - * This priority indicates a message should be generated ASAP and queued for sending. |
|
29 | - * |
|
30 | - * @type |
|
31 | - */ |
|
32 | - const priority_medium = 20; |
|
33 | - |
|
34 | - |
|
35 | - /** |
|
36 | - * This priority indicates a message should be queued for generating. |
|
37 | - * |
|
38 | - * @type int |
|
39 | - */ |
|
40 | - const priority_low = 30; |
|
41 | - |
|
42 | - |
|
43 | - /** |
|
44 | - * indicates this message was sent at the time modified |
|
45 | - */ |
|
46 | - const status_sent = 'MSN'; |
|
47 | - |
|
48 | - |
|
49 | - /** |
|
50 | - * indicates this message is waiting to be sent |
|
51 | - */ |
|
52 | - const status_idle = 'MID'; |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * indicates an attempt was a made to send this message |
|
57 | - * at the scheduled time, but it failed at the time modified. This differs from MDO status in that it will ALWAYS |
|
58 | - * appear to the end user. |
|
59 | - */ |
|
60 | - const status_failed = 'MFL'; |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * indicates the message has been flagged for resending (at the time modified). |
|
65 | - */ |
|
66 | - const status_resend = 'MRS'; |
|
67 | - |
|
68 | - |
|
69 | - /** |
|
70 | - * indicates the message has been flagged for generation but has not been generated yet. Messages always start as |
|
71 | - * this status when added to the queue. |
|
72 | - */ |
|
73 | - const status_incomplete = 'MIC'; |
|
74 | - |
|
75 | - |
|
76 | - /** |
|
77 | - * Indicates everything was generated fine for the message, however, the messenger was unable to send. |
|
78 | - * This status means that its possible to retry sending the message. |
|
79 | - */ |
|
80 | - const status_retry = 'MRT'; |
|
81 | - |
|
82 | - |
|
83 | - /** |
|
84 | - * This is used for more informational messages that may not indicate anything is broken but still cannot be |
|
85 | - * generated or sent correctly. An example of a message that would get flagged this way would be when a not |
|
86 | - * approved message was queued for generation, but at time of generation, the attached registration(s) are |
|
87 | - * approved. So the message queued for generation is no longer valid. Messages for this status will only persist |
|
88 | - * in the db and be viewable in the message activity list table when the messages system is in debug mode. |
|
89 | - * |
|
90 | - * @see EEM_Message::debug() |
|
91 | - */ |
|
92 | - const status_debug_only = 'MDO'; |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * This status is given to messages it is processed by the messenger send method. |
|
97 | - * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually |
|
98 | - * indicative of a PHP timeout or memory limit issue. |
|
99 | - */ |
|
100 | - const status_messenger_executing = 'MEX'; |
|
101 | - |
|
102 | - |
|
103 | - /** |
|
104 | - * Private constructor to prevent direct creation. |
|
105 | - * |
|
106 | - * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and |
|
107 | - * any incoming timezone data that gets saved). Note this just sends the timezone info to |
|
108 | - * the date time model field objects. Default is null (and will be assumed using the set |
|
109 | - * timezone in the 'timezone_string' wp option) |
|
110 | - * @throws EE_Error |
|
111 | - * @throws EE_Error |
|
112 | - * @throws EE_Error |
|
113 | - */ |
|
114 | - protected function __construct($timezone = null) |
|
115 | - { |
|
116 | - $this->singular_item = esc_html__('Message', 'event_espresso'); |
|
117 | - $this->plural_item = esc_html__('Messages', 'event_espresso'); |
|
118 | - |
|
119 | - $this->_tables = array( |
|
120 | - 'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'), |
|
121 | - ); |
|
122 | - |
|
123 | - $allowed_priority = array( |
|
124 | - self::priority_high => esc_html__('high', 'event_espresso'), |
|
125 | - self::priority_medium => esc_html__('medium', 'event_espresso'), |
|
126 | - self::priority_low => esc_html__('low', 'event_espresso'), |
|
127 | - ); |
|
128 | - |
|
129 | - $this->_fields = array( |
|
130 | - 'Message' => array( |
|
131 | - 'MSG_ID' => new EE_Primary_Key_Int_Field('MSG_ID', esc_html__('Message ID', 'event_espresso')), |
|
132 | - 'MSG_token' => new EE_Plain_Text_Field( |
|
133 | - 'MSG_token', |
|
134 | - esc_html__( |
|
135 | - 'Unique Token used to represent this row in publicly viewable contexts (eg. a url).', |
|
136 | - 'event_espresso' |
|
137 | - ), |
|
138 | - false, |
|
139 | - EEH_URL::generate_unique_token() |
|
140 | - ), |
|
141 | - 'GRP_ID' => new EE_Foreign_Key_Int_Field( |
|
142 | - 'GRP_ID', |
|
143 | - esc_html__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'), |
|
144 | - true, |
|
145 | - 0, |
|
146 | - 'Message_Template_Group' |
|
147 | - ), |
|
148 | - 'TXN_ID' => new EE_Foreign_Key_Int_Field( |
|
149 | - 'TXN_ID', |
|
150 | - esc_html__( |
|
151 | - 'Foreign key to the related EE_Transaction. This is required to give context for regenerating the specific message', |
|
152 | - 'event_espresso' |
|
153 | - ), |
|
154 | - true, |
|
155 | - 0, |
|
156 | - 'Transaction' |
|
157 | - ), |
|
158 | - 'MSG_messenger' => new EE_Plain_Text_Field( |
|
159 | - 'MSG_messenger', |
|
160 | - esc_html__( |
|
161 | - 'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.', |
|
162 | - 'event_espresso' |
|
163 | - ), |
|
164 | - false, |
|
165 | - 'email' |
|
166 | - ), |
|
167 | - 'MSG_message_type' => new EE_Plain_Text_Field( |
|
168 | - 'MSG_message_type', |
|
169 | - esc_html__('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'), |
|
170 | - false, |
|
171 | - 'receipt' |
|
172 | - ), |
|
173 | - 'MSG_context' => new EE_Plain_Text_Field('MSG_context', esc_html__('Context', 'event_espresso'), false), |
|
174 | - 'MSG_recipient_ID' => new EE_Foreign_Key_Int_Field( |
|
175 | - 'MSG_recipient_ID', |
|
176 | - esc_html__('Recipient ID', 'event_espresso'), |
|
177 | - true, |
|
178 | - null, |
|
179 | - array('Registration', 'Attendee', 'WP_User') |
|
180 | - ), |
|
181 | - 'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field( |
|
182 | - 'MSG_recipient_type', |
|
183 | - esc_html__('Recipient Type', 'event_espresso'), |
|
184 | - true, |
|
185 | - null, |
|
186 | - array('Registration', 'Attendee', 'WP_User') |
|
187 | - ), |
|
188 | - 'MSG_content' => new EE_Maybe_Serialized_Text_Field( |
|
189 | - 'MSG_content', |
|
190 | - esc_html__('Content', 'event_espresso'), |
|
191 | - true, |
|
192 | - '' |
|
193 | - ), |
|
194 | - 'MSG_to' => new EE_Maybe_Serialized_Text_Field( |
|
195 | - 'MSG_to', |
|
196 | - esc_html__('Address To', 'event_espresso'), |
|
197 | - true |
|
198 | - ), |
|
199 | - 'MSG_from' => new EE_Maybe_Serialized_Text_Field( |
|
200 | - 'MSG_from', |
|
201 | - esc_html__('Address From', 'event_espresso'), |
|
202 | - true |
|
203 | - ), |
|
204 | - 'MSG_subject' => new EE_Maybe_Serialized_Text_Field( |
|
205 | - 'MSG_subject', |
|
206 | - esc_html__('Subject', 'event_espresso'), |
|
207 | - true, |
|
208 | - '' |
|
209 | - ), |
|
210 | - 'MSG_priority' => new EE_Enum_Integer_Field( |
|
211 | - 'MSG_priority', |
|
212 | - esc_html__('Priority', 'event_espresso'), |
|
213 | - false, |
|
214 | - self::priority_low, |
|
215 | - $allowed_priority |
|
216 | - ), |
|
217 | - 'STS_ID' => new EE_Foreign_Key_String_Field( |
|
218 | - 'STS_ID', |
|
219 | - esc_html__('Status', 'event_espresso'), |
|
220 | - false, |
|
221 | - self::status_incomplete, |
|
222 | - 'Status' |
|
223 | - ), |
|
224 | - 'MSG_created' => new EE_Datetime_Field( |
|
225 | - 'MSG_created', |
|
226 | - esc_html__('Created', 'event_espresso'), |
|
227 | - false, |
|
228 | - EE_Datetime_Field::now |
|
229 | - ), |
|
230 | - 'MSG_modified' => new EE_Datetime_Field( |
|
231 | - 'MSG_modified', |
|
232 | - esc_html__('Modified', 'event_espresso'), |
|
233 | - true, |
|
234 | - EE_Datetime_Field::now |
|
235 | - ), |
|
236 | - ), |
|
237 | - ); |
|
238 | - $this->_model_relations = array( |
|
239 | - 'Attendee' => new EE_Belongs_To_Any_Relation(), |
|
240 | - 'Registration' => new EE_Belongs_To_Any_Relation(), |
|
241 | - 'WP_User' => new EE_Belongs_To_Any_Relation(), |
|
242 | - 'Message_Template_Group' => new EE_Belongs_To_Relation(), |
|
243 | - 'Transaction' => new EE_Belongs_To_Relation(), |
|
244 | - ); |
|
245 | - parent::__construct($timezone); |
|
246 | - } |
|
247 | - |
|
248 | - |
|
249 | - /** |
|
250 | - * @return EE_Message |
|
251 | - * @throws EE_Error |
|
252 | - */ |
|
253 | - public function create_default_object() |
|
254 | - { |
|
255 | - /** @type EE_Message $message */ |
|
256 | - $message = parent::create_default_object(); |
|
257 | - if ($message instanceof EE_Message) { |
|
258 | - return EE_Message_Factory::set_messenger_and_message_type($message); |
|
259 | - } |
|
260 | - return null; |
|
261 | - } |
|
262 | - |
|
263 | - |
|
264 | - /** |
|
265 | - * @param mixed $cols_n_values |
|
266 | - * @return EE_Message |
|
267 | - * @throws EE_Error |
|
268 | - * @throws EE_Error |
|
269 | - */ |
|
270 | - public function instantiate_class_from_array_or_object($cols_n_values) |
|
271 | - { |
|
272 | - /** @type EE_Message $message */ |
|
273 | - $message = parent::instantiate_class_from_array_or_object($cols_n_values); |
|
274 | - if ($message instanceof EE_Message) { |
|
275 | - return EE_Message_Factory::set_messenger_and_message_type($message); |
|
276 | - } |
|
277 | - return null; |
|
278 | - } |
|
279 | - |
|
280 | - |
|
281 | - /** |
|
282 | - * Returns whether or not a message of that type was sent for a given attendee. |
|
283 | - * |
|
284 | - * @param EE_Attendee|int $attendee |
|
285 | - * @param string $message_type the message type slug |
|
286 | - * @return boolean |
|
287 | - * @throws EE_Error |
|
288 | - * @throws EE_Error |
|
289 | - * @throws EE_Error |
|
290 | - */ |
|
291 | - public function message_sent_for_attendee($attendee, $message_type) |
|
292 | - { |
|
293 | - $attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee); |
|
294 | - return $this->exists(array( |
|
295 | - array( |
|
296 | - 'Attendee.ATT_ID' => $attendee_ID, |
|
297 | - 'MSG_message_type' => $message_type, |
|
298 | - 'STS_ID' => array('IN', $this->stati_indicating_sent()), |
|
299 | - ), |
|
300 | - )); |
|
301 | - } |
|
302 | - |
|
303 | - |
|
304 | - /** |
|
305 | - * Returns whether or not a message of that type was sent for a given registration |
|
306 | - * |
|
307 | - * @param EE_Registration|int $registration |
|
308 | - * @param string $message_type the message type slug |
|
309 | - * @return boolean |
|
310 | - * @throws EE_Error |
|
311 | - * @throws EE_Error |
|
312 | - * @throws EE_Error |
|
313 | - */ |
|
314 | - public function message_sent_for_registration($registration, $message_type) |
|
315 | - { |
|
316 | - $registrationID = EEM_Registration::instance()->ensure_is_ID($registration); |
|
317 | - return $this->exists(array( |
|
318 | - array( |
|
319 | - 'Registration.REG_ID' => $registrationID, |
|
320 | - 'MSG_message_type' => $message_type, |
|
321 | - 'STS_ID' => array('IN', $this->stati_indicating_sent()), |
|
322 | - ), |
|
323 | - )); |
|
324 | - } |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * This retrieves an EE_Message object from the db matching the given token string. |
|
329 | - * |
|
330 | - * @param string $token |
|
331 | - * @return EE_Message |
|
332 | - * @throws EE_Error |
|
333 | - */ |
|
334 | - public function get_one_by_token($token) |
|
335 | - { |
|
336 | - return $this->get_one(array( |
|
337 | - array( |
|
338 | - 'MSG_token' => $token, |
|
339 | - ), |
|
340 | - )); |
|
341 | - } |
|
342 | - |
|
343 | - |
|
344 | - /** |
|
345 | - * Returns stati that indicate the message HAS been sent |
|
346 | - * |
|
347 | - * @return array of strings for possible stati |
|
348 | - */ |
|
349 | - public function stati_indicating_sent() |
|
350 | - { |
|
351 | - return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent)); |
|
352 | - } |
|
353 | - |
|
354 | - |
|
355 | - /** |
|
356 | - * Returns stati that indicate the message is waiting to be sent. |
|
357 | - * |
|
358 | - * @return array of strings for possible stati. |
|
359 | - */ |
|
360 | - public function stati_indicating_to_send() |
|
361 | - { |
|
362 | - return apply_filters( |
|
363 | - 'FHEE__EEM_Message__stati_indicating_to_send', |
|
364 | - array(self::status_idle, self::status_resend) |
|
365 | - ); |
|
366 | - } |
|
367 | - |
|
368 | - |
|
369 | - /** |
|
370 | - * Returns stati that indicate the message has failed sending |
|
371 | - * |
|
372 | - * @return array array of strings for possible stati. |
|
373 | - */ |
|
374 | - public function stati_indicating_failed_sending() |
|
375 | - { |
|
376 | - $failed_stati = array( |
|
377 | - self::status_failed, |
|
378 | - self::status_retry, |
|
379 | - self::status_messenger_executing, |
|
380 | - ); |
|
381 | - // if WP_DEBUG is set, then let's include debug_only fails |
|
382 | - if (WP_DEBUG) { |
|
383 | - $failed_stati[] = self::status_debug_only; |
|
384 | - } |
|
385 | - return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati); |
|
386 | - } |
|
387 | - |
|
388 | - |
|
389 | - /** |
|
390 | - * Returns filterable array of all EEM_Message statuses. |
|
391 | - * |
|
392 | - * @return array |
|
393 | - */ |
|
394 | - public function all_statuses() |
|
395 | - { |
|
396 | - return apply_filters( |
|
397 | - 'FHEE__EEM_Message__all_statuses', |
|
398 | - array( |
|
399 | - EEM_Message::status_sent, |
|
400 | - EEM_Message::status_incomplete, |
|
401 | - EEM_Message::status_idle, |
|
402 | - EEM_Message::status_resend, |
|
403 | - EEM_Message::status_retry, |
|
404 | - EEM_Message::status_failed, |
|
405 | - EEM_Message::status_messenger_executing, |
|
406 | - EEM_Message::status_debug_only, |
|
407 | - ) |
|
408 | - ); |
|
409 | - } |
|
410 | - |
|
411 | - /** |
|
412 | - * Detects any specific query variables in the request and uses those to setup appropriate |
|
413 | - * filter for any queries. |
|
414 | - * |
|
415 | - * @return array |
|
416 | - */ |
|
417 | - public function filter_by_query_params() |
|
418 | - { |
|
419 | - /** @var RequestInterface $request */ |
|
420 | - $request = EEM_Base::$loader->getShared(RequestInterface::class); |
|
421 | - // expected possible query_vars, the key in this array matches an expected key in the request, |
|
422 | - // the value, matches the corresponding EEM_Base child reference. |
|
423 | - $expected_vars = $this->_expected_vars_for_query_inject(); |
|
424 | - $query_params[0] = array(); |
|
425 | - foreach ($expected_vars as $request_key => $model_name) { |
|
426 | - $request_value = $request->getRequestParam($request_key); |
|
427 | - if ($request_value) { |
|
428 | - // special case |
|
429 | - switch ($request_key) { |
|
430 | - case '_REG_ID': |
|
431 | - $query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array( |
|
432 | - 'Transaction.Registration.REG_ID' => $request_value, |
|
433 | - ); |
|
434 | - break; |
|
435 | - case 'EVT_ID': |
|
436 | - $query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array( |
|
437 | - 'Transaction.Registration.EVT_ID' => $request_value, |
|
438 | - ); |
|
439 | - break; |
|
440 | - default: |
|
441 | - $query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value; |
|
442 | - break; |
|
443 | - } |
|
444 | - } |
|
445 | - } |
|
446 | - return $query_params; |
|
447 | - } |
|
448 | - |
|
449 | - |
|
450 | - /** |
|
451 | - * @return string |
|
452 | - * @throws EE_Error |
|
453 | - * @throws ReflectionException |
|
454 | - */ |
|
455 | - public function get_pretty_label_for_results() |
|
456 | - { |
|
457 | - /** @var RequestInterface $request */ |
|
458 | - $request = EEM_Base::$loader->getShared(RequestInterface::class); |
|
459 | - $expected_vars = $this->_expected_vars_for_query_inject(); |
|
460 | - $pretty_label = ''; |
|
461 | - $label_parts = array(); |
|
462 | - foreach ($expected_vars as $request_key => $model_name) { |
|
463 | - $model_name = strpos($model_name, 'EEM_', true) === 0 ? $model_name : "EEM_{$model_name}"; |
|
464 | - $model = EEM_Base::$loader->getShared($model_name); |
|
465 | - $model_field_value = $request->getRequestParam($request_key); |
|
466 | - if ($model instanceof EEM_Base && $model_field_value !== '') { |
|
467 | - switch ($request_key) { |
|
468 | - case '_REG_ID': |
|
469 | - $label_parts[] = sprintf( |
|
470 | - esc_html__('Registration with the ID: %s', 'event_espresso'), |
|
471 | - $model_field_value |
|
472 | - ); |
|
473 | - break; |
|
474 | - case 'ATT_ID': |
|
475 | - /** @var EE_Attendee $attendee */ |
|
476 | - $attendee = $model->get_one_by_ID($model_field_value); |
|
477 | - $label_parts[] = $attendee instanceof EE_Attendee |
|
478 | - ? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name()) |
|
479 | - : sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value); |
|
480 | - break; |
|
481 | - case 'ID': |
|
482 | - /** @var EE_WP_User $wpUser */ |
|
483 | - $wpUser = $model->get_one_by_ID($model_field_value); |
|
484 | - $label_parts[] = $wpUser instanceof EE_WP_User |
|
485 | - ? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name()) |
|
486 | - : sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value); |
|
487 | - break; |
|
488 | - case 'TXN_ID': |
|
489 | - $label_parts[] = sprintf( |
|
490 | - esc_html__('Transaction with the ID: %s', 'event_espresso'), |
|
491 | - $model_field_value |
|
492 | - ); |
|
493 | - break; |
|
494 | - case 'EVT_ID': |
|
495 | - /** @var EE_Event $Event */ |
|
496 | - $Event = $model->get_one_by_ID($model_field_value); |
|
497 | - $label_parts[] = $Event instanceof EE_Event |
|
498 | - ? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name()) |
|
499 | - : sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value); |
|
500 | - break; |
|
501 | - } |
|
502 | - } |
|
503 | - } |
|
504 | - |
|
505 | - if ($label_parts) { |
|
506 | - // prepend to the last element of $label_parts an "and". |
|
507 | - if (count($label_parts) > 1) { |
|
508 | - $label_parts_index_to_prepend = count($label_parts) - 1; |
|
509 | - $label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ]; |
|
510 | - } |
|
511 | - |
|
512 | - $pretty_label .= sprintf( |
|
513 | - esc_html_x( |
|
514 | - 'Showing messages for %s', |
|
515 | - 'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.', |
|
516 | - 'event_espresso' |
|
517 | - ), |
|
518 | - implode(', ', $label_parts) |
|
519 | - ); |
|
520 | - } |
|
521 | - return $pretty_label; |
|
522 | - } |
|
523 | - |
|
524 | - |
|
525 | - /** |
|
526 | - * This returns the array of expected variables for the EEI_Query_Filter methods being implemented |
|
527 | - * The array is in the format: |
|
528 | - * array( |
|
529 | - * {$field_name} => {$model_name} |
|
530 | - * ); |
|
531 | - * |
|
532 | - * @since 4.9.0 |
|
533 | - * @return array |
|
534 | - */ |
|
535 | - protected function _expected_vars_for_query_inject() |
|
536 | - { |
|
537 | - return array( |
|
538 | - '_REG_ID' => 'Registration', |
|
539 | - 'ATT_ID' => 'Attendee', |
|
540 | - 'ID' => 'WP_User', |
|
541 | - 'TXN_ID' => 'Transaction', |
|
542 | - 'EVT_ID' => 'Event', |
|
543 | - ); |
|
544 | - } |
|
545 | - |
|
546 | - |
|
547 | - /** |
|
548 | - * This returns whether EEM_Message is in debug mode or not. |
|
549 | - * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when |
|
550 | - * generating/sending messages. Debug mode can be set by either: |
|
551 | - * 1. Sending in a value for the $set_debug argument |
|
552 | - * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php |
|
553 | - * 3. Overriding the above via the provided filter. |
|
554 | - * |
|
555 | - * @param bool|null $set_debug If provided, then the debug mode will be set internally until reset via the |
|
556 | - * provided boolean. When no argument is provided (default null) then the debug |
|
557 | - * mode will be returned. |
|
558 | - * @return bool true means Messages is in debug mode. false means messages system is not in debug mode. |
|
559 | - */ |
|
560 | - public static function debug($set_debug = null) |
|
561 | - { |
|
562 | - static $is_debugging = null; |
|
563 | - |
|
564 | - // initialize (use constant if set). |
|
565 | - if (is_null($set_debug) && is_null($is_debugging)) { |
|
566 | - $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES; |
|
567 | - } |
|
568 | - |
|
569 | - if (! is_null($set_debug)) { |
|
570 | - $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN); |
|
571 | - } |
|
572 | - |
|
573 | - // return filtered value |
|
574 | - return apply_filters('FHEE__EEM_Message__debug', $is_debugging); |
|
575 | - } |
|
576 | - |
|
577 | - |
|
578 | - /** |
|
579 | - * Deletes old messages meeting certain criteria for removal from the database. |
|
580 | - * By default, this will delete messages that: |
|
581 | - * - are older than the value of the delete_threshold in months. |
|
582 | - * - have a STS_ID other than EEM_Message::status_idle |
|
583 | - * |
|
584 | - * @param int $delete_threshold This integer will be used to set the boundary for what messages are deleted in |
|
585 | - * months. |
|
586 | - * @return bool|false|int Either the number of records affected or false if there was an error (you can call |
|
587 | - * $wpdb->last_error to find out what the error was. |
|
588 | - * @throws EE_Error |
|
589 | - * @throws EE_Error |
|
590 | - * @throws EE_Error |
|
591 | - */ |
|
592 | - public function delete_old_messages($delete_threshold = 6) |
|
593 | - { |
|
594 | - $number_deleted = 0; |
|
595 | - /** |
|
596 | - * Allows code to change the boundary for what messages are kept. |
|
597 | - * Uses the value of the `delete_threshold` variable by default. |
|
598 | - * |
|
599 | - * @param int $seconds seconds that will be subtracted from the timestamp for now. |
|
600 | - * @return int |
|
601 | - */ |
|
602 | - $time_to_leave_alone = absint( |
|
603 | - apply_filters( |
|
604 | - 'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone', |
|
605 | - ((int) $delete_threshold) * MONTH_IN_SECONDS |
|
606 | - ) |
|
607 | - ); |
|
608 | - |
|
609 | - |
|
610 | - /** |
|
611 | - * Allows code to change what message stati are ignored when deleting. |
|
612 | - * Defaults to only ignore EEM_Message::status_idle messages. |
|
613 | - * |
|
614 | - * @param string $message_stati_to_keep An array of message statuses that will be ignored when deleting. |
|
615 | - */ |
|
616 | - $message_stati_to_keep = (array) apply_filters( |
|
617 | - 'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep', |
|
618 | - array( |
|
619 | - EEM_Message::status_idle |
|
620 | - ) |
|
621 | - ); |
|
622 | - |
|
623 | - // first get all the ids of messages being deleted |
|
624 | - $message_ids_to_delete = EEM_Message::instance()->get_col( |
|
625 | - array( |
|
626 | - 0 => array( |
|
627 | - 'STS_ID' => array('NOT_IN', $message_stati_to_keep), |
|
628 | - 'MSG_modified' => array('<', time() - $time_to_leave_alone) |
|
629 | - ), |
|
630 | - 'limit' => apply_filters( |
|
631 | - 'EEM_Message__delete_old_messages__limit', |
|
632 | - 2000, |
|
633 | - $delete_threshold |
|
634 | - ) |
|
635 | - ) |
|
636 | - ); |
|
637 | - |
|
638 | - if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) { |
|
639 | - global $wpdb; |
|
640 | - $number_deleted = $wpdb->query(' |
|
15 | + // private instance of the Message object |
|
16 | + protected static $_instance = null; |
|
17 | + |
|
18 | + |
|
19 | + /** |
|
20 | + * This priority indicates a message should be generated and sent ASAP |
|
21 | + * |
|
22 | + * @type int |
|
23 | + */ |
|
24 | + const priority_high = 10; |
|
25 | + |
|
26 | + |
|
27 | + /** |
|
28 | + * This priority indicates a message should be generated ASAP and queued for sending. |
|
29 | + * |
|
30 | + * @type |
|
31 | + */ |
|
32 | + const priority_medium = 20; |
|
33 | + |
|
34 | + |
|
35 | + /** |
|
36 | + * This priority indicates a message should be queued for generating. |
|
37 | + * |
|
38 | + * @type int |
|
39 | + */ |
|
40 | + const priority_low = 30; |
|
41 | + |
|
42 | + |
|
43 | + /** |
|
44 | + * indicates this message was sent at the time modified |
|
45 | + */ |
|
46 | + const status_sent = 'MSN'; |
|
47 | + |
|
48 | + |
|
49 | + /** |
|
50 | + * indicates this message is waiting to be sent |
|
51 | + */ |
|
52 | + const status_idle = 'MID'; |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * indicates an attempt was a made to send this message |
|
57 | + * at the scheduled time, but it failed at the time modified. This differs from MDO status in that it will ALWAYS |
|
58 | + * appear to the end user. |
|
59 | + */ |
|
60 | + const status_failed = 'MFL'; |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * indicates the message has been flagged for resending (at the time modified). |
|
65 | + */ |
|
66 | + const status_resend = 'MRS'; |
|
67 | + |
|
68 | + |
|
69 | + /** |
|
70 | + * indicates the message has been flagged for generation but has not been generated yet. Messages always start as |
|
71 | + * this status when added to the queue. |
|
72 | + */ |
|
73 | + const status_incomplete = 'MIC'; |
|
74 | + |
|
75 | + |
|
76 | + /** |
|
77 | + * Indicates everything was generated fine for the message, however, the messenger was unable to send. |
|
78 | + * This status means that its possible to retry sending the message. |
|
79 | + */ |
|
80 | + const status_retry = 'MRT'; |
|
81 | + |
|
82 | + |
|
83 | + /** |
|
84 | + * This is used for more informational messages that may not indicate anything is broken but still cannot be |
|
85 | + * generated or sent correctly. An example of a message that would get flagged this way would be when a not |
|
86 | + * approved message was queued for generation, but at time of generation, the attached registration(s) are |
|
87 | + * approved. So the message queued for generation is no longer valid. Messages for this status will only persist |
|
88 | + * in the db and be viewable in the message activity list table when the messages system is in debug mode. |
|
89 | + * |
|
90 | + * @see EEM_Message::debug() |
|
91 | + */ |
|
92 | + const status_debug_only = 'MDO'; |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * This status is given to messages it is processed by the messenger send method. |
|
97 | + * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually |
|
98 | + * indicative of a PHP timeout or memory limit issue. |
|
99 | + */ |
|
100 | + const status_messenger_executing = 'MEX'; |
|
101 | + |
|
102 | + |
|
103 | + /** |
|
104 | + * Private constructor to prevent direct creation. |
|
105 | + * |
|
106 | + * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and |
|
107 | + * any incoming timezone data that gets saved). Note this just sends the timezone info to |
|
108 | + * the date time model field objects. Default is null (and will be assumed using the set |
|
109 | + * timezone in the 'timezone_string' wp option) |
|
110 | + * @throws EE_Error |
|
111 | + * @throws EE_Error |
|
112 | + * @throws EE_Error |
|
113 | + */ |
|
114 | + protected function __construct($timezone = null) |
|
115 | + { |
|
116 | + $this->singular_item = esc_html__('Message', 'event_espresso'); |
|
117 | + $this->plural_item = esc_html__('Messages', 'event_espresso'); |
|
118 | + |
|
119 | + $this->_tables = array( |
|
120 | + 'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'), |
|
121 | + ); |
|
122 | + |
|
123 | + $allowed_priority = array( |
|
124 | + self::priority_high => esc_html__('high', 'event_espresso'), |
|
125 | + self::priority_medium => esc_html__('medium', 'event_espresso'), |
|
126 | + self::priority_low => esc_html__('low', 'event_espresso'), |
|
127 | + ); |
|
128 | + |
|
129 | + $this->_fields = array( |
|
130 | + 'Message' => array( |
|
131 | + 'MSG_ID' => new EE_Primary_Key_Int_Field('MSG_ID', esc_html__('Message ID', 'event_espresso')), |
|
132 | + 'MSG_token' => new EE_Plain_Text_Field( |
|
133 | + 'MSG_token', |
|
134 | + esc_html__( |
|
135 | + 'Unique Token used to represent this row in publicly viewable contexts (eg. a url).', |
|
136 | + 'event_espresso' |
|
137 | + ), |
|
138 | + false, |
|
139 | + EEH_URL::generate_unique_token() |
|
140 | + ), |
|
141 | + 'GRP_ID' => new EE_Foreign_Key_Int_Field( |
|
142 | + 'GRP_ID', |
|
143 | + esc_html__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'), |
|
144 | + true, |
|
145 | + 0, |
|
146 | + 'Message_Template_Group' |
|
147 | + ), |
|
148 | + 'TXN_ID' => new EE_Foreign_Key_Int_Field( |
|
149 | + 'TXN_ID', |
|
150 | + esc_html__( |
|
151 | + 'Foreign key to the related EE_Transaction. This is required to give context for regenerating the specific message', |
|
152 | + 'event_espresso' |
|
153 | + ), |
|
154 | + true, |
|
155 | + 0, |
|
156 | + 'Transaction' |
|
157 | + ), |
|
158 | + 'MSG_messenger' => new EE_Plain_Text_Field( |
|
159 | + 'MSG_messenger', |
|
160 | + esc_html__( |
|
161 | + 'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.', |
|
162 | + 'event_espresso' |
|
163 | + ), |
|
164 | + false, |
|
165 | + 'email' |
|
166 | + ), |
|
167 | + 'MSG_message_type' => new EE_Plain_Text_Field( |
|
168 | + 'MSG_message_type', |
|
169 | + esc_html__('Corresponds to the EE_message_type::name used to generate this message.', 'event_espresso'), |
|
170 | + false, |
|
171 | + 'receipt' |
|
172 | + ), |
|
173 | + 'MSG_context' => new EE_Plain_Text_Field('MSG_context', esc_html__('Context', 'event_espresso'), false), |
|
174 | + 'MSG_recipient_ID' => new EE_Foreign_Key_Int_Field( |
|
175 | + 'MSG_recipient_ID', |
|
176 | + esc_html__('Recipient ID', 'event_espresso'), |
|
177 | + true, |
|
178 | + null, |
|
179 | + array('Registration', 'Attendee', 'WP_User') |
|
180 | + ), |
|
181 | + 'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field( |
|
182 | + 'MSG_recipient_type', |
|
183 | + esc_html__('Recipient Type', 'event_espresso'), |
|
184 | + true, |
|
185 | + null, |
|
186 | + array('Registration', 'Attendee', 'WP_User') |
|
187 | + ), |
|
188 | + 'MSG_content' => new EE_Maybe_Serialized_Text_Field( |
|
189 | + 'MSG_content', |
|
190 | + esc_html__('Content', 'event_espresso'), |
|
191 | + true, |
|
192 | + '' |
|
193 | + ), |
|
194 | + 'MSG_to' => new EE_Maybe_Serialized_Text_Field( |
|
195 | + 'MSG_to', |
|
196 | + esc_html__('Address To', 'event_espresso'), |
|
197 | + true |
|
198 | + ), |
|
199 | + 'MSG_from' => new EE_Maybe_Serialized_Text_Field( |
|
200 | + 'MSG_from', |
|
201 | + esc_html__('Address From', 'event_espresso'), |
|
202 | + true |
|
203 | + ), |
|
204 | + 'MSG_subject' => new EE_Maybe_Serialized_Text_Field( |
|
205 | + 'MSG_subject', |
|
206 | + esc_html__('Subject', 'event_espresso'), |
|
207 | + true, |
|
208 | + '' |
|
209 | + ), |
|
210 | + 'MSG_priority' => new EE_Enum_Integer_Field( |
|
211 | + 'MSG_priority', |
|
212 | + esc_html__('Priority', 'event_espresso'), |
|
213 | + false, |
|
214 | + self::priority_low, |
|
215 | + $allowed_priority |
|
216 | + ), |
|
217 | + 'STS_ID' => new EE_Foreign_Key_String_Field( |
|
218 | + 'STS_ID', |
|
219 | + esc_html__('Status', 'event_espresso'), |
|
220 | + false, |
|
221 | + self::status_incomplete, |
|
222 | + 'Status' |
|
223 | + ), |
|
224 | + 'MSG_created' => new EE_Datetime_Field( |
|
225 | + 'MSG_created', |
|
226 | + esc_html__('Created', 'event_espresso'), |
|
227 | + false, |
|
228 | + EE_Datetime_Field::now |
|
229 | + ), |
|
230 | + 'MSG_modified' => new EE_Datetime_Field( |
|
231 | + 'MSG_modified', |
|
232 | + esc_html__('Modified', 'event_espresso'), |
|
233 | + true, |
|
234 | + EE_Datetime_Field::now |
|
235 | + ), |
|
236 | + ), |
|
237 | + ); |
|
238 | + $this->_model_relations = array( |
|
239 | + 'Attendee' => new EE_Belongs_To_Any_Relation(), |
|
240 | + 'Registration' => new EE_Belongs_To_Any_Relation(), |
|
241 | + 'WP_User' => new EE_Belongs_To_Any_Relation(), |
|
242 | + 'Message_Template_Group' => new EE_Belongs_To_Relation(), |
|
243 | + 'Transaction' => new EE_Belongs_To_Relation(), |
|
244 | + ); |
|
245 | + parent::__construct($timezone); |
|
246 | + } |
|
247 | + |
|
248 | + |
|
249 | + /** |
|
250 | + * @return EE_Message |
|
251 | + * @throws EE_Error |
|
252 | + */ |
|
253 | + public function create_default_object() |
|
254 | + { |
|
255 | + /** @type EE_Message $message */ |
|
256 | + $message = parent::create_default_object(); |
|
257 | + if ($message instanceof EE_Message) { |
|
258 | + return EE_Message_Factory::set_messenger_and_message_type($message); |
|
259 | + } |
|
260 | + return null; |
|
261 | + } |
|
262 | + |
|
263 | + |
|
264 | + /** |
|
265 | + * @param mixed $cols_n_values |
|
266 | + * @return EE_Message |
|
267 | + * @throws EE_Error |
|
268 | + * @throws EE_Error |
|
269 | + */ |
|
270 | + public function instantiate_class_from_array_or_object($cols_n_values) |
|
271 | + { |
|
272 | + /** @type EE_Message $message */ |
|
273 | + $message = parent::instantiate_class_from_array_or_object($cols_n_values); |
|
274 | + if ($message instanceof EE_Message) { |
|
275 | + return EE_Message_Factory::set_messenger_and_message_type($message); |
|
276 | + } |
|
277 | + return null; |
|
278 | + } |
|
279 | + |
|
280 | + |
|
281 | + /** |
|
282 | + * Returns whether or not a message of that type was sent for a given attendee. |
|
283 | + * |
|
284 | + * @param EE_Attendee|int $attendee |
|
285 | + * @param string $message_type the message type slug |
|
286 | + * @return boolean |
|
287 | + * @throws EE_Error |
|
288 | + * @throws EE_Error |
|
289 | + * @throws EE_Error |
|
290 | + */ |
|
291 | + public function message_sent_for_attendee($attendee, $message_type) |
|
292 | + { |
|
293 | + $attendee_ID = EEM_Attendee::instance()->ensure_is_ID($attendee); |
|
294 | + return $this->exists(array( |
|
295 | + array( |
|
296 | + 'Attendee.ATT_ID' => $attendee_ID, |
|
297 | + 'MSG_message_type' => $message_type, |
|
298 | + 'STS_ID' => array('IN', $this->stati_indicating_sent()), |
|
299 | + ), |
|
300 | + )); |
|
301 | + } |
|
302 | + |
|
303 | + |
|
304 | + /** |
|
305 | + * Returns whether or not a message of that type was sent for a given registration |
|
306 | + * |
|
307 | + * @param EE_Registration|int $registration |
|
308 | + * @param string $message_type the message type slug |
|
309 | + * @return boolean |
|
310 | + * @throws EE_Error |
|
311 | + * @throws EE_Error |
|
312 | + * @throws EE_Error |
|
313 | + */ |
|
314 | + public function message_sent_for_registration($registration, $message_type) |
|
315 | + { |
|
316 | + $registrationID = EEM_Registration::instance()->ensure_is_ID($registration); |
|
317 | + return $this->exists(array( |
|
318 | + array( |
|
319 | + 'Registration.REG_ID' => $registrationID, |
|
320 | + 'MSG_message_type' => $message_type, |
|
321 | + 'STS_ID' => array('IN', $this->stati_indicating_sent()), |
|
322 | + ), |
|
323 | + )); |
|
324 | + } |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * This retrieves an EE_Message object from the db matching the given token string. |
|
329 | + * |
|
330 | + * @param string $token |
|
331 | + * @return EE_Message |
|
332 | + * @throws EE_Error |
|
333 | + */ |
|
334 | + public function get_one_by_token($token) |
|
335 | + { |
|
336 | + return $this->get_one(array( |
|
337 | + array( |
|
338 | + 'MSG_token' => $token, |
|
339 | + ), |
|
340 | + )); |
|
341 | + } |
|
342 | + |
|
343 | + |
|
344 | + /** |
|
345 | + * Returns stati that indicate the message HAS been sent |
|
346 | + * |
|
347 | + * @return array of strings for possible stati |
|
348 | + */ |
|
349 | + public function stati_indicating_sent() |
|
350 | + { |
|
351 | + return apply_filters('FHEE__EEM_Message__stati_indicating_sent', array(self::status_sent)); |
|
352 | + } |
|
353 | + |
|
354 | + |
|
355 | + /** |
|
356 | + * Returns stati that indicate the message is waiting to be sent. |
|
357 | + * |
|
358 | + * @return array of strings for possible stati. |
|
359 | + */ |
|
360 | + public function stati_indicating_to_send() |
|
361 | + { |
|
362 | + return apply_filters( |
|
363 | + 'FHEE__EEM_Message__stati_indicating_to_send', |
|
364 | + array(self::status_idle, self::status_resend) |
|
365 | + ); |
|
366 | + } |
|
367 | + |
|
368 | + |
|
369 | + /** |
|
370 | + * Returns stati that indicate the message has failed sending |
|
371 | + * |
|
372 | + * @return array array of strings for possible stati. |
|
373 | + */ |
|
374 | + public function stati_indicating_failed_sending() |
|
375 | + { |
|
376 | + $failed_stati = array( |
|
377 | + self::status_failed, |
|
378 | + self::status_retry, |
|
379 | + self::status_messenger_executing, |
|
380 | + ); |
|
381 | + // if WP_DEBUG is set, then let's include debug_only fails |
|
382 | + if (WP_DEBUG) { |
|
383 | + $failed_stati[] = self::status_debug_only; |
|
384 | + } |
|
385 | + return apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati); |
|
386 | + } |
|
387 | + |
|
388 | + |
|
389 | + /** |
|
390 | + * Returns filterable array of all EEM_Message statuses. |
|
391 | + * |
|
392 | + * @return array |
|
393 | + */ |
|
394 | + public function all_statuses() |
|
395 | + { |
|
396 | + return apply_filters( |
|
397 | + 'FHEE__EEM_Message__all_statuses', |
|
398 | + array( |
|
399 | + EEM_Message::status_sent, |
|
400 | + EEM_Message::status_incomplete, |
|
401 | + EEM_Message::status_idle, |
|
402 | + EEM_Message::status_resend, |
|
403 | + EEM_Message::status_retry, |
|
404 | + EEM_Message::status_failed, |
|
405 | + EEM_Message::status_messenger_executing, |
|
406 | + EEM_Message::status_debug_only, |
|
407 | + ) |
|
408 | + ); |
|
409 | + } |
|
410 | + |
|
411 | + /** |
|
412 | + * Detects any specific query variables in the request and uses those to setup appropriate |
|
413 | + * filter for any queries. |
|
414 | + * |
|
415 | + * @return array |
|
416 | + */ |
|
417 | + public function filter_by_query_params() |
|
418 | + { |
|
419 | + /** @var RequestInterface $request */ |
|
420 | + $request = EEM_Base::$loader->getShared(RequestInterface::class); |
|
421 | + // expected possible query_vars, the key in this array matches an expected key in the request, |
|
422 | + // the value, matches the corresponding EEM_Base child reference. |
|
423 | + $expected_vars = $this->_expected_vars_for_query_inject(); |
|
424 | + $query_params[0] = array(); |
|
425 | + foreach ($expected_vars as $request_key => $model_name) { |
|
426 | + $request_value = $request->getRequestParam($request_key); |
|
427 | + if ($request_value) { |
|
428 | + // special case |
|
429 | + switch ($request_key) { |
|
430 | + case '_REG_ID': |
|
431 | + $query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = array( |
|
432 | + 'Transaction.Registration.REG_ID' => $request_value, |
|
433 | + ); |
|
434 | + break; |
|
435 | + case 'EVT_ID': |
|
436 | + $query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = array( |
|
437 | + 'Transaction.Registration.EVT_ID' => $request_value, |
|
438 | + ); |
|
439 | + break; |
|
440 | + default: |
|
441 | + $query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] = $request_value; |
|
442 | + break; |
|
443 | + } |
|
444 | + } |
|
445 | + } |
|
446 | + return $query_params; |
|
447 | + } |
|
448 | + |
|
449 | + |
|
450 | + /** |
|
451 | + * @return string |
|
452 | + * @throws EE_Error |
|
453 | + * @throws ReflectionException |
|
454 | + */ |
|
455 | + public function get_pretty_label_for_results() |
|
456 | + { |
|
457 | + /** @var RequestInterface $request */ |
|
458 | + $request = EEM_Base::$loader->getShared(RequestInterface::class); |
|
459 | + $expected_vars = $this->_expected_vars_for_query_inject(); |
|
460 | + $pretty_label = ''; |
|
461 | + $label_parts = array(); |
|
462 | + foreach ($expected_vars as $request_key => $model_name) { |
|
463 | + $model_name = strpos($model_name, 'EEM_', true) === 0 ? $model_name : "EEM_{$model_name}"; |
|
464 | + $model = EEM_Base::$loader->getShared($model_name); |
|
465 | + $model_field_value = $request->getRequestParam($request_key); |
|
466 | + if ($model instanceof EEM_Base && $model_field_value !== '') { |
|
467 | + switch ($request_key) { |
|
468 | + case '_REG_ID': |
|
469 | + $label_parts[] = sprintf( |
|
470 | + esc_html__('Registration with the ID: %s', 'event_espresso'), |
|
471 | + $model_field_value |
|
472 | + ); |
|
473 | + break; |
|
474 | + case 'ATT_ID': |
|
475 | + /** @var EE_Attendee $attendee */ |
|
476 | + $attendee = $model->get_one_by_ID($model_field_value); |
|
477 | + $label_parts[] = $attendee instanceof EE_Attendee |
|
478 | + ? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name()) |
|
479 | + : sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value); |
|
480 | + break; |
|
481 | + case 'ID': |
|
482 | + /** @var EE_WP_User $wpUser */ |
|
483 | + $wpUser = $model->get_one_by_ID($model_field_value); |
|
484 | + $label_parts[] = $wpUser instanceof EE_WP_User |
|
485 | + ? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name()) |
|
486 | + : sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value); |
|
487 | + break; |
|
488 | + case 'TXN_ID': |
|
489 | + $label_parts[] = sprintf( |
|
490 | + esc_html__('Transaction with the ID: %s', 'event_espresso'), |
|
491 | + $model_field_value |
|
492 | + ); |
|
493 | + break; |
|
494 | + case 'EVT_ID': |
|
495 | + /** @var EE_Event $Event */ |
|
496 | + $Event = $model->get_one_by_ID($model_field_value); |
|
497 | + $label_parts[] = $Event instanceof EE_Event |
|
498 | + ? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name()) |
|
499 | + : sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value); |
|
500 | + break; |
|
501 | + } |
|
502 | + } |
|
503 | + } |
|
504 | + |
|
505 | + if ($label_parts) { |
|
506 | + // prepend to the last element of $label_parts an "and". |
|
507 | + if (count($label_parts) > 1) { |
|
508 | + $label_parts_index_to_prepend = count($label_parts) - 1; |
|
509 | + $label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ]; |
|
510 | + } |
|
511 | + |
|
512 | + $pretty_label .= sprintf( |
|
513 | + esc_html_x( |
|
514 | + 'Showing messages for %s', |
|
515 | + 'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.', |
|
516 | + 'event_espresso' |
|
517 | + ), |
|
518 | + implode(', ', $label_parts) |
|
519 | + ); |
|
520 | + } |
|
521 | + return $pretty_label; |
|
522 | + } |
|
523 | + |
|
524 | + |
|
525 | + /** |
|
526 | + * This returns the array of expected variables for the EEI_Query_Filter methods being implemented |
|
527 | + * The array is in the format: |
|
528 | + * array( |
|
529 | + * {$field_name} => {$model_name} |
|
530 | + * ); |
|
531 | + * |
|
532 | + * @since 4.9.0 |
|
533 | + * @return array |
|
534 | + */ |
|
535 | + protected function _expected_vars_for_query_inject() |
|
536 | + { |
|
537 | + return array( |
|
538 | + '_REG_ID' => 'Registration', |
|
539 | + 'ATT_ID' => 'Attendee', |
|
540 | + 'ID' => 'WP_User', |
|
541 | + 'TXN_ID' => 'Transaction', |
|
542 | + 'EVT_ID' => 'Event', |
|
543 | + ); |
|
544 | + } |
|
545 | + |
|
546 | + |
|
547 | + /** |
|
548 | + * This returns whether EEM_Message is in debug mode or not. |
|
549 | + * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when |
|
550 | + * generating/sending messages. Debug mode can be set by either: |
|
551 | + * 1. Sending in a value for the $set_debug argument |
|
552 | + * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php |
|
553 | + * 3. Overriding the above via the provided filter. |
|
554 | + * |
|
555 | + * @param bool|null $set_debug If provided, then the debug mode will be set internally until reset via the |
|
556 | + * provided boolean. When no argument is provided (default null) then the debug |
|
557 | + * mode will be returned. |
|
558 | + * @return bool true means Messages is in debug mode. false means messages system is not in debug mode. |
|
559 | + */ |
|
560 | + public static function debug($set_debug = null) |
|
561 | + { |
|
562 | + static $is_debugging = null; |
|
563 | + |
|
564 | + // initialize (use constant if set). |
|
565 | + if (is_null($set_debug) && is_null($is_debugging)) { |
|
566 | + $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES; |
|
567 | + } |
|
568 | + |
|
569 | + if (! is_null($set_debug)) { |
|
570 | + $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN); |
|
571 | + } |
|
572 | + |
|
573 | + // return filtered value |
|
574 | + return apply_filters('FHEE__EEM_Message__debug', $is_debugging); |
|
575 | + } |
|
576 | + |
|
577 | + |
|
578 | + /** |
|
579 | + * Deletes old messages meeting certain criteria for removal from the database. |
|
580 | + * By default, this will delete messages that: |
|
581 | + * - are older than the value of the delete_threshold in months. |
|
582 | + * - have a STS_ID other than EEM_Message::status_idle |
|
583 | + * |
|
584 | + * @param int $delete_threshold This integer will be used to set the boundary for what messages are deleted in |
|
585 | + * months. |
|
586 | + * @return bool|false|int Either the number of records affected or false if there was an error (you can call |
|
587 | + * $wpdb->last_error to find out what the error was. |
|
588 | + * @throws EE_Error |
|
589 | + * @throws EE_Error |
|
590 | + * @throws EE_Error |
|
591 | + */ |
|
592 | + public function delete_old_messages($delete_threshold = 6) |
|
593 | + { |
|
594 | + $number_deleted = 0; |
|
595 | + /** |
|
596 | + * Allows code to change the boundary for what messages are kept. |
|
597 | + * Uses the value of the `delete_threshold` variable by default. |
|
598 | + * |
|
599 | + * @param int $seconds seconds that will be subtracted from the timestamp for now. |
|
600 | + * @return int |
|
601 | + */ |
|
602 | + $time_to_leave_alone = absint( |
|
603 | + apply_filters( |
|
604 | + 'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone', |
|
605 | + ((int) $delete_threshold) * MONTH_IN_SECONDS |
|
606 | + ) |
|
607 | + ); |
|
608 | + |
|
609 | + |
|
610 | + /** |
|
611 | + * Allows code to change what message stati are ignored when deleting. |
|
612 | + * Defaults to only ignore EEM_Message::status_idle messages. |
|
613 | + * |
|
614 | + * @param string $message_stati_to_keep An array of message statuses that will be ignored when deleting. |
|
615 | + */ |
|
616 | + $message_stati_to_keep = (array) apply_filters( |
|
617 | + 'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep', |
|
618 | + array( |
|
619 | + EEM_Message::status_idle |
|
620 | + ) |
|
621 | + ); |
|
622 | + |
|
623 | + // first get all the ids of messages being deleted |
|
624 | + $message_ids_to_delete = EEM_Message::instance()->get_col( |
|
625 | + array( |
|
626 | + 0 => array( |
|
627 | + 'STS_ID' => array('NOT_IN', $message_stati_to_keep), |
|
628 | + 'MSG_modified' => array('<', time() - $time_to_leave_alone) |
|
629 | + ), |
|
630 | + 'limit' => apply_filters( |
|
631 | + 'EEM_Message__delete_old_messages__limit', |
|
632 | + 2000, |
|
633 | + $delete_threshold |
|
634 | + ) |
|
635 | + ) |
|
636 | + ); |
|
637 | + |
|
638 | + if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) { |
|
639 | + global $wpdb; |
|
640 | + $number_deleted = $wpdb->query(' |
|
641 | 641 | DELETE |
642 | 642 | FROM ' . $this->table() . ' |
643 | 643 | WHERE |
644 | 644 | MSG_ID IN (' . implode(",", $message_ids_to_delete) . ') |
645 | 645 | '); |
646 | - } |
|
647 | - |
|
648 | - /** |
|
649 | - * This will get called if the number of records deleted 0 or greater. So a successful deletion is one where |
|
650 | - * there were no errors. An unsuccessful deletion is where there were errors. Keep that in mind for the actions |
|
651 | - * below. |
|
652 | - */ |
|
653 | - if ($number_deleted !== false) { |
|
654 | - do_action('AHEE__EEM_Message__delete_old_messages__after_successful_deletion', $message_ids_to_delete, $number_deleted); |
|
655 | - } else { |
|
656 | - do_action('AHEE__EEM_Message__delete_old_messages__after_deletion_fail', $message_ids_to_delete, $number_deleted); |
|
657 | - } |
|
658 | - return $number_deleted; |
|
659 | - } |
|
646 | + } |
|
647 | + |
|
648 | + /** |
|
649 | + * This will get called if the number of records deleted 0 or greater. So a successful deletion is one where |
|
650 | + * there were no errors. An unsuccessful deletion is where there were errors. Keep that in mind for the actions |
|
651 | + * below. |
|
652 | + */ |
|
653 | + if ($number_deleted !== false) { |
|
654 | + do_action('AHEE__EEM_Message__delete_old_messages__after_successful_deletion', $message_ids_to_delete, $number_deleted); |
|
655 | + } else { |
|
656 | + do_action('AHEE__EEM_Message__delete_old_messages__after_deletion_fail', $message_ids_to_delete, $number_deleted); |
|
657 | + } |
|
658 | + return $number_deleted; |
|
659 | + } |
|
660 | 660 | } |