@@ -12,432 +12,432 @@ |
||
12 | 12 | */ |
13 | 13 | class EEM_Attendee extends EEM_CPT_Base |
14 | 14 | { |
15 | - // private instance of the Attendee object |
|
16 | - protected static $_instance = null; |
|
15 | + // private instance of the Attendee object |
|
16 | + protected static $_instance = null; |
|
17 | 17 | |
18 | - /** |
|
19 | - * QST_system for questions are strings not integers now, |
|
20 | - * so these constants are deprecated. |
|
21 | - * Please instead use the EEM_Attendee::system_question_* constants |
|
22 | - * |
|
23 | - * @deprecated |
|
24 | - */ |
|
25 | - const fname_question_id = 1; |
|
18 | + /** |
|
19 | + * QST_system for questions are strings not integers now, |
|
20 | + * so these constants are deprecated. |
|
21 | + * Please instead use the EEM_Attendee::system_question_* constants |
|
22 | + * |
|
23 | + * @deprecated |
|
24 | + */ |
|
25 | + const fname_question_id = 1; |
|
26 | 26 | |
27 | - /** |
|
28 | - * @deprecated |
|
29 | - */ |
|
30 | - const lname_question_id = 2; |
|
27 | + /** |
|
28 | + * @deprecated |
|
29 | + */ |
|
30 | + const lname_question_id = 2; |
|
31 | 31 | |
32 | 32 | |
33 | - /** |
|
34 | - * @deprecated |
|
35 | - */ |
|
36 | - const email_question_id = 3; |
|
33 | + /** |
|
34 | + * @deprecated |
|
35 | + */ |
|
36 | + const email_question_id = 3; |
|
37 | 37 | |
38 | 38 | |
39 | - /** |
|
40 | - * @deprecated |
|
41 | - */ |
|
42 | - const address_question_id = 4; |
|
39 | + /** |
|
40 | + * @deprecated |
|
41 | + */ |
|
42 | + const address_question_id = 4; |
|
43 | 43 | |
44 | 44 | |
45 | - /** |
|
46 | - * @deprecated |
|
47 | - */ |
|
48 | - const address2_question_id = 5; |
|
45 | + /** |
|
46 | + * @deprecated |
|
47 | + */ |
|
48 | + const address2_question_id = 5; |
|
49 | 49 | |
50 | - |
|
51 | - /** |
|
52 | - * @deprecated |
|
53 | - */ |
|
54 | - const city_question_id = 6; |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * @deprecated |
|
59 | - */ |
|
60 | - const state_question_id = 7; |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * @deprecated |
|
65 | - */ |
|
66 | - const country_question_id = 8; |
|
67 | - |
|
68 | - |
|
69 | - /** |
|
70 | - * @deprecated |
|
71 | - */ |
|
72 | - const zip_question_id = 9; |
|
73 | - |
|
74 | - |
|
75 | - /** |
|
76 | - * @deprecated |
|
77 | - */ |
|
78 | - const phone_question_id = 10; |
|
79 | - |
|
80 | - /** |
|
81 | - * When looking for questions that correspond to attendee fields, |
|
82 | - * look for the question with this QST_system value. |
|
83 | - * These replace the old constants like EEM_Attendee::*_question_id |
|
84 | - */ |
|
85 | - const system_question_fname = 'fname'; |
|
86 | - |
|
87 | - const system_question_lname = 'lname'; |
|
88 | - |
|
89 | - const system_question_email = 'email'; |
|
90 | - |
|
91 | - const system_question_email_confirm = 'email_confirm'; |
|
92 | - |
|
93 | - const system_question_address = 'address'; |
|
94 | - |
|
95 | - const system_question_address2 = 'address2'; |
|
96 | - |
|
97 | - const system_question_city = 'city'; |
|
98 | - |
|
99 | - const system_question_state = 'state'; |
|
100 | - |
|
101 | - const system_question_country = 'country'; |
|
102 | - |
|
103 | - const system_question_zip = 'zip'; |
|
104 | - |
|
105 | - const system_question_phone = 'phone'; |
|
106 | - |
|
107 | - /** |
|
108 | - * Keys are all the EEM_Attendee::system_question_* constants, which are |
|
109 | - * also all the values of QST_system in the questions table, and values |
|
110 | - * are their corresponding Attendee field names |
|
111 | - * |
|
112 | - * @var array |
|
113 | - */ |
|
114 | - protected $_system_question_to_attendee_field_name = array( |
|
115 | - EEM_Attendee::system_question_fname => 'ATT_fname', |
|
116 | - EEM_Attendee::system_question_lname => 'ATT_lname', |
|
117 | - EEM_Attendee::system_question_email => 'ATT_email', |
|
118 | - EEM_Attendee::system_question_address => 'ATT_address', |
|
119 | - EEM_Attendee::system_question_address2 => 'ATT_address2', |
|
120 | - EEM_Attendee::system_question_city => 'ATT_city', |
|
121 | - EEM_Attendee::system_question_state => 'STA_ID', |
|
122 | - EEM_Attendee::system_question_country => 'CNT_ISO', |
|
123 | - EEM_Attendee::system_question_zip => 'ATT_zip', |
|
124 | - EEM_Attendee::system_question_phone => 'ATT_phone', |
|
125 | - ); |
|
126 | - |
|
127 | - |
|
128 | - |
|
129 | - /** |
|
130 | - * EEM_Attendee constructor. |
|
131 | - * |
|
132 | - * @param null $timezone |
|
133 | - * @param ModelFieldFactory $model_field_factory |
|
134 | - * @throws EE_Error |
|
135 | - * @throws InvalidArgumentException |
|
136 | - */ |
|
137 | - protected function __construct($timezone, ModelFieldFactory $model_field_factory) |
|
138 | - { |
|
139 | - $this->singular_item = esc_html__('Attendee', 'event_espresso'); |
|
140 | - $this->plural_item = esc_html__('Attendees', 'event_espresso'); |
|
141 | - $this->_tables = array( |
|
142 | - 'Attendee_CPT' => new EE_Primary_Table('posts', 'ID'), |
|
143 | - 'Attendee_Meta' => new EE_Secondary_Table( |
|
144 | - 'esp_attendee_meta', |
|
145 | - 'ATTM_ID', |
|
146 | - 'ATT_ID' |
|
147 | - ), |
|
148 | - ); |
|
149 | - $this->_fields = array( |
|
150 | - 'Attendee_CPT' => array( |
|
151 | - 'ATT_ID' => $model_field_factory->createPrimaryKeyIntField( |
|
152 | - 'ID', |
|
153 | - esc_html__('Attendee ID', 'event_espresso') |
|
154 | - ), |
|
155 | - 'ATT_full_name' => $model_field_factory->createPlainTextField( |
|
156 | - 'post_title', |
|
157 | - esc_html__('Attendee Full Name', 'event_espresso'), |
|
158 | - false, |
|
159 | - esc_html__('Unknown', 'event_espresso') |
|
160 | - ), |
|
161 | - 'ATT_bio' => $model_field_factory->createPostContentField( |
|
162 | - 'post_content', |
|
163 | - esc_html__('Attendee Biography', 'event_espresso'), |
|
164 | - false, |
|
165 | - esc_html__('No Biography Provided', 'event_espresso') |
|
166 | - ), |
|
167 | - 'ATT_slug' => $model_field_factory->createSlugField( |
|
168 | - 'post_name', |
|
169 | - esc_html__('Attendee URL Slug', 'event_espresso') |
|
170 | - ), |
|
171 | - 'ATT_created' => $model_field_factory->createDatetimeField( |
|
172 | - 'post_date', |
|
173 | - esc_html__('Time Attendee Created', 'event_espresso') |
|
174 | - ), |
|
175 | - 'ATT_short_bio' => $model_field_factory->createSimpleHtmlField( |
|
176 | - 'post_excerpt', |
|
177 | - esc_html__('Attendee Short Biography', 'event_espresso'), |
|
178 | - true, |
|
179 | - esc_html__('No Biography Provided', 'event_espresso') |
|
180 | - ), |
|
181 | - 'ATT_modified' => $model_field_factory->createDatetimeField( |
|
182 | - 'post_modified', |
|
183 | - esc_html__('Time Attendee Last Modified', 'event_espresso') |
|
184 | - ), |
|
185 | - 'ATT_author' => $model_field_factory->createWpUserField( |
|
186 | - 'post_author', |
|
187 | - esc_html__('Creator ID of the first Event attended', 'event_espresso'), |
|
188 | - false |
|
189 | - ), |
|
190 | - 'ATT_parent' => $model_field_factory->createDbOnlyIntField( |
|
191 | - 'post_parent', |
|
192 | - esc_html__('Parent Attendee (unused)', 'event_espresso'), |
|
193 | - false, |
|
194 | - 0 |
|
195 | - ), |
|
196 | - 'post_type' => $model_field_factory->createWpPostTypeField('espresso_attendees'), |
|
197 | - 'status' => $model_field_factory->createWpPostStatusField( |
|
198 | - 'post_status', |
|
199 | - esc_html__('Attendee Status', 'event_espresso'), |
|
200 | - false, |
|
201 | - 'publish' |
|
202 | - ), |
|
203 | - 'password' => new EE_Password_Field( |
|
204 | - 'post_password', |
|
205 | - esc_html__('Password', 'event_espresso'), |
|
206 | - false, |
|
207 | - '', |
|
208 | - array( |
|
209 | - 'ATT_bio', |
|
210 | - 'ATT_short_bio', |
|
211 | - 'ATT_address', |
|
212 | - 'ATT_address2', |
|
213 | - 'ATT_city', |
|
214 | - 'STA_ID', |
|
215 | - 'CNT_ISO', |
|
216 | - 'ATT_zip', |
|
217 | - 'ATT_email', |
|
218 | - 'ATT_phone' |
|
219 | - ) |
|
220 | - ) |
|
221 | - ), |
|
222 | - 'Attendee_Meta' => array( |
|
223 | - 'ATTM_ID' => $model_field_factory->createDbOnlyIntField( |
|
224 | - 'ATTM_ID', |
|
225 | - esc_html__('Attendee Meta Row ID', 'event_espresso'), |
|
226 | - false |
|
227 | - ), |
|
228 | - 'ATT_ID_fk' => $model_field_factory->createDbOnlyIntField( |
|
229 | - 'ATT_ID', |
|
230 | - esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'), |
|
231 | - false |
|
232 | - ), |
|
233 | - 'ATT_fname' => $model_field_factory->createPlainTextField( |
|
234 | - 'ATT_fname', |
|
235 | - esc_html__('First Name', 'event_espresso') |
|
236 | - ), |
|
237 | - 'ATT_lname' => $model_field_factory->createPlainTextField( |
|
238 | - 'ATT_lname', |
|
239 | - esc_html__('Last Name', 'event_espresso') |
|
240 | - ), |
|
241 | - 'ATT_address' => $model_field_factory->createPlainTextField( |
|
242 | - 'ATT_address', |
|
243 | - esc_html__('Address Part 1', 'event_espresso') |
|
244 | - ), |
|
245 | - 'ATT_address2' => $model_field_factory->createPlainTextField( |
|
246 | - 'ATT_address2', |
|
247 | - esc_html__('Address Part 2', 'event_espresso') |
|
248 | - ), |
|
249 | - 'ATT_city' => $model_field_factory->createPlainTextField( |
|
250 | - 'ATT_city', |
|
251 | - esc_html__('City', 'event_espresso') |
|
252 | - ), |
|
253 | - 'STA_ID' => $model_field_factory->createForeignKeyIntField( |
|
254 | - 'STA_ID', |
|
255 | - esc_html__('State', 'event_espresso'), |
|
256 | - true, |
|
257 | - 0, |
|
258 | - 'State' |
|
259 | - ), |
|
260 | - 'CNT_ISO' => $model_field_factory->createForeignKeyStringField( |
|
261 | - 'CNT_ISO', |
|
262 | - esc_html__('Country', 'event_espresso'), |
|
263 | - true, |
|
264 | - '', |
|
265 | - 'Country' |
|
266 | - ), |
|
267 | - 'ATT_zip' => $model_field_factory->createPlainTextField( |
|
268 | - 'ATT_zip', |
|
269 | - esc_html__('ZIP/Postal Code', 'event_espresso') |
|
270 | - ), |
|
271 | - 'ATT_email' => $model_field_factory->createEmailField( |
|
272 | - 'ATT_email', |
|
273 | - esc_html__('Email Address', 'event_espresso') |
|
274 | - ), |
|
275 | - 'ATT_phone' => $model_field_factory->createPlainTextField( |
|
276 | - 'ATT_phone', |
|
277 | - esc_html__('Phone', 'event_espresso') |
|
278 | - ), |
|
279 | - ), |
|
280 | - ); |
|
281 | - $this->_model_relations = array( |
|
282 | - 'Registration' => new EE_Has_Many_Relation(), |
|
283 | - 'State' => new EE_Belongs_To_Relation(), |
|
284 | - 'Country' => new EE_Belongs_To_Relation(), |
|
285 | - 'Event' => new EE_HABTM_Relation('Registration', false), |
|
286 | - 'WP_User' => new EE_Belongs_To_Relation(), |
|
287 | - 'Message' => new EE_Has_Many_Any_Relation(false), |
|
288 | - // allow deletion of attendees even if they have messages in the queue for them. |
|
289 | - 'Term_Relationship' => new EE_Has_Many_Relation(), |
|
290 | - 'Term_Taxonomy' => new EE_HABTM_Relation('Term_Relationship'), |
|
291 | - ); |
|
292 | - $this->_caps_slug = 'contacts'; |
|
293 | - $this->model_chain_to_password = ''; |
|
294 | - parent::__construct($timezone); |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - |
|
299 | - /** |
|
300 | - * Gets the name of the field on the attendee model corresponding to the system question string |
|
301 | - * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name |
|
302 | - * |
|
303 | - * @param string $system_question_string |
|
304 | - * @return string|null if not found |
|
305 | - */ |
|
306 | - public function get_attendee_field_for_system_question($system_question_string) |
|
307 | - { |
|
308 | - return isset($this->_system_question_to_attendee_field_name[ $system_question_string ]) |
|
309 | - ? $this->_system_question_to_attendee_field_name[ $system_question_string ] |
|
310 | - : null; |
|
311 | - } |
|
312 | - |
|
313 | - |
|
314 | - |
|
315 | - /** |
|
316 | - * Gets mapping from esp_question.QST_system values to their corresponding attendee field names |
|
317 | - * |
|
318 | - * @return array |
|
319 | - */ |
|
320 | - public function system_question_to_attendee_field_mapping() |
|
321 | - { |
|
322 | - return $this->_system_question_to_attendee_field_name; |
|
323 | - } |
|
324 | - |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * Gets all the attendees for a transaction (by using the esp_registration as a join table) |
|
329 | - * |
|
330 | - * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID |
|
331 | - * @return EE_Attendee[]|EE_Base_Class[] |
|
332 | - * @throws EE_Error |
|
333 | - */ |
|
334 | - public function get_attendees_for_transaction($transaction_id_or_obj) |
|
335 | - { |
|
336 | - return $this->get_all( |
|
337 | - array( |
|
338 | - array( |
|
339 | - 'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction |
|
340 | - ? $transaction_id_or_obj->ID() |
|
341 | - : $transaction_id_or_obj, |
|
342 | - ), |
|
343 | - ) |
|
344 | - ); |
|
345 | - } |
|
346 | - |
|
347 | - |
|
348 | - |
|
349 | - /** |
|
350 | - * retrieve a single attendee from db via their ID |
|
351 | - * |
|
352 | - * @param $ATT_ID |
|
353 | - * @return mixed array on success, FALSE on fail |
|
354 | - * @deprecated |
|
355 | - */ |
|
356 | - public function get_attendee_by_ID($ATT_ID = false) |
|
357 | - { |
|
358 | - // retrieve a particular EE_Attendee |
|
359 | - return $this->get_one_by_ID($ATT_ID); |
|
360 | - } |
|
361 | - |
|
362 | - |
|
363 | - |
|
364 | - /** |
|
365 | - * retrieve a single attendee from db via their ID |
|
366 | - * |
|
367 | - * @param array $where_cols_n_values |
|
368 | - * @return mixed array on success, FALSE on fail |
|
369 | - * @throws EE_Error |
|
370 | - */ |
|
371 | - public function get_attendee($where_cols_n_values = array()) |
|
372 | - { |
|
373 | - if (empty($where_cols_n_values)) { |
|
374 | - return false; |
|
375 | - } |
|
376 | - $attendee = $this->get_all(array($where_cols_n_values)); |
|
377 | - if (! empty($attendee)) { |
|
378 | - return array_shift($attendee); |
|
379 | - } |
|
380 | - return false; |
|
381 | - } |
|
382 | - |
|
383 | - |
|
384 | - |
|
385 | - /** |
|
386 | - * Search for an existing Attendee record in the DB |
|
387 | - * |
|
388 | - * @param array $where_cols_n_values |
|
389 | - * @return bool|mixed |
|
390 | - * @throws EE_Error |
|
391 | - */ |
|
392 | - public function find_existing_attendee($where_cols_n_values = null) |
|
393 | - { |
|
394 | - // search by combo of first and last names plus the email address |
|
395 | - $attendee_data_keys = array( |
|
396 | - 'ATT_fname' => $this->_ATT_fname, |
|
397 | - 'ATT_lname' => $this->_ATT_lname, |
|
398 | - 'ATT_email' => $this->_ATT_email, |
|
399 | - ); |
|
400 | - // no search params means attendee object already exists. |
|
401 | - $where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values) |
|
402 | - ? $where_cols_n_values |
|
403 | - : $attendee_data_keys; |
|
404 | - $valid_data = true; |
|
405 | - // check for required values |
|
406 | - $valid_data = isset($where_cols_n_values['ATT_fname']) && ! empty($where_cols_n_values['ATT_fname']) |
|
407 | - ? $valid_data |
|
408 | - : false; |
|
409 | - $valid_data = isset($where_cols_n_values['ATT_lname']) && ! empty($where_cols_n_values['ATT_lname']) |
|
410 | - ? $valid_data |
|
411 | - : false; |
|
412 | - $valid_data = isset($where_cols_n_values['ATT_email']) && ! empty($where_cols_n_values['ATT_email']) |
|
413 | - ? $valid_data |
|
414 | - : false; |
|
415 | - if ($valid_data) { |
|
416 | - $attendee = $this->get_attendee($where_cols_n_values); |
|
417 | - if ($attendee instanceof EE_Attendee) { |
|
418 | - return $attendee; |
|
419 | - } |
|
420 | - } |
|
421 | - return false; |
|
422 | - } |
|
423 | - |
|
424 | - |
|
425 | - |
|
426 | - /** |
|
427 | - * Takes an incoming array of EE_Registration ids |
|
428 | - * and sends back a list of corresponding non duplicate EE_Attendee objects. |
|
429 | - * |
|
430 | - * @since 4.3.0 |
|
431 | - * @param array $ids array of EE_Registration ids |
|
432 | - * @return EE_Attendee[]|EE_Base_Class[] |
|
433 | - * @throws EE_Error |
|
434 | - */ |
|
435 | - public function get_array_of_contacts_from_reg_ids($ids) |
|
436 | - { |
|
437 | - $ids = (array) $ids; |
|
438 | - $_where = array( |
|
439 | - 'Registration.REG_ID' => array('in', $ids), |
|
440 | - ); |
|
441 | - return $this->get_all(array($_where)); |
|
442 | - } |
|
50 | + |
|
51 | + /** |
|
52 | + * @deprecated |
|
53 | + */ |
|
54 | + const city_question_id = 6; |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * @deprecated |
|
59 | + */ |
|
60 | + const state_question_id = 7; |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * @deprecated |
|
65 | + */ |
|
66 | + const country_question_id = 8; |
|
67 | + |
|
68 | + |
|
69 | + /** |
|
70 | + * @deprecated |
|
71 | + */ |
|
72 | + const zip_question_id = 9; |
|
73 | + |
|
74 | + |
|
75 | + /** |
|
76 | + * @deprecated |
|
77 | + */ |
|
78 | + const phone_question_id = 10; |
|
79 | + |
|
80 | + /** |
|
81 | + * When looking for questions that correspond to attendee fields, |
|
82 | + * look for the question with this QST_system value. |
|
83 | + * These replace the old constants like EEM_Attendee::*_question_id |
|
84 | + */ |
|
85 | + const system_question_fname = 'fname'; |
|
86 | + |
|
87 | + const system_question_lname = 'lname'; |
|
88 | + |
|
89 | + const system_question_email = 'email'; |
|
90 | + |
|
91 | + const system_question_email_confirm = 'email_confirm'; |
|
92 | + |
|
93 | + const system_question_address = 'address'; |
|
94 | + |
|
95 | + const system_question_address2 = 'address2'; |
|
96 | + |
|
97 | + const system_question_city = 'city'; |
|
98 | + |
|
99 | + const system_question_state = 'state'; |
|
100 | + |
|
101 | + const system_question_country = 'country'; |
|
102 | + |
|
103 | + const system_question_zip = 'zip'; |
|
104 | + |
|
105 | + const system_question_phone = 'phone'; |
|
106 | + |
|
107 | + /** |
|
108 | + * Keys are all the EEM_Attendee::system_question_* constants, which are |
|
109 | + * also all the values of QST_system in the questions table, and values |
|
110 | + * are their corresponding Attendee field names |
|
111 | + * |
|
112 | + * @var array |
|
113 | + */ |
|
114 | + protected $_system_question_to_attendee_field_name = array( |
|
115 | + EEM_Attendee::system_question_fname => 'ATT_fname', |
|
116 | + EEM_Attendee::system_question_lname => 'ATT_lname', |
|
117 | + EEM_Attendee::system_question_email => 'ATT_email', |
|
118 | + EEM_Attendee::system_question_address => 'ATT_address', |
|
119 | + EEM_Attendee::system_question_address2 => 'ATT_address2', |
|
120 | + EEM_Attendee::system_question_city => 'ATT_city', |
|
121 | + EEM_Attendee::system_question_state => 'STA_ID', |
|
122 | + EEM_Attendee::system_question_country => 'CNT_ISO', |
|
123 | + EEM_Attendee::system_question_zip => 'ATT_zip', |
|
124 | + EEM_Attendee::system_question_phone => 'ATT_phone', |
|
125 | + ); |
|
126 | + |
|
127 | + |
|
128 | + |
|
129 | + /** |
|
130 | + * EEM_Attendee constructor. |
|
131 | + * |
|
132 | + * @param null $timezone |
|
133 | + * @param ModelFieldFactory $model_field_factory |
|
134 | + * @throws EE_Error |
|
135 | + * @throws InvalidArgumentException |
|
136 | + */ |
|
137 | + protected function __construct($timezone, ModelFieldFactory $model_field_factory) |
|
138 | + { |
|
139 | + $this->singular_item = esc_html__('Attendee', 'event_espresso'); |
|
140 | + $this->plural_item = esc_html__('Attendees', 'event_espresso'); |
|
141 | + $this->_tables = array( |
|
142 | + 'Attendee_CPT' => new EE_Primary_Table('posts', 'ID'), |
|
143 | + 'Attendee_Meta' => new EE_Secondary_Table( |
|
144 | + 'esp_attendee_meta', |
|
145 | + 'ATTM_ID', |
|
146 | + 'ATT_ID' |
|
147 | + ), |
|
148 | + ); |
|
149 | + $this->_fields = array( |
|
150 | + 'Attendee_CPT' => array( |
|
151 | + 'ATT_ID' => $model_field_factory->createPrimaryKeyIntField( |
|
152 | + 'ID', |
|
153 | + esc_html__('Attendee ID', 'event_espresso') |
|
154 | + ), |
|
155 | + 'ATT_full_name' => $model_field_factory->createPlainTextField( |
|
156 | + 'post_title', |
|
157 | + esc_html__('Attendee Full Name', 'event_espresso'), |
|
158 | + false, |
|
159 | + esc_html__('Unknown', 'event_espresso') |
|
160 | + ), |
|
161 | + 'ATT_bio' => $model_field_factory->createPostContentField( |
|
162 | + 'post_content', |
|
163 | + esc_html__('Attendee Biography', 'event_espresso'), |
|
164 | + false, |
|
165 | + esc_html__('No Biography Provided', 'event_espresso') |
|
166 | + ), |
|
167 | + 'ATT_slug' => $model_field_factory->createSlugField( |
|
168 | + 'post_name', |
|
169 | + esc_html__('Attendee URL Slug', 'event_espresso') |
|
170 | + ), |
|
171 | + 'ATT_created' => $model_field_factory->createDatetimeField( |
|
172 | + 'post_date', |
|
173 | + esc_html__('Time Attendee Created', 'event_espresso') |
|
174 | + ), |
|
175 | + 'ATT_short_bio' => $model_field_factory->createSimpleHtmlField( |
|
176 | + 'post_excerpt', |
|
177 | + esc_html__('Attendee Short Biography', 'event_espresso'), |
|
178 | + true, |
|
179 | + esc_html__('No Biography Provided', 'event_espresso') |
|
180 | + ), |
|
181 | + 'ATT_modified' => $model_field_factory->createDatetimeField( |
|
182 | + 'post_modified', |
|
183 | + esc_html__('Time Attendee Last Modified', 'event_espresso') |
|
184 | + ), |
|
185 | + 'ATT_author' => $model_field_factory->createWpUserField( |
|
186 | + 'post_author', |
|
187 | + esc_html__('Creator ID of the first Event attended', 'event_espresso'), |
|
188 | + false |
|
189 | + ), |
|
190 | + 'ATT_parent' => $model_field_factory->createDbOnlyIntField( |
|
191 | + 'post_parent', |
|
192 | + esc_html__('Parent Attendee (unused)', 'event_espresso'), |
|
193 | + false, |
|
194 | + 0 |
|
195 | + ), |
|
196 | + 'post_type' => $model_field_factory->createWpPostTypeField('espresso_attendees'), |
|
197 | + 'status' => $model_field_factory->createWpPostStatusField( |
|
198 | + 'post_status', |
|
199 | + esc_html__('Attendee Status', 'event_espresso'), |
|
200 | + false, |
|
201 | + 'publish' |
|
202 | + ), |
|
203 | + 'password' => new EE_Password_Field( |
|
204 | + 'post_password', |
|
205 | + esc_html__('Password', 'event_espresso'), |
|
206 | + false, |
|
207 | + '', |
|
208 | + array( |
|
209 | + 'ATT_bio', |
|
210 | + 'ATT_short_bio', |
|
211 | + 'ATT_address', |
|
212 | + 'ATT_address2', |
|
213 | + 'ATT_city', |
|
214 | + 'STA_ID', |
|
215 | + 'CNT_ISO', |
|
216 | + 'ATT_zip', |
|
217 | + 'ATT_email', |
|
218 | + 'ATT_phone' |
|
219 | + ) |
|
220 | + ) |
|
221 | + ), |
|
222 | + 'Attendee_Meta' => array( |
|
223 | + 'ATTM_ID' => $model_field_factory->createDbOnlyIntField( |
|
224 | + 'ATTM_ID', |
|
225 | + esc_html__('Attendee Meta Row ID', 'event_espresso'), |
|
226 | + false |
|
227 | + ), |
|
228 | + 'ATT_ID_fk' => $model_field_factory->createDbOnlyIntField( |
|
229 | + 'ATT_ID', |
|
230 | + esc_html__('Foreign Key to Attendee in Post Table', 'event_espresso'), |
|
231 | + false |
|
232 | + ), |
|
233 | + 'ATT_fname' => $model_field_factory->createPlainTextField( |
|
234 | + 'ATT_fname', |
|
235 | + esc_html__('First Name', 'event_espresso') |
|
236 | + ), |
|
237 | + 'ATT_lname' => $model_field_factory->createPlainTextField( |
|
238 | + 'ATT_lname', |
|
239 | + esc_html__('Last Name', 'event_espresso') |
|
240 | + ), |
|
241 | + 'ATT_address' => $model_field_factory->createPlainTextField( |
|
242 | + 'ATT_address', |
|
243 | + esc_html__('Address Part 1', 'event_espresso') |
|
244 | + ), |
|
245 | + 'ATT_address2' => $model_field_factory->createPlainTextField( |
|
246 | + 'ATT_address2', |
|
247 | + esc_html__('Address Part 2', 'event_espresso') |
|
248 | + ), |
|
249 | + 'ATT_city' => $model_field_factory->createPlainTextField( |
|
250 | + 'ATT_city', |
|
251 | + esc_html__('City', 'event_espresso') |
|
252 | + ), |
|
253 | + 'STA_ID' => $model_field_factory->createForeignKeyIntField( |
|
254 | + 'STA_ID', |
|
255 | + esc_html__('State', 'event_espresso'), |
|
256 | + true, |
|
257 | + 0, |
|
258 | + 'State' |
|
259 | + ), |
|
260 | + 'CNT_ISO' => $model_field_factory->createForeignKeyStringField( |
|
261 | + 'CNT_ISO', |
|
262 | + esc_html__('Country', 'event_espresso'), |
|
263 | + true, |
|
264 | + '', |
|
265 | + 'Country' |
|
266 | + ), |
|
267 | + 'ATT_zip' => $model_field_factory->createPlainTextField( |
|
268 | + 'ATT_zip', |
|
269 | + esc_html__('ZIP/Postal Code', 'event_espresso') |
|
270 | + ), |
|
271 | + 'ATT_email' => $model_field_factory->createEmailField( |
|
272 | + 'ATT_email', |
|
273 | + esc_html__('Email Address', 'event_espresso') |
|
274 | + ), |
|
275 | + 'ATT_phone' => $model_field_factory->createPlainTextField( |
|
276 | + 'ATT_phone', |
|
277 | + esc_html__('Phone', 'event_espresso') |
|
278 | + ), |
|
279 | + ), |
|
280 | + ); |
|
281 | + $this->_model_relations = array( |
|
282 | + 'Registration' => new EE_Has_Many_Relation(), |
|
283 | + 'State' => new EE_Belongs_To_Relation(), |
|
284 | + 'Country' => new EE_Belongs_To_Relation(), |
|
285 | + 'Event' => new EE_HABTM_Relation('Registration', false), |
|
286 | + 'WP_User' => new EE_Belongs_To_Relation(), |
|
287 | + 'Message' => new EE_Has_Many_Any_Relation(false), |
|
288 | + // allow deletion of attendees even if they have messages in the queue for them. |
|
289 | + 'Term_Relationship' => new EE_Has_Many_Relation(), |
|
290 | + 'Term_Taxonomy' => new EE_HABTM_Relation('Term_Relationship'), |
|
291 | + ); |
|
292 | + $this->_caps_slug = 'contacts'; |
|
293 | + $this->model_chain_to_password = ''; |
|
294 | + parent::__construct($timezone); |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + |
|
299 | + /** |
|
300 | + * Gets the name of the field on the attendee model corresponding to the system question string |
|
301 | + * which should be one of the keys from EEM_Attendee::_system_question_to_attendee_field_name |
|
302 | + * |
|
303 | + * @param string $system_question_string |
|
304 | + * @return string|null if not found |
|
305 | + */ |
|
306 | + public function get_attendee_field_for_system_question($system_question_string) |
|
307 | + { |
|
308 | + return isset($this->_system_question_to_attendee_field_name[ $system_question_string ]) |
|
309 | + ? $this->_system_question_to_attendee_field_name[ $system_question_string ] |
|
310 | + : null; |
|
311 | + } |
|
312 | + |
|
313 | + |
|
314 | + |
|
315 | + /** |
|
316 | + * Gets mapping from esp_question.QST_system values to their corresponding attendee field names |
|
317 | + * |
|
318 | + * @return array |
|
319 | + */ |
|
320 | + public function system_question_to_attendee_field_mapping() |
|
321 | + { |
|
322 | + return $this->_system_question_to_attendee_field_name; |
|
323 | + } |
|
324 | + |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * Gets all the attendees for a transaction (by using the esp_registration as a join table) |
|
329 | + * |
|
330 | + * @param EE_Transaction /int $transaction_id_or_obj EE_Transaction or its ID |
|
331 | + * @return EE_Attendee[]|EE_Base_Class[] |
|
332 | + * @throws EE_Error |
|
333 | + */ |
|
334 | + public function get_attendees_for_transaction($transaction_id_or_obj) |
|
335 | + { |
|
336 | + return $this->get_all( |
|
337 | + array( |
|
338 | + array( |
|
339 | + 'Registration.Transaction.TXN_ID' => $transaction_id_or_obj instanceof EE_Transaction |
|
340 | + ? $transaction_id_or_obj->ID() |
|
341 | + : $transaction_id_or_obj, |
|
342 | + ), |
|
343 | + ) |
|
344 | + ); |
|
345 | + } |
|
346 | + |
|
347 | + |
|
348 | + |
|
349 | + /** |
|
350 | + * retrieve a single attendee from db via their ID |
|
351 | + * |
|
352 | + * @param $ATT_ID |
|
353 | + * @return mixed array on success, FALSE on fail |
|
354 | + * @deprecated |
|
355 | + */ |
|
356 | + public function get_attendee_by_ID($ATT_ID = false) |
|
357 | + { |
|
358 | + // retrieve a particular EE_Attendee |
|
359 | + return $this->get_one_by_ID($ATT_ID); |
|
360 | + } |
|
361 | + |
|
362 | + |
|
363 | + |
|
364 | + /** |
|
365 | + * retrieve a single attendee from db via their ID |
|
366 | + * |
|
367 | + * @param array $where_cols_n_values |
|
368 | + * @return mixed array on success, FALSE on fail |
|
369 | + * @throws EE_Error |
|
370 | + */ |
|
371 | + public function get_attendee($where_cols_n_values = array()) |
|
372 | + { |
|
373 | + if (empty($where_cols_n_values)) { |
|
374 | + return false; |
|
375 | + } |
|
376 | + $attendee = $this->get_all(array($where_cols_n_values)); |
|
377 | + if (! empty($attendee)) { |
|
378 | + return array_shift($attendee); |
|
379 | + } |
|
380 | + return false; |
|
381 | + } |
|
382 | + |
|
383 | + |
|
384 | + |
|
385 | + /** |
|
386 | + * Search for an existing Attendee record in the DB |
|
387 | + * |
|
388 | + * @param array $where_cols_n_values |
|
389 | + * @return bool|mixed |
|
390 | + * @throws EE_Error |
|
391 | + */ |
|
392 | + public function find_existing_attendee($where_cols_n_values = null) |
|
393 | + { |
|
394 | + // search by combo of first and last names plus the email address |
|
395 | + $attendee_data_keys = array( |
|
396 | + 'ATT_fname' => $this->_ATT_fname, |
|
397 | + 'ATT_lname' => $this->_ATT_lname, |
|
398 | + 'ATT_email' => $this->_ATT_email, |
|
399 | + ); |
|
400 | + // no search params means attendee object already exists. |
|
401 | + $where_cols_n_values = is_array($where_cols_n_values) && ! empty($where_cols_n_values) |
|
402 | + ? $where_cols_n_values |
|
403 | + : $attendee_data_keys; |
|
404 | + $valid_data = true; |
|
405 | + // check for required values |
|
406 | + $valid_data = isset($where_cols_n_values['ATT_fname']) && ! empty($where_cols_n_values['ATT_fname']) |
|
407 | + ? $valid_data |
|
408 | + : false; |
|
409 | + $valid_data = isset($where_cols_n_values['ATT_lname']) && ! empty($where_cols_n_values['ATT_lname']) |
|
410 | + ? $valid_data |
|
411 | + : false; |
|
412 | + $valid_data = isset($where_cols_n_values['ATT_email']) && ! empty($where_cols_n_values['ATT_email']) |
|
413 | + ? $valid_data |
|
414 | + : false; |
|
415 | + if ($valid_data) { |
|
416 | + $attendee = $this->get_attendee($where_cols_n_values); |
|
417 | + if ($attendee instanceof EE_Attendee) { |
|
418 | + return $attendee; |
|
419 | + } |
|
420 | + } |
|
421 | + return false; |
|
422 | + } |
|
423 | + |
|
424 | + |
|
425 | + |
|
426 | + /** |
|
427 | + * Takes an incoming array of EE_Registration ids |
|
428 | + * and sends back a list of corresponding non duplicate EE_Attendee objects. |
|
429 | + * |
|
430 | + * @since 4.3.0 |
|
431 | + * @param array $ids array of EE_Registration ids |
|
432 | + * @return EE_Attendee[]|EE_Base_Class[] |
|
433 | + * @throws EE_Error |
|
434 | + */ |
|
435 | + public function get_array_of_contacts_from_reg_ids($ids) |
|
436 | + { |
|
437 | + $ids = (array) $ids; |
|
438 | + $_where = array( |
|
439 | + 'Registration.REG_ID' => array('in', $ids), |
|
440 | + ); |
|
441 | + return $this->get_all(array($_where)); |
|
442 | + } |
|
443 | 443 | } |
@@ -13,218 +13,218 @@ |
||
13 | 13 | */ |
14 | 14 | class NoticesContainer implements NoticesContainerInterface |
15 | 15 | { |
16 | - /** |
|
17 | - * @var NoticeInterface[] $information |
|
18 | - */ |
|
19 | - private $information = array(); |
|
20 | - |
|
21 | - |
|
22 | - /** |
|
23 | - * @var NoticeInterface[] $attention |
|
24 | - */ |
|
25 | - private $attention = array(); |
|
26 | - |
|
27 | - |
|
28 | - /** |
|
29 | - * @var NoticeInterface[] $error |
|
30 | - */ |
|
31 | - private $error = array(); |
|
32 | - |
|
33 | - |
|
34 | - /** |
|
35 | - * @var NoticeInterface[] $success |
|
36 | - */ |
|
37 | - private $success = array(); |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * @param string $notice |
|
42 | - * @param bool $dismissible |
|
43 | - * @param string $file |
|
44 | - * @param string $func |
|
45 | - * @param string $line |
|
46 | - * @throws InvalidDataTypeException |
|
47 | - */ |
|
48 | - public function addInformation($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
49 | - { |
|
50 | - $this->information[] = new Notice( |
|
51 | - Notice::INFORMATION, |
|
52 | - $notice, |
|
53 | - $dismissible, |
|
54 | - $file, |
|
55 | - $func, |
|
56 | - $line |
|
57 | - ); |
|
58 | - } |
|
59 | - |
|
60 | - |
|
61 | - /** |
|
62 | - * @param string $notice |
|
63 | - * @param bool $dismissible |
|
64 | - * @param string $file |
|
65 | - * @param string $func |
|
66 | - * @param string $line |
|
67 | - * @throws InvalidDataTypeException |
|
68 | - */ |
|
69 | - public function addAttention($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
70 | - { |
|
71 | - $this->attention[] = new Notice( |
|
72 | - Notice::ATTENTION, |
|
73 | - $notice, |
|
74 | - $dismissible, |
|
75 | - $file, |
|
76 | - $func, |
|
77 | - $line |
|
78 | - ); |
|
79 | - } |
|
80 | - |
|
81 | - // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd |
|
82 | - /** |
|
83 | - * @param string $notice |
|
84 | - * @param bool $dismissible |
|
85 | - * @param string $file |
|
86 | - * @param string $func |
|
87 | - * @param string $line |
|
88 | - * @throws InvalidDataTypeException |
|
89 | - */ |
|
90 | - public function addError($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
91 | - { |
|
92 | - $this->error[] = new Notice( |
|
93 | - Notice::ERROR, |
|
94 | - $notice, |
|
95 | - $dismissible, |
|
96 | - $file, |
|
97 | - $func, |
|
98 | - $line |
|
99 | - ); |
|
100 | - } |
|
101 | - |
|
102 | - |
|
103 | - /** |
|
104 | - * @param string $notice |
|
105 | - * @param bool $dismissible |
|
106 | - * @param string $file |
|
107 | - * @param string $func |
|
108 | - * @param string $line |
|
109 | - * @throws InvalidDataTypeException |
|
110 | - */ |
|
111 | - public function addSuccess($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
112 | - { |
|
113 | - $this->success[] = new Notice( |
|
114 | - Notice::SUCCESS, |
|
115 | - $notice, |
|
116 | - $dismissible, |
|
117 | - $file, |
|
118 | - $func, |
|
119 | - $line |
|
120 | - ); |
|
121 | - } |
|
122 | - |
|
123 | - |
|
124 | - /** |
|
125 | - * @return boolean |
|
126 | - */ |
|
127 | - public function hasInformation() |
|
128 | - { |
|
129 | - return ! empty($this->information); |
|
130 | - } |
|
131 | - |
|
132 | - |
|
133 | - /** |
|
134 | - * @return boolean |
|
135 | - */ |
|
136 | - public function hasAttention() |
|
137 | - { |
|
138 | - return ! empty($this->attention); |
|
139 | - } |
|
140 | - |
|
141 | - |
|
142 | - /** |
|
143 | - * @return boolean |
|
144 | - */ |
|
145 | - public function hasError() |
|
146 | - { |
|
147 | - return ! empty($this->error); |
|
148 | - } |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * @return boolean |
|
153 | - */ |
|
154 | - public function hasSuccess() |
|
155 | - { |
|
156 | - return ! empty($this->success); |
|
157 | - } |
|
158 | - |
|
159 | - |
|
160 | - /** |
|
161 | - * @return int |
|
162 | - */ |
|
163 | - public function countInformation() |
|
164 | - { |
|
165 | - return count($this->information); |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @return int |
|
171 | - */ |
|
172 | - public function countAttention() |
|
173 | - { |
|
174 | - return count($this->attention); |
|
175 | - } |
|
176 | - |
|
177 | - |
|
178 | - /** |
|
179 | - * @return int |
|
180 | - */ |
|
181 | - public function countError() |
|
182 | - { |
|
183 | - return count($this->error); |
|
184 | - } |
|
185 | - |
|
186 | - |
|
187 | - /** |
|
188 | - * @return int |
|
189 | - */ |
|
190 | - public function countSuccess() |
|
191 | - { |
|
192 | - return count($this->success); |
|
193 | - } |
|
194 | - |
|
195 | - |
|
196 | - /** |
|
197 | - * @return NoticeInterface[] |
|
198 | - */ |
|
199 | - public function getInformation() |
|
200 | - { |
|
201 | - return $this->information; |
|
202 | - } |
|
203 | - |
|
204 | - |
|
205 | - /** |
|
206 | - * @return NoticeInterface[] |
|
207 | - */ |
|
208 | - public function getAttention() |
|
209 | - { |
|
210 | - return $this->attention; |
|
211 | - } |
|
212 | - |
|
213 | - |
|
214 | - /** |
|
215 | - * @return NoticeInterface[] |
|
216 | - */ |
|
217 | - public function getError() |
|
218 | - { |
|
219 | - return $this->error; |
|
220 | - } |
|
221 | - |
|
222 | - |
|
223 | - /** |
|
224 | - * @return NoticeInterface[] |
|
225 | - */ |
|
226 | - public function getSuccess() |
|
227 | - { |
|
228 | - return $this->success; |
|
229 | - } |
|
16 | + /** |
|
17 | + * @var NoticeInterface[] $information |
|
18 | + */ |
|
19 | + private $information = array(); |
|
20 | + |
|
21 | + |
|
22 | + /** |
|
23 | + * @var NoticeInterface[] $attention |
|
24 | + */ |
|
25 | + private $attention = array(); |
|
26 | + |
|
27 | + |
|
28 | + /** |
|
29 | + * @var NoticeInterface[] $error |
|
30 | + */ |
|
31 | + private $error = array(); |
|
32 | + |
|
33 | + |
|
34 | + /** |
|
35 | + * @var NoticeInterface[] $success |
|
36 | + */ |
|
37 | + private $success = array(); |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * @param string $notice |
|
42 | + * @param bool $dismissible |
|
43 | + * @param string $file |
|
44 | + * @param string $func |
|
45 | + * @param string $line |
|
46 | + * @throws InvalidDataTypeException |
|
47 | + */ |
|
48 | + public function addInformation($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
49 | + { |
|
50 | + $this->information[] = new Notice( |
|
51 | + Notice::INFORMATION, |
|
52 | + $notice, |
|
53 | + $dismissible, |
|
54 | + $file, |
|
55 | + $func, |
|
56 | + $line |
|
57 | + ); |
|
58 | + } |
|
59 | + |
|
60 | + |
|
61 | + /** |
|
62 | + * @param string $notice |
|
63 | + * @param bool $dismissible |
|
64 | + * @param string $file |
|
65 | + * @param string $func |
|
66 | + * @param string $line |
|
67 | + * @throws InvalidDataTypeException |
|
68 | + */ |
|
69 | + public function addAttention($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
70 | + { |
|
71 | + $this->attention[] = new Notice( |
|
72 | + Notice::ATTENTION, |
|
73 | + $notice, |
|
74 | + $dismissible, |
|
75 | + $file, |
|
76 | + $func, |
|
77 | + $line |
|
78 | + ); |
|
79 | + } |
|
80 | + |
|
81 | + // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd |
|
82 | + /** |
|
83 | + * @param string $notice |
|
84 | + * @param bool $dismissible |
|
85 | + * @param string $file |
|
86 | + * @param string $func |
|
87 | + * @param string $line |
|
88 | + * @throws InvalidDataTypeException |
|
89 | + */ |
|
90 | + public function addError($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
91 | + { |
|
92 | + $this->error[] = new Notice( |
|
93 | + Notice::ERROR, |
|
94 | + $notice, |
|
95 | + $dismissible, |
|
96 | + $file, |
|
97 | + $func, |
|
98 | + $line |
|
99 | + ); |
|
100 | + } |
|
101 | + |
|
102 | + |
|
103 | + /** |
|
104 | + * @param string $notice |
|
105 | + * @param bool $dismissible |
|
106 | + * @param string $file |
|
107 | + * @param string $func |
|
108 | + * @param string $line |
|
109 | + * @throws InvalidDataTypeException |
|
110 | + */ |
|
111 | + public function addSuccess($notice, $dismissible = true, $file = '', $func = '', $line = '') |
|
112 | + { |
|
113 | + $this->success[] = new Notice( |
|
114 | + Notice::SUCCESS, |
|
115 | + $notice, |
|
116 | + $dismissible, |
|
117 | + $file, |
|
118 | + $func, |
|
119 | + $line |
|
120 | + ); |
|
121 | + } |
|
122 | + |
|
123 | + |
|
124 | + /** |
|
125 | + * @return boolean |
|
126 | + */ |
|
127 | + public function hasInformation() |
|
128 | + { |
|
129 | + return ! empty($this->information); |
|
130 | + } |
|
131 | + |
|
132 | + |
|
133 | + /** |
|
134 | + * @return boolean |
|
135 | + */ |
|
136 | + public function hasAttention() |
|
137 | + { |
|
138 | + return ! empty($this->attention); |
|
139 | + } |
|
140 | + |
|
141 | + |
|
142 | + /** |
|
143 | + * @return boolean |
|
144 | + */ |
|
145 | + public function hasError() |
|
146 | + { |
|
147 | + return ! empty($this->error); |
|
148 | + } |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * @return boolean |
|
153 | + */ |
|
154 | + public function hasSuccess() |
|
155 | + { |
|
156 | + return ! empty($this->success); |
|
157 | + } |
|
158 | + |
|
159 | + |
|
160 | + /** |
|
161 | + * @return int |
|
162 | + */ |
|
163 | + public function countInformation() |
|
164 | + { |
|
165 | + return count($this->information); |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @return int |
|
171 | + */ |
|
172 | + public function countAttention() |
|
173 | + { |
|
174 | + return count($this->attention); |
|
175 | + } |
|
176 | + |
|
177 | + |
|
178 | + /** |
|
179 | + * @return int |
|
180 | + */ |
|
181 | + public function countError() |
|
182 | + { |
|
183 | + return count($this->error); |
|
184 | + } |
|
185 | + |
|
186 | + |
|
187 | + /** |
|
188 | + * @return int |
|
189 | + */ |
|
190 | + public function countSuccess() |
|
191 | + { |
|
192 | + return count($this->success); |
|
193 | + } |
|
194 | + |
|
195 | + |
|
196 | + /** |
|
197 | + * @return NoticeInterface[] |
|
198 | + */ |
|
199 | + public function getInformation() |
|
200 | + { |
|
201 | + return $this->information; |
|
202 | + } |
|
203 | + |
|
204 | + |
|
205 | + /** |
|
206 | + * @return NoticeInterface[] |
|
207 | + */ |
|
208 | + public function getAttention() |
|
209 | + { |
|
210 | + return $this->attention; |
|
211 | + } |
|
212 | + |
|
213 | + |
|
214 | + /** |
|
215 | + * @return NoticeInterface[] |
|
216 | + */ |
|
217 | + public function getError() |
|
218 | + { |
|
219 | + return $this->error; |
|
220 | + } |
|
221 | + |
|
222 | + |
|
223 | + /** |
|
224 | + * @return NoticeInterface[] |
|
225 | + */ |
|
226 | + public function getSuccess() |
|
227 | + { |
|
228 | + return $this->success; |
|
229 | + } |
|
230 | 230 | } |
@@ -12,129 +12,129 @@ |
||
12 | 12 | */ |
13 | 13 | interface NoticesContainerInterface |
14 | 14 | { |
15 | - /** |
|
16 | - * @param string $notice |
|
17 | - * @param bool $dismissible |
|
18 | - * @param string $file |
|
19 | - * @param string $func |
|
20 | - * @param string $line |
|
21 | - */ |
|
22 | - public function addInformation($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
15 | + /** |
|
16 | + * @param string $notice |
|
17 | + * @param bool $dismissible |
|
18 | + * @param string $file |
|
19 | + * @param string $func |
|
20 | + * @param string $line |
|
21 | + */ |
|
22 | + public function addInformation($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
23 | 23 | |
24 | 24 | |
25 | - /** |
|
26 | - * @param string $notice |
|
27 | - * @param bool $dismissible |
|
28 | - * @param string $file |
|
29 | - * @param string $func |
|
30 | - * @param string $line |
|
31 | - * @return |
|
32 | - */ |
|
33 | - public function addAttention($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
25 | + /** |
|
26 | + * @param string $notice |
|
27 | + * @param bool $dismissible |
|
28 | + * @param string $file |
|
29 | + * @param string $func |
|
30 | + * @param string $line |
|
31 | + * @return |
|
32 | + */ |
|
33 | + public function addAttention($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
34 | 34 | |
35 | 35 | |
36 | 36 | |
37 | - /** |
|
38 | - * @param string $notice |
|
39 | - * @param bool $dismissible |
|
40 | - * @param string $file |
|
41 | - * @param string $func |
|
42 | - * @param string $line |
|
43 | - */ |
|
44 | - public function addError($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
37 | + /** |
|
38 | + * @param string $notice |
|
39 | + * @param bool $dismissible |
|
40 | + * @param string $file |
|
41 | + * @param string $func |
|
42 | + * @param string $line |
|
43 | + */ |
|
44 | + public function addError($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
45 | 45 | |
46 | 46 | |
47 | 47 | |
48 | - /** |
|
49 | - * @param string $notice |
|
50 | - * @param bool $dismissible |
|
51 | - * @param string $file |
|
52 | - * @param string $func |
|
53 | - * @param string $line |
|
54 | - */ |
|
55 | - public function addSuccess($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
48 | + /** |
|
49 | + * @param string $notice |
|
50 | + * @param bool $dismissible |
|
51 | + * @param string $file |
|
52 | + * @param string $func |
|
53 | + * @param string $line |
|
54 | + */ |
|
55 | + public function addSuccess($notice, $dismissible = true, $file = '', $func = '', $line = ''); |
|
56 | 56 | |
57 | 57 | |
58 | 58 | |
59 | - /** |
|
60 | - * @return boolean |
|
61 | - */ |
|
62 | - public function hasInformation(); |
|
59 | + /** |
|
60 | + * @return boolean |
|
61 | + */ |
|
62 | + public function hasInformation(); |
|
63 | 63 | |
64 | 64 | |
65 | 65 | |
66 | - /** |
|
67 | - * @return boolean |
|
68 | - */ |
|
69 | - public function hasAttention(); |
|
66 | + /** |
|
67 | + * @return boolean |
|
68 | + */ |
|
69 | + public function hasAttention(); |
|
70 | 70 | |
71 | 71 | |
72 | 72 | |
73 | - /** |
|
74 | - * @return boolean |
|
75 | - */ |
|
76 | - public function hasError(); |
|
73 | + /** |
|
74 | + * @return boolean |
|
75 | + */ |
|
76 | + public function hasError(); |
|
77 | 77 | |
78 | 78 | |
79 | 79 | |
80 | - /** |
|
81 | - * @return boolean |
|
82 | - */ |
|
83 | - public function hasSuccess(); |
|
80 | + /** |
|
81 | + * @return boolean |
|
82 | + */ |
|
83 | + public function hasSuccess(); |
|
84 | 84 | |
85 | 85 | |
86 | 86 | |
87 | - /** |
|
88 | - * @return int |
|
89 | - */ |
|
90 | - public function countInformation(); |
|
87 | + /** |
|
88 | + * @return int |
|
89 | + */ |
|
90 | + public function countInformation(); |
|
91 | 91 | |
92 | 92 | |
93 | 93 | |
94 | - /** |
|
95 | - * @return int |
|
96 | - */ |
|
97 | - public function countAttention(); |
|
94 | + /** |
|
95 | + * @return int |
|
96 | + */ |
|
97 | + public function countAttention(); |
|
98 | 98 | |
99 | 99 | |
100 | 100 | |
101 | - /** |
|
102 | - * @return int |
|
103 | - */ |
|
104 | - public function countError(); |
|
101 | + /** |
|
102 | + * @return int |
|
103 | + */ |
|
104 | + public function countError(); |
|
105 | 105 | |
106 | 106 | |
107 | 107 | |
108 | - /** |
|
109 | - * @return int |
|
110 | - */ |
|
111 | - public function countSuccess(); |
|
108 | + /** |
|
109 | + * @return int |
|
110 | + */ |
|
111 | + public function countSuccess(); |
|
112 | 112 | |
113 | 113 | |
114 | 114 | |
115 | - /** |
|
116 | - * @return NoticeInterface[] |
|
117 | - */ |
|
118 | - public function getInformation(); |
|
115 | + /** |
|
116 | + * @return NoticeInterface[] |
|
117 | + */ |
|
118 | + public function getInformation(); |
|
119 | 119 | |
120 | 120 | |
121 | 121 | |
122 | - /** |
|
123 | - * @return NoticeInterface[] |
|
124 | - */ |
|
125 | - public function getAttention(); |
|
122 | + /** |
|
123 | + * @return NoticeInterface[] |
|
124 | + */ |
|
125 | + public function getAttention(); |
|
126 | 126 | |
127 | 127 | |
128 | 128 | |
129 | - /** |
|
130 | - * @return NoticeInterface[] |
|
131 | - */ |
|
132 | - public function getError(); |
|
129 | + /** |
|
130 | + * @return NoticeInterface[] |
|
131 | + */ |
|
132 | + public function getError(); |
|
133 | 133 | |
134 | 134 | |
135 | 135 | |
136 | - /** |
|
137 | - * @return NoticeInterface[] |
|
138 | - */ |
|
139 | - public function getSuccess(); |
|
136 | + /** |
|
137 | + * @return NoticeInterface[] |
|
138 | + */ |
|
139 | + public function getSuccess(); |
|
140 | 140 | } |
@@ -154,7 +154,7 @@ discard block |
||
154 | 154 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
155 | 155 | // Invisible Recaptcha is ONLY ever required for the frontend and admin |
156 | 156 | // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
157 | - if (! ($request->isAdmin() || $request->isFrontend())) { |
|
157 | + if ( ! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | 158 | return; |
159 | 159 | } |
160 | 160 | wp_localize_script( |
@@ -170,7 +170,7 @@ discard block |
||
170 | 170 | */ |
171 | 171 | public static function assetsUrl() |
172 | 172 | { |
173 | - return plugin_dir_url(__FILE__) . 'assets/'; |
|
173 | + return plugin_dir_url(__FILE__).'assets/'; |
|
174 | 174 | } |
175 | 175 | |
176 | 176 | |
@@ -208,7 +208,7 @@ discard block |
||
208 | 208 | public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
209 | 209 | { |
210 | 210 | // do nothing if form isn't for a reg step or test has already been passed |
211 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
211 | + if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | 212 | return; |
213 | 213 | } |
214 | 214 | $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
@@ -247,12 +247,12 @@ discard block |
||
247 | 247 | public static function receiveSpcoRegStepForm($req_data, EE_Form_Section_Proper $reg_form) |
248 | 248 | { |
249 | 249 | // do nothing if form isn't for a reg step or test has already been passed |
250 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
250 | + if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | 251 | return $req_data; |
252 | 252 | } |
253 | 253 | /** @var RequestInterface $request */ |
254 | 254 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
255 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
255 | + if ( ! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | 256 | if ($request->isAjax()) { |
257 | 257 | $json_response = new EE_SPCO_JSON_Response(); |
258 | 258 | $json_response->echoAndExit(); |
@@ -310,7 +310,7 @@ discard block |
||
310 | 310 | } |
311 | 311 | /** @var RequestInterface $request */ |
312 | 312 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
313 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
313 | + if ( ! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | 314 | $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
315 | 315 | $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
316 | 316 | ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
@@ -17,332 +17,332 @@ |
||
17 | 17 | */ |
18 | 18 | class EED_Recaptcha_Invisible extends EED_Module |
19 | 19 | { |
20 | - /** |
|
21 | - * @var EE_Registration_Config $config |
|
22 | - */ |
|
23 | - private static $config; |
|
24 | - |
|
25 | - |
|
26 | - /** |
|
27 | - * @return EED_Module|EED_Recaptcha |
|
28 | - */ |
|
29 | - public static function instance() |
|
30 | - { |
|
31 | - return parent::get_instance(__CLASS__); |
|
32 | - } |
|
33 | - |
|
34 | - |
|
35 | - /** |
|
36 | - * @return void |
|
37 | - * @throws InvalidInterfaceException |
|
38 | - * @throws InvalidDataTypeException |
|
39 | - * @throws InvalidArgumentException |
|
40 | - */ |
|
41 | - public static function set_hooks() |
|
42 | - { |
|
43 | - EED_Recaptcha_Invisible::setProperties(); |
|
44 | - if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) { |
|
45 | - if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
46 | - // ticket selection |
|
47 | - add_filter( |
|
48 | - 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
49 | - array('EED_Recaptcha_Invisible', 'ticketSelectorForm'), |
|
50 | - 10, |
|
51 | - 3 |
|
52 | - ); |
|
53 | - add_action( |
|
54 | - 'EED_Ticket_Selector__process_ticket_selections__before', |
|
55 | - array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
56 | - ); |
|
57 | - } |
|
58 | - if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
59 | - // checkout |
|
60 | - add_action( |
|
61 | - 'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', |
|
62 | - array('EED_Recaptcha_Invisible', 'spcoRegStepForm') |
|
63 | - ); |
|
64 | - add_filter( |
|
65 | - 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
66 | - array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
67 | - 10, |
|
68 | - 2 |
|
69 | - ); |
|
70 | - } |
|
71 | - add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars')); |
|
72 | - } |
|
73 | - } |
|
74 | - |
|
75 | - |
|
76 | - /** |
|
77 | - * @return void |
|
78 | - * @throws InvalidInterfaceException |
|
79 | - * @throws InvalidDataTypeException |
|
80 | - * @throws InvalidArgumentException |
|
81 | - */ |
|
82 | - public static function set_hooks_admin() |
|
83 | - { |
|
84 | - EED_Recaptcha_Invisible::setProperties(); |
|
85 | - if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
86 | - add_action( |
|
87 | - 'EED_Ticket_Selector__process_ticket_selections__before', |
|
88 | - array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
89 | - ); |
|
90 | - } |
|
91 | - if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
92 | - add_filter( |
|
93 | - 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
94 | - array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
95 | - 10, |
|
96 | - 2 |
|
97 | - ); |
|
98 | - } |
|
99 | - // admin settings |
|
100 | - add_action( |
|
101 | - 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
102 | - array('EED_Recaptcha_Invisible', 'adminSettings') |
|
103 | - ); |
|
104 | - add_filter( |
|
105 | - 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
106 | - array('EED_Recaptcha_Invisible', 'updateAdminSettings') |
|
107 | - ); |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - /** |
|
112 | - * @return void |
|
113 | - * @throws InvalidInterfaceException |
|
114 | - * @throws InvalidDataTypeException |
|
115 | - * @throws InvalidArgumentException |
|
116 | - */ |
|
117 | - public static function setProperties() |
|
118 | - { |
|
119 | - |
|
120 | - EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration; |
|
121 | - } |
|
122 | - |
|
123 | - |
|
124 | - /** |
|
125 | - * @return boolean |
|
126 | - */ |
|
127 | - public static function useInvisibleRecaptcha() |
|
128 | - { |
|
129 | - return EED_Recaptcha_Invisible::$config->use_captcha |
|
130 | - && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible'; |
|
131 | - } |
|
132 | - |
|
133 | - |
|
134 | - /** |
|
135 | - * @param string $form |
|
136 | - * @return boolean |
|
137 | - */ |
|
138 | - public static function protectForm($form) |
|
139 | - { |
|
140 | - return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms) |
|
141 | - && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true); |
|
142 | - } |
|
143 | - |
|
144 | - |
|
145 | - /** |
|
146 | - * @return void |
|
147 | - * @throws InvalidInterfaceException |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws InvalidArgumentException |
|
150 | - */ |
|
151 | - public static function localizeScriptVars() |
|
152 | - { |
|
153 | - /** @var \EventEspresso\core\services\request\Request $request */ |
|
154 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
|
155 | - // Invisible Recaptcha is ONLY ever required for the frontend and admin |
|
156 | - // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
|
157 | - if (! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | - return; |
|
159 | - } |
|
160 | - wp_localize_script( |
|
161 | - EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA, |
|
162 | - 'eeRecaptcha', |
|
163 | - RecaptchaFactory::create()->getLocalizedVars() |
|
164 | - ); |
|
165 | - } |
|
166 | - |
|
167 | - |
|
168 | - /** |
|
169 | - * @return string |
|
170 | - */ |
|
171 | - public static function assetsUrl() |
|
172 | - { |
|
173 | - return plugin_dir_url(__FILE__) . 'assets/'; |
|
174 | - } |
|
175 | - |
|
176 | - |
|
177 | - /** |
|
178 | - * @param \WP $WP |
|
179 | - */ |
|
180 | - public function run($WP) |
|
181 | - { |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - /** |
|
186 | - * @param RequestInterface $request |
|
187 | - * @return bool |
|
188 | - * @throws InvalidArgumentException |
|
189 | - * @throws InvalidDataTypeException |
|
190 | - * @throws InvalidInterfaceException |
|
191 | - * @throws RuntimeException |
|
192 | - */ |
|
193 | - public static function verifyToken(RequestInterface $request) |
|
194 | - { |
|
195 | - return RecaptchaFactory::create()->verifyToken($request); |
|
196 | - } |
|
197 | - |
|
198 | - |
|
199 | - /** |
|
200 | - * @param EE_Form_Section_Proper $reg_form |
|
201 | - * @return void |
|
202 | - * @throws EE_Error |
|
203 | - * @throws InvalidArgumentException |
|
204 | - * @throws InvalidDataTypeException |
|
205 | - * @throws InvalidInterfaceException |
|
206 | - * @throws DomainException |
|
207 | - */ |
|
208 | - public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
209 | - { |
|
210 | - // do nothing if form isn't for a reg step or test has already been passed |
|
211 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | - return; |
|
213 | - } |
|
214 | - $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
|
215 | - if ($default_hidden_inputs instanceof EE_Form_Section_Proper) { |
|
216 | - $invisible_recaptcha = RecaptchaFactory::create(); |
|
217 | - $invisible_recaptcha->addToFormSection($default_hidden_inputs); |
|
218 | - } |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * @param EE_Form_Section_Proper $reg_form |
|
224 | - * @return bool |
|
225 | - * @throws InvalidDataTypeException |
|
226 | - * @throws InvalidInterfaceException |
|
227 | - * @throws EE_Error |
|
228 | - * @throws InvalidArgumentException |
|
229 | - */ |
|
230 | - public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
231 | - { |
|
232 | - return strpos($reg_form->name(), 'reg-step-form') !== false |
|
233 | - && ! RecaptchaFactory::create()->recaptchaPassed(); |
|
234 | - } |
|
235 | - |
|
236 | - |
|
237 | - /** |
|
238 | - * @param array|null $req_data |
|
239 | - * @param EE_Form_Section_Proper $reg_form |
|
240 | - * @return array |
|
241 | - * @throws EE_Error |
|
242 | - * @throws InvalidArgumentException |
|
243 | - * @throws InvalidDataTypeException |
|
244 | - * @throws InvalidInterfaceException |
|
245 | - * @throws RuntimeException |
|
246 | - */ |
|
247 | - public static function receiveSpcoRegStepForm($req_data, EE_Form_Section_Proper $reg_form) |
|
248 | - { |
|
249 | - // do nothing if form isn't for a reg step or test has already been passed |
|
250 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | - return $req_data; |
|
252 | - } |
|
253 | - /** @var RequestInterface $request */ |
|
254 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
255 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | - if ($request->isAjax()) { |
|
257 | - $json_response = new EE_SPCO_JSON_Response(); |
|
258 | - $json_response->echoAndExit(); |
|
259 | - } |
|
260 | - EEH_URL::safeRedirectAndExit( |
|
261 | - EE_Registry::instance()->CFG->core->reg_page_url() |
|
262 | - ); |
|
263 | - } |
|
264 | - return $req_data; |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - /** |
|
269 | - * @param string $html |
|
270 | - * @param EE_Event $event |
|
271 | - * @param bool $iframe |
|
272 | - * @return string |
|
273 | - * @throws EE_Error |
|
274 | - * @throws InvalidArgumentException |
|
275 | - * @throws InvalidDataTypeException |
|
276 | - * @throws InvalidInterfaceException |
|
277 | - * @throws ReflectionException |
|
278 | - * @throws DomainException |
|
279 | - */ |
|
280 | - public static function ticketSelectorForm(string $html, EE_Event $event, $iframe = false) |
|
281 | - { |
|
282 | - $recaptcha = RecaptchaFactory::create(); |
|
283 | - // do nothing if test has already been passed |
|
284 | - if ($recaptcha->recaptchaPassed()) { |
|
285 | - return $html; |
|
286 | - } |
|
287 | - $html .= $recaptcha->getInputHtml( |
|
288 | - array( |
|
289 | - 'recaptcha_id' => $event->ID(), |
|
290 | - 'iframe' => $iframe, |
|
291 | - 'localized_vars' => $recaptcha->getLocalizedVars(), |
|
292 | - ) |
|
293 | - ); |
|
294 | - return $html; |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * @return void |
|
300 | - * @throws InvalidArgumentException |
|
301 | - * @throws InvalidInterfaceException |
|
302 | - * @throws InvalidDataTypeException |
|
303 | - * @throws RuntimeException |
|
304 | - */ |
|
305 | - public static function processTicketSelectorForm() |
|
306 | - { |
|
307 | - // do nothing if test has already been passed |
|
308 | - if (RecaptchaFactory::create()->recaptchaPassed()) { |
|
309 | - return; |
|
310 | - } |
|
311 | - /** @var RequestInterface $request */ |
|
312 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
313 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | - $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
|
315 | - $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
|
316 | - ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
|
317 | - : get_permalink($event_id); |
|
318 | - EEH_URL::safeRedirectAndExit($return_url); |
|
319 | - } |
|
320 | - } |
|
321 | - |
|
322 | - |
|
323 | - /** |
|
324 | - * @throws EE_Error |
|
325 | - * @throws InvalidArgumentException |
|
326 | - * @throws InvalidDataTypeException |
|
327 | - * @throws InvalidInterfaceException |
|
328 | - */ |
|
329 | - public static function adminSettings() |
|
330 | - { |
|
331 | - RecaptchaFactory::getAdminModule()->adminSettings(); |
|
332 | - } |
|
333 | - |
|
334 | - |
|
335 | - /** |
|
336 | - * @param EE_Registration_Config $EE_Registration_Config |
|
337 | - * @return EE_Registration_Config |
|
338 | - * @throws EE_Error |
|
339 | - * @throws InvalidArgumentException |
|
340 | - * @throws InvalidDataTypeException |
|
341 | - * @throws InvalidInterfaceException |
|
342 | - * @throws ReflectionException |
|
343 | - */ |
|
344 | - public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config) |
|
345 | - { |
|
346 | - return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config); |
|
347 | - } |
|
20 | + /** |
|
21 | + * @var EE_Registration_Config $config |
|
22 | + */ |
|
23 | + private static $config; |
|
24 | + |
|
25 | + |
|
26 | + /** |
|
27 | + * @return EED_Module|EED_Recaptcha |
|
28 | + */ |
|
29 | + public static function instance() |
|
30 | + { |
|
31 | + return parent::get_instance(__CLASS__); |
|
32 | + } |
|
33 | + |
|
34 | + |
|
35 | + /** |
|
36 | + * @return void |
|
37 | + * @throws InvalidInterfaceException |
|
38 | + * @throws InvalidDataTypeException |
|
39 | + * @throws InvalidArgumentException |
|
40 | + */ |
|
41 | + public static function set_hooks() |
|
42 | + { |
|
43 | + EED_Recaptcha_Invisible::setProperties(); |
|
44 | + if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) { |
|
45 | + if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
46 | + // ticket selection |
|
47 | + add_filter( |
|
48 | + 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
49 | + array('EED_Recaptcha_Invisible', 'ticketSelectorForm'), |
|
50 | + 10, |
|
51 | + 3 |
|
52 | + ); |
|
53 | + add_action( |
|
54 | + 'EED_Ticket_Selector__process_ticket_selections__before', |
|
55 | + array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
56 | + ); |
|
57 | + } |
|
58 | + if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
59 | + // checkout |
|
60 | + add_action( |
|
61 | + 'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', |
|
62 | + array('EED_Recaptcha_Invisible', 'spcoRegStepForm') |
|
63 | + ); |
|
64 | + add_filter( |
|
65 | + 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
66 | + array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
67 | + 10, |
|
68 | + 2 |
|
69 | + ); |
|
70 | + } |
|
71 | + add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars')); |
|
72 | + } |
|
73 | + } |
|
74 | + |
|
75 | + |
|
76 | + /** |
|
77 | + * @return void |
|
78 | + * @throws InvalidInterfaceException |
|
79 | + * @throws InvalidDataTypeException |
|
80 | + * @throws InvalidArgumentException |
|
81 | + */ |
|
82 | + public static function set_hooks_admin() |
|
83 | + { |
|
84 | + EED_Recaptcha_Invisible::setProperties(); |
|
85 | + if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
86 | + add_action( |
|
87 | + 'EED_Ticket_Selector__process_ticket_selections__before', |
|
88 | + array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
89 | + ); |
|
90 | + } |
|
91 | + if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
92 | + add_filter( |
|
93 | + 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
94 | + array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
95 | + 10, |
|
96 | + 2 |
|
97 | + ); |
|
98 | + } |
|
99 | + // admin settings |
|
100 | + add_action( |
|
101 | + 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
102 | + array('EED_Recaptcha_Invisible', 'adminSettings') |
|
103 | + ); |
|
104 | + add_filter( |
|
105 | + 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
106 | + array('EED_Recaptcha_Invisible', 'updateAdminSettings') |
|
107 | + ); |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + /** |
|
112 | + * @return void |
|
113 | + * @throws InvalidInterfaceException |
|
114 | + * @throws InvalidDataTypeException |
|
115 | + * @throws InvalidArgumentException |
|
116 | + */ |
|
117 | + public static function setProperties() |
|
118 | + { |
|
119 | + |
|
120 | + EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration; |
|
121 | + } |
|
122 | + |
|
123 | + |
|
124 | + /** |
|
125 | + * @return boolean |
|
126 | + */ |
|
127 | + public static function useInvisibleRecaptcha() |
|
128 | + { |
|
129 | + return EED_Recaptcha_Invisible::$config->use_captcha |
|
130 | + && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible'; |
|
131 | + } |
|
132 | + |
|
133 | + |
|
134 | + /** |
|
135 | + * @param string $form |
|
136 | + * @return boolean |
|
137 | + */ |
|
138 | + public static function protectForm($form) |
|
139 | + { |
|
140 | + return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms) |
|
141 | + && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true); |
|
142 | + } |
|
143 | + |
|
144 | + |
|
145 | + /** |
|
146 | + * @return void |
|
147 | + * @throws InvalidInterfaceException |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws InvalidArgumentException |
|
150 | + */ |
|
151 | + public static function localizeScriptVars() |
|
152 | + { |
|
153 | + /** @var \EventEspresso\core\services\request\Request $request */ |
|
154 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
|
155 | + // Invisible Recaptcha is ONLY ever required for the frontend and admin |
|
156 | + // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
|
157 | + if (! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | + return; |
|
159 | + } |
|
160 | + wp_localize_script( |
|
161 | + EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA, |
|
162 | + 'eeRecaptcha', |
|
163 | + RecaptchaFactory::create()->getLocalizedVars() |
|
164 | + ); |
|
165 | + } |
|
166 | + |
|
167 | + |
|
168 | + /** |
|
169 | + * @return string |
|
170 | + */ |
|
171 | + public static function assetsUrl() |
|
172 | + { |
|
173 | + return plugin_dir_url(__FILE__) . 'assets/'; |
|
174 | + } |
|
175 | + |
|
176 | + |
|
177 | + /** |
|
178 | + * @param \WP $WP |
|
179 | + */ |
|
180 | + public function run($WP) |
|
181 | + { |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + /** |
|
186 | + * @param RequestInterface $request |
|
187 | + * @return bool |
|
188 | + * @throws InvalidArgumentException |
|
189 | + * @throws InvalidDataTypeException |
|
190 | + * @throws InvalidInterfaceException |
|
191 | + * @throws RuntimeException |
|
192 | + */ |
|
193 | + public static function verifyToken(RequestInterface $request) |
|
194 | + { |
|
195 | + return RecaptchaFactory::create()->verifyToken($request); |
|
196 | + } |
|
197 | + |
|
198 | + |
|
199 | + /** |
|
200 | + * @param EE_Form_Section_Proper $reg_form |
|
201 | + * @return void |
|
202 | + * @throws EE_Error |
|
203 | + * @throws InvalidArgumentException |
|
204 | + * @throws InvalidDataTypeException |
|
205 | + * @throws InvalidInterfaceException |
|
206 | + * @throws DomainException |
|
207 | + */ |
|
208 | + public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
209 | + { |
|
210 | + // do nothing if form isn't for a reg step or test has already been passed |
|
211 | + if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | + return; |
|
213 | + } |
|
214 | + $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
|
215 | + if ($default_hidden_inputs instanceof EE_Form_Section_Proper) { |
|
216 | + $invisible_recaptcha = RecaptchaFactory::create(); |
|
217 | + $invisible_recaptcha->addToFormSection($default_hidden_inputs); |
|
218 | + } |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * @param EE_Form_Section_Proper $reg_form |
|
224 | + * @return bool |
|
225 | + * @throws InvalidDataTypeException |
|
226 | + * @throws InvalidInterfaceException |
|
227 | + * @throws EE_Error |
|
228 | + * @throws InvalidArgumentException |
|
229 | + */ |
|
230 | + public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
231 | + { |
|
232 | + return strpos($reg_form->name(), 'reg-step-form') !== false |
|
233 | + && ! RecaptchaFactory::create()->recaptchaPassed(); |
|
234 | + } |
|
235 | + |
|
236 | + |
|
237 | + /** |
|
238 | + * @param array|null $req_data |
|
239 | + * @param EE_Form_Section_Proper $reg_form |
|
240 | + * @return array |
|
241 | + * @throws EE_Error |
|
242 | + * @throws InvalidArgumentException |
|
243 | + * @throws InvalidDataTypeException |
|
244 | + * @throws InvalidInterfaceException |
|
245 | + * @throws RuntimeException |
|
246 | + */ |
|
247 | + public static function receiveSpcoRegStepForm($req_data, EE_Form_Section_Proper $reg_form) |
|
248 | + { |
|
249 | + // do nothing if form isn't for a reg step or test has already been passed |
|
250 | + if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | + return $req_data; |
|
252 | + } |
|
253 | + /** @var RequestInterface $request */ |
|
254 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
255 | + if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | + if ($request->isAjax()) { |
|
257 | + $json_response = new EE_SPCO_JSON_Response(); |
|
258 | + $json_response->echoAndExit(); |
|
259 | + } |
|
260 | + EEH_URL::safeRedirectAndExit( |
|
261 | + EE_Registry::instance()->CFG->core->reg_page_url() |
|
262 | + ); |
|
263 | + } |
|
264 | + return $req_data; |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + /** |
|
269 | + * @param string $html |
|
270 | + * @param EE_Event $event |
|
271 | + * @param bool $iframe |
|
272 | + * @return string |
|
273 | + * @throws EE_Error |
|
274 | + * @throws InvalidArgumentException |
|
275 | + * @throws InvalidDataTypeException |
|
276 | + * @throws InvalidInterfaceException |
|
277 | + * @throws ReflectionException |
|
278 | + * @throws DomainException |
|
279 | + */ |
|
280 | + public static function ticketSelectorForm(string $html, EE_Event $event, $iframe = false) |
|
281 | + { |
|
282 | + $recaptcha = RecaptchaFactory::create(); |
|
283 | + // do nothing if test has already been passed |
|
284 | + if ($recaptcha->recaptchaPassed()) { |
|
285 | + return $html; |
|
286 | + } |
|
287 | + $html .= $recaptcha->getInputHtml( |
|
288 | + array( |
|
289 | + 'recaptcha_id' => $event->ID(), |
|
290 | + 'iframe' => $iframe, |
|
291 | + 'localized_vars' => $recaptcha->getLocalizedVars(), |
|
292 | + ) |
|
293 | + ); |
|
294 | + return $html; |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * @return void |
|
300 | + * @throws InvalidArgumentException |
|
301 | + * @throws InvalidInterfaceException |
|
302 | + * @throws InvalidDataTypeException |
|
303 | + * @throws RuntimeException |
|
304 | + */ |
|
305 | + public static function processTicketSelectorForm() |
|
306 | + { |
|
307 | + // do nothing if test has already been passed |
|
308 | + if (RecaptchaFactory::create()->recaptchaPassed()) { |
|
309 | + return; |
|
310 | + } |
|
311 | + /** @var RequestInterface $request */ |
|
312 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
313 | + if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | + $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
|
315 | + $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
|
316 | + ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
|
317 | + : get_permalink($event_id); |
|
318 | + EEH_URL::safeRedirectAndExit($return_url); |
|
319 | + } |
|
320 | + } |
|
321 | + |
|
322 | + |
|
323 | + /** |
|
324 | + * @throws EE_Error |
|
325 | + * @throws InvalidArgumentException |
|
326 | + * @throws InvalidDataTypeException |
|
327 | + * @throws InvalidInterfaceException |
|
328 | + */ |
|
329 | + public static function adminSettings() |
|
330 | + { |
|
331 | + RecaptchaFactory::getAdminModule()->adminSettings(); |
|
332 | + } |
|
333 | + |
|
334 | + |
|
335 | + /** |
|
336 | + * @param EE_Registration_Config $EE_Registration_Config |
|
337 | + * @return EE_Registration_Config |
|
338 | + * @throws EE_Error |
|
339 | + * @throws InvalidArgumentException |
|
340 | + * @throws InvalidDataTypeException |
|
341 | + * @throws InvalidInterfaceException |
|
342 | + * @throws ReflectionException |
|
343 | + */ |
|
344 | + public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config) |
|
345 | + { |
|
346 | + return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config); |
|
347 | + } |
|
348 | 348 | } |
@@ -16,170 +16,170 @@ |
||
16 | 16 | */ |
17 | 17 | class CountryConnectionResolver extends AbstractConnectionResolver |
18 | 18 | { |
19 | - // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
20 | - public function get_loader_name(): string |
|
21 | - { |
|
22 | - return 'espresso_country'; |
|
23 | - } |
|
24 | - |
|
25 | - /** |
|
26 | - * @return EEM_Country |
|
27 | - * @throws EE_Error |
|
28 | - * @throws InvalidArgumentException |
|
29 | - * @throws InvalidDataTypeException |
|
30 | - * @throws InvalidInterfaceException |
|
31 | - * @throws ReflectionException |
|
32 | - */ |
|
33 | - // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
34 | - public function get_query(): EEM_Country |
|
35 | - { |
|
36 | - return EEM_Country::instance(); |
|
37 | - } |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * Return an array of item IDs from the query |
|
42 | - * |
|
43 | - * @return array |
|
44 | - */ |
|
45 | - // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
46 | - public function get_ids(): array |
|
47 | - { |
|
48 | - $results = $this->query->get_col($this->query_args); |
|
49 | - |
|
50 | - return ! empty($results) ? $results : []; |
|
51 | - } |
|
52 | - |
|
53 | - /** |
|
54 | - * Get_query_amount |
|
55 | - * |
|
56 | - * Returns the max between what was requested and what is defined as the $max_query_amount to |
|
57 | - * ensure that queries don't exceed unwanted limits when querying data. |
|
58 | - * |
|
59 | - * @return int |
|
60 | - * @throws Exception |
|
61 | - */ |
|
62 | - // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
63 | - public function get_query_amount() |
|
64 | - { |
|
65 | - // Override the default limit (100) for countries |
|
66 | - return 500; |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * Here, we map the args from the input, then we make sure that we're only querying |
|
72 | - * for IDs. The IDs are then passed down the resolve tree, and deferred resolvers |
|
73 | - * handle batch resolution of the posts. |
|
74 | - * |
|
75 | - * @return array |
|
76 | - * @throws InvalidArgumentException |
|
77 | - * @throws InvalidDataTypeException |
|
78 | - * @throws InvalidInterfaceException |
|
79 | - */ |
|
80 | - // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
81 | - public function get_query_args(): array |
|
82 | - { |
|
83 | - $where_params = []; |
|
84 | - $query_args = []; |
|
85 | - |
|
86 | - $query_args['limit'] = $this->getLimit(); |
|
87 | - |
|
88 | - // Avoid multiple entries by join. |
|
89 | - $query_args['group_by'] = 'CNT_ISO'; |
|
90 | - |
|
91 | - $query_args['default_where_conditions'] = 'minimum'; |
|
92 | - |
|
93 | - /** |
|
94 | - * Collect the input_fields and sanitize them to prepare them for sending to the Query |
|
95 | - */ |
|
96 | - $input_fields = []; |
|
97 | - if (! empty($this->args['where'])) { |
|
98 | - $input_fields = $this->sanitizeInputFields($this->args['where']); |
|
99 | - |
|
100 | - // Since we do not have any falsy values in query params |
|
101 | - // Lets get rid of empty values |
|
102 | - $input_fields = array_filter($input_fields); |
|
103 | - |
|
104 | - // Use the proper operator. |
|
105 | - if (! empty($input_fields['CNT_ISO']) && is_array($input_fields['CNT_ISO'])) { |
|
106 | - $input_fields['CNT_ISO'] = ['IN', $input_fields['CNT_ISO']]; |
|
107 | - } |
|
108 | - if (! empty($input_fields['CNT_ISO3']) && is_array($input_fields['CNT_ISO3'])) { |
|
109 | - $input_fields['CNT_ISO3'] = ['IN', $input_fields['CNT_ISO3']]; |
|
110 | - } |
|
111 | - } |
|
112 | - |
|
113 | - /** |
|
114 | - * Merge the input_fields with the default query_args |
|
115 | - */ |
|
116 | - if (! empty($input_fields)) { |
|
117 | - $where_params = array_merge($where_params, $input_fields); |
|
118 | - } |
|
119 | - |
|
120 | - // limit to active countries by default. |
|
121 | - if (!isset($this->args['where']['activeOnly']) || $this->args['where']['activeOnly']) { |
|
122 | - $where_params['CNT_active'] = true; |
|
123 | - } |
|
124 | - |
|
125 | - [$query_args, $where_params] = $this->mapOrderbyInputArgs($query_args, $where_params, 'CNT_ISO'); |
|
126 | - |
|
127 | - if (empty($query_args['order_by'])) { |
|
128 | - // set order_by to 'name' by default |
|
129 | - $query_args['order_by'] = [ |
|
130 | - 'CNT_name' => 'ASC', |
|
131 | - ]; |
|
132 | - } |
|
133 | - |
|
134 | - $search = $this->getSearchKeywords($this->args['where']); |
|
135 | - |
|
136 | - if (! empty($search)) { |
|
137 | - // use OR operator to search in any of the fields |
|
138 | - $where_params['OR'] = array( |
|
139 | - 'CNT_name' => array('LIKE', '%' . $search . '%'), |
|
140 | - 'CNT_ISO' => array('LIKE', '%' . $search . '%'), |
|
141 | - ); |
|
142 | - } |
|
143 | - |
|
144 | - $where_params = apply_filters( |
|
145 | - 'FHEE__EventEspresso_core_domain_services_graphql_connection_resolvers__country_where_params', |
|
146 | - $where_params, |
|
147 | - $this->source, |
|
148 | - $this->args |
|
149 | - ); |
|
150 | - |
|
151 | - $query_args[] = $where_params; |
|
152 | - |
|
153 | - /** |
|
154 | - * Return the $query_args |
|
155 | - */ |
|
156 | - return apply_filters( |
|
157 | - 'FHEE__EventEspresso_core_domain_services_graphql_connection_resolvers__country_query_args', |
|
158 | - $query_args, |
|
159 | - $this->source, |
|
160 | - $this->args |
|
161 | - ); |
|
162 | - } |
|
163 | - |
|
164 | - |
|
165 | - /** |
|
166 | - * This sets up the "allowed" args, and translates the GraphQL-friendly keys to model |
|
167 | - * friendly keys. |
|
168 | - * |
|
169 | - * @param array $where_args |
|
170 | - * @return array |
|
171 | - */ |
|
172 | - public function sanitizeInputFields(array $where_args): array |
|
173 | - { |
|
174 | - $arg_mapping = [ |
|
175 | - 'isoIn' => 'CNT_ISO', |
|
176 | - 'in' => 'CNT_ISO', |
|
177 | - 'iso3In' => 'CNT_ISO3', |
|
178 | - ]; |
|
179 | - return $this->sanitizeWhereArgsForInputFields( |
|
180 | - $where_args, |
|
181 | - $arg_mapping, |
|
182 | - ['in'] |
|
183 | - ); |
|
184 | - } |
|
19 | + // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
20 | + public function get_loader_name(): string |
|
21 | + { |
|
22 | + return 'espresso_country'; |
|
23 | + } |
|
24 | + |
|
25 | + /** |
|
26 | + * @return EEM_Country |
|
27 | + * @throws EE_Error |
|
28 | + * @throws InvalidArgumentException |
|
29 | + * @throws InvalidDataTypeException |
|
30 | + * @throws InvalidInterfaceException |
|
31 | + * @throws ReflectionException |
|
32 | + */ |
|
33 | + // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
34 | + public function get_query(): EEM_Country |
|
35 | + { |
|
36 | + return EEM_Country::instance(); |
|
37 | + } |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * Return an array of item IDs from the query |
|
42 | + * |
|
43 | + * @return array |
|
44 | + */ |
|
45 | + // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
46 | + public function get_ids(): array |
|
47 | + { |
|
48 | + $results = $this->query->get_col($this->query_args); |
|
49 | + |
|
50 | + return ! empty($results) ? $results : []; |
|
51 | + } |
|
52 | + |
|
53 | + /** |
|
54 | + * Get_query_amount |
|
55 | + * |
|
56 | + * Returns the max between what was requested and what is defined as the $max_query_amount to |
|
57 | + * ensure that queries don't exceed unwanted limits when querying data. |
|
58 | + * |
|
59 | + * @return int |
|
60 | + * @throws Exception |
|
61 | + */ |
|
62 | + // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
63 | + public function get_query_amount() |
|
64 | + { |
|
65 | + // Override the default limit (100) for countries |
|
66 | + return 500; |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * Here, we map the args from the input, then we make sure that we're only querying |
|
72 | + * for IDs. The IDs are then passed down the resolve tree, and deferred resolvers |
|
73 | + * handle batch resolution of the posts. |
|
74 | + * |
|
75 | + * @return array |
|
76 | + * @throws InvalidArgumentException |
|
77 | + * @throws InvalidDataTypeException |
|
78 | + * @throws InvalidInterfaceException |
|
79 | + */ |
|
80 | + // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
|
81 | + public function get_query_args(): array |
|
82 | + { |
|
83 | + $where_params = []; |
|
84 | + $query_args = []; |
|
85 | + |
|
86 | + $query_args['limit'] = $this->getLimit(); |
|
87 | + |
|
88 | + // Avoid multiple entries by join. |
|
89 | + $query_args['group_by'] = 'CNT_ISO'; |
|
90 | + |
|
91 | + $query_args['default_where_conditions'] = 'minimum'; |
|
92 | + |
|
93 | + /** |
|
94 | + * Collect the input_fields and sanitize them to prepare them for sending to the Query |
|
95 | + */ |
|
96 | + $input_fields = []; |
|
97 | + if (! empty($this->args['where'])) { |
|
98 | + $input_fields = $this->sanitizeInputFields($this->args['where']); |
|
99 | + |
|
100 | + // Since we do not have any falsy values in query params |
|
101 | + // Lets get rid of empty values |
|
102 | + $input_fields = array_filter($input_fields); |
|
103 | + |
|
104 | + // Use the proper operator. |
|
105 | + if (! empty($input_fields['CNT_ISO']) && is_array($input_fields['CNT_ISO'])) { |
|
106 | + $input_fields['CNT_ISO'] = ['IN', $input_fields['CNT_ISO']]; |
|
107 | + } |
|
108 | + if (! empty($input_fields['CNT_ISO3']) && is_array($input_fields['CNT_ISO3'])) { |
|
109 | + $input_fields['CNT_ISO3'] = ['IN', $input_fields['CNT_ISO3']]; |
|
110 | + } |
|
111 | + } |
|
112 | + |
|
113 | + /** |
|
114 | + * Merge the input_fields with the default query_args |
|
115 | + */ |
|
116 | + if (! empty($input_fields)) { |
|
117 | + $where_params = array_merge($where_params, $input_fields); |
|
118 | + } |
|
119 | + |
|
120 | + // limit to active countries by default. |
|
121 | + if (!isset($this->args['where']['activeOnly']) || $this->args['where']['activeOnly']) { |
|
122 | + $where_params['CNT_active'] = true; |
|
123 | + } |
|
124 | + |
|
125 | + [$query_args, $where_params] = $this->mapOrderbyInputArgs($query_args, $where_params, 'CNT_ISO'); |
|
126 | + |
|
127 | + if (empty($query_args['order_by'])) { |
|
128 | + // set order_by to 'name' by default |
|
129 | + $query_args['order_by'] = [ |
|
130 | + 'CNT_name' => 'ASC', |
|
131 | + ]; |
|
132 | + } |
|
133 | + |
|
134 | + $search = $this->getSearchKeywords($this->args['where']); |
|
135 | + |
|
136 | + if (! empty($search)) { |
|
137 | + // use OR operator to search in any of the fields |
|
138 | + $where_params['OR'] = array( |
|
139 | + 'CNT_name' => array('LIKE', '%' . $search . '%'), |
|
140 | + 'CNT_ISO' => array('LIKE', '%' . $search . '%'), |
|
141 | + ); |
|
142 | + } |
|
143 | + |
|
144 | + $where_params = apply_filters( |
|
145 | + 'FHEE__EventEspresso_core_domain_services_graphql_connection_resolvers__country_where_params', |
|
146 | + $where_params, |
|
147 | + $this->source, |
|
148 | + $this->args |
|
149 | + ); |
|
150 | + |
|
151 | + $query_args[] = $where_params; |
|
152 | + |
|
153 | + /** |
|
154 | + * Return the $query_args |
|
155 | + */ |
|
156 | + return apply_filters( |
|
157 | + 'FHEE__EventEspresso_core_domain_services_graphql_connection_resolvers__country_query_args', |
|
158 | + $query_args, |
|
159 | + $this->source, |
|
160 | + $this->args |
|
161 | + ); |
|
162 | + } |
|
163 | + |
|
164 | + |
|
165 | + /** |
|
166 | + * This sets up the "allowed" args, and translates the GraphQL-friendly keys to model |
|
167 | + * friendly keys. |
|
168 | + * |
|
169 | + * @param array $where_args |
|
170 | + * @return array |
|
171 | + */ |
|
172 | + public function sanitizeInputFields(array $where_args): array |
|
173 | + { |
|
174 | + $arg_mapping = [ |
|
175 | + 'isoIn' => 'CNT_ISO', |
|
176 | + 'in' => 'CNT_ISO', |
|
177 | + 'iso3In' => 'CNT_ISO3', |
|
178 | + ]; |
|
179 | + return $this->sanitizeWhereArgsForInputFields( |
|
180 | + $where_args, |
|
181 | + $arg_mapping, |
|
182 | + ['in'] |
|
183 | + ); |
|
184 | + } |
|
185 | 185 | } |
@@ -6,52 +6,52 @@ |
||
6 | 6 | */ |
7 | 7 | abstract class EE_Text_Field_Base extends EE_Model_Field_Base |
8 | 8 | { |
9 | - /** |
|
10 | - * Gets the value in the format expected when being set. |
|
11 | - * For display on the front-end, usually you would use prepare_for_pretty_echoing() instead. |
|
12 | - * @param mixed $value_of_field_on_model_object |
|
13 | - * @return mixed|string |
|
14 | - */ |
|
15 | - public function prepare_for_get($value_of_field_on_model_object) |
|
16 | - { |
|
17 | - if (empty($value_of_field_on_model_object)) { |
|
18 | - return $this->is_nullable() ? $value_of_field_on_model_object : ''; |
|
19 | - } |
|
20 | - return $value_of_field_on_model_object; |
|
21 | - } |
|
9 | + /** |
|
10 | + * Gets the value in the format expected when being set. |
|
11 | + * For display on the front-end, usually you would use prepare_for_pretty_echoing() instead. |
|
12 | + * @param mixed $value_of_field_on_model_object |
|
13 | + * @return mixed|string |
|
14 | + */ |
|
15 | + public function prepare_for_get($value_of_field_on_model_object) |
|
16 | + { |
|
17 | + if (empty($value_of_field_on_model_object)) { |
|
18 | + return $this->is_nullable() ? $value_of_field_on_model_object : ''; |
|
19 | + } |
|
20 | + return $value_of_field_on_model_object; |
|
21 | + } |
|
22 | 22 | |
23 | - /** |
|
24 | - * Accepts schema of 'form_input' which formats the string for echoing in form input's value. |
|
25 | - * |
|
26 | - * @param string $value_on_field_to_be_outputted |
|
27 | - * @param string|null $schema |
|
28 | - * @return string |
|
29 | - */ |
|
30 | - public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null) |
|
31 | - { |
|
32 | - if ($schema === 'form_input') { |
|
33 | - $value_on_field_to_be_outputted = (string) htmlentities( |
|
34 | - $value_on_field_to_be_outputted, |
|
35 | - ENT_QUOTES, |
|
36 | - 'UTF-8' |
|
37 | - ); |
|
38 | - } |
|
39 | - return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted); |
|
40 | - } |
|
23 | + /** |
|
24 | + * Accepts schema of 'form_input' which formats the string for echoing in form input's value. |
|
25 | + * |
|
26 | + * @param string $value_on_field_to_be_outputted |
|
27 | + * @param string|null $schema |
|
28 | + * @return string |
|
29 | + */ |
|
30 | + public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null) |
|
31 | + { |
|
32 | + if ($schema === 'form_input') { |
|
33 | + $value_on_field_to_be_outputted = (string) htmlentities( |
|
34 | + $value_on_field_to_be_outputted, |
|
35 | + ENT_QUOTES, |
|
36 | + 'UTF-8' |
|
37 | + ); |
|
38 | + } |
|
39 | + return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted); |
|
40 | + } |
|
41 | 41 | |
42 | - /** |
|
43 | - * Data received from the user should be exactly as they hope to save it in the DB, with the exception that |
|
44 | - * quotes need to have slashes added to it. This method takes care of removing the slashes added by WP |
|
45 | - * in magic-quotes fashion. We used to call html_entity_decode on the value here, |
|
46 | - * because we called htmlentities when in EE_Text_Field_Base::prepare_for_pretty_echoing, but that's not necessary |
|
47 | - * because web browsers always decode HTML entities in element attributes, like a form element's value attribute. |
|
48 | - * So if we do it again here, we'll be removing HTML entities the user intended to have.) |
|
49 | - * |
|
50 | - * @param string $value_inputted_for_field_on_model_object |
|
51 | - * @return string |
|
52 | - */ |
|
53 | - public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
54 | - { |
|
55 | - return stripslashes(parent::prepare_for_set($value_inputted_for_field_on_model_object)); |
|
56 | - } |
|
42 | + /** |
|
43 | + * Data received from the user should be exactly as they hope to save it in the DB, with the exception that |
|
44 | + * quotes need to have slashes added to it. This method takes care of removing the slashes added by WP |
|
45 | + * in magic-quotes fashion. We used to call html_entity_decode on the value here, |
|
46 | + * because we called htmlentities when in EE_Text_Field_Base::prepare_for_pretty_echoing, but that's not necessary |
|
47 | + * because web browsers always decode HTML entities in element attributes, like a form element's value attribute. |
|
48 | + * So if we do it again here, we'll be removing HTML entities the user intended to have.) |
|
49 | + * |
|
50 | + * @param string $value_inputted_for_field_on_model_object |
|
51 | + * @return string |
|
52 | + */ |
|
53 | + public function prepare_for_set($value_inputted_for_field_on_model_object) |
|
54 | + { |
|
55 | + return stripslashes(parent::prepare_for_set($value_inputted_for_field_on_model_object)); |
|
56 | + } |
|
57 | 57 | } |
@@ -16,1600 +16,1600 @@ |
||
16 | 16 | */ |
17 | 17 | class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event |
18 | 18 | { |
19 | - /** |
|
20 | - * cached value for the the logical active status for the event |
|
21 | - * |
|
22 | - * @see get_active_status() |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - protected $_active_status = ''; |
|
26 | - |
|
27 | - /** |
|
28 | - * This is just used for caching the Primary Datetime for the Event on initial retrieval |
|
29 | - * |
|
30 | - * @var EE_Datetime |
|
31 | - */ |
|
32 | - protected $_Primary_Datetime; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var EventSpacesCalculator $available_spaces_calculator |
|
36 | - */ |
|
37 | - protected $available_spaces_calculator; |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * @param array $props_n_values incoming values |
|
42 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
43 | - * used.) |
|
44 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
45 | - * date_format and the second value is the time format |
|
46 | - * @return EE_Event |
|
47 | - * @throws EE_Error |
|
48 | - * @throws ReflectionException |
|
49 | - */ |
|
50 | - public static function new_instance($props_n_values = [], $timezone = null, $date_formats = []): EE_Event |
|
51 | - { |
|
52 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
53 | - return $has_object ?: new self($props_n_values, false, $timezone, $date_formats); |
|
54 | - } |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * @param array $props_n_values incoming values from the database |
|
59 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
60 | - * the website will be used. |
|
61 | - * @return EE_Event |
|
62 | - * @throws EE_Error |
|
63 | - * @throws ReflectionException |
|
64 | - */ |
|
65 | - public static function new_instance_from_db($props_n_values = [], $timezone = null): EE_Event |
|
66 | - { |
|
67 | - return new self($props_n_values, true, $timezone); |
|
68 | - } |
|
69 | - |
|
70 | - |
|
71 | - /** |
|
72 | - * @return EventSpacesCalculator |
|
73 | - * @throws EE_Error |
|
74 | - * @throws ReflectionException |
|
75 | - */ |
|
76 | - public function getAvailableSpacesCalculator(): EventSpacesCalculator |
|
77 | - { |
|
78 | - if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) { |
|
79 | - $this->available_spaces_calculator = new EventSpacesCalculator($this); |
|
80 | - } |
|
81 | - return $this->available_spaces_calculator; |
|
82 | - } |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods |
|
87 | - * |
|
88 | - * @param string $field_name |
|
89 | - * @param mixed $field_value |
|
90 | - * @param bool $use_default |
|
91 | - * @throws EE_Error |
|
92 | - * @throws ReflectionException |
|
93 | - */ |
|
94 | - public function set($field_name, $field_value, $use_default = false) |
|
95 | - { |
|
96 | - switch ($field_name) { |
|
97 | - case 'status': |
|
98 | - $this->set_status($field_value, $use_default); |
|
99 | - break; |
|
100 | - default: |
|
101 | - parent::set($field_name, $field_value, $use_default); |
|
102 | - } |
|
103 | - } |
|
104 | - |
|
105 | - |
|
106 | - /** |
|
107 | - * set_status |
|
108 | - * Checks if event status is being changed to SOLD OUT |
|
109 | - * and updates event meta data with previous event status |
|
110 | - * so that we can revert things if/when the event is no longer sold out |
|
111 | - * |
|
112 | - * @param string $status |
|
113 | - * @param bool $use_default |
|
114 | - * @return void |
|
115 | - * @throws EE_Error |
|
116 | - * @throws ReflectionException |
|
117 | - */ |
|
118 | - public function set_status($status = '', $use_default = false) |
|
119 | - { |
|
120 | - // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave |
|
121 | - if (empty($status) && ! $use_default) { |
|
122 | - return; |
|
123 | - } |
|
124 | - // get current Event status |
|
125 | - $old_status = $this->status(); |
|
126 | - // if status has changed |
|
127 | - if ($old_status !== $status) { |
|
128 | - // TO sold_out |
|
129 | - if ($status === EEM_Event::sold_out) { |
|
130 | - // save the previous event status so that we can revert if the event is no longer sold out |
|
131 | - $this->add_post_meta('_previous_event_status', $old_status); |
|
132 | - do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $status); |
|
133 | - // OR FROM sold_out |
|
134 | - } elseif ($old_status === EEM_Event::sold_out) { |
|
135 | - $this->delete_post_meta('_previous_event_status'); |
|
136 | - do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $status); |
|
137 | - } |
|
138 | - // clear out the active status so that it gets reset the next time it is requested |
|
139 | - $this->_active_status = null; |
|
140 | - // update status |
|
141 | - parent::set('status', $status, $use_default); |
|
142 | - do_action('AHEE__EE_Event__set_status__after_update', $this); |
|
143 | - return; |
|
144 | - } |
|
145 | - // even though the old value matches the new value, it's still good to |
|
146 | - // allow the parent set method to have a say |
|
147 | - parent::set('status', $status, $use_default); |
|
148 | - } |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * Gets all the datetimes for this event |
|
153 | - * |
|
154 | - * @param array|null $query_params |
|
155 | - * @return EE_Base_Class[]|EE_Datetime[] |
|
156 | - * @throws EE_Error |
|
157 | - * @throws ReflectionException |
|
158 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
159 | - */ |
|
160 | - public function datetimes(?array $query_params = []): array |
|
161 | - { |
|
162 | - return $this->get_many_related('Datetime', $query_params); |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - /** |
|
167 | - * Gets all the datetimes for this event that are currently ACTIVE, |
|
168 | - * meaning the datetime has started and has not yet ended. |
|
169 | - * |
|
170 | - * @param int|null $start_date timestamp to use for event date start time, defaults to NOW unless set to 0 |
|
171 | - * @param array|null $query_params will recursively replace default values |
|
172 | - * @throws EE_Error |
|
173 | - * @throws ReflectionException |
|
174 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
175 | - */ |
|
176 | - public function activeDatetimes(?int $start_date, ?array $query_params = []): array |
|
177 | - { |
|
178 | - // if start date is null, then use current time |
|
179 | - $start_date = $start_date ?? time(); |
|
180 | - $where = []; |
|
181 | - if ($start_date) { |
|
182 | - $where['DTT_EVT_start'] = ['<', $start_date]; |
|
183 | - $where['DTT_EVT_end'] = ['>', time()]; |
|
184 | - } |
|
185 | - $query_params = array_replace_recursive( |
|
186 | - [ |
|
187 | - $where, |
|
188 | - 'order_by' => ['DTT_EVT_start' => 'ASC'], |
|
189 | - ], |
|
190 | - $query_params |
|
191 | - ); |
|
192 | - return $this->get_many_related('Datetime', $query_params); |
|
193 | - } |
|
194 | - |
|
195 | - |
|
196 | - /** |
|
197 | - * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order |
|
198 | - * |
|
199 | - * @return EE_Base_Class[]|EE_Datetime[] |
|
200 | - * @throws EE_Error |
|
201 | - * @throws ReflectionException |
|
202 | - */ |
|
203 | - public function datetimes_in_chronological_order(): array |
|
204 | - { |
|
205 | - return $this->get_many_related('Datetime', ['order_by' => ['DTT_EVT_start' => 'ASC']]); |
|
206 | - } |
|
207 | - |
|
208 | - |
|
209 | - /** |
|
210 | - * Gets all the datetimes for this event, ordered by the DTT_order on the datetime. |
|
211 | - * @darren, we should probably UNSET timezone on the EEM_Datetime model |
|
212 | - * after running our query, so that this timezone isn't set for EVERY query |
|
213 | - * on EEM_Datetime for the rest of the request, no? |
|
214 | - * |
|
215 | - * @param bool $show_expired whether or not to include expired events |
|
216 | - * @param bool $show_deleted whether or not to include deleted events |
|
217 | - * @param int|null $limit |
|
218 | - * @return EE_Datetime[] |
|
219 | - * @throws EE_Error |
|
220 | - * @throws ReflectionException |
|
221 | - */ |
|
222 | - public function datetimes_ordered(bool $show_expired = true, bool $show_deleted = false, ?int $limit = null): array |
|
223 | - { |
|
224 | - return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order( |
|
225 | - $this->ID(), |
|
226 | - $show_expired, |
|
227 | - $show_deleted, |
|
228 | - $limit |
|
229 | - ); |
|
230 | - } |
|
231 | - |
|
232 | - |
|
233 | - /** |
|
234 | - * Returns one related datetime. Mostly only used by some legacy code. |
|
235 | - * |
|
236 | - * @return EE_Base_Class|EE_Datetime |
|
237 | - * @throws EE_Error |
|
238 | - * @throws ReflectionException |
|
239 | - */ |
|
240 | - public function first_datetime(): EE_Datetime |
|
241 | - { |
|
242 | - return $this->get_first_related('Datetime'); |
|
243 | - } |
|
244 | - |
|
245 | - |
|
246 | - /** |
|
247 | - * Returns the 'primary' datetime for the event |
|
248 | - * |
|
249 | - * @param bool $try_to_exclude_expired |
|
250 | - * @param bool $try_to_exclude_deleted |
|
251 | - * @return EE_Datetime|null |
|
252 | - * @throws EE_Error |
|
253 | - * @throws ReflectionException |
|
254 | - */ |
|
255 | - public function primary_datetime( |
|
256 | - bool $try_to_exclude_expired = true, |
|
257 | - bool $try_to_exclude_deleted = true |
|
258 | - ): ?EE_Datetime { |
|
259 | - if (! empty($this->_Primary_Datetime)) { |
|
260 | - return $this->_Primary_Datetime; |
|
261 | - } |
|
262 | - $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event( |
|
263 | - $this->ID(), |
|
264 | - $try_to_exclude_expired, |
|
265 | - $try_to_exclude_deleted |
|
266 | - ); |
|
267 | - return $this->_Primary_Datetime; |
|
268 | - } |
|
269 | - |
|
270 | - |
|
271 | - /** |
|
272 | - * Gets all the tickets available for purchase of this event |
|
273 | - * |
|
274 | - * @param array|null $query_params |
|
275 | - * @return EE_Base_Class[]|EE_Ticket[] |
|
276 | - * @throws EE_Error |
|
277 | - * @throws ReflectionException |
|
278 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
279 | - */ |
|
280 | - public function tickets(?array $query_params = []): array |
|
281 | - { |
|
282 | - // first get all datetimes |
|
283 | - $datetimes = $this->datetimes_ordered(); |
|
284 | - if (! $datetimes) { |
|
285 | - return []; |
|
286 | - } |
|
287 | - $datetime_ids = []; |
|
288 | - foreach ($datetimes as $datetime) { |
|
289 | - $datetime_ids[] = $datetime->ID(); |
|
290 | - } |
|
291 | - $where_params = ['Datetime.DTT_ID' => ['IN', $datetime_ids]]; |
|
292 | - // if incoming $query_params has where conditions let's merge but not override existing. |
|
293 | - if (is_array($query_params) && isset($query_params[0])) { |
|
294 | - $where_params = array_merge($query_params[0], $where_params); |
|
295 | - unset($query_params[0]); |
|
296 | - } |
|
297 | - // now add $where_params to $query_params |
|
298 | - $query_params[0] = $where_params; |
|
299 | - return EEM_Ticket::instance()->get_all($query_params); |
|
300 | - } |
|
301 | - |
|
302 | - |
|
303 | - /** |
|
304 | - * get all unexpired not-trashed tickets |
|
305 | - * |
|
306 | - * @return EE_Ticket[] |
|
307 | - * @throws EE_Error |
|
308 | - * @throws ReflectionException |
|
309 | - */ |
|
310 | - public function active_tickets(): array |
|
311 | - { |
|
312 | - return $this->tickets( |
|
313 | - [ |
|
314 | - [ |
|
315 | - 'TKT_end_date' => ['>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')], |
|
316 | - 'TKT_deleted' => false, |
|
317 | - ], |
|
318 | - ] |
|
319 | - ); |
|
320 | - } |
|
321 | - |
|
322 | - |
|
323 | - /** |
|
324 | - * @return int |
|
325 | - * @throws EE_Error |
|
326 | - * @throws ReflectionException |
|
327 | - */ |
|
328 | - public function additional_limit(): int |
|
329 | - { |
|
330 | - return $this->get('EVT_additional_limit'); |
|
331 | - } |
|
332 | - |
|
333 | - |
|
334 | - /** |
|
335 | - * @return bool |
|
336 | - * @throws EE_Error |
|
337 | - * @throws ReflectionException |
|
338 | - */ |
|
339 | - public function allow_overflow(): bool |
|
340 | - { |
|
341 | - return $this->get('EVT_allow_overflow'); |
|
342 | - } |
|
343 | - |
|
344 | - |
|
345 | - /** |
|
346 | - * @return string |
|
347 | - * @throws EE_Error |
|
348 | - * @throws ReflectionException |
|
349 | - */ |
|
350 | - public function created(): string |
|
351 | - { |
|
352 | - return $this->get('EVT_created'); |
|
353 | - } |
|
354 | - |
|
355 | - |
|
356 | - /** |
|
357 | - * @return string |
|
358 | - * @throws EE_Error |
|
359 | - * @throws ReflectionException |
|
360 | - */ |
|
361 | - public function description(): string |
|
362 | - { |
|
363 | - return $this->get('EVT_desc'); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - /** |
|
368 | - * Runs do_shortcode and wpautop on the description |
|
369 | - * |
|
370 | - * @return string of html |
|
371 | - * @throws EE_Error |
|
372 | - * @throws ReflectionException |
|
373 | - */ |
|
374 | - public function description_filtered(): string |
|
375 | - { |
|
376 | - return $this->get_pretty('EVT_desc'); |
|
377 | - } |
|
378 | - |
|
379 | - |
|
380 | - /** |
|
381 | - * @return bool |
|
382 | - * @throws EE_Error |
|
383 | - * @throws ReflectionException |
|
384 | - */ |
|
385 | - public function display_description(): bool |
|
386 | - { |
|
387 | - return $this->get('EVT_display_desc'); |
|
388 | - } |
|
389 | - |
|
390 | - |
|
391 | - /** |
|
392 | - * @return bool |
|
393 | - * @throws EE_Error |
|
394 | - * @throws ReflectionException |
|
395 | - */ |
|
396 | - public function display_ticket_selector(): bool |
|
397 | - { |
|
398 | - return (bool) $this->get('EVT_display_ticket_selector'); |
|
399 | - } |
|
400 | - |
|
401 | - |
|
402 | - /** |
|
403 | - * @return string |
|
404 | - * @throws EE_Error |
|
405 | - * @throws ReflectionException |
|
406 | - */ |
|
407 | - public function external_url(): ?string |
|
408 | - { |
|
409 | - return $this->get('EVT_external_URL') ?? ''; |
|
410 | - } |
|
411 | - |
|
412 | - |
|
413 | - /** |
|
414 | - * @return bool |
|
415 | - * @throws EE_Error |
|
416 | - * @throws ReflectionException |
|
417 | - */ |
|
418 | - public function member_only(): bool |
|
419 | - { |
|
420 | - return $this->get('EVT_member_only'); |
|
421 | - } |
|
422 | - |
|
423 | - |
|
424 | - /** |
|
425 | - * @return string |
|
426 | - * @throws EE_Error |
|
427 | - * @throws ReflectionException |
|
428 | - */ |
|
429 | - public function phone(): string |
|
430 | - { |
|
431 | - return $this->get('EVT_phone'); |
|
432 | - } |
|
433 | - |
|
434 | - |
|
435 | - /** |
|
436 | - * @return string |
|
437 | - * @throws EE_Error |
|
438 | - * @throws ReflectionException |
|
439 | - */ |
|
440 | - public function modified(): string |
|
441 | - { |
|
442 | - return $this->get('EVT_modified'); |
|
443 | - } |
|
444 | - |
|
445 | - |
|
446 | - /** |
|
447 | - * @return string |
|
448 | - * @throws EE_Error |
|
449 | - * @throws ReflectionException |
|
450 | - */ |
|
451 | - public function name(): string |
|
452 | - { |
|
453 | - return $this->get('EVT_name'); |
|
454 | - } |
|
455 | - |
|
456 | - |
|
457 | - /** |
|
458 | - * @return int |
|
459 | - * @throws EE_Error |
|
460 | - * @throws ReflectionException |
|
461 | - */ |
|
462 | - public function order(): int |
|
463 | - { |
|
464 | - return $this->get('EVT_order'); |
|
465 | - } |
|
466 | - |
|
467 | - |
|
468 | - /** |
|
469 | - * @return string |
|
470 | - * @throws EE_Error |
|
471 | - * @throws ReflectionException |
|
472 | - */ |
|
473 | - public function default_registration_status(): string |
|
474 | - { |
|
475 | - $event_default_registration_status = $this->get('EVT_default_registration_status'); |
|
476 | - return ! empty($event_default_registration_status) |
|
477 | - ? $event_default_registration_status |
|
478 | - : EE_Registry::instance()->CFG->registration->default_STS_ID; |
|
479 | - } |
|
480 | - |
|
481 | - |
|
482 | - /** |
|
483 | - * @param int|null $num_words |
|
484 | - * @param string|null $more |
|
485 | - * @param bool $not_full_desc |
|
486 | - * @return string |
|
487 | - * @throws EE_Error |
|
488 | - * @throws ReflectionException |
|
489 | - */ |
|
490 | - public function short_description(?int $num_words = 55, string $more = null, bool $not_full_desc = false): string |
|
491 | - { |
|
492 | - $short_desc = $this->get('EVT_short_desc'); |
|
493 | - if (! empty($short_desc) || $not_full_desc) { |
|
494 | - return $short_desc; |
|
495 | - } |
|
496 | - $full_desc = $this->get('EVT_desc'); |
|
497 | - return wp_trim_words($full_desc, $num_words, $more); |
|
498 | - } |
|
499 | - |
|
500 | - |
|
501 | - /** |
|
502 | - * @return string |
|
503 | - * @throws EE_Error |
|
504 | - * @throws ReflectionException |
|
505 | - */ |
|
506 | - public function slug(): string |
|
507 | - { |
|
508 | - return $this->get('EVT_slug'); |
|
509 | - } |
|
510 | - |
|
511 | - |
|
512 | - /** |
|
513 | - * @return string |
|
514 | - * @throws EE_Error |
|
515 | - * @throws ReflectionException |
|
516 | - */ |
|
517 | - public function timezone_string(): string |
|
518 | - { |
|
519 | - return $this->get('EVT_timezone_string'); |
|
520 | - } |
|
521 | - |
|
522 | - |
|
523 | - /** |
|
524 | - * @return string |
|
525 | - * @throws EE_Error |
|
526 | - * @throws ReflectionException |
|
527 | - */ |
|
528 | - public function visible_on(): string |
|
529 | - { |
|
530 | - return $this->get('EVT_visible_on'); |
|
531 | - } |
|
532 | - |
|
533 | - |
|
534 | - /** |
|
535 | - * @return int |
|
536 | - * @throws EE_Error |
|
537 | - * @throws ReflectionException |
|
538 | - */ |
|
539 | - public function wp_user(): int |
|
540 | - { |
|
541 | - return $this->get('EVT_wp_user'); |
|
542 | - } |
|
543 | - |
|
544 | - |
|
545 | - /** |
|
546 | - * @return bool |
|
547 | - * @throws EE_Error |
|
548 | - * @throws ReflectionException |
|
549 | - */ |
|
550 | - public function donations(): bool |
|
551 | - { |
|
552 | - return $this->get('EVT_donations'); |
|
553 | - } |
|
554 | - |
|
555 | - |
|
556 | - /** |
|
557 | - * @param int $limit |
|
558 | - * @throws EE_Error |
|
559 | - * @throws ReflectionException |
|
560 | - */ |
|
561 | - public function set_additional_limit(int $limit) |
|
562 | - { |
|
563 | - $this->set('EVT_additional_limit', $limit); |
|
564 | - } |
|
565 | - |
|
566 | - |
|
567 | - /** |
|
568 | - * @param $created |
|
569 | - * @throws EE_Error |
|
570 | - * @throws ReflectionException |
|
571 | - */ |
|
572 | - public function set_created($created) |
|
573 | - { |
|
574 | - $this->set('EVT_created', $created); |
|
575 | - } |
|
576 | - |
|
577 | - |
|
578 | - /** |
|
579 | - * @param $desc |
|
580 | - * @throws EE_Error |
|
581 | - * @throws ReflectionException |
|
582 | - */ |
|
583 | - public function set_description($desc) |
|
584 | - { |
|
585 | - $this->set('EVT_desc', $desc); |
|
586 | - } |
|
587 | - |
|
588 | - |
|
589 | - /** |
|
590 | - * @param $display_desc |
|
591 | - * @throws EE_Error |
|
592 | - * @throws ReflectionException |
|
593 | - */ |
|
594 | - public function set_display_description($display_desc) |
|
595 | - { |
|
596 | - $this->set('EVT_display_desc', $display_desc); |
|
597 | - } |
|
598 | - |
|
599 | - |
|
600 | - /** |
|
601 | - * @param $display_ticket_selector |
|
602 | - * @throws EE_Error |
|
603 | - * @throws ReflectionException |
|
604 | - */ |
|
605 | - public function set_display_ticket_selector($display_ticket_selector) |
|
606 | - { |
|
607 | - $this->set('EVT_display_ticket_selector', $display_ticket_selector); |
|
608 | - } |
|
609 | - |
|
610 | - |
|
611 | - /** |
|
612 | - * @param $external_url |
|
613 | - * @throws EE_Error |
|
614 | - * @throws ReflectionException |
|
615 | - */ |
|
616 | - public function set_external_url($external_url) |
|
617 | - { |
|
618 | - $this->set('EVT_external_URL', $external_url); |
|
619 | - } |
|
620 | - |
|
621 | - |
|
622 | - /** |
|
623 | - * @param $member_only |
|
624 | - * @throws EE_Error |
|
625 | - * @throws ReflectionException |
|
626 | - */ |
|
627 | - public function set_member_only($member_only) |
|
628 | - { |
|
629 | - $this->set('EVT_member_only', $member_only); |
|
630 | - } |
|
631 | - |
|
632 | - |
|
633 | - /** |
|
634 | - * @param $event_phone |
|
635 | - * @throws EE_Error |
|
636 | - * @throws ReflectionException |
|
637 | - */ |
|
638 | - public function set_event_phone($event_phone) |
|
639 | - { |
|
640 | - $this->set('EVT_phone', $event_phone); |
|
641 | - } |
|
642 | - |
|
643 | - |
|
644 | - /** |
|
645 | - * @param $modified |
|
646 | - * @throws EE_Error |
|
647 | - * @throws ReflectionException |
|
648 | - */ |
|
649 | - public function set_modified($modified) |
|
650 | - { |
|
651 | - $this->set('EVT_modified', $modified); |
|
652 | - } |
|
653 | - |
|
654 | - |
|
655 | - /** |
|
656 | - * @param $name |
|
657 | - * @throws EE_Error |
|
658 | - * @throws ReflectionException |
|
659 | - */ |
|
660 | - public function set_name($name) |
|
661 | - { |
|
662 | - $this->set('EVT_name', $name); |
|
663 | - } |
|
664 | - |
|
665 | - |
|
666 | - /** |
|
667 | - * @param $order |
|
668 | - * @throws EE_Error |
|
669 | - * @throws ReflectionException |
|
670 | - */ |
|
671 | - public function set_order($order) |
|
672 | - { |
|
673 | - $this->set('EVT_order', $order); |
|
674 | - } |
|
675 | - |
|
676 | - |
|
677 | - /** |
|
678 | - * @param $short_desc |
|
679 | - * @throws EE_Error |
|
680 | - * @throws ReflectionException |
|
681 | - */ |
|
682 | - public function set_short_description($short_desc) |
|
683 | - { |
|
684 | - $this->set('EVT_short_desc', $short_desc); |
|
685 | - } |
|
686 | - |
|
687 | - |
|
688 | - /** |
|
689 | - * @param $slug |
|
690 | - * @throws EE_Error |
|
691 | - * @throws ReflectionException |
|
692 | - */ |
|
693 | - public function set_slug($slug) |
|
694 | - { |
|
695 | - $this->set('EVT_slug', $slug); |
|
696 | - } |
|
697 | - |
|
698 | - |
|
699 | - /** |
|
700 | - * @param $timezone_string |
|
701 | - * @throws EE_Error |
|
702 | - * @throws ReflectionException |
|
703 | - */ |
|
704 | - public function set_timezone_string($timezone_string) |
|
705 | - { |
|
706 | - $this->set('EVT_timezone_string', $timezone_string); |
|
707 | - } |
|
708 | - |
|
709 | - |
|
710 | - /** |
|
711 | - * @param $visible_on |
|
712 | - * @throws EE_Error |
|
713 | - * @throws ReflectionException |
|
714 | - */ |
|
715 | - public function set_visible_on($visible_on) |
|
716 | - { |
|
717 | - $this->set('EVT_visible_on', $visible_on); |
|
718 | - } |
|
719 | - |
|
720 | - |
|
721 | - /** |
|
722 | - * @param $wp_user |
|
723 | - * @throws EE_Error |
|
724 | - * @throws ReflectionException |
|
725 | - */ |
|
726 | - public function set_wp_user($wp_user) |
|
727 | - { |
|
728 | - $this->set('EVT_wp_user', $wp_user); |
|
729 | - } |
|
730 | - |
|
731 | - |
|
732 | - /** |
|
733 | - * @param $default_registration_status |
|
734 | - * @throws EE_Error |
|
735 | - * @throws ReflectionException |
|
736 | - */ |
|
737 | - public function set_default_registration_status($default_registration_status) |
|
738 | - { |
|
739 | - $this->set('EVT_default_registration_status', $default_registration_status); |
|
740 | - } |
|
741 | - |
|
742 | - |
|
743 | - /** |
|
744 | - * @param $donations |
|
745 | - * @throws EE_Error |
|
746 | - * @throws ReflectionException |
|
747 | - */ |
|
748 | - public function set_donations($donations) |
|
749 | - { |
|
750 | - $this->set('EVT_donations', $donations); |
|
751 | - } |
|
752 | - |
|
753 | - |
|
754 | - /** |
|
755 | - * Adds a venue to this event |
|
756 | - * |
|
757 | - * @param int|EE_Venue /int $venue_id_or_obj |
|
758 | - * @return EE_Base_Class|EE_Venue |
|
759 | - * @throws EE_Error |
|
760 | - * @throws ReflectionException |
|
761 | - */ |
|
762 | - public function add_venue($venue_id_or_obj): EE_Venue |
|
763 | - { |
|
764 | - return $this->_add_relation_to($venue_id_or_obj, 'Venue'); |
|
765 | - } |
|
766 | - |
|
767 | - |
|
768 | - /** |
|
769 | - * Removes a venue from the event |
|
770 | - * |
|
771 | - * @param EE_Venue /int $venue_id_or_obj |
|
772 | - * @return EE_Base_Class|EE_Venue |
|
773 | - * @throws EE_Error |
|
774 | - * @throws ReflectionException |
|
775 | - */ |
|
776 | - public function remove_venue($venue_id_or_obj): EE_Venue |
|
777 | - { |
|
778 | - $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue(); |
|
779 | - return $this->_remove_relation_to($venue_id_or_obj, 'Venue'); |
|
780 | - } |
|
781 | - |
|
782 | - |
|
783 | - /** |
|
784 | - * Gets the venue related to the event. May provide additional $query_params if desired |
|
785 | - * |
|
786 | - * @param array $query_params |
|
787 | - * @return int |
|
788 | - * @throws EE_Error |
|
789 | - * @throws ReflectionException |
|
790 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
791 | - */ |
|
792 | - public function venue_ID(array $query_params = []): int |
|
793 | - { |
|
794 | - $venue = $this->get_first_related('Venue', $query_params); |
|
795 | - return $venue instanceof EE_Venue ? $venue->ID() : 0; |
|
796 | - } |
|
797 | - |
|
798 | - |
|
799 | - /** |
|
800 | - * Gets the venue related to the event. May provide additional $query_params if desired |
|
801 | - * |
|
802 | - * @param array $query_params |
|
803 | - * @return EE_Base_Class|EE_Venue|null |
|
804 | - * @throws EE_Error |
|
805 | - * @throws ReflectionException |
|
806 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
807 | - */ |
|
808 | - public function venue(array $query_params = []): ?EE_Venue |
|
809 | - { |
|
810 | - return $this->get_first_related('Venue', $query_params); |
|
811 | - } |
|
812 | - |
|
813 | - |
|
814 | - /** |
|
815 | - * @param array $query_params |
|
816 | - * @return EE_Base_Class[]|EE_Venue[] |
|
817 | - * @throws EE_Error |
|
818 | - * @throws ReflectionException |
|
819 | - * @deprecated $VID:$ |
|
820 | - */ |
|
821 | - public function venues(array $query_params = []): array |
|
822 | - { |
|
823 | - return [$this->venue($query_params)]; |
|
824 | - } |
|
825 | - |
|
826 | - |
|
827 | - /** |
|
828 | - * check if event id is present and if event is published |
|
829 | - * |
|
830 | - * @return boolean true yes, false no |
|
831 | - * @throws EE_Error |
|
832 | - * @throws ReflectionException |
|
833 | - */ |
|
834 | - private function _has_ID_and_is_published(): bool |
|
835 | - { |
|
836 | - // first check if event id is present and not NULL, |
|
837 | - // then check if this event is published (or any of the equivalent "published" statuses) |
|
838 | - return |
|
839 | - $this->ID() && $this->ID() !== null |
|
840 | - && ( |
|
841 | - $this->status() === 'publish' |
|
842 | - || $this->status() === EEM_Event::sold_out |
|
843 | - || $this->status() === EEM_Event::postponed |
|
844 | - || $this->status() === EEM_Event::cancelled |
|
845 | - ); |
|
846 | - } |
|
847 | - |
|
848 | - |
|
849 | - /** |
|
850 | - * This simply compares the internal dates with NOW and determines if the event is upcoming or not. |
|
851 | - * |
|
852 | - * @return boolean true yes, false no |
|
853 | - * @throws EE_Error |
|
854 | - * @throws ReflectionException |
|
855 | - */ |
|
856 | - public function is_upcoming(): bool |
|
857 | - { |
|
858 | - // check if event id is present and if this event is published |
|
859 | - if ($this->is_inactive()) { |
|
860 | - return false; |
|
861 | - } |
|
862 | - // set initial value |
|
863 | - $upcoming = false; |
|
864 | - // next let's get all datetimes and loop through them |
|
865 | - $datetimes = $this->datetimes_in_chronological_order(); |
|
866 | - foreach ($datetimes as $datetime) { |
|
867 | - if ($datetime instanceof EE_Datetime) { |
|
868 | - // if this dtt is expired then we continue cause one of the other datetimes might be upcoming. |
|
869 | - if ($datetime->is_expired()) { |
|
870 | - continue; |
|
871 | - } |
|
872 | - // if this dtt is active then we return false. |
|
873 | - if ($datetime->is_active()) { |
|
874 | - return false; |
|
875 | - } |
|
876 | - // otherwise let's check upcoming status |
|
877 | - $upcoming = $datetime->is_upcoming(); |
|
878 | - } |
|
879 | - } |
|
880 | - return $upcoming; |
|
881 | - } |
|
882 | - |
|
883 | - |
|
884 | - /** |
|
885 | - * @return bool |
|
886 | - * @throws EE_Error |
|
887 | - * @throws ReflectionException |
|
888 | - */ |
|
889 | - public function is_active(): bool |
|
890 | - { |
|
891 | - // check if event id is present and if this event is published |
|
892 | - if ($this->is_inactive()) { |
|
893 | - return false; |
|
894 | - } |
|
895 | - // set initial value |
|
896 | - $active = false; |
|
897 | - // next let's get all datetimes and loop through them |
|
898 | - $datetimes = $this->datetimes_in_chronological_order(); |
|
899 | - foreach ($datetimes as $datetime) { |
|
900 | - if ($datetime instanceof EE_Datetime) { |
|
901 | - // if this dtt is expired then we continue cause one of the other datetimes might be active. |
|
902 | - if ($datetime->is_expired()) { |
|
903 | - continue; |
|
904 | - } |
|
905 | - // if this dtt is upcoming then we return false. |
|
906 | - if ($datetime->is_upcoming()) { |
|
907 | - return false; |
|
908 | - } |
|
909 | - // otherwise let's check active status |
|
910 | - $active = $datetime->is_active(); |
|
911 | - } |
|
912 | - } |
|
913 | - return $active; |
|
914 | - } |
|
915 | - |
|
916 | - |
|
917 | - /** |
|
918 | - * @return bool |
|
919 | - * @throws EE_Error |
|
920 | - * @throws ReflectionException |
|
921 | - */ |
|
922 | - public function is_expired(): bool |
|
923 | - { |
|
924 | - // check if event id is present and if this event is published |
|
925 | - if ($this->is_inactive()) { |
|
926 | - return false; |
|
927 | - } |
|
928 | - // set initial value |
|
929 | - $expired = false; |
|
930 | - // first let's get all datetimes and loop through them |
|
931 | - $datetimes = $this->datetimes_in_chronological_order(); |
|
932 | - foreach ($datetimes as $datetime) { |
|
933 | - if ($datetime instanceof EE_Datetime) { |
|
934 | - // if this dtt is upcoming or active then we return false. |
|
935 | - if ($datetime->is_upcoming() || $datetime->is_active()) { |
|
936 | - return false; |
|
937 | - } |
|
938 | - // otherwise let's check active status |
|
939 | - $expired = $datetime->is_expired(); |
|
940 | - } |
|
941 | - } |
|
942 | - return $expired; |
|
943 | - } |
|
944 | - |
|
945 | - |
|
946 | - /** |
|
947 | - * @return bool |
|
948 | - * @throws EE_Error |
|
949 | - * @throws ReflectionException |
|
950 | - */ |
|
951 | - public function is_inactive(): bool |
|
952 | - { |
|
953 | - // check if event id is present and if this event is published |
|
954 | - if ($this->_has_ID_and_is_published()) { |
|
955 | - return false; |
|
956 | - } |
|
957 | - return true; |
|
958 | - } |
|
959 | - |
|
960 | - |
|
961 | - /** |
|
962 | - * calculate spaces remaining based on "saleable" tickets |
|
963 | - * |
|
964 | - * @param array|null $tickets |
|
965 | - * @param bool $filtered |
|
966 | - * @return int|float |
|
967 | - * @throws EE_Error |
|
968 | - * @throws DomainException |
|
969 | - * @throws UnexpectedEntityException |
|
970 | - * @throws ReflectionException |
|
971 | - */ |
|
972 | - public function spaces_remaining(?array $tickets = [], ?bool $filtered = true) |
|
973 | - { |
|
974 | - $this->getAvailableSpacesCalculator()->setActiveTickets($tickets); |
|
975 | - $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining(); |
|
976 | - return $filtered |
|
977 | - ? apply_filters( |
|
978 | - 'FHEE_EE_Event__spaces_remaining', |
|
979 | - $spaces_remaining, |
|
980 | - $this, |
|
981 | - $tickets |
|
982 | - ) |
|
983 | - : $spaces_remaining; |
|
984 | - } |
|
985 | - |
|
986 | - |
|
987 | - /** |
|
988 | - * perform_sold_out_status_check |
|
989 | - * checks all of this event's datetime reg_limit - sold values to determine if ANY datetimes have spaces |
|
990 | - * available... if NOT, then the event status will get toggled to 'sold_out' |
|
991 | - * |
|
992 | - * @return bool return the ACTUAL sold out state. |
|
993 | - * @throws EE_Error |
|
994 | - * @throws DomainException |
|
995 | - * @throws UnexpectedEntityException |
|
996 | - * @throws ReflectionException |
|
997 | - */ |
|
998 | - public function perform_sold_out_status_check(): bool |
|
999 | - { |
|
1000 | - // get all tickets |
|
1001 | - $tickets = $this->tickets( |
|
1002 | - [ |
|
1003 | - 'default_where_conditions' => 'none', |
|
1004 | - 'order_by' => ['TKT_qty' => 'ASC'], |
|
1005 | - ] |
|
1006 | - ); |
|
1007 | - $all_expired = true; |
|
1008 | - foreach ($tickets as $ticket) { |
|
1009 | - if (! $ticket->is_expired()) { |
|
1010 | - $all_expired = false; |
|
1011 | - break; |
|
1012 | - } |
|
1013 | - } |
|
1014 | - // if all the tickets are just expired, then don't update the event status to sold out |
|
1015 | - if ($all_expired) { |
|
1016 | - return true; |
|
1017 | - } |
|
1018 | - $spaces_remaining = $this->spaces_remaining($tickets); |
|
1019 | - if ($spaces_remaining < 1) { |
|
1020 | - if ($this->status() !== EEM_CPT_Base::post_status_private) { |
|
1021 | - $this->set_status(EEM_Event::sold_out); |
|
1022 | - $this->save(); |
|
1023 | - } |
|
1024 | - $sold_out = true; |
|
1025 | - } else { |
|
1026 | - $sold_out = false; |
|
1027 | - // was event previously marked as sold out ? |
|
1028 | - if ($this->status() === EEM_Event::sold_out) { |
|
1029 | - // revert status to previous value, if it was set |
|
1030 | - $previous_event_status = $this->get_post_meta('_previous_event_status', true); |
|
1031 | - if ($previous_event_status) { |
|
1032 | - $this->set_status($previous_event_status); |
|
1033 | - $this->save(); |
|
1034 | - } |
|
1035 | - } |
|
1036 | - } |
|
1037 | - do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets); |
|
1038 | - return $sold_out; |
|
1039 | - } |
|
1040 | - |
|
1041 | - |
|
1042 | - /** |
|
1043 | - * This returns the total remaining spaces for sale on this event. |
|
1044 | - * |
|
1045 | - * @return int|float |
|
1046 | - * @throws EE_Error |
|
1047 | - * @throws DomainException |
|
1048 | - * @throws UnexpectedEntityException |
|
1049 | - * @throws ReflectionException |
|
1050 | - * @uses EE_Event::total_available_spaces() |
|
1051 | - */ |
|
1052 | - public function spaces_remaining_for_sale() |
|
1053 | - { |
|
1054 | - return $this->total_available_spaces(true); |
|
1055 | - } |
|
1056 | - |
|
1057 | - |
|
1058 | - /** |
|
1059 | - * This returns the total spaces available for an event |
|
1060 | - * while considering all the quantities on the tickets and the reg limits |
|
1061 | - * on the datetimes attached to this event. |
|
1062 | - * |
|
1063 | - * @param bool $consider_sold Whether to consider any tickets that have already sold in our calculation. |
|
1064 | - * If this is false, then we return the most tickets that could ever be sold |
|
1065 | - * for this event with the datetime and tickets setup on the event under optimal |
|
1066 | - * selling conditions. Otherwise we return a live calculation of spaces available |
|
1067 | - * based on tickets sold. Depending on setup and stage of sales, this |
|
1068 | - * may appear to equal remaining tickets. However, the more tickets are |
|
1069 | - * sold out, the more accurate the "live" total is. |
|
1070 | - * @return int|float |
|
1071 | - * @throws EE_Error |
|
1072 | - * @throws DomainException |
|
1073 | - * @throws UnexpectedEntityException |
|
1074 | - * @throws ReflectionException |
|
1075 | - */ |
|
1076 | - public function total_available_spaces(bool $consider_sold = false) |
|
1077 | - { |
|
1078 | - $spaces_available = $consider_sold |
|
1079 | - ? $this->getAvailableSpacesCalculator()->spacesRemaining() |
|
1080 | - : $this->getAvailableSpacesCalculator()->totalSpacesAvailable(); |
|
1081 | - return apply_filters( |
|
1082 | - 'FHEE_EE_Event__total_available_spaces__spaces_available', |
|
1083 | - $spaces_available, |
|
1084 | - $this, |
|
1085 | - $this->getAvailableSpacesCalculator()->getDatetimes(), |
|
1086 | - $this->getAvailableSpacesCalculator()->getActiveTickets() |
|
1087 | - ); |
|
1088 | - } |
|
1089 | - |
|
1090 | - |
|
1091 | - /** |
|
1092 | - * Checks if the event is set to sold out |
|
1093 | - * |
|
1094 | - * @param bool $actual whether or not to perform calculations to not only figure the |
|
1095 | - * actual status but also to flip the status if necessary to sold |
|
1096 | - * out If false, we just check the existing status of the event |
|
1097 | - * @return boolean |
|
1098 | - * @throws EE_Error |
|
1099 | - * @throws ReflectionException |
|
1100 | - */ |
|
1101 | - public function is_sold_out(bool $actual = false): bool |
|
1102 | - { |
|
1103 | - if (! $actual) { |
|
1104 | - return $this->status() === EEM_Event::sold_out; |
|
1105 | - } |
|
1106 | - return $this->perform_sold_out_status_check(); |
|
1107 | - } |
|
1108 | - |
|
1109 | - |
|
1110 | - /** |
|
1111 | - * Checks if the event is marked as postponed |
|
1112 | - * |
|
1113 | - * @return boolean |
|
1114 | - */ |
|
1115 | - public function is_postponed(): bool |
|
1116 | - { |
|
1117 | - return $this->status() === EEM_Event::postponed; |
|
1118 | - } |
|
1119 | - |
|
1120 | - |
|
1121 | - /** |
|
1122 | - * Checks if the event is marked as cancelled |
|
1123 | - * |
|
1124 | - * @return boolean |
|
1125 | - */ |
|
1126 | - public function is_cancelled(): bool |
|
1127 | - { |
|
1128 | - return $this->status() === EEM_Event::cancelled; |
|
1129 | - } |
|
1130 | - |
|
1131 | - |
|
1132 | - /** |
|
1133 | - * Get the logical active status in a hierarchical order for all the datetimes. Note |
|
1134 | - * Basically, we order the datetimes by EVT_start_date. Then first test on whether the event is published. If its |
|
1135 | - * NOT published then we test for whether its expired or not. IF it IS published then we test first on whether an |
|
1136 | - * event has any active dates. If no active dates then we check for any upcoming dates. If no upcoming dates then |
|
1137 | - * the event is considered expired. |
|
1138 | - * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published. Sold Out is a |
|
1139 | - * status set on the EVENT when it is not published and thus is done |
|
1140 | - * |
|
1141 | - * @param bool $reset |
|
1142 | - * @return bool | string - based on EE_Datetime active constants or FALSE if error. |
|
1143 | - * @throws EE_Error |
|
1144 | - * @throws ReflectionException |
|
1145 | - */ |
|
1146 | - public function get_active_status(bool $reset = false) |
|
1147 | - { |
|
1148 | - // if the active status has already been set, then just use that value (unless we are resetting it) |
|
1149 | - if (! empty($this->_active_status) && ! $reset) { |
|
1150 | - return $this->_active_status; |
|
1151 | - } |
|
1152 | - // first check if event id is present on this object |
|
1153 | - if (! $this->ID()) { |
|
1154 | - return false; |
|
1155 | - } |
|
1156 | - $where_params_for_event = [['EVT_ID' => $this->ID()]]; |
|
1157 | - // if event is published: |
|
1158 | - if ( |
|
1159 | - $this->status() === EEM_CPT_Base::post_status_publish |
|
1160 | - || $this->status() === EEM_CPT_Base::post_status_private |
|
1161 | - ) { |
|
1162 | - // active? |
|
1163 | - if ( |
|
1164 | - EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1165 | - EE_Datetime::active, |
|
1166 | - $where_params_for_event |
|
1167 | - ) > 0 |
|
1168 | - ) { |
|
1169 | - $this->_active_status = EE_Datetime::active; |
|
1170 | - } else { |
|
1171 | - // upcoming? |
|
1172 | - if ( |
|
1173 | - EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1174 | - EE_Datetime::upcoming, |
|
1175 | - $where_params_for_event |
|
1176 | - ) > 0 |
|
1177 | - ) { |
|
1178 | - $this->_active_status = EE_Datetime::upcoming; |
|
1179 | - } else { |
|
1180 | - // expired? |
|
1181 | - if ( |
|
1182 | - EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1183 | - EE_Datetime::expired, |
|
1184 | - $where_params_for_event |
|
1185 | - ) > 0 |
|
1186 | - ) { |
|
1187 | - $this->_active_status = EE_Datetime::expired; |
|
1188 | - } else { |
|
1189 | - // it would be odd if things make it this far |
|
1190 | - // because it basically means there are no datetimes attached to the event. |
|
1191 | - // So in this case it will just be considered inactive. |
|
1192 | - $this->_active_status = EE_Datetime::inactive; |
|
1193 | - } |
|
1194 | - } |
|
1195 | - } |
|
1196 | - } else { |
|
1197 | - // the event is not published, so let's just set it's active status according to its' post status |
|
1198 | - switch ($this->status()) { |
|
1199 | - case EEM_Event::sold_out: |
|
1200 | - $this->_active_status = EE_Datetime::sold_out; |
|
1201 | - break; |
|
1202 | - case EEM_Event::cancelled: |
|
1203 | - $this->_active_status = EE_Datetime::cancelled; |
|
1204 | - break; |
|
1205 | - case EEM_Event::postponed: |
|
1206 | - $this->_active_status = EE_Datetime::postponed; |
|
1207 | - break; |
|
1208 | - default: |
|
1209 | - $this->_active_status = EE_Datetime::inactive; |
|
1210 | - } |
|
1211 | - } |
|
1212 | - return $this->_active_status; |
|
1213 | - } |
|
1214 | - |
|
1215 | - |
|
1216 | - /** |
|
1217 | - * pretty_active_status |
|
1218 | - * |
|
1219 | - * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE) |
|
1220 | - * @return string |
|
1221 | - * @throws EE_Error |
|
1222 | - * @throws ReflectionException |
|
1223 | - */ |
|
1224 | - public function pretty_active_status(bool $echo = true): string |
|
1225 | - { |
|
1226 | - $active_status = $this->get_active_status(); |
|
1227 | - $status = " |
|
19 | + /** |
|
20 | + * cached value for the the logical active status for the event |
|
21 | + * |
|
22 | + * @see get_active_status() |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + protected $_active_status = ''; |
|
26 | + |
|
27 | + /** |
|
28 | + * This is just used for caching the Primary Datetime for the Event on initial retrieval |
|
29 | + * |
|
30 | + * @var EE_Datetime |
|
31 | + */ |
|
32 | + protected $_Primary_Datetime; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var EventSpacesCalculator $available_spaces_calculator |
|
36 | + */ |
|
37 | + protected $available_spaces_calculator; |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * @param array $props_n_values incoming values |
|
42 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
43 | + * used.) |
|
44 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
45 | + * date_format and the second value is the time format |
|
46 | + * @return EE_Event |
|
47 | + * @throws EE_Error |
|
48 | + * @throws ReflectionException |
|
49 | + */ |
|
50 | + public static function new_instance($props_n_values = [], $timezone = null, $date_formats = []): EE_Event |
|
51 | + { |
|
52 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
53 | + return $has_object ?: new self($props_n_values, false, $timezone, $date_formats); |
|
54 | + } |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * @param array $props_n_values incoming values from the database |
|
59 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
60 | + * the website will be used. |
|
61 | + * @return EE_Event |
|
62 | + * @throws EE_Error |
|
63 | + * @throws ReflectionException |
|
64 | + */ |
|
65 | + public static function new_instance_from_db($props_n_values = [], $timezone = null): EE_Event |
|
66 | + { |
|
67 | + return new self($props_n_values, true, $timezone); |
|
68 | + } |
|
69 | + |
|
70 | + |
|
71 | + /** |
|
72 | + * @return EventSpacesCalculator |
|
73 | + * @throws EE_Error |
|
74 | + * @throws ReflectionException |
|
75 | + */ |
|
76 | + public function getAvailableSpacesCalculator(): EventSpacesCalculator |
|
77 | + { |
|
78 | + if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) { |
|
79 | + $this->available_spaces_calculator = new EventSpacesCalculator($this); |
|
80 | + } |
|
81 | + return $this->available_spaces_calculator; |
|
82 | + } |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods |
|
87 | + * |
|
88 | + * @param string $field_name |
|
89 | + * @param mixed $field_value |
|
90 | + * @param bool $use_default |
|
91 | + * @throws EE_Error |
|
92 | + * @throws ReflectionException |
|
93 | + */ |
|
94 | + public function set($field_name, $field_value, $use_default = false) |
|
95 | + { |
|
96 | + switch ($field_name) { |
|
97 | + case 'status': |
|
98 | + $this->set_status($field_value, $use_default); |
|
99 | + break; |
|
100 | + default: |
|
101 | + parent::set($field_name, $field_value, $use_default); |
|
102 | + } |
|
103 | + } |
|
104 | + |
|
105 | + |
|
106 | + /** |
|
107 | + * set_status |
|
108 | + * Checks if event status is being changed to SOLD OUT |
|
109 | + * and updates event meta data with previous event status |
|
110 | + * so that we can revert things if/when the event is no longer sold out |
|
111 | + * |
|
112 | + * @param string $status |
|
113 | + * @param bool $use_default |
|
114 | + * @return void |
|
115 | + * @throws EE_Error |
|
116 | + * @throws ReflectionException |
|
117 | + */ |
|
118 | + public function set_status($status = '', $use_default = false) |
|
119 | + { |
|
120 | + // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave |
|
121 | + if (empty($status) && ! $use_default) { |
|
122 | + return; |
|
123 | + } |
|
124 | + // get current Event status |
|
125 | + $old_status = $this->status(); |
|
126 | + // if status has changed |
|
127 | + if ($old_status !== $status) { |
|
128 | + // TO sold_out |
|
129 | + if ($status === EEM_Event::sold_out) { |
|
130 | + // save the previous event status so that we can revert if the event is no longer sold out |
|
131 | + $this->add_post_meta('_previous_event_status', $old_status); |
|
132 | + do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $status); |
|
133 | + // OR FROM sold_out |
|
134 | + } elseif ($old_status === EEM_Event::sold_out) { |
|
135 | + $this->delete_post_meta('_previous_event_status'); |
|
136 | + do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $status); |
|
137 | + } |
|
138 | + // clear out the active status so that it gets reset the next time it is requested |
|
139 | + $this->_active_status = null; |
|
140 | + // update status |
|
141 | + parent::set('status', $status, $use_default); |
|
142 | + do_action('AHEE__EE_Event__set_status__after_update', $this); |
|
143 | + return; |
|
144 | + } |
|
145 | + // even though the old value matches the new value, it's still good to |
|
146 | + // allow the parent set method to have a say |
|
147 | + parent::set('status', $status, $use_default); |
|
148 | + } |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * Gets all the datetimes for this event |
|
153 | + * |
|
154 | + * @param array|null $query_params |
|
155 | + * @return EE_Base_Class[]|EE_Datetime[] |
|
156 | + * @throws EE_Error |
|
157 | + * @throws ReflectionException |
|
158 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
159 | + */ |
|
160 | + public function datetimes(?array $query_params = []): array |
|
161 | + { |
|
162 | + return $this->get_many_related('Datetime', $query_params); |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + /** |
|
167 | + * Gets all the datetimes for this event that are currently ACTIVE, |
|
168 | + * meaning the datetime has started and has not yet ended. |
|
169 | + * |
|
170 | + * @param int|null $start_date timestamp to use for event date start time, defaults to NOW unless set to 0 |
|
171 | + * @param array|null $query_params will recursively replace default values |
|
172 | + * @throws EE_Error |
|
173 | + * @throws ReflectionException |
|
174 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
175 | + */ |
|
176 | + public function activeDatetimes(?int $start_date, ?array $query_params = []): array |
|
177 | + { |
|
178 | + // if start date is null, then use current time |
|
179 | + $start_date = $start_date ?? time(); |
|
180 | + $where = []; |
|
181 | + if ($start_date) { |
|
182 | + $where['DTT_EVT_start'] = ['<', $start_date]; |
|
183 | + $where['DTT_EVT_end'] = ['>', time()]; |
|
184 | + } |
|
185 | + $query_params = array_replace_recursive( |
|
186 | + [ |
|
187 | + $where, |
|
188 | + 'order_by' => ['DTT_EVT_start' => 'ASC'], |
|
189 | + ], |
|
190 | + $query_params |
|
191 | + ); |
|
192 | + return $this->get_many_related('Datetime', $query_params); |
|
193 | + } |
|
194 | + |
|
195 | + |
|
196 | + /** |
|
197 | + * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order |
|
198 | + * |
|
199 | + * @return EE_Base_Class[]|EE_Datetime[] |
|
200 | + * @throws EE_Error |
|
201 | + * @throws ReflectionException |
|
202 | + */ |
|
203 | + public function datetimes_in_chronological_order(): array |
|
204 | + { |
|
205 | + return $this->get_many_related('Datetime', ['order_by' => ['DTT_EVT_start' => 'ASC']]); |
|
206 | + } |
|
207 | + |
|
208 | + |
|
209 | + /** |
|
210 | + * Gets all the datetimes for this event, ordered by the DTT_order on the datetime. |
|
211 | + * @darren, we should probably UNSET timezone on the EEM_Datetime model |
|
212 | + * after running our query, so that this timezone isn't set for EVERY query |
|
213 | + * on EEM_Datetime for the rest of the request, no? |
|
214 | + * |
|
215 | + * @param bool $show_expired whether or not to include expired events |
|
216 | + * @param bool $show_deleted whether or not to include deleted events |
|
217 | + * @param int|null $limit |
|
218 | + * @return EE_Datetime[] |
|
219 | + * @throws EE_Error |
|
220 | + * @throws ReflectionException |
|
221 | + */ |
|
222 | + public function datetimes_ordered(bool $show_expired = true, bool $show_deleted = false, ?int $limit = null): array |
|
223 | + { |
|
224 | + return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order( |
|
225 | + $this->ID(), |
|
226 | + $show_expired, |
|
227 | + $show_deleted, |
|
228 | + $limit |
|
229 | + ); |
|
230 | + } |
|
231 | + |
|
232 | + |
|
233 | + /** |
|
234 | + * Returns one related datetime. Mostly only used by some legacy code. |
|
235 | + * |
|
236 | + * @return EE_Base_Class|EE_Datetime |
|
237 | + * @throws EE_Error |
|
238 | + * @throws ReflectionException |
|
239 | + */ |
|
240 | + public function first_datetime(): EE_Datetime |
|
241 | + { |
|
242 | + return $this->get_first_related('Datetime'); |
|
243 | + } |
|
244 | + |
|
245 | + |
|
246 | + /** |
|
247 | + * Returns the 'primary' datetime for the event |
|
248 | + * |
|
249 | + * @param bool $try_to_exclude_expired |
|
250 | + * @param bool $try_to_exclude_deleted |
|
251 | + * @return EE_Datetime|null |
|
252 | + * @throws EE_Error |
|
253 | + * @throws ReflectionException |
|
254 | + */ |
|
255 | + public function primary_datetime( |
|
256 | + bool $try_to_exclude_expired = true, |
|
257 | + bool $try_to_exclude_deleted = true |
|
258 | + ): ?EE_Datetime { |
|
259 | + if (! empty($this->_Primary_Datetime)) { |
|
260 | + return $this->_Primary_Datetime; |
|
261 | + } |
|
262 | + $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event( |
|
263 | + $this->ID(), |
|
264 | + $try_to_exclude_expired, |
|
265 | + $try_to_exclude_deleted |
|
266 | + ); |
|
267 | + return $this->_Primary_Datetime; |
|
268 | + } |
|
269 | + |
|
270 | + |
|
271 | + /** |
|
272 | + * Gets all the tickets available for purchase of this event |
|
273 | + * |
|
274 | + * @param array|null $query_params |
|
275 | + * @return EE_Base_Class[]|EE_Ticket[] |
|
276 | + * @throws EE_Error |
|
277 | + * @throws ReflectionException |
|
278 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
279 | + */ |
|
280 | + public function tickets(?array $query_params = []): array |
|
281 | + { |
|
282 | + // first get all datetimes |
|
283 | + $datetimes = $this->datetimes_ordered(); |
|
284 | + if (! $datetimes) { |
|
285 | + return []; |
|
286 | + } |
|
287 | + $datetime_ids = []; |
|
288 | + foreach ($datetimes as $datetime) { |
|
289 | + $datetime_ids[] = $datetime->ID(); |
|
290 | + } |
|
291 | + $where_params = ['Datetime.DTT_ID' => ['IN', $datetime_ids]]; |
|
292 | + // if incoming $query_params has where conditions let's merge but not override existing. |
|
293 | + if (is_array($query_params) && isset($query_params[0])) { |
|
294 | + $where_params = array_merge($query_params[0], $where_params); |
|
295 | + unset($query_params[0]); |
|
296 | + } |
|
297 | + // now add $where_params to $query_params |
|
298 | + $query_params[0] = $where_params; |
|
299 | + return EEM_Ticket::instance()->get_all($query_params); |
|
300 | + } |
|
301 | + |
|
302 | + |
|
303 | + /** |
|
304 | + * get all unexpired not-trashed tickets |
|
305 | + * |
|
306 | + * @return EE_Ticket[] |
|
307 | + * @throws EE_Error |
|
308 | + * @throws ReflectionException |
|
309 | + */ |
|
310 | + public function active_tickets(): array |
|
311 | + { |
|
312 | + return $this->tickets( |
|
313 | + [ |
|
314 | + [ |
|
315 | + 'TKT_end_date' => ['>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')], |
|
316 | + 'TKT_deleted' => false, |
|
317 | + ], |
|
318 | + ] |
|
319 | + ); |
|
320 | + } |
|
321 | + |
|
322 | + |
|
323 | + /** |
|
324 | + * @return int |
|
325 | + * @throws EE_Error |
|
326 | + * @throws ReflectionException |
|
327 | + */ |
|
328 | + public function additional_limit(): int |
|
329 | + { |
|
330 | + return $this->get('EVT_additional_limit'); |
|
331 | + } |
|
332 | + |
|
333 | + |
|
334 | + /** |
|
335 | + * @return bool |
|
336 | + * @throws EE_Error |
|
337 | + * @throws ReflectionException |
|
338 | + */ |
|
339 | + public function allow_overflow(): bool |
|
340 | + { |
|
341 | + return $this->get('EVT_allow_overflow'); |
|
342 | + } |
|
343 | + |
|
344 | + |
|
345 | + /** |
|
346 | + * @return string |
|
347 | + * @throws EE_Error |
|
348 | + * @throws ReflectionException |
|
349 | + */ |
|
350 | + public function created(): string |
|
351 | + { |
|
352 | + return $this->get('EVT_created'); |
|
353 | + } |
|
354 | + |
|
355 | + |
|
356 | + /** |
|
357 | + * @return string |
|
358 | + * @throws EE_Error |
|
359 | + * @throws ReflectionException |
|
360 | + */ |
|
361 | + public function description(): string |
|
362 | + { |
|
363 | + return $this->get('EVT_desc'); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + /** |
|
368 | + * Runs do_shortcode and wpautop on the description |
|
369 | + * |
|
370 | + * @return string of html |
|
371 | + * @throws EE_Error |
|
372 | + * @throws ReflectionException |
|
373 | + */ |
|
374 | + public function description_filtered(): string |
|
375 | + { |
|
376 | + return $this->get_pretty('EVT_desc'); |
|
377 | + } |
|
378 | + |
|
379 | + |
|
380 | + /** |
|
381 | + * @return bool |
|
382 | + * @throws EE_Error |
|
383 | + * @throws ReflectionException |
|
384 | + */ |
|
385 | + public function display_description(): bool |
|
386 | + { |
|
387 | + return $this->get('EVT_display_desc'); |
|
388 | + } |
|
389 | + |
|
390 | + |
|
391 | + /** |
|
392 | + * @return bool |
|
393 | + * @throws EE_Error |
|
394 | + * @throws ReflectionException |
|
395 | + */ |
|
396 | + public function display_ticket_selector(): bool |
|
397 | + { |
|
398 | + return (bool) $this->get('EVT_display_ticket_selector'); |
|
399 | + } |
|
400 | + |
|
401 | + |
|
402 | + /** |
|
403 | + * @return string |
|
404 | + * @throws EE_Error |
|
405 | + * @throws ReflectionException |
|
406 | + */ |
|
407 | + public function external_url(): ?string |
|
408 | + { |
|
409 | + return $this->get('EVT_external_URL') ?? ''; |
|
410 | + } |
|
411 | + |
|
412 | + |
|
413 | + /** |
|
414 | + * @return bool |
|
415 | + * @throws EE_Error |
|
416 | + * @throws ReflectionException |
|
417 | + */ |
|
418 | + public function member_only(): bool |
|
419 | + { |
|
420 | + return $this->get('EVT_member_only'); |
|
421 | + } |
|
422 | + |
|
423 | + |
|
424 | + /** |
|
425 | + * @return string |
|
426 | + * @throws EE_Error |
|
427 | + * @throws ReflectionException |
|
428 | + */ |
|
429 | + public function phone(): string |
|
430 | + { |
|
431 | + return $this->get('EVT_phone'); |
|
432 | + } |
|
433 | + |
|
434 | + |
|
435 | + /** |
|
436 | + * @return string |
|
437 | + * @throws EE_Error |
|
438 | + * @throws ReflectionException |
|
439 | + */ |
|
440 | + public function modified(): string |
|
441 | + { |
|
442 | + return $this->get('EVT_modified'); |
|
443 | + } |
|
444 | + |
|
445 | + |
|
446 | + /** |
|
447 | + * @return string |
|
448 | + * @throws EE_Error |
|
449 | + * @throws ReflectionException |
|
450 | + */ |
|
451 | + public function name(): string |
|
452 | + { |
|
453 | + return $this->get('EVT_name'); |
|
454 | + } |
|
455 | + |
|
456 | + |
|
457 | + /** |
|
458 | + * @return int |
|
459 | + * @throws EE_Error |
|
460 | + * @throws ReflectionException |
|
461 | + */ |
|
462 | + public function order(): int |
|
463 | + { |
|
464 | + return $this->get('EVT_order'); |
|
465 | + } |
|
466 | + |
|
467 | + |
|
468 | + /** |
|
469 | + * @return string |
|
470 | + * @throws EE_Error |
|
471 | + * @throws ReflectionException |
|
472 | + */ |
|
473 | + public function default_registration_status(): string |
|
474 | + { |
|
475 | + $event_default_registration_status = $this->get('EVT_default_registration_status'); |
|
476 | + return ! empty($event_default_registration_status) |
|
477 | + ? $event_default_registration_status |
|
478 | + : EE_Registry::instance()->CFG->registration->default_STS_ID; |
|
479 | + } |
|
480 | + |
|
481 | + |
|
482 | + /** |
|
483 | + * @param int|null $num_words |
|
484 | + * @param string|null $more |
|
485 | + * @param bool $not_full_desc |
|
486 | + * @return string |
|
487 | + * @throws EE_Error |
|
488 | + * @throws ReflectionException |
|
489 | + */ |
|
490 | + public function short_description(?int $num_words = 55, string $more = null, bool $not_full_desc = false): string |
|
491 | + { |
|
492 | + $short_desc = $this->get('EVT_short_desc'); |
|
493 | + if (! empty($short_desc) || $not_full_desc) { |
|
494 | + return $short_desc; |
|
495 | + } |
|
496 | + $full_desc = $this->get('EVT_desc'); |
|
497 | + return wp_trim_words($full_desc, $num_words, $more); |
|
498 | + } |
|
499 | + |
|
500 | + |
|
501 | + /** |
|
502 | + * @return string |
|
503 | + * @throws EE_Error |
|
504 | + * @throws ReflectionException |
|
505 | + */ |
|
506 | + public function slug(): string |
|
507 | + { |
|
508 | + return $this->get('EVT_slug'); |
|
509 | + } |
|
510 | + |
|
511 | + |
|
512 | + /** |
|
513 | + * @return string |
|
514 | + * @throws EE_Error |
|
515 | + * @throws ReflectionException |
|
516 | + */ |
|
517 | + public function timezone_string(): string |
|
518 | + { |
|
519 | + return $this->get('EVT_timezone_string'); |
|
520 | + } |
|
521 | + |
|
522 | + |
|
523 | + /** |
|
524 | + * @return string |
|
525 | + * @throws EE_Error |
|
526 | + * @throws ReflectionException |
|
527 | + */ |
|
528 | + public function visible_on(): string |
|
529 | + { |
|
530 | + return $this->get('EVT_visible_on'); |
|
531 | + } |
|
532 | + |
|
533 | + |
|
534 | + /** |
|
535 | + * @return int |
|
536 | + * @throws EE_Error |
|
537 | + * @throws ReflectionException |
|
538 | + */ |
|
539 | + public function wp_user(): int |
|
540 | + { |
|
541 | + return $this->get('EVT_wp_user'); |
|
542 | + } |
|
543 | + |
|
544 | + |
|
545 | + /** |
|
546 | + * @return bool |
|
547 | + * @throws EE_Error |
|
548 | + * @throws ReflectionException |
|
549 | + */ |
|
550 | + public function donations(): bool |
|
551 | + { |
|
552 | + return $this->get('EVT_donations'); |
|
553 | + } |
|
554 | + |
|
555 | + |
|
556 | + /** |
|
557 | + * @param int $limit |
|
558 | + * @throws EE_Error |
|
559 | + * @throws ReflectionException |
|
560 | + */ |
|
561 | + public function set_additional_limit(int $limit) |
|
562 | + { |
|
563 | + $this->set('EVT_additional_limit', $limit); |
|
564 | + } |
|
565 | + |
|
566 | + |
|
567 | + /** |
|
568 | + * @param $created |
|
569 | + * @throws EE_Error |
|
570 | + * @throws ReflectionException |
|
571 | + */ |
|
572 | + public function set_created($created) |
|
573 | + { |
|
574 | + $this->set('EVT_created', $created); |
|
575 | + } |
|
576 | + |
|
577 | + |
|
578 | + /** |
|
579 | + * @param $desc |
|
580 | + * @throws EE_Error |
|
581 | + * @throws ReflectionException |
|
582 | + */ |
|
583 | + public function set_description($desc) |
|
584 | + { |
|
585 | + $this->set('EVT_desc', $desc); |
|
586 | + } |
|
587 | + |
|
588 | + |
|
589 | + /** |
|
590 | + * @param $display_desc |
|
591 | + * @throws EE_Error |
|
592 | + * @throws ReflectionException |
|
593 | + */ |
|
594 | + public function set_display_description($display_desc) |
|
595 | + { |
|
596 | + $this->set('EVT_display_desc', $display_desc); |
|
597 | + } |
|
598 | + |
|
599 | + |
|
600 | + /** |
|
601 | + * @param $display_ticket_selector |
|
602 | + * @throws EE_Error |
|
603 | + * @throws ReflectionException |
|
604 | + */ |
|
605 | + public function set_display_ticket_selector($display_ticket_selector) |
|
606 | + { |
|
607 | + $this->set('EVT_display_ticket_selector', $display_ticket_selector); |
|
608 | + } |
|
609 | + |
|
610 | + |
|
611 | + /** |
|
612 | + * @param $external_url |
|
613 | + * @throws EE_Error |
|
614 | + * @throws ReflectionException |
|
615 | + */ |
|
616 | + public function set_external_url($external_url) |
|
617 | + { |
|
618 | + $this->set('EVT_external_URL', $external_url); |
|
619 | + } |
|
620 | + |
|
621 | + |
|
622 | + /** |
|
623 | + * @param $member_only |
|
624 | + * @throws EE_Error |
|
625 | + * @throws ReflectionException |
|
626 | + */ |
|
627 | + public function set_member_only($member_only) |
|
628 | + { |
|
629 | + $this->set('EVT_member_only', $member_only); |
|
630 | + } |
|
631 | + |
|
632 | + |
|
633 | + /** |
|
634 | + * @param $event_phone |
|
635 | + * @throws EE_Error |
|
636 | + * @throws ReflectionException |
|
637 | + */ |
|
638 | + public function set_event_phone($event_phone) |
|
639 | + { |
|
640 | + $this->set('EVT_phone', $event_phone); |
|
641 | + } |
|
642 | + |
|
643 | + |
|
644 | + /** |
|
645 | + * @param $modified |
|
646 | + * @throws EE_Error |
|
647 | + * @throws ReflectionException |
|
648 | + */ |
|
649 | + public function set_modified($modified) |
|
650 | + { |
|
651 | + $this->set('EVT_modified', $modified); |
|
652 | + } |
|
653 | + |
|
654 | + |
|
655 | + /** |
|
656 | + * @param $name |
|
657 | + * @throws EE_Error |
|
658 | + * @throws ReflectionException |
|
659 | + */ |
|
660 | + public function set_name($name) |
|
661 | + { |
|
662 | + $this->set('EVT_name', $name); |
|
663 | + } |
|
664 | + |
|
665 | + |
|
666 | + /** |
|
667 | + * @param $order |
|
668 | + * @throws EE_Error |
|
669 | + * @throws ReflectionException |
|
670 | + */ |
|
671 | + public function set_order($order) |
|
672 | + { |
|
673 | + $this->set('EVT_order', $order); |
|
674 | + } |
|
675 | + |
|
676 | + |
|
677 | + /** |
|
678 | + * @param $short_desc |
|
679 | + * @throws EE_Error |
|
680 | + * @throws ReflectionException |
|
681 | + */ |
|
682 | + public function set_short_description($short_desc) |
|
683 | + { |
|
684 | + $this->set('EVT_short_desc', $short_desc); |
|
685 | + } |
|
686 | + |
|
687 | + |
|
688 | + /** |
|
689 | + * @param $slug |
|
690 | + * @throws EE_Error |
|
691 | + * @throws ReflectionException |
|
692 | + */ |
|
693 | + public function set_slug($slug) |
|
694 | + { |
|
695 | + $this->set('EVT_slug', $slug); |
|
696 | + } |
|
697 | + |
|
698 | + |
|
699 | + /** |
|
700 | + * @param $timezone_string |
|
701 | + * @throws EE_Error |
|
702 | + * @throws ReflectionException |
|
703 | + */ |
|
704 | + public function set_timezone_string($timezone_string) |
|
705 | + { |
|
706 | + $this->set('EVT_timezone_string', $timezone_string); |
|
707 | + } |
|
708 | + |
|
709 | + |
|
710 | + /** |
|
711 | + * @param $visible_on |
|
712 | + * @throws EE_Error |
|
713 | + * @throws ReflectionException |
|
714 | + */ |
|
715 | + public function set_visible_on($visible_on) |
|
716 | + { |
|
717 | + $this->set('EVT_visible_on', $visible_on); |
|
718 | + } |
|
719 | + |
|
720 | + |
|
721 | + /** |
|
722 | + * @param $wp_user |
|
723 | + * @throws EE_Error |
|
724 | + * @throws ReflectionException |
|
725 | + */ |
|
726 | + public function set_wp_user($wp_user) |
|
727 | + { |
|
728 | + $this->set('EVT_wp_user', $wp_user); |
|
729 | + } |
|
730 | + |
|
731 | + |
|
732 | + /** |
|
733 | + * @param $default_registration_status |
|
734 | + * @throws EE_Error |
|
735 | + * @throws ReflectionException |
|
736 | + */ |
|
737 | + public function set_default_registration_status($default_registration_status) |
|
738 | + { |
|
739 | + $this->set('EVT_default_registration_status', $default_registration_status); |
|
740 | + } |
|
741 | + |
|
742 | + |
|
743 | + /** |
|
744 | + * @param $donations |
|
745 | + * @throws EE_Error |
|
746 | + * @throws ReflectionException |
|
747 | + */ |
|
748 | + public function set_donations($donations) |
|
749 | + { |
|
750 | + $this->set('EVT_donations', $donations); |
|
751 | + } |
|
752 | + |
|
753 | + |
|
754 | + /** |
|
755 | + * Adds a venue to this event |
|
756 | + * |
|
757 | + * @param int|EE_Venue /int $venue_id_or_obj |
|
758 | + * @return EE_Base_Class|EE_Venue |
|
759 | + * @throws EE_Error |
|
760 | + * @throws ReflectionException |
|
761 | + */ |
|
762 | + public function add_venue($venue_id_or_obj): EE_Venue |
|
763 | + { |
|
764 | + return $this->_add_relation_to($venue_id_or_obj, 'Venue'); |
|
765 | + } |
|
766 | + |
|
767 | + |
|
768 | + /** |
|
769 | + * Removes a venue from the event |
|
770 | + * |
|
771 | + * @param EE_Venue /int $venue_id_or_obj |
|
772 | + * @return EE_Base_Class|EE_Venue |
|
773 | + * @throws EE_Error |
|
774 | + * @throws ReflectionException |
|
775 | + */ |
|
776 | + public function remove_venue($venue_id_or_obj): EE_Venue |
|
777 | + { |
|
778 | + $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue(); |
|
779 | + return $this->_remove_relation_to($venue_id_or_obj, 'Venue'); |
|
780 | + } |
|
781 | + |
|
782 | + |
|
783 | + /** |
|
784 | + * Gets the venue related to the event. May provide additional $query_params if desired |
|
785 | + * |
|
786 | + * @param array $query_params |
|
787 | + * @return int |
|
788 | + * @throws EE_Error |
|
789 | + * @throws ReflectionException |
|
790 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
791 | + */ |
|
792 | + public function venue_ID(array $query_params = []): int |
|
793 | + { |
|
794 | + $venue = $this->get_first_related('Venue', $query_params); |
|
795 | + return $venue instanceof EE_Venue ? $venue->ID() : 0; |
|
796 | + } |
|
797 | + |
|
798 | + |
|
799 | + /** |
|
800 | + * Gets the venue related to the event. May provide additional $query_params if desired |
|
801 | + * |
|
802 | + * @param array $query_params |
|
803 | + * @return EE_Base_Class|EE_Venue|null |
|
804 | + * @throws EE_Error |
|
805 | + * @throws ReflectionException |
|
806 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
807 | + */ |
|
808 | + public function venue(array $query_params = []): ?EE_Venue |
|
809 | + { |
|
810 | + return $this->get_first_related('Venue', $query_params); |
|
811 | + } |
|
812 | + |
|
813 | + |
|
814 | + /** |
|
815 | + * @param array $query_params |
|
816 | + * @return EE_Base_Class[]|EE_Venue[] |
|
817 | + * @throws EE_Error |
|
818 | + * @throws ReflectionException |
|
819 | + * @deprecated $VID:$ |
|
820 | + */ |
|
821 | + public function venues(array $query_params = []): array |
|
822 | + { |
|
823 | + return [$this->venue($query_params)]; |
|
824 | + } |
|
825 | + |
|
826 | + |
|
827 | + /** |
|
828 | + * check if event id is present and if event is published |
|
829 | + * |
|
830 | + * @return boolean true yes, false no |
|
831 | + * @throws EE_Error |
|
832 | + * @throws ReflectionException |
|
833 | + */ |
|
834 | + private function _has_ID_and_is_published(): bool |
|
835 | + { |
|
836 | + // first check if event id is present and not NULL, |
|
837 | + // then check if this event is published (or any of the equivalent "published" statuses) |
|
838 | + return |
|
839 | + $this->ID() && $this->ID() !== null |
|
840 | + && ( |
|
841 | + $this->status() === 'publish' |
|
842 | + || $this->status() === EEM_Event::sold_out |
|
843 | + || $this->status() === EEM_Event::postponed |
|
844 | + || $this->status() === EEM_Event::cancelled |
|
845 | + ); |
|
846 | + } |
|
847 | + |
|
848 | + |
|
849 | + /** |
|
850 | + * This simply compares the internal dates with NOW and determines if the event is upcoming or not. |
|
851 | + * |
|
852 | + * @return boolean true yes, false no |
|
853 | + * @throws EE_Error |
|
854 | + * @throws ReflectionException |
|
855 | + */ |
|
856 | + public function is_upcoming(): bool |
|
857 | + { |
|
858 | + // check if event id is present and if this event is published |
|
859 | + if ($this->is_inactive()) { |
|
860 | + return false; |
|
861 | + } |
|
862 | + // set initial value |
|
863 | + $upcoming = false; |
|
864 | + // next let's get all datetimes and loop through them |
|
865 | + $datetimes = $this->datetimes_in_chronological_order(); |
|
866 | + foreach ($datetimes as $datetime) { |
|
867 | + if ($datetime instanceof EE_Datetime) { |
|
868 | + // if this dtt is expired then we continue cause one of the other datetimes might be upcoming. |
|
869 | + if ($datetime->is_expired()) { |
|
870 | + continue; |
|
871 | + } |
|
872 | + // if this dtt is active then we return false. |
|
873 | + if ($datetime->is_active()) { |
|
874 | + return false; |
|
875 | + } |
|
876 | + // otherwise let's check upcoming status |
|
877 | + $upcoming = $datetime->is_upcoming(); |
|
878 | + } |
|
879 | + } |
|
880 | + return $upcoming; |
|
881 | + } |
|
882 | + |
|
883 | + |
|
884 | + /** |
|
885 | + * @return bool |
|
886 | + * @throws EE_Error |
|
887 | + * @throws ReflectionException |
|
888 | + */ |
|
889 | + public function is_active(): bool |
|
890 | + { |
|
891 | + // check if event id is present and if this event is published |
|
892 | + if ($this->is_inactive()) { |
|
893 | + return false; |
|
894 | + } |
|
895 | + // set initial value |
|
896 | + $active = false; |
|
897 | + // next let's get all datetimes and loop through them |
|
898 | + $datetimes = $this->datetimes_in_chronological_order(); |
|
899 | + foreach ($datetimes as $datetime) { |
|
900 | + if ($datetime instanceof EE_Datetime) { |
|
901 | + // if this dtt is expired then we continue cause one of the other datetimes might be active. |
|
902 | + if ($datetime->is_expired()) { |
|
903 | + continue; |
|
904 | + } |
|
905 | + // if this dtt is upcoming then we return false. |
|
906 | + if ($datetime->is_upcoming()) { |
|
907 | + return false; |
|
908 | + } |
|
909 | + // otherwise let's check active status |
|
910 | + $active = $datetime->is_active(); |
|
911 | + } |
|
912 | + } |
|
913 | + return $active; |
|
914 | + } |
|
915 | + |
|
916 | + |
|
917 | + /** |
|
918 | + * @return bool |
|
919 | + * @throws EE_Error |
|
920 | + * @throws ReflectionException |
|
921 | + */ |
|
922 | + public function is_expired(): bool |
|
923 | + { |
|
924 | + // check if event id is present and if this event is published |
|
925 | + if ($this->is_inactive()) { |
|
926 | + return false; |
|
927 | + } |
|
928 | + // set initial value |
|
929 | + $expired = false; |
|
930 | + // first let's get all datetimes and loop through them |
|
931 | + $datetimes = $this->datetimes_in_chronological_order(); |
|
932 | + foreach ($datetimes as $datetime) { |
|
933 | + if ($datetime instanceof EE_Datetime) { |
|
934 | + // if this dtt is upcoming or active then we return false. |
|
935 | + if ($datetime->is_upcoming() || $datetime->is_active()) { |
|
936 | + return false; |
|
937 | + } |
|
938 | + // otherwise let's check active status |
|
939 | + $expired = $datetime->is_expired(); |
|
940 | + } |
|
941 | + } |
|
942 | + return $expired; |
|
943 | + } |
|
944 | + |
|
945 | + |
|
946 | + /** |
|
947 | + * @return bool |
|
948 | + * @throws EE_Error |
|
949 | + * @throws ReflectionException |
|
950 | + */ |
|
951 | + public function is_inactive(): bool |
|
952 | + { |
|
953 | + // check if event id is present and if this event is published |
|
954 | + if ($this->_has_ID_and_is_published()) { |
|
955 | + return false; |
|
956 | + } |
|
957 | + return true; |
|
958 | + } |
|
959 | + |
|
960 | + |
|
961 | + /** |
|
962 | + * calculate spaces remaining based on "saleable" tickets |
|
963 | + * |
|
964 | + * @param array|null $tickets |
|
965 | + * @param bool $filtered |
|
966 | + * @return int|float |
|
967 | + * @throws EE_Error |
|
968 | + * @throws DomainException |
|
969 | + * @throws UnexpectedEntityException |
|
970 | + * @throws ReflectionException |
|
971 | + */ |
|
972 | + public function spaces_remaining(?array $tickets = [], ?bool $filtered = true) |
|
973 | + { |
|
974 | + $this->getAvailableSpacesCalculator()->setActiveTickets($tickets); |
|
975 | + $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining(); |
|
976 | + return $filtered |
|
977 | + ? apply_filters( |
|
978 | + 'FHEE_EE_Event__spaces_remaining', |
|
979 | + $spaces_remaining, |
|
980 | + $this, |
|
981 | + $tickets |
|
982 | + ) |
|
983 | + : $spaces_remaining; |
|
984 | + } |
|
985 | + |
|
986 | + |
|
987 | + /** |
|
988 | + * perform_sold_out_status_check |
|
989 | + * checks all of this event's datetime reg_limit - sold values to determine if ANY datetimes have spaces |
|
990 | + * available... if NOT, then the event status will get toggled to 'sold_out' |
|
991 | + * |
|
992 | + * @return bool return the ACTUAL sold out state. |
|
993 | + * @throws EE_Error |
|
994 | + * @throws DomainException |
|
995 | + * @throws UnexpectedEntityException |
|
996 | + * @throws ReflectionException |
|
997 | + */ |
|
998 | + public function perform_sold_out_status_check(): bool |
|
999 | + { |
|
1000 | + // get all tickets |
|
1001 | + $tickets = $this->tickets( |
|
1002 | + [ |
|
1003 | + 'default_where_conditions' => 'none', |
|
1004 | + 'order_by' => ['TKT_qty' => 'ASC'], |
|
1005 | + ] |
|
1006 | + ); |
|
1007 | + $all_expired = true; |
|
1008 | + foreach ($tickets as $ticket) { |
|
1009 | + if (! $ticket->is_expired()) { |
|
1010 | + $all_expired = false; |
|
1011 | + break; |
|
1012 | + } |
|
1013 | + } |
|
1014 | + // if all the tickets are just expired, then don't update the event status to sold out |
|
1015 | + if ($all_expired) { |
|
1016 | + return true; |
|
1017 | + } |
|
1018 | + $spaces_remaining = $this->spaces_remaining($tickets); |
|
1019 | + if ($spaces_remaining < 1) { |
|
1020 | + if ($this->status() !== EEM_CPT_Base::post_status_private) { |
|
1021 | + $this->set_status(EEM_Event::sold_out); |
|
1022 | + $this->save(); |
|
1023 | + } |
|
1024 | + $sold_out = true; |
|
1025 | + } else { |
|
1026 | + $sold_out = false; |
|
1027 | + // was event previously marked as sold out ? |
|
1028 | + if ($this->status() === EEM_Event::sold_out) { |
|
1029 | + // revert status to previous value, if it was set |
|
1030 | + $previous_event_status = $this->get_post_meta('_previous_event_status', true); |
|
1031 | + if ($previous_event_status) { |
|
1032 | + $this->set_status($previous_event_status); |
|
1033 | + $this->save(); |
|
1034 | + } |
|
1035 | + } |
|
1036 | + } |
|
1037 | + do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets); |
|
1038 | + return $sold_out; |
|
1039 | + } |
|
1040 | + |
|
1041 | + |
|
1042 | + /** |
|
1043 | + * This returns the total remaining spaces for sale on this event. |
|
1044 | + * |
|
1045 | + * @return int|float |
|
1046 | + * @throws EE_Error |
|
1047 | + * @throws DomainException |
|
1048 | + * @throws UnexpectedEntityException |
|
1049 | + * @throws ReflectionException |
|
1050 | + * @uses EE_Event::total_available_spaces() |
|
1051 | + */ |
|
1052 | + public function spaces_remaining_for_sale() |
|
1053 | + { |
|
1054 | + return $this->total_available_spaces(true); |
|
1055 | + } |
|
1056 | + |
|
1057 | + |
|
1058 | + /** |
|
1059 | + * This returns the total spaces available for an event |
|
1060 | + * while considering all the quantities on the tickets and the reg limits |
|
1061 | + * on the datetimes attached to this event. |
|
1062 | + * |
|
1063 | + * @param bool $consider_sold Whether to consider any tickets that have already sold in our calculation. |
|
1064 | + * If this is false, then we return the most tickets that could ever be sold |
|
1065 | + * for this event with the datetime and tickets setup on the event under optimal |
|
1066 | + * selling conditions. Otherwise we return a live calculation of spaces available |
|
1067 | + * based on tickets sold. Depending on setup and stage of sales, this |
|
1068 | + * may appear to equal remaining tickets. However, the more tickets are |
|
1069 | + * sold out, the more accurate the "live" total is. |
|
1070 | + * @return int|float |
|
1071 | + * @throws EE_Error |
|
1072 | + * @throws DomainException |
|
1073 | + * @throws UnexpectedEntityException |
|
1074 | + * @throws ReflectionException |
|
1075 | + */ |
|
1076 | + public function total_available_spaces(bool $consider_sold = false) |
|
1077 | + { |
|
1078 | + $spaces_available = $consider_sold |
|
1079 | + ? $this->getAvailableSpacesCalculator()->spacesRemaining() |
|
1080 | + : $this->getAvailableSpacesCalculator()->totalSpacesAvailable(); |
|
1081 | + return apply_filters( |
|
1082 | + 'FHEE_EE_Event__total_available_spaces__spaces_available', |
|
1083 | + $spaces_available, |
|
1084 | + $this, |
|
1085 | + $this->getAvailableSpacesCalculator()->getDatetimes(), |
|
1086 | + $this->getAvailableSpacesCalculator()->getActiveTickets() |
|
1087 | + ); |
|
1088 | + } |
|
1089 | + |
|
1090 | + |
|
1091 | + /** |
|
1092 | + * Checks if the event is set to sold out |
|
1093 | + * |
|
1094 | + * @param bool $actual whether or not to perform calculations to not only figure the |
|
1095 | + * actual status but also to flip the status if necessary to sold |
|
1096 | + * out If false, we just check the existing status of the event |
|
1097 | + * @return boolean |
|
1098 | + * @throws EE_Error |
|
1099 | + * @throws ReflectionException |
|
1100 | + */ |
|
1101 | + public function is_sold_out(bool $actual = false): bool |
|
1102 | + { |
|
1103 | + if (! $actual) { |
|
1104 | + return $this->status() === EEM_Event::sold_out; |
|
1105 | + } |
|
1106 | + return $this->perform_sold_out_status_check(); |
|
1107 | + } |
|
1108 | + |
|
1109 | + |
|
1110 | + /** |
|
1111 | + * Checks if the event is marked as postponed |
|
1112 | + * |
|
1113 | + * @return boolean |
|
1114 | + */ |
|
1115 | + public function is_postponed(): bool |
|
1116 | + { |
|
1117 | + return $this->status() === EEM_Event::postponed; |
|
1118 | + } |
|
1119 | + |
|
1120 | + |
|
1121 | + /** |
|
1122 | + * Checks if the event is marked as cancelled |
|
1123 | + * |
|
1124 | + * @return boolean |
|
1125 | + */ |
|
1126 | + public function is_cancelled(): bool |
|
1127 | + { |
|
1128 | + return $this->status() === EEM_Event::cancelled; |
|
1129 | + } |
|
1130 | + |
|
1131 | + |
|
1132 | + /** |
|
1133 | + * Get the logical active status in a hierarchical order for all the datetimes. Note |
|
1134 | + * Basically, we order the datetimes by EVT_start_date. Then first test on whether the event is published. If its |
|
1135 | + * NOT published then we test for whether its expired or not. IF it IS published then we test first on whether an |
|
1136 | + * event has any active dates. If no active dates then we check for any upcoming dates. If no upcoming dates then |
|
1137 | + * the event is considered expired. |
|
1138 | + * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published. Sold Out is a |
|
1139 | + * status set on the EVENT when it is not published and thus is done |
|
1140 | + * |
|
1141 | + * @param bool $reset |
|
1142 | + * @return bool | string - based on EE_Datetime active constants or FALSE if error. |
|
1143 | + * @throws EE_Error |
|
1144 | + * @throws ReflectionException |
|
1145 | + */ |
|
1146 | + public function get_active_status(bool $reset = false) |
|
1147 | + { |
|
1148 | + // if the active status has already been set, then just use that value (unless we are resetting it) |
|
1149 | + if (! empty($this->_active_status) && ! $reset) { |
|
1150 | + return $this->_active_status; |
|
1151 | + } |
|
1152 | + // first check if event id is present on this object |
|
1153 | + if (! $this->ID()) { |
|
1154 | + return false; |
|
1155 | + } |
|
1156 | + $where_params_for_event = [['EVT_ID' => $this->ID()]]; |
|
1157 | + // if event is published: |
|
1158 | + if ( |
|
1159 | + $this->status() === EEM_CPT_Base::post_status_publish |
|
1160 | + || $this->status() === EEM_CPT_Base::post_status_private |
|
1161 | + ) { |
|
1162 | + // active? |
|
1163 | + if ( |
|
1164 | + EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1165 | + EE_Datetime::active, |
|
1166 | + $where_params_for_event |
|
1167 | + ) > 0 |
|
1168 | + ) { |
|
1169 | + $this->_active_status = EE_Datetime::active; |
|
1170 | + } else { |
|
1171 | + // upcoming? |
|
1172 | + if ( |
|
1173 | + EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1174 | + EE_Datetime::upcoming, |
|
1175 | + $where_params_for_event |
|
1176 | + ) > 0 |
|
1177 | + ) { |
|
1178 | + $this->_active_status = EE_Datetime::upcoming; |
|
1179 | + } else { |
|
1180 | + // expired? |
|
1181 | + if ( |
|
1182 | + EEM_Datetime::instance()->get_datetime_count_for_status( |
|
1183 | + EE_Datetime::expired, |
|
1184 | + $where_params_for_event |
|
1185 | + ) > 0 |
|
1186 | + ) { |
|
1187 | + $this->_active_status = EE_Datetime::expired; |
|
1188 | + } else { |
|
1189 | + // it would be odd if things make it this far |
|
1190 | + // because it basically means there are no datetimes attached to the event. |
|
1191 | + // So in this case it will just be considered inactive. |
|
1192 | + $this->_active_status = EE_Datetime::inactive; |
|
1193 | + } |
|
1194 | + } |
|
1195 | + } |
|
1196 | + } else { |
|
1197 | + // the event is not published, so let's just set it's active status according to its' post status |
|
1198 | + switch ($this->status()) { |
|
1199 | + case EEM_Event::sold_out: |
|
1200 | + $this->_active_status = EE_Datetime::sold_out; |
|
1201 | + break; |
|
1202 | + case EEM_Event::cancelled: |
|
1203 | + $this->_active_status = EE_Datetime::cancelled; |
|
1204 | + break; |
|
1205 | + case EEM_Event::postponed: |
|
1206 | + $this->_active_status = EE_Datetime::postponed; |
|
1207 | + break; |
|
1208 | + default: |
|
1209 | + $this->_active_status = EE_Datetime::inactive; |
|
1210 | + } |
|
1211 | + } |
|
1212 | + return $this->_active_status; |
|
1213 | + } |
|
1214 | + |
|
1215 | + |
|
1216 | + /** |
|
1217 | + * pretty_active_status |
|
1218 | + * |
|
1219 | + * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE) |
|
1220 | + * @return string |
|
1221 | + * @throws EE_Error |
|
1222 | + * @throws ReflectionException |
|
1223 | + */ |
|
1224 | + public function pretty_active_status(bool $echo = true): string |
|
1225 | + { |
|
1226 | + $active_status = $this->get_active_status(); |
|
1227 | + $status = " |
|
1228 | 1228 | <span class='ee-status ee-status-bg--$active_status event-active-status-$active_status'> |
1229 | 1229 | " . EEH_Template::pretty_status($active_status, false, 'sentence') . " |
1230 | 1230 | </span >"; |
1231 | - if ($echo) { |
|
1232 | - echo wp_kses($status, AllowedTags::getAllowedTags()); |
|
1233 | - return ''; |
|
1234 | - } |
|
1235 | - return $status; |
|
1236 | - } |
|
1237 | - |
|
1238 | - |
|
1239 | - /** |
|
1240 | - * @return bool|int |
|
1241 | - * @throws EE_Error |
|
1242 | - * @throws ReflectionException |
|
1243 | - */ |
|
1244 | - public function get_number_of_tickets_sold() |
|
1245 | - { |
|
1246 | - $tkt_sold = 0; |
|
1247 | - if (! $this->ID()) { |
|
1248 | - return 0; |
|
1249 | - } |
|
1250 | - $datetimes = $this->datetimes(); |
|
1251 | - foreach ($datetimes as $datetime) { |
|
1252 | - if ($datetime instanceof EE_Datetime) { |
|
1253 | - $tkt_sold += $datetime->sold(); |
|
1254 | - } |
|
1255 | - } |
|
1256 | - return $tkt_sold; |
|
1257 | - } |
|
1258 | - |
|
1259 | - |
|
1260 | - /** |
|
1261 | - * This just returns a count of all the registrations for this event |
|
1262 | - * |
|
1263 | - * @return int |
|
1264 | - * @throws EE_Error |
|
1265 | - * @throws ReflectionException |
|
1266 | - */ |
|
1267 | - public function get_count_of_all_registrations(): int |
|
1268 | - { |
|
1269 | - return EEM_Event::instance()->count_related($this, 'Registration'); |
|
1270 | - } |
|
1271 | - |
|
1272 | - |
|
1273 | - /** |
|
1274 | - * This returns the ticket with the earliest start time that is |
|
1275 | - * available for this event (across all datetimes attached to the event) |
|
1276 | - * |
|
1277 | - * @return EE_Base_Class|EE_Ticket|null |
|
1278 | - * @throws EE_Error |
|
1279 | - * @throws ReflectionException |
|
1280 | - */ |
|
1281 | - public function get_ticket_with_earliest_start_time() |
|
1282 | - { |
|
1283 | - $where['Datetime.EVT_ID'] = $this->ID(); |
|
1284 | - $query_params = [$where, 'order_by' => ['TKT_start_date' => 'ASC']]; |
|
1285 | - return EE_Registry::instance()->load_model('Ticket')->get_one($query_params); |
|
1286 | - } |
|
1287 | - |
|
1288 | - |
|
1289 | - /** |
|
1290 | - * This returns the ticket with the latest end time that is available |
|
1291 | - * for this event (across all datetimes attached to the event) |
|
1292 | - * |
|
1293 | - * @return EE_Base_Class|EE_Ticket|null |
|
1294 | - * @throws EE_Error |
|
1295 | - * @throws ReflectionException |
|
1296 | - */ |
|
1297 | - public function get_ticket_with_latest_end_time() |
|
1298 | - { |
|
1299 | - $where['Datetime.EVT_ID'] = $this->ID(); |
|
1300 | - $query_params = [$where, 'order_by' => ['TKT_end_date' => 'DESC']]; |
|
1301 | - return EE_Registry::instance()->load_model('Ticket')->get_one($query_params); |
|
1302 | - } |
|
1303 | - |
|
1304 | - |
|
1305 | - /** |
|
1306 | - * This returns the number of different ticket types currently on sale for this event. |
|
1307 | - * |
|
1308 | - * @return int |
|
1309 | - * @throws EE_Error |
|
1310 | - * @throws ReflectionException |
|
1311 | - */ |
|
1312 | - public function countTicketsOnSale(): int |
|
1313 | - { |
|
1314 | - $where = [ |
|
1315 | - 'Datetime.EVT_ID' => $this->ID(), |
|
1316 | - 'TKT_start_date' => ['<', time()], |
|
1317 | - 'TKT_end_date' => ['>', time()], |
|
1318 | - ]; |
|
1319 | - return EEM_Ticket::instance()->count([$where]); |
|
1320 | - } |
|
1321 | - |
|
1322 | - |
|
1323 | - /** |
|
1324 | - * This returns whether there are any tickets on sale for this event. |
|
1325 | - * |
|
1326 | - * @return bool true = YES tickets on sale. |
|
1327 | - * @throws EE_Error |
|
1328 | - * @throws ReflectionException |
|
1329 | - */ |
|
1330 | - public function tickets_on_sale(): bool |
|
1331 | - { |
|
1332 | - return $this->countTicketsOnSale() > 0; |
|
1333 | - } |
|
1334 | - |
|
1335 | - |
|
1336 | - /** |
|
1337 | - * Gets the URL for viewing this event on the front-end. Overrides parent |
|
1338 | - * to check for an external URL first |
|
1339 | - * |
|
1340 | - * @return string |
|
1341 | - * @throws EE_Error |
|
1342 | - * @throws ReflectionException |
|
1343 | - */ |
|
1344 | - public function get_permalink(): string |
|
1345 | - { |
|
1346 | - if ($this->external_url()) { |
|
1347 | - return $this->external_url(); |
|
1348 | - } |
|
1349 | - return parent::get_permalink(); |
|
1350 | - } |
|
1351 | - |
|
1352 | - |
|
1353 | - /** |
|
1354 | - * Gets the first term for 'espresso_event_categories' we can find |
|
1355 | - * |
|
1356 | - * @param array $query_params |
|
1357 | - * @return EE_Base_Class|EE_Term|null |
|
1358 | - * @throws EE_Error |
|
1359 | - * @throws ReflectionException |
|
1360 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1361 | - */ |
|
1362 | - public function first_event_category(array $query_params = []): ?EE_Term |
|
1363 | - { |
|
1364 | - $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
1365 | - $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID(); |
|
1366 | - return EEM_Term::instance()->get_one($query_params); |
|
1367 | - } |
|
1368 | - |
|
1369 | - |
|
1370 | - /** |
|
1371 | - * Gets all terms for 'espresso_event_categories' we can find |
|
1372 | - * |
|
1373 | - * @param array $query_params |
|
1374 | - * @return EE_Base_Class[]|EE_Term[] |
|
1375 | - * @throws EE_Error |
|
1376 | - * @throws ReflectionException |
|
1377 | - */ |
|
1378 | - public function get_all_event_categories(array $query_params = []): array |
|
1379 | - { |
|
1380 | - $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
1381 | - $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID(); |
|
1382 | - return EEM_Term::instance()->get_all($query_params); |
|
1383 | - } |
|
1384 | - |
|
1385 | - |
|
1386 | - /** |
|
1387 | - * Adds a question group to this event |
|
1388 | - * |
|
1389 | - * @param EE_Question_Group|int $question_group_id_or_obj |
|
1390 | - * @param bool $for_primary if true, the question group will be added for the primary |
|
1391 | - * registrant, if false will be added for others. default: false |
|
1392 | - * @return EE_Base_Class|EE_Question_Group |
|
1393 | - * @throws EE_Error |
|
1394 | - * @throws InvalidArgumentException |
|
1395 | - * @throws InvalidDataTypeException |
|
1396 | - * @throws InvalidInterfaceException |
|
1397 | - * @throws ReflectionException |
|
1398 | - */ |
|
1399 | - public function add_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group |
|
1400 | - { |
|
1401 | - // If the row already exists, it will be updated. If it doesn't, it will be inserted. |
|
1402 | - // That's in EE_HABTM_Relation::add_relation_to(). |
|
1403 | - return $this->_add_relation_to( |
|
1404 | - $question_group_id_or_obj, |
|
1405 | - 'Question_Group', |
|
1406 | - [ |
|
1407 | - EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true, |
|
1408 | - ] |
|
1409 | - ); |
|
1410 | - } |
|
1411 | - |
|
1412 | - |
|
1413 | - /** |
|
1414 | - * Removes a question group from the event |
|
1415 | - * |
|
1416 | - * @param EE_Question_Group|int $question_group_id_or_obj |
|
1417 | - * @param bool $for_primary if true, the question group will be removed from the primary |
|
1418 | - * registrant, if false will be removed from others. default: false |
|
1419 | - * @return EE_Base_Class|EE_Question_Group|int |
|
1420 | - * @throws EE_Error |
|
1421 | - * @throws InvalidArgumentException |
|
1422 | - * @throws ReflectionException |
|
1423 | - * @throws InvalidDataTypeException |
|
1424 | - * @throws InvalidInterfaceException |
|
1425 | - */ |
|
1426 | - public function remove_question_group($question_group_id_or_obj, bool $for_primary = false) |
|
1427 | - { |
|
1428 | - // If the question group is used for the other type (primary or additional) |
|
1429 | - // then just update it. If not, delete it outright. |
|
1430 | - $existing_relation = $this->get_first_related( |
|
1431 | - 'Event_Question_Group', |
|
1432 | - [ |
|
1433 | - [ |
|
1434 | - 'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj), |
|
1435 | - ], |
|
1436 | - ] |
|
1437 | - ); |
|
1438 | - $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary); |
|
1439 | - $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary); |
|
1440 | - if ($existing_relation->get($other_field) === false) { |
|
1441 | - // Delete it. It's now no longer for primary or additional question groups. |
|
1442 | - return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group'); |
|
1443 | - } |
|
1444 | - // Just update it. They'll still use this question group for the other category |
|
1445 | - $existing_relation->save( |
|
1446 | - [ |
|
1447 | - $field_to_update => false, |
|
1448 | - ] |
|
1449 | - ); |
|
1450 | - return $question_group_id_or_obj; |
|
1451 | - } |
|
1452 | - |
|
1453 | - |
|
1454 | - /** |
|
1455 | - * Gets all the question groups, ordering them by QSG_order ascending |
|
1456 | - * |
|
1457 | - * @param array $query_params |
|
1458 | - * @return EE_Base_Class[]|EE_Question_Group[] |
|
1459 | - * @throws EE_Error |
|
1460 | - * @throws ReflectionException |
|
1461 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1462 | - */ |
|
1463 | - public function question_groups(array $query_params = []): array |
|
1464 | - { |
|
1465 | - $query_params = ! empty($query_params) ? $query_params : ['order_by' => ['QSG_order' => 'ASC']]; |
|
1466 | - return $this->get_many_related('Question_Group', $query_params); |
|
1467 | - } |
|
1468 | - |
|
1469 | - |
|
1470 | - /** |
|
1471 | - * Implementation for EEI_Has_Icon interface method. |
|
1472 | - * |
|
1473 | - * @return string |
|
1474 | - * @see EEI_Visual_Representation for comments |
|
1475 | - */ |
|
1476 | - public function get_icon(): string |
|
1477 | - { |
|
1478 | - return '<span class="dashicons dashicons-flag"></span>'; |
|
1479 | - } |
|
1480 | - |
|
1481 | - |
|
1482 | - /** |
|
1483 | - * Implementation for EEI_Admin_Links interface method. |
|
1484 | - * |
|
1485 | - * @return string |
|
1486 | - * @throws EE_Error |
|
1487 | - * @throws ReflectionException |
|
1488 | - * @see EEI_Admin_Links for comments |
|
1489 | - */ |
|
1490 | - public function get_admin_details_link(): string |
|
1491 | - { |
|
1492 | - return $this->get_admin_edit_link(); |
|
1493 | - } |
|
1494 | - |
|
1495 | - |
|
1496 | - /** |
|
1497 | - * Implementation for EEI_Admin_Links interface method. |
|
1498 | - * |
|
1499 | - * @return string |
|
1500 | - * @throws EE_Error |
|
1501 | - * @throws ReflectionException |
|
1502 | - * @see EEI_Admin_Links for comments |
|
1503 | - */ |
|
1504 | - public function get_admin_edit_link(): string |
|
1505 | - { |
|
1506 | - return EEH_URL::add_query_args_and_nonce( |
|
1507 | - [ |
|
1508 | - 'page' => 'espresso_events', |
|
1509 | - 'action' => 'edit', |
|
1510 | - 'post' => $this->ID(), |
|
1511 | - ], |
|
1512 | - admin_url('admin.php') |
|
1513 | - ); |
|
1514 | - } |
|
1515 | - |
|
1516 | - |
|
1517 | - /** |
|
1518 | - * Implementation for EEI_Admin_Links interface method. |
|
1519 | - * |
|
1520 | - * @return string |
|
1521 | - * @see EEI_Admin_Links for comments |
|
1522 | - */ |
|
1523 | - public function get_admin_settings_link(): string |
|
1524 | - { |
|
1525 | - return EEH_URL::add_query_args_and_nonce( |
|
1526 | - [ |
|
1527 | - 'page' => 'espresso_events', |
|
1528 | - 'action' => 'default_event_settings', |
|
1529 | - ], |
|
1530 | - admin_url('admin.php') |
|
1531 | - ); |
|
1532 | - } |
|
1533 | - |
|
1534 | - |
|
1535 | - /** |
|
1536 | - * Implementation for EEI_Admin_Links interface method. |
|
1537 | - * |
|
1538 | - * @return string |
|
1539 | - * @see EEI_Admin_Links for comments |
|
1540 | - */ |
|
1541 | - public function get_admin_overview_link(): string |
|
1542 | - { |
|
1543 | - return EEH_URL::add_query_args_and_nonce( |
|
1544 | - [ |
|
1545 | - 'page' => 'espresso_events', |
|
1546 | - 'action' => 'default', |
|
1547 | - ], |
|
1548 | - admin_url('admin.php') |
|
1549 | - ); |
|
1550 | - } |
|
1551 | - |
|
1552 | - |
|
1553 | - /** |
|
1554 | - * @return string|null |
|
1555 | - * @throws EE_Error |
|
1556 | - * @throws ReflectionException |
|
1557 | - */ |
|
1558 | - public function registrationFormUuid(): ?string |
|
1559 | - { |
|
1560 | - return $this->get('FSC_UUID') ?? ''; |
|
1561 | - } |
|
1562 | - |
|
1563 | - |
|
1564 | - /** |
|
1565 | - * Gets all the form sections for this event |
|
1566 | - * |
|
1567 | - * @return EE_Base_Class[]|EE_Form_Section[] |
|
1568 | - * @throws EE_Error |
|
1569 | - * @throws ReflectionException |
|
1570 | - */ |
|
1571 | - public function registrationForm(): array |
|
1572 | - { |
|
1573 | - $FSC_UUID = $this->registrationFormUuid(); |
|
1574 | - |
|
1575 | - if (empty($FSC_UUID)) { |
|
1576 | - return []; |
|
1577 | - } |
|
1578 | - |
|
1579 | - return EEM_Form_Section::instance()->get_all( |
|
1580 | - [ |
|
1581 | - [ |
|
1582 | - 'OR' => [ |
|
1583 | - 'FSC_UUID' => $FSC_UUID, // top level form |
|
1584 | - 'FSC_belongsTo' => $FSC_UUID, // child form sections |
|
1585 | - ], |
|
1586 | - ], |
|
1587 | - 'order_by' => ['FSC_order' => 'ASC'], |
|
1588 | - ] |
|
1589 | - ); |
|
1590 | - } |
|
1591 | - |
|
1592 | - |
|
1593 | - /** |
|
1594 | - * @param string $UUID |
|
1595 | - * @throws EE_Error |
|
1596 | - * @throws ReflectionException |
|
1597 | - */ |
|
1598 | - public function setRegistrationFormUuid(string $UUID): void |
|
1599 | - { |
|
1600 | - if (! Cuid::isCuid($UUID)) { |
|
1601 | - throw new InvalidArgumentException( |
|
1602 | - sprintf( |
|
1603 | - /* translators: 1: UUID value, 2: UUID generator function. */ |
|
1604 | - esc_html__( |
|
1605 | - 'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.', |
|
1606 | - 'event_espresso' |
|
1607 | - ), |
|
1608 | - $UUID, |
|
1609 | - '`Cuid::cuid()`' |
|
1610 | - ) |
|
1611 | - ); |
|
1612 | - } |
|
1613 | - $this->set('FSC_UUID', $UUID); |
|
1614 | - } |
|
1231 | + if ($echo) { |
|
1232 | + echo wp_kses($status, AllowedTags::getAllowedTags()); |
|
1233 | + return ''; |
|
1234 | + } |
|
1235 | + return $status; |
|
1236 | + } |
|
1237 | + |
|
1238 | + |
|
1239 | + /** |
|
1240 | + * @return bool|int |
|
1241 | + * @throws EE_Error |
|
1242 | + * @throws ReflectionException |
|
1243 | + */ |
|
1244 | + public function get_number_of_tickets_sold() |
|
1245 | + { |
|
1246 | + $tkt_sold = 0; |
|
1247 | + if (! $this->ID()) { |
|
1248 | + return 0; |
|
1249 | + } |
|
1250 | + $datetimes = $this->datetimes(); |
|
1251 | + foreach ($datetimes as $datetime) { |
|
1252 | + if ($datetime instanceof EE_Datetime) { |
|
1253 | + $tkt_sold += $datetime->sold(); |
|
1254 | + } |
|
1255 | + } |
|
1256 | + return $tkt_sold; |
|
1257 | + } |
|
1258 | + |
|
1259 | + |
|
1260 | + /** |
|
1261 | + * This just returns a count of all the registrations for this event |
|
1262 | + * |
|
1263 | + * @return int |
|
1264 | + * @throws EE_Error |
|
1265 | + * @throws ReflectionException |
|
1266 | + */ |
|
1267 | + public function get_count_of_all_registrations(): int |
|
1268 | + { |
|
1269 | + return EEM_Event::instance()->count_related($this, 'Registration'); |
|
1270 | + } |
|
1271 | + |
|
1272 | + |
|
1273 | + /** |
|
1274 | + * This returns the ticket with the earliest start time that is |
|
1275 | + * available for this event (across all datetimes attached to the event) |
|
1276 | + * |
|
1277 | + * @return EE_Base_Class|EE_Ticket|null |
|
1278 | + * @throws EE_Error |
|
1279 | + * @throws ReflectionException |
|
1280 | + */ |
|
1281 | + public function get_ticket_with_earliest_start_time() |
|
1282 | + { |
|
1283 | + $where['Datetime.EVT_ID'] = $this->ID(); |
|
1284 | + $query_params = [$where, 'order_by' => ['TKT_start_date' => 'ASC']]; |
|
1285 | + return EE_Registry::instance()->load_model('Ticket')->get_one($query_params); |
|
1286 | + } |
|
1287 | + |
|
1288 | + |
|
1289 | + /** |
|
1290 | + * This returns the ticket with the latest end time that is available |
|
1291 | + * for this event (across all datetimes attached to the event) |
|
1292 | + * |
|
1293 | + * @return EE_Base_Class|EE_Ticket|null |
|
1294 | + * @throws EE_Error |
|
1295 | + * @throws ReflectionException |
|
1296 | + */ |
|
1297 | + public function get_ticket_with_latest_end_time() |
|
1298 | + { |
|
1299 | + $where['Datetime.EVT_ID'] = $this->ID(); |
|
1300 | + $query_params = [$where, 'order_by' => ['TKT_end_date' => 'DESC']]; |
|
1301 | + return EE_Registry::instance()->load_model('Ticket')->get_one($query_params); |
|
1302 | + } |
|
1303 | + |
|
1304 | + |
|
1305 | + /** |
|
1306 | + * This returns the number of different ticket types currently on sale for this event. |
|
1307 | + * |
|
1308 | + * @return int |
|
1309 | + * @throws EE_Error |
|
1310 | + * @throws ReflectionException |
|
1311 | + */ |
|
1312 | + public function countTicketsOnSale(): int |
|
1313 | + { |
|
1314 | + $where = [ |
|
1315 | + 'Datetime.EVT_ID' => $this->ID(), |
|
1316 | + 'TKT_start_date' => ['<', time()], |
|
1317 | + 'TKT_end_date' => ['>', time()], |
|
1318 | + ]; |
|
1319 | + return EEM_Ticket::instance()->count([$where]); |
|
1320 | + } |
|
1321 | + |
|
1322 | + |
|
1323 | + /** |
|
1324 | + * This returns whether there are any tickets on sale for this event. |
|
1325 | + * |
|
1326 | + * @return bool true = YES tickets on sale. |
|
1327 | + * @throws EE_Error |
|
1328 | + * @throws ReflectionException |
|
1329 | + */ |
|
1330 | + public function tickets_on_sale(): bool |
|
1331 | + { |
|
1332 | + return $this->countTicketsOnSale() > 0; |
|
1333 | + } |
|
1334 | + |
|
1335 | + |
|
1336 | + /** |
|
1337 | + * Gets the URL for viewing this event on the front-end. Overrides parent |
|
1338 | + * to check for an external URL first |
|
1339 | + * |
|
1340 | + * @return string |
|
1341 | + * @throws EE_Error |
|
1342 | + * @throws ReflectionException |
|
1343 | + */ |
|
1344 | + public function get_permalink(): string |
|
1345 | + { |
|
1346 | + if ($this->external_url()) { |
|
1347 | + return $this->external_url(); |
|
1348 | + } |
|
1349 | + return parent::get_permalink(); |
|
1350 | + } |
|
1351 | + |
|
1352 | + |
|
1353 | + /** |
|
1354 | + * Gets the first term for 'espresso_event_categories' we can find |
|
1355 | + * |
|
1356 | + * @param array $query_params |
|
1357 | + * @return EE_Base_Class|EE_Term|null |
|
1358 | + * @throws EE_Error |
|
1359 | + * @throws ReflectionException |
|
1360 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1361 | + */ |
|
1362 | + public function first_event_category(array $query_params = []): ?EE_Term |
|
1363 | + { |
|
1364 | + $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
1365 | + $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID(); |
|
1366 | + return EEM_Term::instance()->get_one($query_params); |
|
1367 | + } |
|
1368 | + |
|
1369 | + |
|
1370 | + /** |
|
1371 | + * Gets all terms for 'espresso_event_categories' we can find |
|
1372 | + * |
|
1373 | + * @param array $query_params |
|
1374 | + * @return EE_Base_Class[]|EE_Term[] |
|
1375 | + * @throws EE_Error |
|
1376 | + * @throws ReflectionException |
|
1377 | + */ |
|
1378 | + public function get_all_event_categories(array $query_params = []): array |
|
1379 | + { |
|
1380 | + $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
1381 | + $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID(); |
|
1382 | + return EEM_Term::instance()->get_all($query_params); |
|
1383 | + } |
|
1384 | + |
|
1385 | + |
|
1386 | + /** |
|
1387 | + * Adds a question group to this event |
|
1388 | + * |
|
1389 | + * @param EE_Question_Group|int $question_group_id_or_obj |
|
1390 | + * @param bool $for_primary if true, the question group will be added for the primary |
|
1391 | + * registrant, if false will be added for others. default: false |
|
1392 | + * @return EE_Base_Class|EE_Question_Group |
|
1393 | + * @throws EE_Error |
|
1394 | + * @throws InvalidArgumentException |
|
1395 | + * @throws InvalidDataTypeException |
|
1396 | + * @throws InvalidInterfaceException |
|
1397 | + * @throws ReflectionException |
|
1398 | + */ |
|
1399 | + public function add_question_group($question_group_id_or_obj, bool $for_primary = false): EE_Question_Group |
|
1400 | + { |
|
1401 | + // If the row already exists, it will be updated. If it doesn't, it will be inserted. |
|
1402 | + // That's in EE_HABTM_Relation::add_relation_to(). |
|
1403 | + return $this->_add_relation_to( |
|
1404 | + $question_group_id_or_obj, |
|
1405 | + 'Question_Group', |
|
1406 | + [ |
|
1407 | + EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true, |
|
1408 | + ] |
|
1409 | + ); |
|
1410 | + } |
|
1411 | + |
|
1412 | + |
|
1413 | + /** |
|
1414 | + * Removes a question group from the event |
|
1415 | + * |
|
1416 | + * @param EE_Question_Group|int $question_group_id_or_obj |
|
1417 | + * @param bool $for_primary if true, the question group will be removed from the primary |
|
1418 | + * registrant, if false will be removed from others. default: false |
|
1419 | + * @return EE_Base_Class|EE_Question_Group|int |
|
1420 | + * @throws EE_Error |
|
1421 | + * @throws InvalidArgumentException |
|
1422 | + * @throws ReflectionException |
|
1423 | + * @throws InvalidDataTypeException |
|
1424 | + * @throws InvalidInterfaceException |
|
1425 | + */ |
|
1426 | + public function remove_question_group($question_group_id_or_obj, bool $for_primary = false) |
|
1427 | + { |
|
1428 | + // If the question group is used for the other type (primary or additional) |
|
1429 | + // then just update it. If not, delete it outright. |
|
1430 | + $existing_relation = $this->get_first_related( |
|
1431 | + 'Event_Question_Group', |
|
1432 | + [ |
|
1433 | + [ |
|
1434 | + 'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj), |
|
1435 | + ], |
|
1436 | + ] |
|
1437 | + ); |
|
1438 | + $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary); |
|
1439 | + $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary); |
|
1440 | + if ($existing_relation->get($other_field) === false) { |
|
1441 | + // Delete it. It's now no longer for primary or additional question groups. |
|
1442 | + return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group'); |
|
1443 | + } |
|
1444 | + // Just update it. They'll still use this question group for the other category |
|
1445 | + $existing_relation->save( |
|
1446 | + [ |
|
1447 | + $field_to_update => false, |
|
1448 | + ] |
|
1449 | + ); |
|
1450 | + return $question_group_id_or_obj; |
|
1451 | + } |
|
1452 | + |
|
1453 | + |
|
1454 | + /** |
|
1455 | + * Gets all the question groups, ordering them by QSG_order ascending |
|
1456 | + * |
|
1457 | + * @param array $query_params |
|
1458 | + * @return EE_Base_Class[]|EE_Question_Group[] |
|
1459 | + * @throws EE_Error |
|
1460 | + * @throws ReflectionException |
|
1461 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
1462 | + */ |
|
1463 | + public function question_groups(array $query_params = []): array |
|
1464 | + { |
|
1465 | + $query_params = ! empty($query_params) ? $query_params : ['order_by' => ['QSG_order' => 'ASC']]; |
|
1466 | + return $this->get_many_related('Question_Group', $query_params); |
|
1467 | + } |
|
1468 | + |
|
1469 | + |
|
1470 | + /** |
|
1471 | + * Implementation for EEI_Has_Icon interface method. |
|
1472 | + * |
|
1473 | + * @return string |
|
1474 | + * @see EEI_Visual_Representation for comments |
|
1475 | + */ |
|
1476 | + public function get_icon(): string |
|
1477 | + { |
|
1478 | + return '<span class="dashicons dashicons-flag"></span>'; |
|
1479 | + } |
|
1480 | + |
|
1481 | + |
|
1482 | + /** |
|
1483 | + * Implementation for EEI_Admin_Links interface method. |
|
1484 | + * |
|
1485 | + * @return string |
|
1486 | + * @throws EE_Error |
|
1487 | + * @throws ReflectionException |
|
1488 | + * @see EEI_Admin_Links for comments |
|
1489 | + */ |
|
1490 | + public function get_admin_details_link(): string |
|
1491 | + { |
|
1492 | + return $this->get_admin_edit_link(); |
|
1493 | + } |
|
1494 | + |
|
1495 | + |
|
1496 | + /** |
|
1497 | + * Implementation for EEI_Admin_Links interface method. |
|
1498 | + * |
|
1499 | + * @return string |
|
1500 | + * @throws EE_Error |
|
1501 | + * @throws ReflectionException |
|
1502 | + * @see EEI_Admin_Links for comments |
|
1503 | + */ |
|
1504 | + public function get_admin_edit_link(): string |
|
1505 | + { |
|
1506 | + return EEH_URL::add_query_args_and_nonce( |
|
1507 | + [ |
|
1508 | + 'page' => 'espresso_events', |
|
1509 | + 'action' => 'edit', |
|
1510 | + 'post' => $this->ID(), |
|
1511 | + ], |
|
1512 | + admin_url('admin.php') |
|
1513 | + ); |
|
1514 | + } |
|
1515 | + |
|
1516 | + |
|
1517 | + /** |
|
1518 | + * Implementation for EEI_Admin_Links interface method. |
|
1519 | + * |
|
1520 | + * @return string |
|
1521 | + * @see EEI_Admin_Links for comments |
|
1522 | + */ |
|
1523 | + public function get_admin_settings_link(): string |
|
1524 | + { |
|
1525 | + return EEH_URL::add_query_args_and_nonce( |
|
1526 | + [ |
|
1527 | + 'page' => 'espresso_events', |
|
1528 | + 'action' => 'default_event_settings', |
|
1529 | + ], |
|
1530 | + admin_url('admin.php') |
|
1531 | + ); |
|
1532 | + } |
|
1533 | + |
|
1534 | + |
|
1535 | + /** |
|
1536 | + * Implementation for EEI_Admin_Links interface method. |
|
1537 | + * |
|
1538 | + * @return string |
|
1539 | + * @see EEI_Admin_Links for comments |
|
1540 | + */ |
|
1541 | + public function get_admin_overview_link(): string |
|
1542 | + { |
|
1543 | + return EEH_URL::add_query_args_and_nonce( |
|
1544 | + [ |
|
1545 | + 'page' => 'espresso_events', |
|
1546 | + 'action' => 'default', |
|
1547 | + ], |
|
1548 | + admin_url('admin.php') |
|
1549 | + ); |
|
1550 | + } |
|
1551 | + |
|
1552 | + |
|
1553 | + /** |
|
1554 | + * @return string|null |
|
1555 | + * @throws EE_Error |
|
1556 | + * @throws ReflectionException |
|
1557 | + */ |
|
1558 | + public function registrationFormUuid(): ?string |
|
1559 | + { |
|
1560 | + return $this->get('FSC_UUID') ?? ''; |
|
1561 | + } |
|
1562 | + |
|
1563 | + |
|
1564 | + /** |
|
1565 | + * Gets all the form sections for this event |
|
1566 | + * |
|
1567 | + * @return EE_Base_Class[]|EE_Form_Section[] |
|
1568 | + * @throws EE_Error |
|
1569 | + * @throws ReflectionException |
|
1570 | + */ |
|
1571 | + public function registrationForm(): array |
|
1572 | + { |
|
1573 | + $FSC_UUID = $this->registrationFormUuid(); |
|
1574 | + |
|
1575 | + if (empty($FSC_UUID)) { |
|
1576 | + return []; |
|
1577 | + } |
|
1578 | + |
|
1579 | + return EEM_Form_Section::instance()->get_all( |
|
1580 | + [ |
|
1581 | + [ |
|
1582 | + 'OR' => [ |
|
1583 | + 'FSC_UUID' => $FSC_UUID, // top level form |
|
1584 | + 'FSC_belongsTo' => $FSC_UUID, // child form sections |
|
1585 | + ], |
|
1586 | + ], |
|
1587 | + 'order_by' => ['FSC_order' => 'ASC'], |
|
1588 | + ] |
|
1589 | + ); |
|
1590 | + } |
|
1591 | + |
|
1592 | + |
|
1593 | + /** |
|
1594 | + * @param string $UUID |
|
1595 | + * @throws EE_Error |
|
1596 | + * @throws ReflectionException |
|
1597 | + */ |
|
1598 | + public function setRegistrationFormUuid(string $UUID): void |
|
1599 | + { |
|
1600 | + if (! Cuid::isCuid($UUID)) { |
|
1601 | + throw new InvalidArgumentException( |
|
1602 | + sprintf( |
|
1603 | + /* translators: 1: UUID value, 2: UUID generator function. */ |
|
1604 | + esc_html__( |
|
1605 | + 'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.', |
|
1606 | + 'event_espresso' |
|
1607 | + ), |
|
1608 | + $UUID, |
|
1609 | + '`Cuid::cuid()`' |
|
1610 | + ) |
|
1611 | + ); |
|
1612 | + } |
|
1613 | + $this->set('FSC_UUID', $UUID); |
|
1614 | + } |
|
1615 | 1615 | } |
@@ -15,1353 +15,1353 @@ |
||
15 | 15 | */ |
16 | 16 | class EED_Messages extends EED_Module |
17 | 17 | { |
18 | - /** |
|
19 | - * This holds the EE_messages controller |
|
20 | - * |
|
21 | - * @deprecated 4.9.0 |
|
22 | - * @var EE_messages $_EEMSG |
|
23 | - */ |
|
24 | - protected static $_EEMSG; |
|
25 | - |
|
26 | - /** |
|
27 | - * @type EE_Message_Resource_Manager $_message_resource_manager |
|
28 | - */ |
|
29 | - protected static $_message_resource_manager; |
|
30 | - |
|
31 | - /** |
|
32 | - * This holds the EE_Messages_Processor business class. |
|
33 | - * |
|
34 | - * @type EE_Messages_Processor |
|
35 | - */ |
|
36 | - protected static $_MSG_PROCESSOR; |
|
37 | - |
|
38 | - /** |
|
39 | - * holds all the paths for various messages components. |
|
40 | - * Utilized by autoloader registry |
|
41 | - * |
|
42 | - * @var array |
|
43 | - */ |
|
44 | - protected static $_MSG_PATHS; |
|
45 | - |
|
46 | - |
|
47 | - /** |
|
48 | - * This will hold an array of messages template packs that are registered in the messages system. |
|
49 | - * Format is: |
|
50 | - * array( |
|
51 | - * 'template_pack_dbref' => EE_Messages_Template_Pack (instance) |
|
52 | - * ) |
|
53 | - * |
|
54 | - * @var EE_Messages_Template_Pack[] |
|
55 | - */ |
|
56 | - protected static $_TMP_PACKS = []; |
|
57 | - |
|
58 | - |
|
59 | - /** |
|
60 | - * @return EED_Messages|EED_Module |
|
61 | - * @throws EE_Error |
|
62 | - * @throws ReflectionException |
|
63 | - */ |
|
64 | - public static function instance() |
|
65 | - { |
|
66 | - return parent::get_instance(__CLASS__); |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * set_hooks - for hooking into EE Core, other modules, etc |
|
72 | - * |
|
73 | - * @return void |
|
74 | - * @since 4.5.0 |
|
75 | - */ |
|
76 | - public static function set_hooks() |
|
77 | - { |
|
78 | - // actions |
|
79 | - add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2); |
|
80 | - add_action( |
|
81 | - 'AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
82 | - ['EED_Messages', 'maybe_registration'], |
|
83 | - 10, |
|
84 | - 2 |
|
85 | - ); |
|
86 | - // filters |
|
87 | - add_filter( |
|
88 | - 'FHEE__EE_Registration__receipt_url__receipt_url', |
|
89 | - ['EED_Messages', 'registration_message_trigger_url'], |
|
90 | - 10, |
|
91 | - 4 |
|
92 | - ); |
|
93 | - add_filter( |
|
94 | - 'FHEE__EE_Registration__invoice_url__invoice_url', |
|
95 | - ['EED_Messages', 'registration_message_trigger_url'], |
|
96 | - 10, |
|
97 | - 4 |
|
98 | - ); |
|
99 | - // register routes |
|
100 | - self::_register_routes(); |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
106 | - * |
|
107 | - * @access public |
|
108 | - * @return void |
|
109 | - */ |
|
110 | - public static function set_hooks_admin() |
|
111 | - { |
|
112 | - // actions |
|
113 | - add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2); |
|
114 | - add_action( |
|
115 | - 'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
116 | - ['EED_Messages', 'payment_reminder'], |
|
117 | - 10 |
|
118 | - ); |
|
119 | - add_action( |
|
120 | - 'AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
121 | - ['EED_Messages', 'maybe_registration'], |
|
122 | - 10, |
|
123 | - 3 |
|
124 | - ); |
|
125 | - add_action( |
|
126 | - 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
127 | - ['EED_Messages', 'send_newsletter_message'], |
|
128 | - 10, |
|
129 | - 2 |
|
130 | - ); |
|
131 | - add_action( |
|
132 | - 'AHEE__EES_Espresso_Cancelled__process_shortcode__transaction', |
|
133 | - ['EED_Messages', 'cancelled_registration'], |
|
134 | - 10 |
|
135 | - ); |
|
136 | - add_action( |
|
137 | - 'AHEE__EE_Admin_Page___process_admin_payment_notification', |
|
138 | - ['EED_Messages', 'process_admin_payment'], |
|
139 | - 10, |
|
140 | - 1 |
|
141 | - ); |
|
142 | - // filters |
|
143 | - add_filter( |
|
144 | - 'FHEE__EE_Admin_Page___process_resend_registration__success', |
|
145 | - ['EED_Messages', 'process_resend'], |
|
146 | - 10, |
|
147 | - 2 |
|
148 | - ); |
|
149 | - add_filter( |
|
150 | - 'FHEE__EE_Registration__receipt_url__receipt_url', |
|
151 | - ['EED_Messages', 'registration_message_trigger_url'], |
|
152 | - 10, |
|
153 | - 4 |
|
154 | - ); |
|
155 | - add_filter( |
|
156 | - 'FHEE__EE_Registration__invoice_url__invoice_url', |
|
157 | - ['EED_Messages', 'registration_message_trigger_url'], |
|
158 | - 10, |
|
159 | - 4 |
|
160 | - ); |
|
161 | - } |
|
162 | - |
|
163 | - |
|
164 | - /** |
|
165 | - * All the message triggers done by route go in here. |
|
166 | - * |
|
167 | - * @return void |
|
168 | - * @since 4.5.0 |
|
169 | - */ |
|
170 | - protected static function _register_routes() |
|
171 | - { |
|
172 | - EE_Config::register_route('msg_url_trigger', 'Messages', 'run'); |
|
173 | - EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request'); |
|
174 | - EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger'); |
|
175 | - EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger'); |
|
176 | - do_action('AHEE__EED_Messages___register_routes'); |
|
177 | - } |
|
178 | - |
|
179 | - |
|
180 | - /** |
|
181 | - * This is called when a browser display trigger is executed. |
|
182 | - * The browser display trigger is typically used when a already generated message is displayed directly in the |
|
183 | - * browser. |
|
184 | - * |
|
185 | - * @param WP $WP |
|
186 | - * @throws EE_Error |
|
187 | - * @throws InvalidArgumentException |
|
188 | - * @throws ReflectionException |
|
189 | - * @throws InvalidDataTypeException |
|
190 | - * @throws InvalidInterfaceException |
|
191 | - * @since 4.9.0 |
|
192 | - */ |
|
193 | - public function browser_trigger($WP) |
|
194 | - { |
|
195 | - // ensure controller is loaded |
|
196 | - self::_load_controller(); |
|
197 | - $token = self::getRequest()->getRequestParam('token'); |
|
198 | - try { |
|
199 | - $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager); |
|
200 | - self::$_MSG_PROCESSOR->generate_and_send_now($mtg); |
|
201 | - } catch (EE_Error $e) { |
|
202 | - $error_msg = esc_html__( |
|
203 | - 'Please note that a system message failed to send due to a technical issue.', |
|
204 | - 'event_espresso' |
|
205 | - ); |
|
206 | - // add specific message for developers if WP_DEBUG in on |
|
207 | - $error_msg .= '||' . $e->getMessage(); |
|
208 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
209 | - } |
|
210 | - } |
|
211 | - |
|
212 | - |
|
213 | - /** |
|
214 | - * This is called when a browser error trigger is executed. |
|
215 | - * When triggered this will grab the EE_Message matching the token in the request and use that to get the error |
|
216 | - * message and display it. |
|
217 | - * |
|
218 | - * @param $WP |
|
219 | - * @throws EE_Error |
|
220 | - * @throws InvalidArgumentException |
|
221 | - * @throws InvalidDataTypeException |
|
222 | - * @throws InvalidInterfaceException |
|
223 | - * @since 4.9.0 |
|
224 | - */ |
|
225 | - public function browser_error_trigger($WP) |
|
226 | - { |
|
227 | - $token = self::getRequest()->getRequestParam('token'); |
|
228 | - if ($token) { |
|
229 | - $message = EEM_Message::instance()->get_one_by_token($token); |
|
230 | - if ($message instanceof EE_Message) { |
|
231 | - header('HTTP/1.1 200 OK'); |
|
232 | - $error_msg = nl2br($message->error_message()); |
|
233 | - ?> |
|
18 | + /** |
|
19 | + * This holds the EE_messages controller |
|
20 | + * |
|
21 | + * @deprecated 4.9.0 |
|
22 | + * @var EE_messages $_EEMSG |
|
23 | + */ |
|
24 | + protected static $_EEMSG; |
|
25 | + |
|
26 | + /** |
|
27 | + * @type EE_Message_Resource_Manager $_message_resource_manager |
|
28 | + */ |
|
29 | + protected static $_message_resource_manager; |
|
30 | + |
|
31 | + /** |
|
32 | + * This holds the EE_Messages_Processor business class. |
|
33 | + * |
|
34 | + * @type EE_Messages_Processor |
|
35 | + */ |
|
36 | + protected static $_MSG_PROCESSOR; |
|
37 | + |
|
38 | + /** |
|
39 | + * holds all the paths for various messages components. |
|
40 | + * Utilized by autoloader registry |
|
41 | + * |
|
42 | + * @var array |
|
43 | + */ |
|
44 | + protected static $_MSG_PATHS; |
|
45 | + |
|
46 | + |
|
47 | + /** |
|
48 | + * This will hold an array of messages template packs that are registered in the messages system. |
|
49 | + * Format is: |
|
50 | + * array( |
|
51 | + * 'template_pack_dbref' => EE_Messages_Template_Pack (instance) |
|
52 | + * ) |
|
53 | + * |
|
54 | + * @var EE_Messages_Template_Pack[] |
|
55 | + */ |
|
56 | + protected static $_TMP_PACKS = []; |
|
57 | + |
|
58 | + |
|
59 | + /** |
|
60 | + * @return EED_Messages|EED_Module |
|
61 | + * @throws EE_Error |
|
62 | + * @throws ReflectionException |
|
63 | + */ |
|
64 | + public static function instance() |
|
65 | + { |
|
66 | + return parent::get_instance(__CLASS__); |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * set_hooks - for hooking into EE Core, other modules, etc |
|
72 | + * |
|
73 | + * @return void |
|
74 | + * @since 4.5.0 |
|
75 | + */ |
|
76 | + public static function set_hooks() |
|
77 | + { |
|
78 | + // actions |
|
79 | + add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2); |
|
80 | + add_action( |
|
81 | + 'AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
82 | + ['EED_Messages', 'maybe_registration'], |
|
83 | + 10, |
|
84 | + 2 |
|
85 | + ); |
|
86 | + // filters |
|
87 | + add_filter( |
|
88 | + 'FHEE__EE_Registration__receipt_url__receipt_url', |
|
89 | + ['EED_Messages', 'registration_message_trigger_url'], |
|
90 | + 10, |
|
91 | + 4 |
|
92 | + ); |
|
93 | + add_filter( |
|
94 | + 'FHEE__EE_Registration__invoice_url__invoice_url', |
|
95 | + ['EED_Messages', 'registration_message_trigger_url'], |
|
96 | + 10, |
|
97 | + 4 |
|
98 | + ); |
|
99 | + // register routes |
|
100 | + self::_register_routes(); |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
106 | + * |
|
107 | + * @access public |
|
108 | + * @return void |
|
109 | + */ |
|
110 | + public static function set_hooks_admin() |
|
111 | + { |
|
112 | + // actions |
|
113 | + add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2); |
|
114 | + add_action( |
|
115 | + 'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
116 | + ['EED_Messages', 'payment_reminder'], |
|
117 | + 10 |
|
118 | + ); |
|
119 | + add_action( |
|
120 | + 'AHEE__EE_Registration_Processor__trigger_registration_update_notifications', |
|
121 | + ['EED_Messages', 'maybe_registration'], |
|
122 | + 10, |
|
123 | + 3 |
|
124 | + ); |
|
125 | + add_action( |
|
126 | + 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
127 | + ['EED_Messages', 'send_newsletter_message'], |
|
128 | + 10, |
|
129 | + 2 |
|
130 | + ); |
|
131 | + add_action( |
|
132 | + 'AHEE__EES_Espresso_Cancelled__process_shortcode__transaction', |
|
133 | + ['EED_Messages', 'cancelled_registration'], |
|
134 | + 10 |
|
135 | + ); |
|
136 | + add_action( |
|
137 | + 'AHEE__EE_Admin_Page___process_admin_payment_notification', |
|
138 | + ['EED_Messages', 'process_admin_payment'], |
|
139 | + 10, |
|
140 | + 1 |
|
141 | + ); |
|
142 | + // filters |
|
143 | + add_filter( |
|
144 | + 'FHEE__EE_Admin_Page___process_resend_registration__success', |
|
145 | + ['EED_Messages', 'process_resend'], |
|
146 | + 10, |
|
147 | + 2 |
|
148 | + ); |
|
149 | + add_filter( |
|
150 | + 'FHEE__EE_Registration__receipt_url__receipt_url', |
|
151 | + ['EED_Messages', 'registration_message_trigger_url'], |
|
152 | + 10, |
|
153 | + 4 |
|
154 | + ); |
|
155 | + add_filter( |
|
156 | + 'FHEE__EE_Registration__invoice_url__invoice_url', |
|
157 | + ['EED_Messages', 'registration_message_trigger_url'], |
|
158 | + 10, |
|
159 | + 4 |
|
160 | + ); |
|
161 | + } |
|
162 | + |
|
163 | + |
|
164 | + /** |
|
165 | + * All the message triggers done by route go in here. |
|
166 | + * |
|
167 | + * @return void |
|
168 | + * @since 4.5.0 |
|
169 | + */ |
|
170 | + protected static function _register_routes() |
|
171 | + { |
|
172 | + EE_Config::register_route('msg_url_trigger', 'Messages', 'run'); |
|
173 | + EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request'); |
|
174 | + EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger'); |
|
175 | + EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger'); |
|
176 | + do_action('AHEE__EED_Messages___register_routes'); |
|
177 | + } |
|
178 | + |
|
179 | + |
|
180 | + /** |
|
181 | + * This is called when a browser display trigger is executed. |
|
182 | + * The browser display trigger is typically used when a already generated message is displayed directly in the |
|
183 | + * browser. |
|
184 | + * |
|
185 | + * @param WP $WP |
|
186 | + * @throws EE_Error |
|
187 | + * @throws InvalidArgumentException |
|
188 | + * @throws ReflectionException |
|
189 | + * @throws InvalidDataTypeException |
|
190 | + * @throws InvalidInterfaceException |
|
191 | + * @since 4.9.0 |
|
192 | + */ |
|
193 | + public function browser_trigger($WP) |
|
194 | + { |
|
195 | + // ensure controller is loaded |
|
196 | + self::_load_controller(); |
|
197 | + $token = self::getRequest()->getRequestParam('token'); |
|
198 | + try { |
|
199 | + $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager); |
|
200 | + self::$_MSG_PROCESSOR->generate_and_send_now($mtg); |
|
201 | + } catch (EE_Error $e) { |
|
202 | + $error_msg = esc_html__( |
|
203 | + 'Please note that a system message failed to send due to a technical issue.', |
|
204 | + 'event_espresso' |
|
205 | + ); |
|
206 | + // add specific message for developers if WP_DEBUG in on |
|
207 | + $error_msg .= '||' . $e->getMessage(); |
|
208 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
209 | + } |
|
210 | + } |
|
211 | + |
|
212 | + |
|
213 | + /** |
|
214 | + * This is called when a browser error trigger is executed. |
|
215 | + * When triggered this will grab the EE_Message matching the token in the request and use that to get the error |
|
216 | + * message and display it. |
|
217 | + * |
|
218 | + * @param $WP |
|
219 | + * @throws EE_Error |
|
220 | + * @throws InvalidArgumentException |
|
221 | + * @throws InvalidDataTypeException |
|
222 | + * @throws InvalidInterfaceException |
|
223 | + * @since 4.9.0 |
|
224 | + */ |
|
225 | + public function browser_error_trigger($WP) |
|
226 | + { |
|
227 | + $token = self::getRequest()->getRequestParam('token'); |
|
228 | + if ($token) { |
|
229 | + $message = EEM_Message::instance()->get_one_by_token($token); |
|
230 | + if ($message instanceof EE_Message) { |
|
231 | + header('HTTP/1.1 200 OK'); |
|
232 | + $error_msg = nl2br($message->error_message()); |
|
233 | + ?> |
|
234 | 234 | <!DOCTYPE html> |
235 | 235 | <html> |
236 | 236 | <head></head> |
237 | 237 | <body> |
238 | 238 | <?php echo empty($error_msg) |
239 | - ? esc_html__( |
|
240 | - 'Unfortunately, we were unable to capture the error message for this message.', |
|
241 | - 'event_espresso' |
|
242 | - ) |
|
243 | - : wp_kses( |
|
244 | - $error_msg, |
|
245 | - [ |
|
246 | - 'a' => [ |
|
247 | - 'href' => [], |
|
248 | - 'title' => [], |
|
249 | - ], |
|
250 | - 'span' => [], |
|
251 | - 'div' => [], |
|
252 | - 'p' => [], |
|
253 | - 'strong' => [], |
|
254 | - 'em' => [], |
|
255 | - 'br' => [], |
|
256 | - ] |
|
257 | - ); ?> |
|
239 | + ? esc_html__( |
|
240 | + 'Unfortunately, we were unable to capture the error message for this message.', |
|
241 | + 'event_espresso' |
|
242 | + ) |
|
243 | + : wp_kses( |
|
244 | + $error_msg, |
|
245 | + [ |
|
246 | + 'a' => [ |
|
247 | + 'href' => [], |
|
248 | + 'title' => [], |
|
249 | + ], |
|
250 | + 'span' => [], |
|
251 | + 'div' => [], |
|
252 | + 'p' => [], |
|
253 | + 'strong' => [], |
|
254 | + 'em' => [], |
|
255 | + 'br' => [], |
|
256 | + ] |
|
257 | + ); ?> |
|
258 | 258 | </body> |
259 | 259 | </html> |
260 | 260 | <?php |
261 | - exit; |
|
262 | - } |
|
263 | - } |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - /** |
|
268 | - * This runs when the msg_url_trigger route has initiated. |
|
269 | - * |
|
270 | - * @param WP $WP |
|
271 | - * @throws EE_Error |
|
272 | - * @throws InvalidArgumentException |
|
273 | - * @throws ReflectionException |
|
274 | - * @throws InvalidDataTypeException |
|
275 | - * @throws InvalidInterfaceException |
|
276 | - * @since 4.5.0 |
|
277 | - */ |
|
278 | - public function run($WP) |
|
279 | - { |
|
280 | - // ensure controller is loaded |
|
281 | - self::_load_controller(); |
|
282 | - // attempt to process message |
|
283 | - try { |
|
284 | - /** @type EE_Message_To_Generate_From_Request $message_to_generate */ |
|
285 | - $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request'); |
|
286 | - self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate); |
|
287 | - } catch (EE_Error $e) { |
|
288 | - $error_msg = esc_html__( |
|
289 | - 'Please note that a system message failed to send due to a technical issue.', |
|
290 | - 'event_espresso' |
|
291 | - ); |
|
292 | - // add specific message for developers if WP_DEBUG in on |
|
293 | - $error_msg .= '||' . $e->getMessage(); |
|
294 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
295 | - } |
|
296 | - } |
|
297 | - |
|
298 | - |
|
299 | - /** |
|
300 | - * This is triggered by the 'msg_cron_trigger' route. |
|
301 | - * |
|
302 | - * @param WP $WP |
|
303 | - */ |
|
304 | - public function execute_batch_request($WP) |
|
305 | - { |
|
306 | - $this->run_cron(); |
|
307 | - header('HTTP/1.1 200 OK'); |
|
308 | - exit(); |
|
309 | - } |
|
310 | - |
|
311 | - |
|
312 | - /** |
|
313 | - * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp |
|
314 | - * request. |
|
315 | - */ |
|
316 | - public function run_cron() |
|
317 | - { |
|
318 | - self::_load_controller(); |
|
319 | - $request = self::getRequest(); |
|
320 | - // get required vars |
|
321 | - $cron_type = $request->getRequestParam('type'); |
|
322 | - $transient_key = $request->getRequestParam('key'); |
|
323 | - |
|
324 | - // now let's verify transient, if not valid exit immediately |
|
325 | - if (! get_transient($transient_key)) { |
|
326 | - /** |
|
327 | - * trigger error so this gets in the error logs. This is important because it happens on a non-user |
|
328 | - * request. |
|
329 | - */ |
|
330 | - trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso')); |
|
331 | - } |
|
332 | - |
|
333 | - // if made it here, lets' delete the transient to keep the db clean |
|
334 | - delete_transient($transient_key); |
|
335 | - |
|
336 | - if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) { |
|
337 | - $method = 'batch_' . $cron_type . '_from_queue'; |
|
338 | - if (method_exists(self::$_MSG_PROCESSOR, $method)) { |
|
339 | - self::$_MSG_PROCESSOR->$method(); |
|
340 | - } else { |
|
341 | - // no matching task |
|
342 | - /** |
|
343 | - * trigger error so this gets in the error logs. This is important because it happens on a non user |
|
344 | - * request. |
|
345 | - */ |
|
346 | - trigger_error( |
|
347 | - esc_attr( |
|
348 | - sprintf( |
|
349 | - esc_html__('There is no task corresponding to this route %s', 'event_espresso'), |
|
350 | - $cron_type |
|
351 | - ) |
|
352 | - ) |
|
353 | - ); |
|
354 | - } |
|
355 | - } |
|
356 | - |
|
357 | - do_action('FHEE__EED_Messages__run_cron__end'); |
|
358 | - } |
|
359 | - |
|
360 | - |
|
361 | - /** |
|
362 | - * This is used to retrieve the template pack for the given name. |
|
363 | - * Retrieved packs are cached on the static $_TMP_PACKS array. If there is no class matching the given name then |
|
364 | - * the default template pack is returned. |
|
365 | - * |
|
366 | - * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used |
|
367 | - * in generating the Pack class name). |
|
368 | - * @return EE_Messages_Template_Pack |
|
369 | - * @throws EE_Error |
|
370 | - * @throws InvalidArgumentException |
|
371 | - * @throws ReflectionException |
|
372 | - * @throws InvalidDataTypeException |
|
373 | - * @throws InvalidInterfaceException |
|
374 | - * @deprecated 4.9.0 @see EEH_MSG_Template::get_template_pack() |
|
375 | - */ |
|
376 | - public static function get_template_pack($template_pack_name) |
|
377 | - { |
|
378 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
379 | - return EEH_MSG_Template::get_template_pack($template_pack_name); |
|
380 | - } |
|
381 | - |
|
382 | - |
|
383 | - /** |
|
384 | - * Retrieves an array of all template packs. |
|
385 | - * Array is in the format array( 'dbref' => EE_Messages_Template_Pack ) |
|
386 | - * |
|
387 | - * @return EE_Messages_Template_Pack[] |
|
388 | - * @throws EE_Error |
|
389 | - * @throws InvalidArgumentException |
|
390 | - * @throws ReflectionException |
|
391 | - * @throws InvalidDataTypeException |
|
392 | - * @throws InvalidInterfaceException |
|
393 | - * @deprecated 4.9.0 @see EEH_MSG_Template_Pack::get_template_pack_collection |
|
394 | - */ |
|
395 | - public static function get_template_packs() |
|
396 | - { |
|
397 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
398 | - |
|
399 | - // for backward compat, let's make sure this returns in the same format as originally. |
|
400 | - $template_pack_collection = EEH_MSG_Template::get_template_pack_collection(); |
|
401 | - $template_pack_collection->rewind(); |
|
402 | - $template_packs = []; |
|
403 | - while ($template_pack_collection->valid()) { |
|
404 | - $template_packs[ $template_pack_collection->current()->dbref ] = $template_pack_collection->current(); |
|
405 | - $template_pack_collection->next(); |
|
406 | - } |
|
407 | - return $template_packs; |
|
408 | - } |
|
409 | - |
|
410 | - |
|
411 | - /** |
|
412 | - * This simply makes sure the autoloaders are registered for the EE_messages system. |
|
413 | - * |
|
414 | - * @return void |
|
415 | - * @throws EE_Error |
|
416 | - * @since 4.5.0 |
|
417 | - */ |
|
418 | - public static function set_autoloaders() |
|
419 | - { |
|
420 | - if (empty(self::$_MSG_PATHS)) { |
|
421 | - self::_set_messages_paths(); |
|
422 | - foreach (self::$_MSG_PATHS as $path) { |
|
423 | - EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path); |
|
424 | - } |
|
425 | - // add aliases |
|
426 | - EEH_Autoloader::add_alias('EE_messages', 'EE_messages'); |
|
427 | - EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger'); |
|
428 | - } |
|
429 | - } |
|
430 | - |
|
431 | - |
|
432 | - /** |
|
433 | - * Take care of adding all the paths for the messages components to the $_MSG_PATHS property |
|
434 | - * for use by the Messages Autoloaders |
|
435 | - * |
|
436 | - * @return void. |
|
437 | - * @since 4.5.0 |
|
438 | - */ |
|
439 | - protected static function _set_messages_paths() |
|
440 | - { |
|
441 | - self::$_MSG_PATHS = apply_filters( |
|
442 | - 'FHEE__EED_Messages___set_messages_paths___MSG_PATHS', |
|
443 | - [ |
|
444 | - EE_LIBRARIES . 'messages/message_type', |
|
445 | - EE_LIBRARIES . 'messages/messenger', |
|
446 | - EE_LIBRARIES . 'messages/defaults', |
|
447 | - EE_LIBRARIES . 'messages/defaults/email', |
|
448 | - EE_LIBRARIES . 'messages/data_class', |
|
449 | - EE_LIBRARIES . 'messages/validators', |
|
450 | - EE_LIBRARIES . 'messages/validators/email', |
|
451 | - EE_LIBRARIES . 'messages/validators/html', |
|
452 | - EE_LIBRARIES . 'shortcodes', |
|
453 | - ] |
|
454 | - ); |
|
455 | - } |
|
456 | - |
|
457 | - |
|
458 | - /** |
|
459 | - * Takes care of loading dependencies |
|
460 | - * |
|
461 | - * @return void |
|
462 | - * @throws EE_Error |
|
463 | - * @throws InvalidArgumentException |
|
464 | - * @throws ReflectionException |
|
465 | - * @throws InvalidDataTypeException |
|
466 | - * @throws InvalidInterfaceException |
|
467 | - * @since 4.5.0 |
|
468 | - */ |
|
469 | - protected static function _load_controller() |
|
470 | - { |
|
471 | - if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
472 | - EE_Registry::instance()->load_core('Request_Handler'); |
|
473 | - self::set_autoloaders(); |
|
474 | - self::$_EEMSG = EE_Registry::instance()->load_lib('messages'); |
|
475 | - self::$_MSG_PROCESSOR = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
476 | - self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
477 | - } |
|
478 | - } |
|
479 | - |
|
480 | - |
|
481 | - /** |
|
482 | - * @param EE_Transaction $transaction |
|
483 | - * @throws EE_Error |
|
484 | - * @throws InvalidArgumentException |
|
485 | - * @throws InvalidDataTypeException |
|
486 | - * @throws InvalidInterfaceException |
|
487 | - * @throws ReflectionException |
|
488 | - */ |
|
489 | - public static function payment_reminder(EE_Transaction $transaction) |
|
490 | - { |
|
491 | - self::_load_controller(); |
|
492 | - $data = [$transaction, null]; |
|
493 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data); |
|
494 | - } |
|
495 | - |
|
496 | - |
|
497 | - /** |
|
498 | - * Any messages triggers for after successful gateway payments should go in here. |
|
499 | - * |
|
500 | - * @param EE_Transaction $transaction object |
|
501 | - * @param EE_Payment|null $payment object |
|
502 | - * @return void |
|
503 | - * @throws EE_Error |
|
504 | - * @throws InvalidArgumentException |
|
505 | - * @throws ReflectionException |
|
506 | - * @throws InvalidDataTypeException |
|
507 | - * @throws InvalidInterfaceException |
|
508 | - */ |
|
509 | - public static function payment(EE_Transaction $transaction, EE_Payment $payment = null) |
|
510 | - { |
|
511 | - // if there's no payment object, then we cannot do a payment type message! |
|
512 | - if (! $payment instanceof EE_Payment) { |
|
513 | - return; |
|
514 | - } |
|
515 | - self::_load_controller(); |
|
516 | - $data = [$transaction, $payment]; |
|
517 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
518 | - $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
519 | - // if payment amount is less than 0 then switch to payment_refund message type. |
|
520 | - $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
521 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
522 | - } |
|
523 | - |
|
524 | - |
|
525 | - /** |
|
526 | - * @param EE_Transaction $transaction |
|
527 | - * @throws EE_Error |
|
528 | - * @throws InvalidArgumentException |
|
529 | - * @throws InvalidDataTypeException |
|
530 | - * @throws InvalidInterfaceException |
|
531 | - * @throws ReflectionException |
|
532 | - */ |
|
533 | - public static function cancelled_registration(EE_Transaction $transaction) |
|
534 | - { |
|
535 | - self::_load_controller(); |
|
536 | - $data = [$transaction, null]; |
|
537 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data); |
|
538 | - } |
|
539 | - |
|
540 | - |
|
541 | - /** |
|
542 | - * Trigger for Registration messages |
|
543 | - * Note that what registration message type is sent depends on what the reg status is for the registrations on the |
|
544 | - * incoming transaction. |
|
545 | - * |
|
546 | - * @param EE_Registration $registration |
|
547 | - * @param array $extra_details |
|
548 | - * @return void |
|
549 | - * @throws EE_Error |
|
550 | - * @throws InvalidArgumentException |
|
551 | - * @throws InvalidDataTypeException |
|
552 | - * @throws InvalidInterfaceException |
|
553 | - * @throws ReflectionException |
|
554 | - * @throws EntityNotFoundException |
|
555 | - */ |
|
556 | - public static function maybe_registration(EE_Registration $registration, $extra_details = []) |
|
557 | - { |
|
558 | - |
|
559 | - if (! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
560 | - // no messages please |
|
561 | - return; |
|
562 | - } |
|
563 | - |
|
564 | - // get all non-trashed registrations so we make sure we send messages for the right status. |
|
565 | - $all_registrations = $registration->transaction()->registrations( |
|
566 | - [ |
|
567 | - ['REG_deleted' => false], |
|
568 | - 'order_by' => [ |
|
569 | - 'Event.EVT_name' => 'ASC', |
|
570 | - 'Attendee.ATT_lname' => 'ASC', |
|
571 | - 'Attendee.ATT_fname' => 'ASC', |
|
572 | - ], |
|
573 | - ] |
|
574 | - ); |
|
575 | - // cached array of statuses so we only trigger messages once per status. |
|
576 | - $statuses_sent = []; |
|
577 | - self::_load_controller(); |
|
578 | - $mtgs = []; |
|
579 | - |
|
580 | - // loop through registrations and trigger messages once per status. |
|
581 | - foreach ($all_registrations as $reg) { |
|
582 | - // already triggered? |
|
583 | - if (in_array($reg->status_ID(), $statuses_sent)) { |
|
584 | - continue; |
|
585 | - } |
|
586 | - |
|
587 | - $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID()); |
|
588 | - $mtgs = array_merge( |
|
589 | - $mtgs, |
|
590 | - self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
591 | - $message_type, |
|
592 | - [$registration->transaction(), null, $reg->status_ID()] |
|
593 | - ) |
|
594 | - ); |
|
595 | - $statuses_sent[] = $reg->status_ID(); |
|
596 | - } |
|
597 | - |
|
598 | - if (count($statuses_sent) > 1) { |
|
599 | - $mtgs = array_merge( |
|
600 | - $mtgs, |
|
601 | - self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
602 | - 'registration_summary', |
|
603 | - [$registration->transaction(), null] |
|
604 | - ) |
|
605 | - ); |
|
606 | - } |
|
607 | - |
|
608 | - // batch queue and initiate request |
|
609 | - self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs); |
|
610 | - self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
611 | - } |
|
612 | - |
|
613 | - |
|
614 | - /** |
|
615 | - * This is a helper method used to very whether a registration notification should be sent or |
|
616 | - * not. Prevents duplicate notifications going out for registration context notifications. |
|
617 | - * |
|
618 | - * @param EE_Registration $registration [description] |
|
619 | - * @param array $extra_details [description] |
|
620 | - * @return bool true = send away, false = nope halt the presses. |
|
621 | - */ |
|
622 | - protected static function _verify_registration_notification_send( |
|
623 | - EE_Registration $registration, |
|
624 | - $extra_details = [] |
|
625 | - ) { |
|
626 | - $request = self::getRequest(); |
|
627 | - if ( |
|
628 | - ! $request->getRequestParam('non_primary_reg_notification', 0, 'int') |
|
629 | - && ! $registration->is_primary_registrant() |
|
630 | - ) { |
|
631 | - return false; |
|
632 | - } |
|
633 | - // first we check if we're in admin and not doing front ajax |
|
634 | - if ( |
|
635 | - ($request->isAdmin() || $request->isAdminAjax()) |
|
636 | - && ! $request->isFrontAjax() |
|
637 | - ) { |
|
638 | - $status_change = $request->getRequestParam('txn_reg_status_change', [], 'int', true); |
|
639 | - // make sure appropriate admin params are set for sending messages |
|
640 | - if ( |
|
641 | - ! isset($status_change['send_notifications']) |
|
642 | - || (isset($status_change['send_notifications']) && ! $status_change['send_notifications']) |
|
643 | - ) { |
|
644 | - // no messages sent please. |
|
645 | - return false; |
|
646 | - } |
|
647 | - } else { |
|
648 | - // frontend request (either regular or via AJAX) |
|
649 | - // TXN is NOT finalized ? |
|
650 | - if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
651 | - return false; |
|
652 | - } |
|
653 | - // return visit but nothing changed ??? |
|
654 | - if ( |
|
655 | - isset($extra_details['revisit'], $extra_details['status_updates']) |
|
656 | - && $extra_details['revisit'] |
|
657 | - && ! $extra_details['status_updates'] |
|
658 | - ) { |
|
659 | - return false; |
|
660 | - } |
|
661 | - // NOT sending messages && reg status is something other than "Not-Approved" |
|
662 | - if ( |
|
663 | - ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) |
|
664 | - && $registration->status_ID() !== EEM_Registration::status_id_not_approved |
|
665 | - ) { |
|
666 | - return false; |
|
667 | - } |
|
668 | - } |
|
669 | - // release the kraken |
|
670 | - return true; |
|
671 | - } |
|
672 | - |
|
673 | - |
|
674 | - /** |
|
675 | - * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that |
|
676 | - * status id. |
|
677 | - * |
|
678 | - * @param string $reg_status |
|
679 | - * @return array |
|
680 | - * @throws EE_Error |
|
681 | - * @throws InvalidArgumentException |
|
682 | - * @throws ReflectionException |
|
683 | - * @throws InvalidDataTypeException |
|
684 | - * @throws InvalidInterfaceException |
|
685 | - * @deprecated 4.9.0 Use EEH_MSG_Template::reg_status_to_message_type_array() |
|
686 | - * or EEH_MSG_Template::convert_reg_status_to_message_type |
|
687 | - */ |
|
688 | - protected static function _get_reg_status_array($reg_status = '') |
|
689 | - { |
|
690 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
691 | - return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
692 | - ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
693 | - : EEH_MSG_Template::reg_status_to_message_type_array(); |
|
694 | - } |
|
695 | - |
|
696 | - |
|
697 | - /** |
|
698 | - * Simply returns the payment message type for the given payment status. |
|
699 | - * |
|
700 | - * @param string $payment_status The payment status being matched. |
|
701 | - * @return bool|string The payment message type slug matching the status or false if no match. |
|
702 | - * @throws EE_Error |
|
703 | - * @throws InvalidArgumentException |
|
704 | - * @throws ReflectionException |
|
705 | - * @throws InvalidDataTypeException |
|
706 | - * @throws InvalidInterfaceException |
|
707 | - * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array |
|
708 | - * or EEH_MSG_Template::convert_payment_status_to_message_type |
|
709 | - */ |
|
710 | - protected static function _get_payment_message_type($payment_status) |
|
711 | - { |
|
712 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
713 | - return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
714 | - ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
715 | - : false; |
|
716 | - } |
|
717 | - |
|
718 | - |
|
719 | - /** |
|
720 | - * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
721 | - * |
|
722 | - * @access public |
|
723 | - * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages |
|
724 | - * @return bool success/fail |
|
725 | - * @throws EE_Error |
|
726 | - * @throws InvalidArgumentException |
|
727 | - * @throws InvalidDataTypeException |
|
728 | - * @throws InvalidInterfaceException |
|
729 | - * @throws ReflectionException |
|
730 | - */ |
|
731 | - public static function process_resend(array $req_data = []) |
|
732 | - { |
|
733 | - self::_load_controller(); |
|
734 | - $request = self::getRequest(); |
|
735 | - // if $msgID in this request then skip to the new resend_message |
|
736 | - if ($request->getRequestParam('MSG_ID')) { |
|
737 | - return self::resend_message(); |
|
738 | - } |
|
739 | - |
|
740 | - // make sure any incoming request data is set on the request so that it gets picked up later. |
|
741 | - foreach ((array) $req_data as $request_key => $request_value) { |
|
742 | - if (! $request->requestParamIsSet($request_key)) { |
|
743 | - $request->setRequestParam($request_key, $request_value); |
|
744 | - } |
|
745 | - } |
|
746 | - |
|
747 | - if ( |
|
748 | - ! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request() |
|
749 | - ) { |
|
750 | - return false; |
|
751 | - } |
|
752 | - |
|
753 | - try { |
|
754 | - self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send); |
|
755 | - self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
756 | - } catch (EE_Error $e) { |
|
757 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
758 | - return false; |
|
759 | - } |
|
760 | - EE_Error::add_success( |
|
761 | - esc_html__('Messages have been successfully queued for generation and sending.', 'event_espresso') |
|
762 | - ); |
|
763 | - return true; // everything got queued. |
|
764 | - } |
|
765 | - |
|
766 | - |
|
767 | - /** |
|
768 | - * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
769 | - * |
|
770 | - * @return bool |
|
771 | - * @throws EE_Error |
|
772 | - * @throws InvalidArgumentException |
|
773 | - * @throws InvalidDataTypeException |
|
774 | - * @throws InvalidInterfaceException |
|
775 | - * @throws ReflectionException |
|
776 | - */ |
|
777 | - public static function resend_message() |
|
778 | - { |
|
779 | - self::_load_controller(); |
|
780 | - |
|
781 | - $msgID = self::getRequest()->getRequestParam('MSG_ID', 0, 'int'); |
|
782 | - if (! $msgID) { |
|
783 | - EE_Error::add_error( |
|
784 | - esc_html__( |
|
785 | - 'Something went wrong because there is no "MSG_ID" value in the request', |
|
786 | - 'event_espresso' |
|
787 | - ), |
|
788 | - __FILE__, |
|
789 | - __FUNCTION__, |
|
790 | - __LINE__ |
|
791 | - ); |
|
792 | - return false; |
|
793 | - } |
|
794 | - |
|
795 | - self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array) $msgID); |
|
796 | - |
|
797 | - // setup success message. |
|
798 | - $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
799 | - EE_Error::add_success( |
|
800 | - sprintf( |
|
801 | - _n( |
|
802 | - 'There was %d message queued for resending.', |
|
803 | - 'There were %d messages queued for resending.', |
|
804 | - $count_ready_for_resend, |
|
805 | - 'event_espresso' |
|
806 | - ), |
|
807 | - $count_ready_for_resend |
|
808 | - ) |
|
809 | - ); |
|
810 | - return true; |
|
811 | - } |
|
812 | - |
|
813 | - |
|
814 | - /** |
|
815 | - * Message triggers for manual payment applied by admin |
|
816 | - * |
|
817 | - * @param EE_Payment $payment EE_payment object |
|
818 | - * @return bool success/fail |
|
819 | - * @throws EE_Error |
|
820 | - * @throws InvalidArgumentException |
|
821 | - * @throws ReflectionException |
|
822 | - * @throws InvalidDataTypeException |
|
823 | - * @throws InvalidInterfaceException |
|
824 | - */ |
|
825 | - public static function process_admin_payment(EE_Payment $payment) |
|
826 | - { |
|
827 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
828 | - // we need to get the transaction object |
|
829 | - $transaction = $payment->transaction(); |
|
830 | - if ($transaction instanceof EE_Transaction) { |
|
831 | - $data = [$transaction, $payment]; |
|
832 | - $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
833 | - |
|
834 | - // if payment amount is less than 0 then switch to payment_refund message type. |
|
835 | - $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
836 | - |
|
837 | - // if payment_refund is selected, but the status is NOT accepted. Then change message type to false so NO message notification goes out. |
|
838 | - $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved |
|
839 | - ? false : $message_type; |
|
840 | - |
|
841 | - self::_load_controller(); |
|
842 | - |
|
843 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
844 | - |
|
845 | - // get count of queued for generation |
|
846 | - $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue( |
|
847 | - [ |
|
848 | - EEM_Message::status_incomplete, |
|
849 | - EEM_Message::status_idle, |
|
850 | - ] |
|
851 | - ); |
|
852 | - |
|
853 | - if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) { |
|
854 | - add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
855 | - return true; |
|
856 | - } else { |
|
857 | - $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue( |
|
858 | - EEM_Message::instance()->stati_indicating_failed_sending() |
|
859 | - ); |
|
860 | - /** |
|
861 | - * Verify that there are actually errors. If not then we return a success message because the queue might have been emptied due to successful |
|
862 | - * IMMEDIATE generation. |
|
863 | - */ |
|
864 | - if ($count_failed > 0) { |
|
865 | - EE_Error::add_error( |
|
866 | - sprintf( |
|
867 | - _n( |
|
868 | - 'The payment notification generation failed.', |
|
869 | - '%d payment notifications failed being sent.', |
|
870 | - $count_failed, |
|
871 | - 'event_espresso' |
|
872 | - ), |
|
873 | - $count_failed |
|
874 | - ), |
|
875 | - __FILE__, |
|
876 | - __FUNCTION__, |
|
877 | - __LINE__ |
|
878 | - ); |
|
879 | - |
|
880 | - return false; |
|
881 | - } else { |
|
882 | - add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
883 | - return true; |
|
884 | - } |
|
885 | - } |
|
886 | - } else { |
|
887 | - EE_Error::add_error( |
|
888 | - 'Unable to generate the payment notification because the given value for the transaction is invalid.', |
|
889 | - 'event_espresso' |
|
890 | - ); |
|
891 | - return false; |
|
892 | - } |
|
893 | - } |
|
894 | - |
|
895 | - |
|
896 | - /** |
|
897 | - * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger |
|
898 | - * |
|
899 | - * @param EE_Registration[] $registrations an array of EE_Registration objects |
|
900 | - * @param int $grp_id a specific message template group id. |
|
901 | - * @return void |
|
902 | - * @throws EE_Error |
|
903 | - * @throws InvalidArgumentException |
|
904 | - * @throws InvalidDataTypeException |
|
905 | - * @throws InvalidInterfaceException |
|
906 | - * @throws ReflectionException |
|
907 | - * @since 4.3.0 |
|
908 | - */ |
|
909 | - public static function send_newsletter_message($registrations, $grp_id) |
|
910 | - { |
|
911 | - // make sure mtp is id and set it in the request later messages setup. |
|
912 | - self::getRequest()->setRequestParam('GRP_ID', (int) $grp_id); |
|
913 | - self::_load_controller(); |
|
914 | - self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations); |
|
915 | - } |
|
916 | - |
|
917 | - |
|
918 | - /** |
|
919 | - * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url |
|
920 | - * |
|
921 | - * @param string $registration_message_trigger_url |
|
922 | - * @param EE_Registration $registration |
|
923 | - * @param string $messenger |
|
924 | - * @param string $message_type |
|
925 | - * @return string |
|
926 | - * @throws EE_Error |
|
927 | - * @throws InvalidArgumentException |
|
928 | - * @throws InvalidDataTypeException |
|
929 | - * @throws InvalidInterfaceException |
|
930 | - * @since 4.3.0 |
|
931 | - */ |
|
932 | - public static function registration_message_trigger_url( |
|
933 | - $registration_message_trigger_url, |
|
934 | - EE_Registration $registration, |
|
935 | - $messenger = 'html', |
|
936 | - $message_type = 'invoice' |
|
937 | - ) { |
|
938 | - // whitelist $messenger |
|
939 | - switch ($messenger) { |
|
940 | - case 'pdf': |
|
941 | - $sending_messenger = 'pdf'; |
|
942 | - $generating_messenger = 'html'; |
|
943 | - break; |
|
944 | - case 'html': |
|
945 | - default: |
|
946 | - $sending_messenger = 'html'; |
|
947 | - $generating_messenger = 'html'; |
|
948 | - break; |
|
949 | - } |
|
950 | - // whitelist $message_type |
|
951 | - switch ($message_type) { |
|
952 | - case 'receipt': |
|
953 | - $message_type = 'receipt'; |
|
954 | - break; |
|
955 | - case 'invoice': |
|
956 | - default: |
|
957 | - $message_type = 'invoice'; |
|
958 | - break; |
|
959 | - } |
|
960 | - // verify that both the messenger AND the message type are active |
|
961 | - if ( |
|
962 | - EEH_MSG_Template::is_messenger_active($sending_messenger) |
|
963 | - && EEH_MSG_Template::is_mt_active($message_type) |
|
964 | - ) { |
|
965 | - // need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?) |
|
966 | - $template_query_params = [ |
|
967 | - 'MTP_is_active' => true, |
|
968 | - 'MTP_messenger' => $generating_messenger, |
|
969 | - 'MTP_message_type' => $message_type, |
|
970 | - 'Event.EVT_ID' => $registration->event_ID(), |
|
971 | - ]; |
|
972 | - // get the message template group. |
|
973 | - $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]); |
|
974 | - // if we don't have an EE_Message_Template_Group then return |
|
975 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
976 | - // remove EVT_ID from query params so that global templates get picked up |
|
977 | - unset($template_query_params['Event.EVT_ID']); |
|
978 | - // get global template as the fallback |
|
979 | - $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]); |
|
980 | - } |
|
981 | - // if we don't have an EE_Message_Template_Group then return |
|
982 | - if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
983 | - return ''; |
|
984 | - } |
|
985 | - // generate the URL |
|
986 | - $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger( |
|
987 | - $sending_messenger, |
|
988 | - $generating_messenger, |
|
989 | - 'purchaser', |
|
990 | - $message_type, |
|
991 | - $registration, |
|
992 | - $msg_template_group->ID(), |
|
993 | - $registration->transaction_ID() |
|
994 | - ); |
|
995 | - } |
|
996 | - return $registration_message_trigger_url; |
|
997 | - } |
|
998 | - |
|
999 | - |
|
1000 | - /** |
|
1001 | - * Use to generate and return a message preview! |
|
1002 | - * |
|
1003 | - * @param string $type This should correspond with a valid message type |
|
1004 | - * @param string $context This should correspond with a valid context for the message type |
|
1005 | - * @param string $messenger This should correspond with a valid messenger. |
|
1006 | - * @param bool $send true we will do a test send using the messenger delivery, false we just do a regular |
|
1007 | - * preview |
|
1008 | - * @return bool|string The body of the message or if send is requested, sends. |
|
1009 | - * @throws EE_Error |
|
1010 | - * @throws InvalidArgumentException |
|
1011 | - * @throws InvalidDataTypeException |
|
1012 | - * @throws InvalidInterfaceException |
|
1013 | - * @throws ReflectionException |
|
1014 | - */ |
|
1015 | - public static function preview_message($type, $context, $messenger, $send = false) |
|
1016 | - { |
|
1017 | - self::_load_controller(); |
|
1018 | - $message_to_generate = new EE_Message_To_Generate( |
|
1019 | - $messenger, |
|
1020 | - $type, |
|
1021 | - [], |
|
1022 | - $context, |
|
1023 | - true |
|
1024 | - ); |
|
1025 | - $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($message_to_generate, $send); |
|
1026 | - |
|
1027 | - if ($generated_preview_queue instanceof EE_Messages_Queue) { |
|
1028 | - // loop through all content for the preview and remove any persisted records. |
|
1029 | - $content = ''; |
|
1030 | - foreach ($generated_preview_queue->get_message_repository() as $message) { |
|
1031 | - $content = $message->content(); |
|
1032 | - if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) { |
|
1033 | - $message->delete(); |
|
1034 | - } |
|
1035 | - } |
|
1036 | - return $content; |
|
1037 | - } |
|
1038 | - return $generated_preview_queue; |
|
1039 | - } |
|
1040 | - |
|
1041 | - |
|
1042 | - /** |
|
1043 | - * This is a method that allows for sending a message using a messenger matching the string given and the provided |
|
1044 | - * EE_Message_Queue object. The EE_Message_Queue object is used to create a single aggregate EE_Message via the |
|
1045 | - * content found in the EE_Message objects in the queue. |
|
1046 | - * |
|
1047 | - * @param string $messenger a string matching a valid active messenger in the system |
|
1048 | - * @param string $message_type Although it seems contrary to the name of the method, a message |
|
1049 | - * type name is still required to send along the message type to the |
|
1050 | - * messenger because this is used for determining what specific |
|
1051 | - * variations might be loaded for the generated message. |
|
1052 | - * @param EE_Messages_Queue $queue |
|
1053 | - * @param string $custom_subject Can be used to set what the custom subject string will be on the |
|
1054 | - * aggregate EE_Message object. |
|
1055 | - * @return bool success or fail. |
|
1056 | - * @throws EE_Error |
|
1057 | - * @throws InvalidArgumentException |
|
1058 | - * @throws ReflectionException |
|
1059 | - * @throws InvalidDataTypeException |
|
1060 | - * @throws InvalidInterfaceException |
|
1061 | - * @since 4.9.0 |
|
1062 | - */ |
|
1063 | - public static function send_message_with_messenger_only( |
|
1064 | - $messenger, |
|
1065 | - $message_type, |
|
1066 | - EE_Messages_Queue $queue, |
|
1067 | - $custom_subject = '' |
|
1068 | - ) { |
|
1069 | - self::_load_controller(); |
|
1070 | - /** @type EE_Message_To_Generate_From_Queue $message_to_generate */ |
|
1071 | - $message_to_generate = EE_Registry::instance()->load_lib( |
|
1072 | - 'Message_To_Generate_From_Queue', |
|
1073 | - [ |
|
1074 | - $messenger, |
|
1075 | - $message_type, |
|
1076 | - $queue, |
|
1077 | - $custom_subject, |
|
1078 | - ] |
|
1079 | - ); |
|
1080 | - return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate); |
|
1081 | - } |
|
1082 | - |
|
1083 | - |
|
1084 | - /** |
|
1085 | - * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation) |
|
1086 | - * |
|
1087 | - * @param array $message_ids An array of message ids |
|
1088 | - * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated |
|
1089 | - * messages. |
|
1090 | - * @throws EE_Error |
|
1091 | - * @throws InvalidArgumentException |
|
1092 | - * @throws InvalidDataTypeException |
|
1093 | - * @throws InvalidInterfaceException |
|
1094 | - * @throws ReflectionException |
|
1095 | - * @since 4.9.0 |
|
1096 | - */ |
|
1097 | - public static function generate_now($message_ids) |
|
1098 | - { |
|
1099 | - self::_load_controller(); |
|
1100 | - $messages = EEM_Message::instance()->get_all( |
|
1101 | - [ |
|
1102 | - 0 => [ |
|
1103 | - 'MSG_ID' => ['IN', $message_ids], |
|
1104 | - 'STS_ID' => EEM_Message::status_incomplete, |
|
1105 | - ], |
|
1106 | - ] |
|
1107 | - ); |
|
1108 | - $generated_queue = false; |
|
1109 | - if ($messages) { |
|
1110 | - $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages); |
|
1111 | - } |
|
1112 | - |
|
1113 | - if (! $generated_queue instanceof EE_Messages_Queue) { |
|
1114 | - EE_Error::add_error( |
|
1115 | - esc_html__( |
|
1116 | - 'The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.', |
|
1117 | - 'event_espresso' |
|
1118 | - ), |
|
1119 | - __FILE__, |
|
1120 | - __FUNCTION__, |
|
1121 | - __LINE__ |
|
1122 | - ); |
|
1123 | - } |
|
1124 | - return $generated_queue; |
|
1125 | - } |
|
1126 | - |
|
1127 | - |
|
1128 | - /** |
|
1129 | - * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or, |
|
1130 | - * EEM_Message::status_idle |
|
1131 | - * |
|
1132 | - * @param $message_ids |
|
1133 | - * @return bool|EE_Messages_Queue false if no messages sent. |
|
1134 | - * @throws EE_Error |
|
1135 | - * @throws InvalidArgumentException |
|
1136 | - * @throws InvalidDataTypeException |
|
1137 | - * @throws InvalidInterfaceException |
|
1138 | - * @throws ReflectionException |
|
1139 | - * @since 4.9.0 |
|
1140 | - */ |
|
1141 | - public static function send_now($message_ids) |
|
1142 | - { |
|
1143 | - self::_load_controller(); |
|
1144 | - $messages = EEM_Message::instance()->get_all( |
|
1145 | - [ |
|
1146 | - 0 => [ |
|
1147 | - 'MSG_ID' => ['IN', $message_ids], |
|
1148 | - 'STS_ID' => [ |
|
1149 | - 'IN', |
|
1150 | - [EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry], |
|
1151 | - ], |
|
1152 | - ], |
|
1153 | - ] |
|
1154 | - ); |
|
1155 | - $sent_queue = false; |
|
1156 | - if ($messages) { |
|
1157 | - $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages); |
|
1158 | - } |
|
1159 | - |
|
1160 | - if (! $sent_queue instanceof EE_Messages_Queue) { |
|
1161 | - EE_Error::add_error( |
|
1162 | - esc_html__( |
|
1163 | - 'The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', |
|
1164 | - 'event_espresso' |
|
1165 | - ), |
|
1166 | - __FILE__, |
|
1167 | - __FUNCTION__, |
|
1168 | - __LINE__ |
|
1169 | - ); |
|
1170 | - } else { |
|
1171 | - // can count how many sent by using the messages in the queue |
|
1172 | - $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent()); |
|
1173 | - if ($sent_count > 0) { |
|
1174 | - EE_Error::add_success( |
|
1175 | - sprintf( |
|
1176 | - _n( |
|
1177 | - 'There was %d message successfully sent.', |
|
1178 | - 'There were %d messages successfully sent.', |
|
1179 | - $sent_count, |
|
1180 | - 'event_espresso' |
|
1181 | - ), |
|
1182 | - $sent_count |
|
1183 | - ) |
|
1184 | - ); |
|
1185 | - } else { |
|
1186 | - EE_Error::overwrite_errors(); |
|
1187 | - EE_Error::add_error( |
|
1188 | - esc_html__( |
|
1189 | - 'No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error. |
|
261 | + exit; |
|
262 | + } |
|
263 | + } |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + /** |
|
268 | + * This runs when the msg_url_trigger route has initiated. |
|
269 | + * |
|
270 | + * @param WP $WP |
|
271 | + * @throws EE_Error |
|
272 | + * @throws InvalidArgumentException |
|
273 | + * @throws ReflectionException |
|
274 | + * @throws InvalidDataTypeException |
|
275 | + * @throws InvalidInterfaceException |
|
276 | + * @since 4.5.0 |
|
277 | + */ |
|
278 | + public function run($WP) |
|
279 | + { |
|
280 | + // ensure controller is loaded |
|
281 | + self::_load_controller(); |
|
282 | + // attempt to process message |
|
283 | + try { |
|
284 | + /** @type EE_Message_To_Generate_From_Request $message_to_generate */ |
|
285 | + $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request'); |
|
286 | + self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate); |
|
287 | + } catch (EE_Error $e) { |
|
288 | + $error_msg = esc_html__( |
|
289 | + 'Please note that a system message failed to send due to a technical issue.', |
|
290 | + 'event_espresso' |
|
291 | + ); |
|
292 | + // add specific message for developers if WP_DEBUG in on |
|
293 | + $error_msg .= '||' . $e->getMessage(); |
|
294 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
295 | + } |
|
296 | + } |
|
297 | + |
|
298 | + |
|
299 | + /** |
|
300 | + * This is triggered by the 'msg_cron_trigger' route. |
|
301 | + * |
|
302 | + * @param WP $WP |
|
303 | + */ |
|
304 | + public function execute_batch_request($WP) |
|
305 | + { |
|
306 | + $this->run_cron(); |
|
307 | + header('HTTP/1.1 200 OK'); |
|
308 | + exit(); |
|
309 | + } |
|
310 | + |
|
311 | + |
|
312 | + /** |
|
313 | + * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp |
|
314 | + * request. |
|
315 | + */ |
|
316 | + public function run_cron() |
|
317 | + { |
|
318 | + self::_load_controller(); |
|
319 | + $request = self::getRequest(); |
|
320 | + // get required vars |
|
321 | + $cron_type = $request->getRequestParam('type'); |
|
322 | + $transient_key = $request->getRequestParam('key'); |
|
323 | + |
|
324 | + // now let's verify transient, if not valid exit immediately |
|
325 | + if (! get_transient($transient_key)) { |
|
326 | + /** |
|
327 | + * trigger error so this gets in the error logs. This is important because it happens on a non-user |
|
328 | + * request. |
|
329 | + */ |
|
330 | + trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso')); |
|
331 | + } |
|
332 | + |
|
333 | + // if made it here, lets' delete the transient to keep the db clean |
|
334 | + delete_transient($transient_key); |
|
335 | + |
|
336 | + if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) { |
|
337 | + $method = 'batch_' . $cron_type . '_from_queue'; |
|
338 | + if (method_exists(self::$_MSG_PROCESSOR, $method)) { |
|
339 | + self::$_MSG_PROCESSOR->$method(); |
|
340 | + } else { |
|
341 | + // no matching task |
|
342 | + /** |
|
343 | + * trigger error so this gets in the error logs. This is important because it happens on a non user |
|
344 | + * request. |
|
345 | + */ |
|
346 | + trigger_error( |
|
347 | + esc_attr( |
|
348 | + sprintf( |
|
349 | + esc_html__('There is no task corresponding to this route %s', 'event_espresso'), |
|
350 | + $cron_type |
|
351 | + ) |
|
352 | + ) |
|
353 | + ); |
|
354 | + } |
|
355 | + } |
|
356 | + |
|
357 | + do_action('FHEE__EED_Messages__run_cron__end'); |
|
358 | + } |
|
359 | + |
|
360 | + |
|
361 | + /** |
|
362 | + * This is used to retrieve the template pack for the given name. |
|
363 | + * Retrieved packs are cached on the static $_TMP_PACKS array. If there is no class matching the given name then |
|
364 | + * the default template pack is returned. |
|
365 | + * |
|
366 | + * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used |
|
367 | + * in generating the Pack class name). |
|
368 | + * @return EE_Messages_Template_Pack |
|
369 | + * @throws EE_Error |
|
370 | + * @throws InvalidArgumentException |
|
371 | + * @throws ReflectionException |
|
372 | + * @throws InvalidDataTypeException |
|
373 | + * @throws InvalidInterfaceException |
|
374 | + * @deprecated 4.9.0 @see EEH_MSG_Template::get_template_pack() |
|
375 | + */ |
|
376 | + public static function get_template_pack($template_pack_name) |
|
377 | + { |
|
378 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
379 | + return EEH_MSG_Template::get_template_pack($template_pack_name); |
|
380 | + } |
|
381 | + |
|
382 | + |
|
383 | + /** |
|
384 | + * Retrieves an array of all template packs. |
|
385 | + * Array is in the format array( 'dbref' => EE_Messages_Template_Pack ) |
|
386 | + * |
|
387 | + * @return EE_Messages_Template_Pack[] |
|
388 | + * @throws EE_Error |
|
389 | + * @throws InvalidArgumentException |
|
390 | + * @throws ReflectionException |
|
391 | + * @throws InvalidDataTypeException |
|
392 | + * @throws InvalidInterfaceException |
|
393 | + * @deprecated 4.9.0 @see EEH_MSG_Template_Pack::get_template_pack_collection |
|
394 | + */ |
|
395 | + public static function get_template_packs() |
|
396 | + { |
|
397 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
398 | + |
|
399 | + // for backward compat, let's make sure this returns in the same format as originally. |
|
400 | + $template_pack_collection = EEH_MSG_Template::get_template_pack_collection(); |
|
401 | + $template_pack_collection->rewind(); |
|
402 | + $template_packs = []; |
|
403 | + while ($template_pack_collection->valid()) { |
|
404 | + $template_packs[ $template_pack_collection->current()->dbref ] = $template_pack_collection->current(); |
|
405 | + $template_pack_collection->next(); |
|
406 | + } |
|
407 | + return $template_packs; |
|
408 | + } |
|
409 | + |
|
410 | + |
|
411 | + /** |
|
412 | + * This simply makes sure the autoloaders are registered for the EE_messages system. |
|
413 | + * |
|
414 | + * @return void |
|
415 | + * @throws EE_Error |
|
416 | + * @since 4.5.0 |
|
417 | + */ |
|
418 | + public static function set_autoloaders() |
|
419 | + { |
|
420 | + if (empty(self::$_MSG_PATHS)) { |
|
421 | + self::_set_messages_paths(); |
|
422 | + foreach (self::$_MSG_PATHS as $path) { |
|
423 | + EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path); |
|
424 | + } |
|
425 | + // add aliases |
|
426 | + EEH_Autoloader::add_alias('EE_messages', 'EE_messages'); |
|
427 | + EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger'); |
|
428 | + } |
|
429 | + } |
|
430 | + |
|
431 | + |
|
432 | + /** |
|
433 | + * Take care of adding all the paths for the messages components to the $_MSG_PATHS property |
|
434 | + * for use by the Messages Autoloaders |
|
435 | + * |
|
436 | + * @return void. |
|
437 | + * @since 4.5.0 |
|
438 | + */ |
|
439 | + protected static function _set_messages_paths() |
|
440 | + { |
|
441 | + self::$_MSG_PATHS = apply_filters( |
|
442 | + 'FHEE__EED_Messages___set_messages_paths___MSG_PATHS', |
|
443 | + [ |
|
444 | + EE_LIBRARIES . 'messages/message_type', |
|
445 | + EE_LIBRARIES . 'messages/messenger', |
|
446 | + EE_LIBRARIES . 'messages/defaults', |
|
447 | + EE_LIBRARIES . 'messages/defaults/email', |
|
448 | + EE_LIBRARIES . 'messages/data_class', |
|
449 | + EE_LIBRARIES . 'messages/validators', |
|
450 | + EE_LIBRARIES . 'messages/validators/email', |
|
451 | + EE_LIBRARIES . 'messages/validators/html', |
|
452 | + EE_LIBRARIES . 'shortcodes', |
|
453 | + ] |
|
454 | + ); |
|
455 | + } |
|
456 | + |
|
457 | + |
|
458 | + /** |
|
459 | + * Takes care of loading dependencies |
|
460 | + * |
|
461 | + * @return void |
|
462 | + * @throws EE_Error |
|
463 | + * @throws InvalidArgumentException |
|
464 | + * @throws ReflectionException |
|
465 | + * @throws InvalidDataTypeException |
|
466 | + * @throws InvalidInterfaceException |
|
467 | + * @since 4.5.0 |
|
468 | + */ |
|
469 | + protected static function _load_controller() |
|
470 | + { |
|
471 | + if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) { |
|
472 | + EE_Registry::instance()->load_core('Request_Handler'); |
|
473 | + self::set_autoloaders(); |
|
474 | + self::$_EEMSG = EE_Registry::instance()->load_lib('messages'); |
|
475 | + self::$_MSG_PROCESSOR = EE_Registry::instance()->load_lib('Messages_Processor'); |
|
476 | + self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
477 | + } |
|
478 | + } |
|
479 | + |
|
480 | + |
|
481 | + /** |
|
482 | + * @param EE_Transaction $transaction |
|
483 | + * @throws EE_Error |
|
484 | + * @throws InvalidArgumentException |
|
485 | + * @throws InvalidDataTypeException |
|
486 | + * @throws InvalidInterfaceException |
|
487 | + * @throws ReflectionException |
|
488 | + */ |
|
489 | + public static function payment_reminder(EE_Transaction $transaction) |
|
490 | + { |
|
491 | + self::_load_controller(); |
|
492 | + $data = [$transaction, null]; |
|
493 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data); |
|
494 | + } |
|
495 | + |
|
496 | + |
|
497 | + /** |
|
498 | + * Any messages triggers for after successful gateway payments should go in here. |
|
499 | + * |
|
500 | + * @param EE_Transaction $transaction object |
|
501 | + * @param EE_Payment|null $payment object |
|
502 | + * @return void |
|
503 | + * @throws EE_Error |
|
504 | + * @throws InvalidArgumentException |
|
505 | + * @throws ReflectionException |
|
506 | + * @throws InvalidDataTypeException |
|
507 | + * @throws InvalidInterfaceException |
|
508 | + */ |
|
509 | + public static function payment(EE_Transaction $transaction, EE_Payment $payment = null) |
|
510 | + { |
|
511 | + // if there's no payment object, then we cannot do a payment type message! |
|
512 | + if (! $payment instanceof EE_Payment) { |
|
513 | + return; |
|
514 | + } |
|
515 | + self::_load_controller(); |
|
516 | + $data = [$transaction, $payment]; |
|
517 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
518 | + $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
519 | + // if payment amount is less than 0 then switch to payment_refund message type. |
|
520 | + $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
521 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
522 | + } |
|
523 | + |
|
524 | + |
|
525 | + /** |
|
526 | + * @param EE_Transaction $transaction |
|
527 | + * @throws EE_Error |
|
528 | + * @throws InvalidArgumentException |
|
529 | + * @throws InvalidDataTypeException |
|
530 | + * @throws InvalidInterfaceException |
|
531 | + * @throws ReflectionException |
|
532 | + */ |
|
533 | + public static function cancelled_registration(EE_Transaction $transaction) |
|
534 | + { |
|
535 | + self::_load_controller(); |
|
536 | + $data = [$transaction, null]; |
|
537 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data); |
|
538 | + } |
|
539 | + |
|
540 | + |
|
541 | + /** |
|
542 | + * Trigger for Registration messages |
|
543 | + * Note that what registration message type is sent depends on what the reg status is for the registrations on the |
|
544 | + * incoming transaction. |
|
545 | + * |
|
546 | + * @param EE_Registration $registration |
|
547 | + * @param array $extra_details |
|
548 | + * @return void |
|
549 | + * @throws EE_Error |
|
550 | + * @throws InvalidArgumentException |
|
551 | + * @throws InvalidDataTypeException |
|
552 | + * @throws InvalidInterfaceException |
|
553 | + * @throws ReflectionException |
|
554 | + * @throws EntityNotFoundException |
|
555 | + */ |
|
556 | + public static function maybe_registration(EE_Registration $registration, $extra_details = []) |
|
557 | + { |
|
558 | + |
|
559 | + if (! self::_verify_registration_notification_send($registration, $extra_details)) { |
|
560 | + // no messages please |
|
561 | + return; |
|
562 | + } |
|
563 | + |
|
564 | + // get all non-trashed registrations so we make sure we send messages for the right status. |
|
565 | + $all_registrations = $registration->transaction()->registrations( |
|
566 | + [ |
|
567 | + ['REG_deleted' => false], |
|
568 | + 'order_by' => [ |
|
569 | + 'Event.EVT_name' => 'ASC', |
|
570 | + 'Attendee.ATT_lname' => 'ASC', |
|
571 | + 'Attendee.ATT_fname' => 'ASC', |
|
572 | + ], |
|
573 | + ] |
|
574 | + ); |
|
575 | + // cached array of statuses so we only trigger messages once per status. |
|
576 | + $statuses_sent = []; |
|
577 | + self::_load_controller(); |
|
578 | + $mtgs = []; |
|
579 | + |
|
580 | + // loop through registrations and trigger messages once per status. |
|
581 | + foreach ($all_registrations as $reg) { |
|
582 | + // already triggered? |
|
583 | + if (in_array($reg->status_ID(), $statuses_sent)) { |
|
584 | + continue; |
|
585 | + } |
|
586 | + |
|
587 | + $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID()); |
|
588 | + $mtgs = array_merge( |
|
589 | + $mtgs, |
|
590 | + self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
591 | + $message_type, |
|
592 | + [$registration->transaction(), null, $reg->status_ID()] |
|
593 | + ) |
|
594 | + ); |
|
595 | + $statuses_sent[] = $reg->status_ID(); |
|
596 | + } |
|
597 | + |
|
598 | + if (count($statuses_sent) > 1) { |
|
599 | + $mtgs = array_merge( |
|
600 | + $mtgs, |
|
601 | + self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers( |
|
602 | + 'registration_summary', |
|
603 | + [$registration->transaction(), null] |
|
604 | + ) |
|
605 | + ); |
|
606 | + } |
|
607 | + |
|
608 | + // batch queue and initiate request |
|
609 | + self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs); |
|
610 | + self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
611 | + } |
|
612 | + |
|
613 | + |
|
614 | + /** |
|
615 | + * This is a helper method used to very whether a registration notification should be sent or |
|
616 | + * not. Prevents duplicate notifications going out for registration context notifications. |
|
617 | + * |
|
618 | + * @param EE_Registration $registration [description] |
|
619 | + * @param array $extra_details [description] |
|
620 | + * @return bool true = send away, false = nope halt the presses. |
|
621 | + */ |
|
622 | + protected static function _verify_registration_notification_send( |
|
623 | + EE_Registration $registration, |
|
624 | + $extra_details = [] |
|
625 | + ) { |
|
626 | + $request = self::getRequest(); |
|
627 | + if ( |
|
628 | + ! $request->getRequestParam('non_primary_reg_notification', 0, 'int') |
|
629 | + && ! $registration->is_primary_registrant() |
|
630 | + ) { |
|
631 | + return false; |
|
632 | + } |
|
633 | + // first we check if we're in admin and not doing front ajax |
|
634 | + if ( |
|
635 | + ($request->isAdmin() || $request->isAdminAjax()) |
|
636 | + && ! $request->isFrontAjax() |
|
637 | + ) { |
|
638 | + $status_change = $request->getRequestParam('txn_reg_status_change', [], 'int', true); |
|
639 | + // make sure appropriate admin params are set for sending messages |
|
640 | + if ( |
|
641 | + ! isset($status_change['send_notifications']) |
|
642 | + || (isset($status_change['send_notifications']) && ! $status_change['send_notifications']) |
|
643 | + ) { |
|
644 | + // no messages sent please. |
|
645 | + return false; |
|
646 | + } |
|
647 | + } else { |
|
648 | + // frontend request (either regular or via AJAX) |
|
649 | + // TXN is NOT finalized ? |
|
650 | + if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) { |
|
651 | + return false; |
|
652 | + } |
|
653 | + // return visit but nothing changed ??? |
|
654 | + if ( |
|
655 | + isset($extra_details['revisit'], $extra_details['status_updates']) |
|
656 | + && $extra_details['revisit'] |
|
657 | + && ! $extra_details['status_updates'] |
|
658 | + ) { |
|
659 | + return false; |
|
660 | + } |
|
661 | + // NOT sending messages && reg status is something other than "Not-Approved" |
|
662 | + if ( |
|
663 | + ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false) |
|
664 | + && $registration->status_ID() !== EEM_Registration::status_id_not_approved |
|
665 | + ) { |
|
666 | + return false; |
|
667 | + } |
|
668 | + } |
|
669 | + // release the kraken |
|
670 | + return true; |
|
671 | + } |
|
672 | + |
|
673 | + |
|
674 | + /** |
|
675 | + * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that |
|
676 | + * status id. |
|
677 | + * |
|
678 | + * @param string $reg_status |
|
679 | + * @return array |
|
680 | + * @throws EE_Error |
|
681 | + * @throws InvalidArgumentException |
|
682 | + * @throws ReflectionException |
|
683 | + * @throws InvalidDataTypeException |
|
684 | + * @throws InvalidInterfaceException |
|
685 | + * @deprecated 4.9.0 Use EEH_MSG_Template::reg_status_to_message_type_array() |
|
686 | + * or EEH_MSG_Template::convert_reg_status_to_message_type |
|
687 | + */ |
|
688 | + protected static function _get_reg_status_array($reg_status = '') |
|
689 | + { |
|
690 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
691 | + return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
692 | + ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status) |
|
693 | + : EEH_MSG_Template::reg_status_to_message_type_array(); |
|
694 | + } |
|
695 | + |
|
696 | + |
|
697 | + /** |
|
698 | + * Simply returns the payment message type for the given payment status. |
|
699 | + * |
|
700 | + * @param string $payment_status The payment status being matched. |
|
701 | + * @return bool|string The payment message type slug matching the status or false if no match. |
|
702 | + * @throws EE_Error |
|
703 | + * @throws InvalidArgumentException |
|
704 | + * @throws ReflectionException |
|
705 | + * @throws InvalidDataTypeException |
|
706 | + * @throws InvalidInterfaceException |
|
707 | + * @deprecated 4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array |
|
708 | + * or EEH_MSG_Template::convert_payment_status_to_message_type |
|
709 | + */ |
|
710 | + protected static function _get_payment_message_type($payment_status) |
|
711 | + { |
|
712 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
713 | + return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
714 | + ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status) |
|
715 | + : false; |
|
716 | + } |
|
717 | + |
|
718 | + |
|
719 | + /** |
|
720 | + * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
721 | + * |
|
722 | + * @access public |
|
723 | + * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages |
|
724 | + * @return bool success/fail |
|
725 | + * @throws EE_Error |
|
726 | + * @throws InvalidArgumentException |
|
727 | + * @throws InvalidDataTypeException |
|
728 | + * @throws InvalidInterfaceException |
|
729 | + * @throws ReflectionException |
|
730 | + */ |
|
731 | + public static function process_resend(array $req_data = []) |
|
732 | + { |
|
733 | + self::_load_controller(); |
|
734 | + $request = self::getRequest(); |
|
735 | + // if $msgID in this request then skip to the new resend_message |
|
736 | + if ($request->getRequestParam('MSG_ID')) { |
|
737 | + return self::resend_message(); |
|
738 | + } |
|
739 | + |
|
740 | + // make sure any incoming request data is set on the request so that it gets picked up later. |
|
741 | + foreach ((array) $req_data as $request_key => $request_value) { |
|
742 | + if (! $request->requestParamIsSet($request_key)) { |
|
743 | + $request->setRequestParam($request_key, $request_value); |
|
744 | + } |
|
745 | + } |
|
746 | + |
|
747 | + if ( |
|
748 | + ! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request() |
|
749 | + ) { |
|
750 | + return false; |
|
751 | + } |
|
752 | + |
|
753 | + try { |
|
754 | + self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send); |
|
755 | + self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority(); |
|
756 | + } catch (EE_Error $e) { |
|
757 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
758 | + return false; |
|
759 | + } |
|
760 | + EE_Error::add_success( |
|
761 | + esc_html__('Messages have been successfully queued for generation and sending.', 'event_espresso') |
|
762 | + ); |
|
763 | + return true; // everything got queued. |
|
764 | + } |
|
765 | + |
|
766 | + |
|
767 | + /** |
|
768 | + * Message triggers for a resending already sent message(s) (via EE_Message list table) |
|
769 | + * |
|
770 | + * @return bool |
|
771 | + * @throws EE_Error |
|
772 | + * @throws InvalidArgumentException |
|
773 | + * @throws InvalidDataTypeException |
|
774 | + * @throws InvalidInterfaceException |
|
775 | + * @throws ReflectionException |
|
776 | + */ |
|
777 | + public static function resend_message() |
|
778 | + { |
|
779 | + self::_load_controller(); |
|
780 | + |
|
781 | + $msgID = self::getRequest()->getRequestParam('MSG_ID', 0, 'int'); |
|
782 | + if (! $msgID) { |
|
783 | + EE_Error::add_error( |
|
784 | + esc_html__( |
|
785 | + 'Something went wrong because there is no "MSG_ID" value in the request', |
|
786 | + 'event_espresso' |
|
787 | + ), |
|
788 | + __FILE__, |
|
789 | + __FUNCTION__, |
|
790 | + __LINE__ |
|
791 | + ); |
|
792 | + return false; |
|
793 | + } |
|
794 | + |
|
795 | + self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array) $msgID); |
|
796 | + |
|
797 | + // setup success message. |
|
798 | + $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
799 | + EE_Error::add_success( |
|
800 | + sprintf( |
|
801 | + _n( |
|
802 | + 'There was %d message queued for resending.', |
|
803 | + 'There were %d messages queued for resending.', |
|
804 | + $count_ready_for_resend, |
|
805 | + 'event_espresso' |
|
806 | + ), |
|
807 | + $count_ready_for_resend |
|
808 | + ) |
|
809 | + ); |
|
810 | + return true; |
|
811 | + } |
|
812 | + |
|
813 | + |
|
814 | + /** |
|
815 | + * Message triggers for manual payment applied by admin |
|
816 | + * |
|
817 | + * @param EE_Payment $payment EE_payment object |
|
818 | + * @return bool success/fail |
|
819 | + * @throws EE_Error |
|
820 | + * @throws InvalidArgumentException |
|
821 | + * @throws ReflectionException |
|
822 | + * @throws InvalidDataTypeException |
|
823 | + * @throws InvalidInterfaceException |
|
824 | + */ |
|
825 | + public static function process_admin_payment(EE_Payment $payment) |
|
826 | + { |
|
827 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
828 | + // we need to get the transaction object |
|
829 | + $transaction = $payment->transaction(); |
|
830 | + if ($transaction instanceof EE_Transaction) { |
|
831 | + $data = [$transaction, $payment]; |
|
832 | + $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID()); |
|
833 | + |
|
834 | + // if payment amount is less than 0 then switch to payment_refund message type. |
|
835 | + $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type; |
|
836 | + |
|
837 | + // if payment_refund is selected, but the status is NOT accepted. Then change message type to false so NO message notification goes out. |
|
838 | + $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved |
|
839 | + ? false : $message_type; |
|
840 | + |
|
841 | + self::_load_controller(); |
|
842 | + |
|
843 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data); |
|
844 | + |
|
845 | + // get count of queued for generation |
|
846 | + $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue( |
|
847 | + [ |
|
848 | + EEM_Message::status_incomplete, |
|
849 | + EEM_Message::status_idle, |
|
850 | + ] |
|
851 | + ); |
|
852 | + |
|
853 | + if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) { |
|
854 | + add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
855 | + return true; |
|
856 | + } else { |
|
857 | + $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue( |
|
858 | + EEM_Message::instance()->stati_indicating_failed_sending() |
|
859 | + ); |
|
860 | + /** |
|
861 | + * Verify that there are actually errors. If not then we return a success message because the queue might have been emptied due to successful |
|
862 | + * IMMEDIATE generation. |
|
863 | + */ |
|
864 | + if ($count_failed > 0) { |
|
865 | + EE_Error::add_error( |
|
866 | + sprintf( |
|
867 | + _n( |
|
868 | + 'The payment notification generation failed.', |
|
869 | + '%d payment notifications failed being sent.', |
|
870 | + $count_failed, |
|
871 | + 'event_espresso' |
|
872 | + ), |
|
873 | + $count_failed |
|
874 | + ), |
|
875 | + __FILE__, |
|
876 | + __FUNCTION__, |
|
877 | + __LINE__ |
|
878 | + ); |
|
879 | + |
|
880 | + return false; |
|
881 | + } else { |
|
882 | + add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true'); |
|
883 | + return true; |
|
884 | + } |
|
885 | + } |
|
886 | + } else { |
|
887 | + EE_Error::add_error( |
|
888 | + 'Unable to generate the payment notification because the given value for the transaction is invalid.', |
|
889 | + 'event_espresso' |
|
890 | + ); |
|
891 | + return false; |
|
892 | + } |
|
893 | + } |
|
894 | + |
|
895 | + |
|
896 | + /** |
|
897 | + * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger |
|
898 | + * |
|
899 | + * @param EE_Registration[] $registrations an array of EE_Registration objects |
|
900 | + * @param int $grp_id a specific message template group id. |
|
901 | + * @return void |
|
902 | + * @throws EE_Error |
|
903 | + * @throws InvalidArgumentException |
|
904 | + * @throws InvalidDataTypeException |
|
905 | + * @throws InvalidInterfaceException |
|
906 | + * @throws ReflectionException |
|
907 | + * @since 4.3.0 |
|
908 | + */ |
|
909 | + public static function send_newsletter_message($registrations, $grp_id) |
|
910 | + { |
|
911 | + // make sure mtp is id and set it in the request later messages setup. |
|
912 | + self::getRequest()->setRequestParam('GRP_ID', (int) $grp_id); |
|
913 | + self::_load_controller(); |
|
914 | + self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations); |
|
915 | + } |
|
916 | + |
|
917 | + |
|
918 | + /** |
|
919 | + * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url |
|
920 | + * |
|
921 | + * @param string $registration_message_trigger_url |
|
922 | + * @param EE_Registration $registration |
|
923 | + * @param string $messenger |
|
924 | + * @param string $message_type |
|
925 | + * @return string |
|
926 | + * @throws EE_Error |
|
927 | + * @throws InvalidArgumentException |
|
928 | + * @throws InvalidDataTypeException |
|
929 | + * @throws InvalidInterfaceException |
|
930 | + * @since 4.3.0 |
|
931 | + */ |
|
932 | + public static function registration_message_trigger_url( |
|
933 | + $registration_message_trigger_url, |
|
934 | + EE_Registration $registration, |
|
935 | + $messenger = 'html', |
|
936 | + $message_type = 'invoice' |
|
937 | + ) { |
|
938 | + // whitelist $messenger |
|
939 | + switch ($messenger) { |
|
940 | + case 'pdf': |
|
941 | + $sending_messenger = 'pdf'; |
|
942 | + $generating_messenger = 'html'; |
|
943 | + break; |
|
944 | + case 'html': |
|
945 | + default: |
|
946 | + $sending_messenger = 'html'; |
|
947 | + $generating_messenger = 'html'; |
|
948 | + break; |
|
949 | + } |
|
950 | + // whitelist $message_type |
|
951 | + switch ($message_type) { |
|
952 | + case 'receipt': |
|
953 | + $message_type = 'receipt'; |
|
954 | + break; |
|
955 | + case 'invoice': |
|
956 | + default: |
|
957 | + $message_type = 'invoice'; |
|
958 | + break; |
|
959 | + } |
|
960 | + // verify that both the messenger AND the message type are active |
|
961 | + if ( |
|
962 | + EEH_MSG_Template::is_messenger_active($sending_messenger) |
|
963 | + && EEH_MSG_Template::is_mt_active($message_type) |
|
964 | + ) { |
|
965 | + // need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?) |
|
966 | + $template_query_params = [ |
|
967 | + 'MTP_is_active' => true, |
|
968 | + 'MTP_messenger' => $generating_messenger, |
|
969 | + 'MTP_message_type' => $message_type, |
|
970 | + 'Event.EVT_ID' => $registration->event_ID(), |
|
971 | + ]; |
|
972 | + // get the message template group. |
|
973 | + $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]); |
|
974 | + // if we don't have an EE_Message_Template_Group then return |
|
975 | + if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
976 | + // remove EVT_ID from query params so that global templates get picked up |
|
977 | + unset($template_query_params['Event.EVT_ID']); |
|
978 | + // get global template as the fallback |
|
979 | + $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]); |
|
980 | + } |
|
981 | + // if we don't have an EE_Message_Template_Group then return |
|
982 | + if (! $msg_template_group instanceof EE_Message_Template_Group) { |
|
983 | + return ''; |
|
984 | + } |
|
985 | + // generate the URL |
|
986 | + $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger( |
|
987 | + $sending_messenger, |
|
988 | + $generating_messenger, |
|
989 | + 'purchaser', |
|
990 | + $message_type, |
|
991 | + $registration, |
|
992 | + $msg_template_group->ID(), |
|
993 | + $registration->transaction_ID() |
|
994 | + ); |
|
995 | + } |
|
996 | + return $registration_message_trigger_url; |
|
997 | + } |
|
998 | + |
|
999 | + |
|
1000 | + /** |
|
1001 | + * Use to generate and return a message preview! |
|
1002 | + * |
|
1003 | + * @param string $type This should correspond with a valid message type |
|
1004 | + * @param string $context This should correspond with a valid context for the message type |
|
1005 | + * @param string $messenger This should correspond with a valid messenger. |
|
1006 | + * @param bool $send true we will do a test send using the messenger delivery, false we just do a regular |
|
1007 | + * preview |
|
1008 | + * @return bool|string The body of the message or if send is requested, sends. |
|
1009 | + * @throws EE_Error |
|
1010 | + * @throws InvalidArgumentException |
|
1011 | + * @throws InvalidDataTypeException |
|
1012 | + * @throws InvalidInterfaceException |
|
1013 | + * @throws ReflectionException |
|
1014 | + */ |
|
1015 | + public static function preview_message($type, $context, $messenger, $send = false) |
|
1016 | + { |
|
1017 | + self::_load_controller(); |
|
1018 | + $message_to_generate = new EE_Message_To_Generate( |
|
1019 | + $messenger, |
|
1020 | + $type, |
|
1021 | + [], |
|
1022 | + $context, |
|
1023 | + true |
|
1024 | + ); |
|
1025 | + $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($message_to_generate, $send); |
|
1026 | + |
|
1027 | + if ($generated_preview_queue instanceof EE_Messages_Queue) { |
|
1028 | + // loop through all content for the preview and remove any persisted records. |
|
1029 | + $content = ''; |
|
1030 | + foreach ($generated_preview_queue->get_message_repository() as $message) { |
|
1031 | + $content = $message->content(); |
|
1032 | + if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) { |
|
1033 | + $message->delete(); |
|
1034 | + } |
|
1035 | + } |
|
1036 | + return $content; |
|
1037 | + } |
|
1038 | + return $generated_preview_queue; |
|
1039 | + } |
|
1040 | + |
|
1041 | + |
|
1042 | + /** |
|
1043 | + * This is a method that allows for sending a message using a messenger matching the string given and the provided |
|
1044 | + * EE_Message_Queue object. The EE_Message_Queue object is used to create a single aggregate EE_Message via the |
|
1045 | + * content found in the EE_Message objects in the queue. |
|
1046 | + * |
|
1047 | + * @param string $messenger a string matching a valid active messenger in the system |
|
1048 | + * @param string $message_type Although it seems contrary to the name of the method, a message |
|
1049 | + * type name is still required to send along the message type to the |
|
1050 | + * messenger because this is used for determining what specific |
|
1051 | + * variations might be loaded for the generated message. |
|
1052 | + * @param EE_Messages_Queue $queue |
|
1053 | + * @param string $custom_subject Can be used to set what the custom subject string will be on the |
|
1054 | + * aggregate EE_Message object. |
|
1055 | + * @return bool success or fail. |
|
1056 | + * @throws EE_Error |
|
1057 | + * @throws InvalidArgumentException |
|
1058 | + * @throws ReflectionException |
|
1059 | + * @throws InvalidDataTypeException |
|
1060 | + * @throws InvalidInterfaceException |
|
1061 | + * @since 4.9.0 |
|
1062 | + */ |
|
1063 | + public static function send_message_with_messenger_only( |
|
1064 | + $messenger, |
|
1065 | + $message_type, |
|
1066 | + EE_Messages_Queue $queue, |
|
1067 | + $custom_subject = '' |
|
1068 | + ) { |
|
1069 | + self::_load_controller(); |
|
1070 | + /** @type EE_Message_To_Generate_From_Queue $message_to_generate */ |
|
1071 | + $message_to_generate = EE_Registry::instance()->load_lib( |
|
1072 | + 'Message_To_Generate_From_Queue', |
|
1073 | + [ |
|
1074 | + $messenger, |
|
1075 | + $message_type, |
|
1076 | + $queue, |
|
1077 | + $custom_subject, |
|
1078 | + ] |
|
1079 | + ); |
|
1080 | + return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate); |
|
1081 | + } |
|
1082 | + |
|
1083 | + |
|
1084 | + /** |
|
1085 | + * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation) |
|
1086 | + * |
|
1087 | + * @param array $message_ids An array of message ids |
|
1088 | + * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated |
|
1089 | + * messages. |
|
1090 | + * @throws EE_Error |
|
1091 | + * @throws InvalidArgumentException |
|
1092 | + * @throws InvalidDataTypeException |
|
1093 | + * @throws InvalidInterfaceException |
|
1094 | + * @throws ReflectionException |
|
1095 | + * @since 4.9.0 |
|
1096 | + */ |
|
1097 | + public static function generate_now($message_ids) |
|
1098 | + { |
|
1099 | + self::_load_controller(); |
|
1100 | + $messages = EEM_Message::instance()->get_all( |
|
1101 | + [ |
|
1102 | + 0 => [ |
|
1103 | + 'MSG_ID' => ['IN', $message_ids], |
|
1104 | + 'STS_ID' => EEM_Message::status_incomplete, |
|
1105 | + ], |
|
1106 | + ] |
|
1107 | + ); |
|
1108 | + $generated_queue = false; |
|
1109 | + if ($messages) { |
|
1110 | + $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages); |
|
1111 | + } |
|
1112 | + |
|
1113 | + if (! $generated_queue instanceof EE_Messages_Queue) { |
|
1114 | + EE_Error::add_error( |
|
1115 | + esc_html__( |
|
1116 | + 'The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.', |
|
1117 | + 'event_espresso' |
|
1118 | + ), |
|
1119 | + __FILE__, |
|
1120 | + __FUNCTION__, |
|
1121 | + __LINE__ |
|
1122 | + ); |
|
1123 | + } |
|
1124 | + return $generated_queue; |
|
1125 | + } |
|
1126 | + |
|
1127 | + |
|
1128 | + /** |
|
1129 | + * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or, |
|
1130 | + * EEM_Message::status_idle |
|
1131 | + * |
|
1132 | + * @param $message_ids |
|
1133 | + * @return bool|EE_Messages_Queue false if no messages sent. |
|
1134 | + * @throws EE_Error |
|
1135 | + * @throws InvalidArgumentException |
|
1136 | + * @throws InvalidDataTypeException |
|
1137 | + * @throws InvalidInterfaceException |
|
1138 | + * @throws ReflectionException |
|
1139 | + * @since 4.9.0 |
|
1140 | + */ |
|
1141 | + public static function send_now($message_ids) |
|
1142 | + { |
|
1143 | + self::_load_controller(); |
|
1144 | + $messages = EEM_Message::instance()->get_all( |
|
1145 | + [ |
|
1146 | + 0 => [ |
|
1147 | + 'MSG_ID' => ['IN', $message_ids], |
|
1148 | + 'STS_ID' => [ |
|
1149 | + 'IN', |
|
1150 | + [EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry], |
|
1151 | + ], |
|
1152 | + ], |
|
1153 | + ] |
|
1154 | + ); |
|
1155 | + $sent_queue = false; |
|
1156 | + if ($messages) { |
|
1157 | + $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages); |
|
1158 | + } |
|
1159 | + |
|
1160 | + if (! $sent_queue instanceof EE_Messages_Queue) { |
|
1161 | + EE_Error::add_error( |
|
1162 | + esc_html__( |
|
1163 | + 'The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.', |
|
1164 | + 'event_espresso' |
|
1165 | + ), |
|
1166 | + __FILE__, |
|
1167 | + __FUNCTION__, |
|
1168 | + __LINE__ |
|
1169 | + ); |
|
1170 | + } else { |
|
1171 | + // can count how many sent by using the messages in the queue |
|
1172 | + $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent()); |
|
1173 | + if ($sent_count > 0) { |
|
1174 | + EE_Error::add_success( |
|
1175 | + sprintf( |
|
1176 | + _n( |
|
1177 | + 'There was %d message successfully sent.', |
|
1178 | + 'There were %d messages successfully sent.', |
|
1179 | + $sent_count, |
|
1180 | + 'event_espresso' |
|
1181 | + ), |
|
1182 | + $sent_count |
|
1183 | + ) |
|
1184 | + ); |
|
1185 | + } else { |
|
1186 | + EE_Error::overwrite_errors(); |
|
1187 | + EE_Error::add_error( |
|
1188 | + esc_html__( |
|
1189 | + 'No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error. |
|
1190 | 1190 | If there was an error, you can look at the messages in the message activity list table for any error messages.', |
1191 | - 'event_espresso' |
|
1192 | - ), |
|
1193 | - __FILE__, |
|
1194 | - __FUNCTION__, |
|
1195 | - __LINE__ |
|
1196 | - ); |
|
1197 | - } |
|
1198 | - } |
|
1199 | - return $sent_queue; |
|
1200 | - } |
|
1201 | - |
|
1202 | - |
|
1203 | - /** |
|
1204 | - * Generate and send immediately from the given $message_ids |
|
1205 | - * |
|
1206 | - * @param array $message_ids EE_Message entity ids. |
|
1207 | - * @throws EE_Error |
|
1208 | - * @throws InvalidArgumentException |
|
1209 | - * @throws InvalidDataTypeException |
|
1210 | - * @throws InvalidInterfaceException |
|
1211 | - * @throws ReflectionException |
|
1212 | - */ |
|
1213 | - public static function generate_and_send_now(array $message_ids) |
|
1214 | - { |
|
1215 | - $generated_queue = self::generate_now($message_ids); |
|
1216 | - // now let's just trigger sending immediately from this queue. |
|
1217 | - $messages_sent = $generated_queue instanceof EE_Messages_Queue |
|
1218 | - ? $generated_queue->execute() |
|
1219 | - : 0; |
|
1220 | - if ($messages_sent) { |
|
1221 | - EE_Error::add_success( |
|
1222 | - esc_html( |
|
1223 | - sprintf( |
|
1224 | - _n( |
|
1225 | - 'There was %d message successfully generated and sent.', |
|
1226 | - 'There were %d messages successfully generated and sent.', |
|
1227 | - $messages_sent, |
|
1228 | - 'event_espresso' |
|
1229 | - ), |
|
1230 | - $messages_sent |
|
1231 | - ) |
|
1232 | - ) |
|
1233 | - ); |
|
1234 | - // errors would be added via the generate_now method. |
|
1235 | - } |
|
1236 | - } |
|
1237 | - |
|
1238 | - |
|
1239 | - /** |
|
1240 | - * This will queue the incoming message ids for resending. |
|
1241 | - * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued. |
|
1242 | - * |
|
1243 | - * @param array $message_ids An array of EE_Message IDs |
|
1244 | - * @return bool true means messages were successfully queued for resending, false means none were queued for |
|
1245 | - * resending. |
|
1246 | - * @throws EE_Error |
|
1247 | - * @throws InvalidArgumentException |
|
1248 | - * @throws InvalidDataTypeException |
|
1249 | - * @throws InvalidInterfaceException |
|
1250 | - * @throws ReflectionException |
|
1251 | - * @since 4.9.0 |
|
1252 | - */ |
|
1253 | - public static function queue_for_resending($message_ids) |
|
1254 | - { |
|
1255 | - self::_load_controller(); |
|
1256 | - self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids); |
|
1257 | - |
|
1258 | - // get queue and count |
|
1259 | - $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
1260 | - |
|
1261 | - if ( |
|
1262 | - $queue_count > 0 |
|
1263 | - ) { |
|
1264 | - EE_Error::add_success( |
|
1265 | - sprintf( |
|
1266 | - _n( |
|
1267 | - '%d message successfully queued for resending.', |
|
1268 | - '%d messages successfully queued for resending.', |
|
1269 | - $queue_count, |
|
1270 | - 'event_espresso' |
|
1271 | - ), |
|
1272 | - $queue_count |
|
1273 | - ) |
|
1274 | - ); |
|
1275 | - /** |
|
1276 | - * @see filter usage in EE_Messages_Queue::initiate_request_by_priority |
|
1277 | - */ |
|
1278 | - } elseif ( |
|
1279 | - apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true) |
|
1280 | - || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
1281 | - ) { |
|
1282 | - $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent); |
|
1283 | - if ($queue_count > 0) { |
|
1284 | - EE_Error::add_success( |
|
1285 | - sprintf( |
|
1286 | - _n( |
|
1287 | - '%d message successfully sent.', |
|
1288 | - '%d messages successfully sent.', |
|
1289 | - $queue_count, |
|
1290 | - 'event_espresso' |
|
1291 | - ), |
|
1292 | - $queue_count |
|
1293 | - ) |
|
1294 | - ); |
|
1295 | - } else { |
|
1296 | - EE_Error::add_error( |
|
1297 | - esc_html__( |
|
1298 | - 'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1299 | - 'event_espresso' |
|
1300 | - ), |
|
1301 | - __FILE__, |
|
1302 | - __FUNCTION__, |
|
1303 | - __LINE__ |
|
1304 | - ); |
|
1305 | - } |
|
1306 | - } else { |
|
1307 | - EE_Error::add_error( |
|
1308 | - esc_html__( |
|
1309 | - 'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1310 | - 'event_espresso' |
|
1311 | - ), |
|
1312 | - __FILE__, |
|
1313 | - __FUNCTION__, |
|
1314 | - __LINE__ |
|
1315 | - ); |
|
1316 | - } |
|
1317 | - return (bool) $queue_count; |
|
1318 | - } |
|
1319 | - |
|
1320 | - |
|
1321 | - /** |
|
1322 | - * debug |
|
1323 | - * |
|
1324 | - * @param string $class |
|
1325 | - * @param string $func |
|
1326 | - * @param string $line |
|
1327 | - * @param \EE_Transaction $transaction |
|
1328 | - * @param array $info |
|
1329 | - * @param bool $display_request |
|
1330 | - * @throws EE_Error |
|
1331 | - * @throws \EventEspresso\core\exceptions\InvalidSessionDataException |
|
1332 | - */ |
|
1333 | - protected static function log( |
|
1334 | - $class = '', |
|
1335 | - $func = '', |
|
1336 | - $line = '', |
|
1337 | - EE_Transaction $transaction = null, |
|
1338 | - $info = [], |
|
1339 | - $display_request = false |
|
1340 | - ) { |
|
1341 | - if (defined('EE_DEBUG') && EE_DEBUG) { |
|
1342 | - if ($transaction instanceof EE_Transaction) { |
|
1343 | - // don't serialize objects |
|
1344 | - $info = EEH_Debug_Tools::strip_objects($info); |
|
1345 | - $info['TXN_status'] = $transaction->status_ID(); |
|
1346 | - $info['TXN_reg_steps'] = $transaction->reg_steps(); |
|
1347 | - if ($transaction->ID()) { |
|
1348 | - $index = 'EE_Transaction: ' . $transaction->ID(); |
|
1349 | - EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index); |
|
1350 | - } |
|
1351 | - } |
|
1352 | - } |
|
1353 | - } |
|
1354 | - |
|
1355 | - |
|
1356 | - /** |
|
1357 | - * Resets all the static properties in this class when called. |
|
1358 | - */ |
|
1359 | - public static function reset() |
|
1360 | - { |
|
1361 | - self::$_EEMSG = null; |
|
1362 | - self::$_message_resource_manager = null; |
|
1363 | - self::$_MSG_PROCESSOR = null; |
|
1364 | - self::$_MSG_PATHS = null; |
|
1365 | - self::$_TMP_PACKS = []; |
|
1366 | - } |
|
1191 | + 'event_espresso' |
|
1192 | + ), |
|
1193 | + __FILE__, |
|
1194 | + __FUNCTION__, |
|
1195 | + __LINE__ |
|
1196 | + ); |
|
1197 | + } |
|
1198 | + } |
|
1199 | + return $sent_queue; |
|
1200 | + } |
|
1201 | + |
|
1202 | + |
|
1203 | + /** |
|
1204 | + * Generate and send immediately from the given $message_ids |
|
1205 | + * |
|
1206 | + * @param array $message_ids EE_Message entity ids. |
|
1207 | + * @throws EE_Error |
|
1208 | + * @throws InvalidArgumentException |
|
1209 | + * @throws InvalidDataTypeException |
|
1210 | + * @throws InvalidInterfaceException |
|
1211 | + * @throws ReflectionException |
|
1212 | + */ |
|
1213 | + public static function generate_and_send_now(array $message_ids) |
|
1214 | + { |
|
1215 | + $generated_queue = self::generate_now($message_ids); |
|
1216 | + // now let's just trigger sending immediately from this queue. |
|
1217 | + $messages_sent = $generated_queue instanceof EE_Messages_Queue |
|
1218 | + ? $generated_queue->execute() |
|
1219 | + : 0; |
|
1220 | + if ($messages_sent) { |
|
1221 | + EE_Error::add_success( |
|
1222 | + esc_html( |
|
1223 | + sprintf( |
|
1224 | + _n( |
|
1225 | + 'There was %d message successfully generated and sent.', |
|
1226 | + 'There were %d messages successfully generated and sent.', |
|
1227 | + $messages_sent, |
|
1228 | + 'event_espresso' |
|
1229 | + ), |
|
1230 | + $messages_sent |
|
1231 | + ) |
|
1232 | + ) |
|
1233 | + ); |
|
1234 | + // errors would be added via the generate_now method. |
|
1235 | + } |
|
1236 | + } |
|
1237 | + |
|
1238 | + |
|
1239 | + /** |
|
1240 | + * This will queue the incoming message ids for resending. |
|
1241 | + * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued. |
|
1242 | + * |
|
1243 | + * @param array $message_ids An array of EE_Message IDs |
|
1244 | + * @return bool true means messages were successfully queued for resending, false means none were queued for |
|
1245 | + * resending. |
|
1246 | + * @throws EE_Error |
|
1247 | + * @throws InvalidArgumentException |
|
1248 | + * @throws InvalidDataTypeException |
|
1249 | + * @throws InvalidInterfaceException |
|
1250 | + * @throws ReflectionException |
|
1251 | + * @since 4.9.0 |
|
1252 | + */ |
|
1253 | + public static function queue_for_resending($message_ids) |
|
1254 | + { |
|
1255 | + self::_load_controller(); |
|
1256 | + self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids); |
|
1257 | + |
|
1258 | + // get queue and count |
|
1259 | + $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend); |
|
1260 | + |
|
1261 | + if ( |
|
1262 | + $queue_count > 0 |
|
1263 | + ) { |
|
1264 | + EE_Error::add_success( |
|
1265 | + sprintf( |
|
1266 | + _n( |
|
1267 | + '%d message successfully queued for resending.', |
|
1268 | + '%d messages successfully queued for resending.', |
|
1269 | + $queue_count, |
|
1270 | + 'event_espresso' |
|
1271 | + ), |
|
1272 | + $queue_count |
|
1273 | + ) |
|
1274 | + ); |
|
1275 | + /** |
|
1276 | + * @see filter usage in EE_Messages_Queue::initiate_request_by_priority |
|
1277 | + */ |
|
1278 | + } elseif ( |
|
1279 | + apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true) |
|
1280 | + || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request |
|
1281 | + ) { |
|
1282 | + $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent); |
|
1283 | + if ($queue_count > 0) { |
|
1284 | + EE_Error::add_success( |
|
1285 | + sprintf( |
|
1286 | + _n( |
|
1287 | + '%d message successfully sent.', |
|
1288 | + '%d messages successfully sent.', |
|
1289 | + $queue_count, |
|
1290 | + 'event_espresso' |
|
1291 | + ), |
|
1292 | + $queue_count |
|
1293 | + ) |
|
1294 | + ); |
|
1295 | + } else { |
|
1296 | + EE_Error::add_error( |
|
1297 | + esc_html__( |
|
1298 | + 'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1299 | + 'event_espresso' |
|
1300 | + ), |
|
1301 | + __FILE__, |
|
1302 | + __FUNCTION__, |
|
1303 | + __LINE__ |
|
1304 | + ); |
|
1305 | + } |
|
1306 | + } else { |
|
1307 | + EE_Error::add_error( |
|
1308 | + esc_html__( |
|
1309 | + 'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.', |
|
1310 | + 'event_espresso' |
|
1311 | + ), |
|
1312 | + __FILE__, |
|
1313 | + __FUNCTION__, |
|
1314 | + __LINE__ |
|
1315 | + ); |
|
1316 | + } |
|
1317 | + return (bool) $queue_count; |
|
1318 | + } |
|
1319 | + |
|
1320 | + |
|
1321 | + /** |
|
1322 | + * debug |
|
1323 | + * |
|
1324 | + * @param string $class |
|
1325 | + * @param string $func |
|
1326 | + * @param string $line |
|
1327 | + * @param \EE_Transaction $transaction |
|
1328 | + * @param array $info |
|
1329 | + * @param bool $display_request |
|
1330 | + * @throws EE_Error |
|
1331 | + * @throws \EventEspresso\core\exceptions\InvalidSessionDataException |
|
1332 | + */ |
|
1333 | + protected static function log( |
|
1334 | + $class = '', |
|
1335 | + $func = '', |
|
1336 | + $line = '', |
|
1337 | + EE_Transaction $transaction = null, |
|
1338 | + $info = [], |
|
1339 | + $display_request = false |
|
1340 | + ) { |
|
1341 | + if (defined('EE_DEBUG') && EE_DEBUG) { |
|
1342 | + if ($transaction instanceof EE_Transaction) { |
|
1343 | + // don't serialize objects |
|
1344 | + $info = EEH_Debug_Tools::strip_objects($info); |
|
1345 | + $info['TXN_status'] = $transaction->status_ID(); |
|
1346 | + $info['TXN_reg_steps'] = $transaction->reg_steps(); |
|
1347 | + if ($transaction->ID()) { |
|
1348 | + $index = 'EE_Transaction: ' . $transaction->ID(); |
|
1349 | + EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index); |
|
1350 | + } |
|
1351 | + } |
|
1352 | + } |
|
1353 | + } |
|
1354 | + |
|
1355 | + |
|
1356 | + /** |
|
1357 | + * Resets all the static properties in this class when called. |
|
1358 | + */ |
|
1359 | + public static function reset() |
|
1360 | + { |
|
1361 | + self::$_EEMSG = null; |
|
1362 | + self::$_message_resource_manager = null; |
|
1363 | + self::$_MSG_PROCESSOR = null; |
|
1364 | + self::$_MSG_PATHS = null; |
|
1365 | + self::$_TMP_PACKS = []; |
|
1366 | + } |
|
1367 | 1367 | } |
@@ -76,7 +76,7 @@ discard block |
||
76 | 76 | protected function _setup_metaboxes() |
77 | 77 | { |
78 | 78 | // if we were going to add our own metaboxes we'd use the below. |
79 | - $this->_metaboxes = [ |
|
79 | + $this->_metaboxes = [ |
|
80 | 80 | 0 => [ |
81 | 81 | 'page_route' => ['edit', 'create_new'], |
82 | 82 | 'func' => [$this, 'pricing_metabox'], |
@@ -119,7 +119,7 @@ discard block |
||
119 | 119 | $this->_date_format_strings['date'] = $this->_date_format_strings['date'] ?? ''; |
120 | 120 | $this->_date_format_strings['time'] = $this->_date_format_strings['time'] ?? ''; |
121 | 121 | |
122 | - $this->_date_time_format = $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time']; |
|
122 | + $this->_date_time_format = $this->_date_format_strings['date'].' '.$this->_date_format_strings['time']; |
|
123 | 123 | } |
124 | 124 | |
125 | 125 | |
@@ -143,7 +143,7 @@ discard block |
||
143 | 143 | ); |
144 | 144 | $msg .= '</p><ul>'; |
145 | 145 | foreach ($format_validation as $error) { |
146 | - $msg .= '<li>' . $error . '</li>'; |
|
146 | + $msg .= '<li>'.$error.'</li>'; |
|
147 | 147 | } |
148 | 148 | $msg .= '</ul><p>'; |
149 | 149 | $msg .= sprintf( |
@@ -172,11 +172,11 @@ discard block |
||
172 | 172 | $this->_scripts_styles = [ |
173 | 173 | 'registers' => [ |
174 | 174 | 'ee-tickets-datetimes-css' => [ |
175 | - 'url' => PRICING_ASSETS_URL . 'event-tickets-datetimes.css', |
|
175 | + 'url' => PRICING_ASSETS_URL.'event-tickets-datetimes.css', |
|
176 | 176 | 'type' => 'css', |
177 | 177 | ], |
178 | 178 | 'ee-dtt-ticket-metabox' => [ |
179 | - 'url' => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js', |
|
179 | + 'url' => PRICING_ASSETS_URL.'ee-datetime-ticket-metabox.js', |
|
180 | 180 | 'depends' => ['ee-datepicker', 'ee-dialog', 'underscore'], |
181 | 181 | ], |
182 | 182 | ], |
@@ -201,11 +201,11 @@ discard block |
||
201 | 201 | ), |
202 | 202 | 'cancel_button' => ' |
203 | 203 | <button class="button--secondary ee-modal-cancel"> |
204 | - ' . esc_html__('Cancel', 'event_espresso') . ' |
|
204 | + ' . esc_html__('Cancel', 'event_espresso').' |
|
205 | 205 | </button>', |
206 | 206 | 'close_button' => ' |
207 | 207 | <button class="button--secondary ee-modal-cancel"> |
208 | - ' . esc_html__('Close', 'event_espresso') . ' |
|
208 | + ' . esc_html__('Close', 'event_espresso').' |
|
209 | 209 | </button>', |
210 | 210 | 'single_warning_from_tkt' => esc_html__( |
211 | 211 | 'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.', |
@@ -217,7 +217,7 @@ discard block |
||
217 | 217 | ), |
218 | 218 | 'dismiss_button' => ' |
219 | 219 | <button class="button--secondary ee-modal-cancel"> |
220 | - ' . esc_html__('Dismiss', 'event_espresso') . ' |
|
220 | + ' . esc_html__('Dismiss', 'event_espresso').' |
|
221 | 221 | </button>', |
222 | 222 | ], |
223 | 223 | 'DTT_ERROR_MSG' => [ |
@@ -225,7 +225,7 @@ discard block |
||
225 | 225 | 'dismiss_button' => ' |
226 | 226 | <div class="save-cancel-button-container"> |
227 | 227 | <button class="button--secondary ee-modal-cancel"> |
228 | - ' . esc_html__('Dismiss', 'event_espresso') . ' |
|
228 | + ' . esc_html__('Dismiss', 'event_espresso').' |
|
229 | 229 | </button> |
230 | 230 | </div>', |
231 | 231 | ], |
@@ -311,8 +311,8 @@ discard block |
||
311 | 311 | } |
312 | 312 | foreach ($data['edit_event_datetimes'] as $row => $datetime_data) { |
313 | 313 | // trim all values to ensure any excess whitespace is removed. |
314 | - $datetime_data = array_map( |
|
315 | - function ($datetime_data) { |
|
314 | + $datetime_data = array_map( |
|
315 | + function($datetime_data) { |
|
316 | 316 | return is_array($datetime_data) ? $datetime_data : trim($datetime_data); |
317 | 317 | }, |
318 | 318 | $datetime_data |
@@ -323,7 +323,7 @@ discard block |
||
323 | 323 | ? $datetime_data['DTT_EVT_end'] |
324 | 324 | : $datetime_data['DTT_EVT_start']; |
325 | 325 | |
326 | - $datetime_values = [ |
|
326 | + $datetime_values = [ |
|
327 | 327 | 'DTT_ID' => ! empty($datetime_data['DTT_ID']) |
328 | 328 | ? $datetime_data['DTT_ID'] |
329 | 329 | : null, |
@@ -345,7 +345,7 @@ discard block |
||
345 | 345 | |
346 | 346 | // if we have an id then let's get existing object first and then set the new values. |
347 | 347 | // Otherwise we instantiate a new object for save. |
348 | - if (! empty($datetime_data['DTT_ID'])) { |
|
348 | + if ( ! empty($datetime_data['DTT_ID'])) { |
|
349 | 349 | $datetime = EEM_Datetime::instance($timezone)->get_one_by_ID($datetime_data['DTT_ID']); |
350 | 350 | // set date and time format according to what is set in this class. |
351 | 351 | $datetime->set_date_format($this->_date_format_strings['date']); |
@@ -358,7 +358,7 @@ discard block |
||
358 | 358 | // after the add_relation_to() the autosave replaces it. |
359 | 359 | // We need to do this so we dont' TRASH the parent DTT. |
360 | 360 | // (save the ID for both key and value to avoid duplications) |
361 | - $saved_datetime_ids[ $datetime->ID() ] = $datetime->ID(); |
|
361 | + $saved_datetime_ids[$datetime->ID()] = $datetime->ID(); |
|
362 | 362 | } else { |
363 | 363 | $datetime = EE_Datetime::new_instance( |
364 | 364 | $datetime_values, |
@@ -389,8 +389,8 @@ discard block |
||
389 | 389 | // because it is possible there was a new one created for the autosave. |
390 | 390 | // (save the ID for both key and value to avoid duplications) |
391 | 391 | $DTT_ID = $datetime->ID(); |
392 | - $saved_datetime_ids[ $DTT_ID ] = $DTT_ID; |
|
393 | - $saved_datetime_objs[ $row ] = $datetime; |
|
392 | + $saved_datetime_ids[$DTT_ID] = $DTT_ID; |
|
393 | + $saved_datetime_objs[$row] = $datetime; |
|
394 | 394 | // @todo if ANY of these updates fail then we want the appropriate global error message. |
395 | 395 | } |
396 | 396 | $event->save(); |
@@ -454,13 +454,13 @@ discard block |
||
454 | 454 | $update_prices = $create_new_TKT = false; |
455 | 455 | // figure out what datetimes were added to the ticket |
456 | 456 | // and what datetimes were removed from the ticket in the session. |
457 | - $starting_ticket_datetime_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]); |
|
458 | - $ticket_datetime_rows = explode(',', $data['ticket_datetime_rows'][ $row ]); |
|
457 | + $starting_ticket_datetime_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]); |
|
458 | + $ticket_datetime_rows = explode(',', $data['ticket_datetime_rows'][$row]); |
|
459 | 459 | $datetimes_added = array_diff($ticket_datetime_rows, $starting_ticket_datetime_rows); |
460 | 460 | $datetimes_removed = array_diff($starting_ticket_datetime_rows, $ticket_datetime_rows); |
461 | 461 | // trim inputs to ensure any excess whitespace is removed. |
462 | 462 | $ticket_data = array_map( |
463 | - function ($ticket_data) { |
|
463 | + function($ticket_data) { |
|
464 | 464 | return is_array($ticket_data) ? $ticket_data : trim($ticket_data); |
465 | 465 | }, |
466 | 466 | $ticket_data |
@@ -480,8 +480,8 @@ discard block |
||
480 | 480 | ? $base_price |
481 | 481 | : $ticket_price; |
482 | 482 | $base_price_id = $ticket_data['TKT_base_price_ID'] ?? 0; |
483 | - $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ]) |
|
484 | - ? $data['edit_prices'][ $row ] |
|
483 | + $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row]) |
|
484 | + ? $data['edit_prices'][$row] |
|
485 | 485 | : []; |
486 | 486 | $now = null; |
487 | 487 | if (empty($ticket_data['TKT_start_date'])) { |
@@ -493,7 +493,7 @@ discard block |
||
493 | 493 | /** |
494 | 494 | * set the TKT_end_date to the first datetime attached to the ticket. |
495 | 495 | */ |
496 | - $first_datetime = $saved_datetimes[ reset($ticket_datetime_rows) ]; |
|
496 | + $first_datetime = $saved_datetimes[reset($ticket_datetime_rows)]; |
|
497 | 497 | $ticket_data['TKT_end_date'] = $first_datetime->start_date_and_time($this->_date_time_format); |
498 | 498 | } |
499 | 499 | $TKT_values = [ |
@@ -592,7 +592,7 @@ discard block |
||
592 | 592 | if ($ticket instanceof EE_Ticket) { |
593 | 593 | // make sure ticket has an ID of setting relations won't work |
594 | 594 | $ticket->save(); |
595 | - $ticket = $this->_update_ticket_datetimes( |
|
595 | + $ticket = $this->_update_ticket_datetimes( |
|
596 | 596 | $ticket, |
597 | 597 | $saved_datetimes, |
598 | 598 | $datetimes_added, |
@@ -626,7 +626,7 @@ discard block |
||
626 | 626 | // need to make sue that the TKT_price is accurate after saving the prices. |
627 | 627 | $ticket->ensure_TKT_Price_correct(); |
628 | 628 | // handle CREATING a default ticket from the incoming ticket but ONLY if this isn't an autosave. |
629 | - if (! defined('DOING_AUTOSAVE') && ! empty($ticket_data['TKT_is_default_selector'])) { |
|
629 | + if ( ! defined('DOING_AUTOSAVE') && ! empty($ticket_data['TKT_is_default_selector'])) { |
|
630 | 630 | $new_default = clone $ticket; |
631 | 631 | $new_default->set('TKT_ID', 0); |
632 | 632 | $new_default->set('TKT_is_default', 1); |
@@ -670,7 +670,7 @@ discard block |
||
670 | 670 | // save new TKT |
671 | 671 | $new_ticket->save(); |
672 | 672 | // add new ticket to array |
673 | - $saved_tickets[ $new_ticket->ID() ] = $new_ticket; |
|
673 | + $saved_tickets[$new_ticket->ID()] = $new_ticket; |
|
674 | 674 | do_action( |
675 | 675 | 'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket', |
676 | 676 | $new_ticket, |
@@ -680,7 +680,7 @@ discard block |
||
680 | 680 | ); |
681 | 681 | } else { |
682 | 682 | // add ticket to saved tickets |
683 | - $saved_tickets[ $ticket->ID() ] = $ticket; |
|
683 | + $saved_tickets[$ticket->ID()] = $ticket; |
|
684 | 684 | do_action( |
685 | 685 | 'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket', |
686 | 686 | $ticket, |
@@ -748,20 +748,20 @@ discard block |
||
748 | 748 | // to start we have to add the ticket to all the datetimes its supposed to be with, |
749 | 749 | // and removing the ticket from datetimes it got removed from. |
750 | 750 | // first let's add datetimes |
751 | - if (! empty($added_datetimes) && is_array($added_datetimes)) { |
|
751 | + if ( ! empty($added_datetimes) && is_array($added_datetimes)) { |
|
752 | 752 | foreach ($added_datetimes as $row_id) { |
753 | - if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
754 | - $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
753 | + if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) { |
|
754 | + $ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime'); |
|
755 | 755 | } |
756 | 756 | } |
757 | 757 | } |
758 | 758 | // then remove datetimes |
759 | - if (! empty($removed_datetimes) && is_array($removed_datetimes)) { |
|
759 | + if ( ! empty($removed_datetimes) && is_array($removed_datetimes)) { |
|
760 | 760 | foreach ($removed_datetimes as $row_id) { |
761 | 761 | // its entirely possible that a datetime got deleted (instead of just removed from relationship. |
762 | 762 | // So make sure we skip over this if the datetime isn't in the $saved_datetimes array) |
763 | - if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
764 | - $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
763 | + if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) { |
|
764 | + $ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime'); |
|
765 | 765 | } |
766 | 766 | } |
767 | 767 | } |
@@ -872,7 +872,7 @@ discard block |
||
872 | 872 | ]; |
873 | 873 | } |
874 | 874 | // possibly need to save ticket |
875 | - if (! $ticket->ID()) { |
|
875 | + if ( ! $ticket->ID()) { |
|
876 | 876 | $ticket->save(); |
877 | 877 | } |
878 | 878 | foreach ($prices as $row => $prc) { |
@@ -906,17 +906,17 @@ discard block |
||
906 | 906 | } |
907 | 907 | } |
908 | 908 | $price->save(); |
909 | - $updated_prices[ $price->ID() ] = $price; |
|
909 | + $updated_prices[$price->ID()] = $price; |
|
910 | 910 | $ticket->_add_relation_to($price, 'Price'); |
911 | 911 | } |
912 | 912 | // now let's remove any prices that got removed from the ticket |
913 | - if (! empty($current_prices_on_ticket)) { |
|
913 | + if ( ! empty($current_prices_on_ticket)) { |
|
914 | 914 | $current = array_keys($current_prices_on_ticket); |
915 | 915 | $updated = array_keys($updated_prices); |
916 | 916 | $prices_to_remove = array_diff($current, $updated); |
917 | - if (! empty($prices_to_remove)) { |
|
917 | + if ( ! empty($prices_to_remove)) { |
|
918 | 918 | foreach ($prices_to_remove as $prc_id) { |
919 | - $p = $current_prices_on_ticket[ $prc_id ]; |
|
919 | + $p = $current_prices_on_ticket[$prc_id]; |
|
920 | 920 | $ticket->_remove_relation_to($p, 'Price'); |
921 | 921 | // delete permanently the price |
922 | 922 | $p->delete_permanently(); |
@@ -965,7 +965,7 @@ discard block |
||
965 | 965 | 'ticket_rows' => '', |
966 | 966 | 'ee_collapsible_status' => ' ee-collapsible-open', |
967 | 967 | ]; |
968 | - $timezone = $event instanceof EE_Event ? $event->timezone_string() : null; |
|
968 | + $timezone = $event instanceof EE_Event ? $event->timezone_string() : null; |
|
969 | 969 | do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
970 | 970 | |
971 | 971 | /** |
@@ -1029,18 +1029,18 @@ discard block |
||
1029 | 1029 | $TKT_ID = $ticket->get('TKT_ID'); |
1030 | 1030 | $ticket_row = $ticket->get('TKT_row'); |
1031 | 1031 | // we only want unique tickets in our final display!! |
1032 | - if (! in_array($TKT_ID, $existing_ticket_ids, true)) { |
|
1032 | + if ( ! in_array($TKT_ID, $existing_ticket_ids, true)) { |
|
1033 | 1033 | $existing_ticket_ids[] = $TKT_ID; |
1034 | 1034 | $all_tickets[] = $ticket; |
1035 | 1035 | } |
1036 | 1036 | // temporary cache of this ticket info for this datetime for later processing of datetime rows. |
1037 | - $datetime_tickets[ $DTT_ID ][] = $ticket_row; |
|
1037 | + $datetime_tickets[$DTT_ID][] = $ticket_row; |
|
1038 | 1038 | // temporary cache of this datetime info for this ticket for later processing of ticket rows. |
1039 | 1039 | if ( |
1040 | - ! isset($ticket_datetimes[ $TKT_ID ]) |
|
1041 | - || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true) |
|
1040 | + ! isset($ticket_datetimes[$TKT_ID]) |
|
1041 | + || ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true) |
|
1042 | 1042 | ) { |
1043 | - $ticket_datetimes[ $TKT_ID ][] = $datetime_row; |
|
1043 | + $ticket_datetimes[$TKT_ID][] = $datetime_row; |
|
1044 | 1044 | } |
1045 | 1045 | } |
1046 | 1046 | $datetime_row++; |
@@ -1051,7 +1051,7 @@ discard block |
||
1051 | 1051 | // sort $all_tickets by order |
1052 | 1052 | usort( |
1053 | 1053 | $all_tickets, |
1054 | - function (EE_Ticket $a, EE_Ticket $b) { |
|
1054 | + function(EE_Ticket $a, EE_Ticket $b) { |
|
1055 | 1055 | $a_order = (int) $a->get('TKT_order'); |
1056 | 1056 | $b_order = (int) $b->get('TKT_order'); |
1057 | 1057 | if ($a_order === $b_order) { |
@@ -1099,7 +1099,7 @@ discard block |
||
1099 | 1099 | ); |
1100 | 1100 | |
1101 | 1101 | EEH_Template::display_template( |
1102 | - PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php', |
|
1102 | + PRICING_TEMPLATE_PATH.'event_tickets_metabox_main.template.php', |
|
1103 | 1103 | $main_template_args |
1104 | 1104 | ); |
1105 | 1105 | } |
@@ -1126,7 +1126,7 @@ discard block |
||
1126 | 1126 | array $all_datetimes = [] |
1127 | 1127 | ): string { |
1128 | 1128 | return EEH_Template::display_template( |
1129 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php', |
|
1129 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_row_wrapper.template.php', |
|
1130 | 1130 | [ |
1131 | 1131 | 'dtt_edit_row' => $this->_get_dtt_edit_row( |
1132 | 1132 | $datetime_row, |
@@ -1215,7 +1215,7 @@ discard block |
||
1215 | 1215 | $this->_is_creating_event |
1216 | 1216 | ); |
1217 | 1217 | return EEH_Template::display_template( |
1218 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php', |
|
1218 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_edit_row.template.php', |
|
1219 | 1219 | $template_args, |
1220 | 1220 | true |
1221 | 1221 | ); |
@@ -1255,7 +1255,7 @@ discard block |
||
1255 | 1255 | 'DTT_ID' => $default ? '' : $datetime->ID(), |
1256 | 1256 | ]; |
1257 | 1257 | // need to setup the list items (but only if this isn't a default skeleton setup) |
1258 | - if (! $default) { |
|
1258 | + if ( ! $default) { |
|
1259 | 1259 | $ticket_row = 1; |
1260 | 1260 | foreach ($all_tickets as $ticket) { |
1261 | 1261 | $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
@@ -1281,7 +1281,7 @@ discard block |
||
1281 | 1281 | $this->_is_creating_event |
1282 | 1282 | ); |
1283 | 1283 | return EEH_Template::display_template( |
1284 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php', |
|
1284 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_attached_tickets_row.template.php', |
|
1285 | 1285 | $template_args, |
1286 | 1286 | true |
1287 | 1287 | ); |
@@ -1307,8 +1307,8 @@ discard block |
||
1307 | 1307 | array $datetime_tickets = [], |
1308 | 1308 | bool $default = false |
1309 | 1309 | ): string { |
1310 | - $datetime_tickets = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ]) |
|
1311 | - ? $datetime_tickets[ $datetime->ID() ] |
|
1310 | + $datetime_tickets = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()]) |
|
1311 | + ? $datetime_tickets[$datetime->ID()] |
|
1312 | 1312 | : []; |
1313 | 1313 | $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0; |
1314 | 1314 | $no_ticket = $default && empty($ticket); |
@@ -1329,8 +1329,8 @@ discard block |
||
1329 | 1329 | ? 'TKTNAME' |
1330 | 1330 | : $ticket->get('TKT_name'), |
1331 | 1331 | 'tkt_status_class' => $no_ticket || $this->_is_creating_event |
1332 | - ? ' tkt-status-' . EE_Ticket::onsale |
|
1333 | - : ' tkt-status-' . $ticket->ticket_status(), |
|
1332 | + ? ' tkt-status-'.EE_Ticket::onsale |
|
1333 | + : ' tkt-status-'.$ticket->ticket_status(), |
|
1334 | 1334 | ]; |
1335 | 1335 | // filter template args |
1336 | 1336 | $template_args = apply_filters( |
@@ -1345,7 +1345,7 @@ discard block |
||
1345 | 1345 | $this->_is_creating_event |
1346 | 1346 | ); |
1347 | 1347 | return EEH_Template::display_template( |
1348 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php', |
|
1348 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_dtt_tickets_list.template.php', |
|
1349 | 1349 | $template_args, |
1350 | 1350 | true |
1351 | 1351 | ); |
@@ -1401,19 +1401,19 @@ discard block |
||
1401 | 1401 | // (otherwise there won't be any new relationships created for tickets based off of the default ticket). |
1402 | 1402 | // This will future proof in case there is ever any behaviour change between what the primary_key defaults to. |
1403 | 1403 | $default_datetime = $default || ($ticket instanceof EE_Ticket && $ticket->is_default()); |
1404 | - $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
1405 | - ? $ticket_datetimes[ $ticket->ID() ] |
|
1404 | + $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()]) |
|
1405 | + ? $ticket_datetimes[$ticket->ID()] |
|
1406 | 1406 | : []; |
1407 | 1407 | $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal(); |
1408 | 1408 | $base_price = $default ? null : $ticket->base_price(); |
1409 | 1409 | $count_price_mods = EEM_Price::instance()->get_all_default_prices(true); |
1410 | 1410 | // breaking out complicated condition for ticket_status |
1411 | 1411 | if ($default) { |
1412 | - $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale; |
|
1412 | + $ticket_status_class = ' tkt-status-'.EE_Ticket::onsale; |
|
1413 | 1413 | } else { |
1414 | 1414 | $ticket_status_class = $ticket->is_default() |
1415 | - ? ' tkt-status-' . EE_Ticket::onsale |
|
1416 | - : ' tkt-status-' . $ticket->ticket_status(); |
|
1415 | + ? ' tkt-status-'.EE_Ticket::onsale |
|
1416 | + : ' tkt-status-'.$ticket->ticket_status(); |
|
1417 | 1417 | } |
1418 | 1418 | // breaking out complicated condition for TKT_taxable |
1419 | 1419 | if ($default) { |
@@ -1438,7 +1438,7 @@ discard block |
||
1438 | 1438 | $TKT_min = ''; |
1439 | 1439 | } |
1440 | 1440 | } |
1441 | - $template_args = [ |
|
1441 | + $template_args = [ |
|
1442 | 1442 | 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
1443 | 1443 | 'TKT_order' => $default ? 'TICKETNUM' : $ticket_row, |
1444 | 1444 | // on initial page load this will always be the correct order. |
@@ -1505,7 +1505,7 @@ discard block |
||
1505 | 1505 | : 'display:none;', |
1506 | 1506 | 'show_price_mod_button' => count($prices) > 1 |
1507 | 1507 | || ($default && $count_price_mods > 0) |
1508 | - || (! $default && $ticket->deleted()) |
|
1508 | + || ( ! $default && $ticket->deleted()) |
|
1509 | 1509 | ? 'display:none;' |
1510 | 1510 | : '', |
1511 | 1511 | 'total_price_rows' => count($prices) > 1 ? count($prices) : 1, |
@@ -1546,11 +1546,11 @@ discard block |
||
1546 | 1546 | // handle rows that should NOT be empty |
1547 | 1547 | if (empty($template_args['TKT_start_date'])) { |
1548 | 1548 | // if empty then the start date will be now. |
1549 | - $template_args['TKT_start_date'] = date( |
|
1549 | + $template_args['TKT_start_date'] = date( |
|
1550 | 1550 | $this->_date_time_format, |
1551 | 1551 | current_time('timestamp') |
1552 | 1552 | ); |
1553 | - $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1553 | + $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale; |
|
1554 | 1554 | } |
1555 | 1555 | if (empty($template_args['TKT_end_date'])) { |
1556 | 1556 | // get the earliest datetime (if present); |
@@ -1560,7 +1560,7 @@ discard block |
||
1560 | 1560 | ['order_by' => ['DTT_EVT_start' => 'ASC']] |
1561 | 1561 | ) |
1562 | 1562 | : null; |
1563 | - if (! empty($earliest_datetime)) { |
|
1563 | + if ( ! empty($earliest_datetime)) { |
|
1564 | 1564 | $template_args['TKT_end_date'] = $earliest_datetime->get_datetime( |
1565 | 1565 | 'DTT_EVT_start', |
1566 | 1566 | $this->_date_time_format |
@@ -1579,10 +1579,10 @@ discard block |
||
1579 | 1579 | ) |
1580 | 1580 | ); |
1581 | 1581 | } |
1582 | - $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1582 | + $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale; |
|
1583 | 1583 | } |
1584 | 1584 | // generate ticket_datetime items |
1585 | - if (! $default) { |
|
1585 | + if ( ! $default) { |
|
1586 | 1586 | $datetime_row = 1; |
1587 | 1587 | foreach ($all_datetimes as $datetime) { |
1588 | 1588 | $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item( |
@@ -1598,7 +1598,7 @@ discard block |
||
1598 | 1598 | } |
1599 | 1599 | $price_row = 1; |
1600 | 1600 | foreach ($prices as $price) { |
1601 | - if (! $price instanceof EE_Price) { |
|
1601 | + if ( ! $price instanceof EE_Price) { |
|
1602 | 1602 | continue; |
1603 | 1603 | } |
1604 | 1604 | if ($price->is_base_price()) { |
@@ -1633,7 +1633,7 @@ discard block |
||
1633 | 1633 | $this->_is_creating_event |
1634 | 1634 | ); |
1635 | 1635 | return EEH_Template::display_template( |
1636 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php', |
|
1636 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_row.template.php', |
|
1637 | 1637 | $template_args, |
1638 | 1638 | true |
1639 | 1639 | ); |
@@ -1673,8 +1673,8 @@ discard block |
||
1673 | 1673 | $ticket, |
1674 | 1674 | $this->_is_creating_event |
1675 | 1675 | ); |
1676 | - $tax_rows .= EEH_Template::display_template( |
|
1677 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php', |
|
1676 | + $tax_rows .= EEH_Template::display_template( |
|
1677 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_tax_row.template.php', |
|
1678 | 1678 | $template_args, |
1679 | 1679 | true |
1680 | 1680 | ); |
@@ -1794,7 +1794,7 @@ discard block |
||
1794 | 1794 | $this->_is_creating_event |
1795 | 1795 | ); |
1796 | 1796 | return EEH_Template::display_template( |
1797 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php', |
|
1797 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_price_row.template.php', |
|
1798 | 1798 | $template_args, |
1799 | 1799 | true |
1800 | 1800 | ); |
@@ -1874,7 +1874,7 @@ discard block |
||
1874 | 1874 | $this->_is_creating_event |
1875 | 1875 | ); |
1876 | 1876 | return EEH_Template::display_template( |
1877 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php', |
|
1877 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_type_base.template.php', |
|
1878 | 1878 | $template_args, |
1879 | 1879 | true |
1880 | 1880 | ); |
@@ -1904,7 +1904,7 @@ discard block |
||
1904 | 1904 | ): string { |
1905 | 1905 | $select_name = $default && ! $price instanceof EE_Price |
1906 | 1906 | ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]' |
1907 | - : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]'; |
|
1907 | + : 'edit_prices['.esc_attr($ticket_row).']['.esc_attr($price_row).'][PRT_ID]'; |
|
1908 | 1908 | /** @var EEM_Price_Type $price_type_model */ |
1909 | 1909 | $price_type_model = EE_Registry::instance()->load_model('Price_Type'); |
1910 | 1910 | $price_types = $price_type_model->get_all( |
@@ -1924,25 +1924,25 @@ discard block |
||
1924 | 1924 | $price_option_spans = ''; |
1925 | 1925 | // setup price types for selector |
1926 | 1926 | foreach ($price_types as $price_type) { |
1927 | - if (! $price_type instanceof EE_Price_Type) { |
|
1927 | + if ( ! $price_type instanceof EE_Price_Type) { |
|
1928 | 1928 | continue; |
1929 | 1929 | } |
1930 | - $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name'); |
|
1930 | + $all_price_types[$price_type->ID()] = $price_type->get('PRT_name'); |
|
1931 | 1931 | // while we're in the loop let's setup the option spans used by js |
1932 | - $span_args = [ |
|
1932 | + $span_args = [ |
|
1933 | 1933 | 'PRT_ID' => $price_type->ID(), |
1934 | 1934 | 'PRT_operator' => $price_type->is_discount() ? '-' : '+', |
1935 | 1935 | 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0, |
1936 | 1936 | ]; |
1937 | 1937 | $price_option_spans .= EEH_Template::display_template( |
1938 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php', |
|
1938 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_option_span.template.php', |
|
1939 | 1939 | $span_args, |
1940 | 1940 | true |
1941 | 1941 | ); |
1942 | 1942 | } |
1943 | 1943 | |
1944 | 1944 | $select_name = $disabled |
1945 | - ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]' |
|
1945 | + ? 'archive_price['.$ticket_row.']['.$price_row.'][PRT_ID]' |
|
1946 | 1946 | : $select_name; |
1947 | 1947 | |
1948 | 1948 | $select_input = new EE_Select_Input( |
@@ -1970,7 +1970,7 @@ discard block |
||
1970 | 1970 | 'price_selected_is_percent' => $price_selected_is_percent, |
1971 | 1971 | 'disabled' => $disabled, |
1972 | 1972 | ]; |
1973 | - $template_args = apply_filters( |
|
1973 | + $template_args = apply_filters( |
|
1974 | 1974 | 'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args', |
1975 | 1975 | $template_args, |
1976 | 1976 | $ticket_row, |
@@ -1981,7 +1981,7 @@ discard block |
||
1981 | 1981 | $this->_is_creating_event |
1982 | 1982 | ); |
1983 | 1983 | return EEH_Template::display_template( |
1984 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php', |
|
1984 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_modifier_selector.template.php', |
|
1985 | 1985 | $template_args, |
1986 | 1986 | true |
1987 | 1987 | ); |
@@ -2008,8 +2008,8 @@ discard block |
||
2008 | 2008 | array $ticket_datetimes = [], |
2009 | 2009 | bool $default = false |
2010 | 2010 | ): string { |
2011 | - $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
2012 | - ? $ticket_datetimes[ $ticket->ID() ] |
|
2011 | + $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()]) |
|
2012 | + ? $ticket_datetimes[$ticket->ID()] |
|
2013 | 2013 | : []; |
2014 | 2014 | $template_args = [ |
2015 | 2015 | 'dtt_row' => $default && ! $datetime instanceof EE_Datetime |
@@ -2029,7 +2029,7 @@ discard block |
||
2029 | 2029 | : $datetime->get_dtt_display_name(true), |
2030 | 2030 | 'tkt_status_class' => '', |
2031 | 2031 | ]; |
2032 | - $template_args = apply_filters( |
|
2032 | + $template_args = apply_filters( |
|
2033 | 2033 | 'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args', |
2034 | 2034 | $template_args, |
2035 | 2035 | $datetime_row, |
@@ -2041,7 +2041,7 @@ discard block |
||
2041 | 2041 | $this->_is_creating_event |
2042 | 2042 | ); |
2043 | 2043 | return EEH_Template::display_template( |
2044 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php', |
|
2044 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_datetimes_list_item.template.php', |
|
2045 | 2045 | $template_args, |
2046 | 2046 | true |
2047 | 2047 | ); |
@@ -2119,7 +2119,7 @@ discard block |
||
2119 | 2119 | true |
2120 | 2120 | ), |
2121 | 2121 | ]; |
2122 | - $ticket_row = 1; |
|
2122 | + $ticket_row = 1; |
|
2123 | 2123 | foreach ($all_tickets as $ticket) { |
2124 | 2124 | $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
2125 | 2125 | 'DTTNUM', |
@@ -2148,11 +2148,11 @@ discard block |
||
2148 | 2148 | $default_prices = $price_model->get_all_default_prices(); |
2149 | 2149 | $price_row = 1; |
2150 | 2150 | foreach ($default_prices as $price) { |
2151 | - if (! $price instanceof EE_Price) { |
|
2151 | + if ( ! $price instanceof EE_Price) { |
|
2152 | 2152 | continue; |
2153 | 2153 | } |
2154 | 2154 | if ($price->is_base_price()) { |
2155 | - $template_args['default_base_price_amount'] = $price->get_pretty( |
|
2155 | + $template_args['default_base_price_amount'] = $price->get_pretty( |
|
2156 | 2156 | 'PRC_amount', |
2157 | 2157 | 'localized_float' |
2158 | 2158 | ); |
@@ -2184,7 +2184,7 @@ discard block |
||
2184 | 2184 | $this->_is_creating_event |
2185 | 2185 | ); |
2186 | 2186 | return EEH_Template::display_template( |
2187 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php', |
|
2187 | + PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_js_structure.template.php', |
|
2188 | 2188 | $template_args, |
2189 | 2189 | true |
2190 | 2190 | ); |
@@ -15,2178 +15,2178 @@ |
||
15 | 15 | */ |
16 | 16 | class espresso_events_Pricing_Hooks extends EE_Admin_Hooks |
17 | 17 | { |
18 | - /** |
|
19 | - * This property is just used to hold the status of whether an event is currently being |
|
20 | - * created (true) or edited (false) |
|
21 | - * |
|
22 | - * @access protected |
|
23 | - * @var bool |
|
24 | - */ |
|
25 | - protected $_is_creating_event; |
|
26 | - |
|
27 | - /** |
|
28 | - * Used to contain the format strings for date and time that will be used for php date and |
|
29 | - * time. |
|
30 | - * Is set in the _set_hooks_properties() method. |
|
31 | - * |
|
32 | - * @var array |
|
33 | - */ |
|
34 | - protected $_date_format_strings; |
|
35 | - |
|
36 | - /** |
|
37 | - * @var string $_date_time_format |
|
38 | - */ |
|
39 | - protected $_date_time_format; |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * @throws InvalidArgumentException |
|
44 | - * @throws InvalidInterfaceException |
|
45 | - * @throws InvalidDataTypeException |
|
46 | - */ |
|
47 | - protected function _set_hooks_properties() |
|
48 | - { |
|
49 | - $this->_name = 'pricing'; |
|
50 | - // capability check |
|
51 | - if ( |
|
52 | - $this->_adminpage_obj->adminConfig()->useAdvancedEditor() |
|
53 | - || ! EE_Registry::instance()->CAP->current_user_can( |
|
54 | - 'ee_read_default_prices', |
|
55 | - 'advanced_ticket_datetime_metabox' |
|
56 | - ) |
|
57 | - ) { |
|
58 | - $this->_metaboxes = []; |
|
59 | - $this->_scripts_styles = []; |
|
60 | - return; |
|
61 | - } |
|
62 | - $this->_setup_metaboxes(); |
|
63 | - $this->_set_date_time_formats(); |
|
64 | - $this->_validate_format_strings(); |
|
65 | - $this->_set_scripts_styles(); |
|
66 | - add_filter( |
|
67 | - 'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks', |
|
68 | - [$this, 'caf_updates'] |
|
69 | - ); |
|
70 | - } |
|
71 | - |
|
72 | - |
|
73 | - /** |
|
74 | - * @return void |
|
75 | - */ |
|
76 | - protected function _setup_metaboxes() |
|
77 | - { |
|
78 | - // if we were going to add our own metaboxes we'd use the below. |
|
79 | - $this->_metaboxes = [ |
|
80 | - 0 => [ |
|
81 | - 'page_route' => ['edit', 'create_new'], |
|
82 | - 'func' => [$this, 'pricing_metabox'], |
|
83 | - 'label' => esc_html__('Event Tickets & Datetimes', 'event_espresso'), |
|
84 | - 'priority' => 'high', |
|
85 | - 'context' => 'normal', |
|
86 | - ], |
|
87 | - ]; |
|
88 | - $this->_remove_metaboxes = [ |
|
89 | - 0 => [ |
|
90 | - 'page_route' => ['edit', 'create_new'], |
|
91 | - 'id' => 'espresso_event_editor_tickets', |
|
92 | - 'context' => 'normal', |
|
93 | - ], |
|
94 | - ]; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * @return void |
|
100 | - */ |
|
101 | - protected function _set_date_time_formats() |
|
102 | - { |
|
103 | - /** |
|
104 | - * Format strings for date and time. Defaults are existing behaviour from 4.1. |
|
105 | - * Note, that if you return null as the value for 'date', and 'time' in the array, then |
|
106 | - * EE will automatically use the set wp_options, 'date_format', and 'time_format'. |
|
107 | - * |
|
108 | - * @since 4.6.7 |
|
109 | - * @var array Expected an array returned with 'date' and 'time' keys. |
|
110 | - */ |
|
111 | - $this->_date_format_strings = apply_filters( |
|
112 | - 'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings', |
|
113 | - [ |
|
114 | - 'date' => 'Y-m-d', |
|
115 | - 'time' => 'h:i a', |
|
116 | - ] |
|
117 | - ); |
|
118 | - // validate |
|
119 | - $this->_date_format_strings['date'] = $this->_date_format_strings['date'] ?? ''; |
|
120 | - $this->_date_format_strings['time'] = $this->_date_format_strings['time'] ?? ''; |
|
121 | - |
|
122 | - $this->_date_time_format = $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time']; |
|
123 | - } |
|
124 | - |
|
125 | - |
|
126 | - /** |
|
127 | - * @return void |
|
128 | - */ |
|
129 | - protected function _validate_format_strings() |
|
130 | - { |
|
131 | - // validate format strings |
|
132 | - $format_validation = EEH_DTT_Helper::validate_format_string( |
|
133 | - $this->_date_time_format |
|
134 | - ); |
|
135 | - if (is_array($format_validation)) { |
|
136 | - $msg = '<p>'; |
|
137 | - $msg .= sprintf( |
|
138 | - esc_html__( |
|
139 | - 'The format "%s" was likely added via a filter and is invalid for the following reasons:', |
|
140 | - 'event_espresso' |
|
141 | - ), |
|
142 | - $this->_date_time_format |
|
143 | - ); |
|
144 | - $msg .= '</p><ul>'; |
|
145 | - foreach ($format_validation as $error) { |
|
146 | - $msg .= '<li>' . $error . '</li>'; |
|
147 | - } |
|
148 | - $msg .= '</ul><p>'; |
|
149 | - $msg .= sprintf( |
|
150 | - esc_html__( |
|
151 | - '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s', |
|
152 | - 'event_espresso' |
|
153 | - ), |
|
154 | - '<span style="color:#D54E21;">', |
|
155 | - '</span>' |
|
156 | - ); |
|
157 | - $msg .= '</p>'; |
|
158 | - EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__); |
|
159 | - $this->_date_format_strings = [ |
|
160 | - 'date' => 'Y-m-d', |
|
161 | - 'time' => 'h:i a', |
|
162 | - ]; |
|
163 | - } |
|
164 | - } |
|
165 | - |
|
166 | - |
|
167 | - /** |
|
168 | - * @return void |
|
169 | - */ |
|
170 | - protected function _set_scripts_styles() |
|
171 | - { |
|
172 | - $this->_scripts_styles = [ |
|
173 | - 'registers' => [ |
|
174 | - 'ee-tickets-datetimes-css' => [ |
|
175 | - 'url' => PRICING_ASSETS_URL . 'event-tickets-datetimes.css', |
|
176 | - 'type' => 'css', |
|
177 | - ], |
|
178 | - 'ee-dtt-ticket-metabox' => [ |
|
179 | - 'url' => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js', |
|
180 | - 'depends' => ['ee-datepicker', 'ee-dialog', 'underscore'], |
|
181 | - ], |
|
182 | - ], |
|
183 | - 'deregisters' => [ |
|
184 | - 'event-editor-css' => ['type' => 'css'], |
|
185 | - 'event-datetime-metabox' => ['type' => 'js'], |
|
186 | - ], |
|
187 | - 'enqueues' => [ |
|
188 | - 'ee-tickets-datetimes-css' => ['edit', 'create_new'], |
|
189 | - 'ee-dtt-ticket-metabox' => ['edit', 'create_new'], |
|
190 | - ], |
|
191 | - 'localize' => [ |
|
192 | - 'ee-dtt-ticket-metabox' => [ |
|
193 | - 'DTT_TRASH_BLOCK' => [ |
|
194 | - 'main_warning' => esc_html__( |
|
195 | - 'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):', |
|
196 | - 'event_espresso' |
|
197 | - ), |
|
198 | - 'after_warning' => esc_html__( |
|
199 | - 'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.', |
|
200 | - 'event_espresso' |
|
201 | - ), |
|
202 | - 'cancel_button' => ' |
|
18 | + /** |
|
19 | + * This property is just used to hold the status of whether an event is currently being |
|
20 | + * created (true) or edited (false) |
|
21 | + * |
|
22 | + * @access protected |
|
23 | + * @var bool |
|
24 | + */ |
|
25 | + protected $_is_creating_event; |
|
26 | + |
|
27 | + /** |
|
28 | + * Used to contain the format strings for date and time that will be used for php date and |
|
29 | + * time. |
|
30 | + * Is set in the _set_hooks_properties() method. |
|
31 | + * |
|
32 | + * @var array |
|
33 | + */ |
|
34 | + protected $_date_format_strings; |
|
35 | + |
|
36 | + /** |
|
37 | + * @var string $_date_time_format |
|
38 | + */ |
|
39 | + protected $_date_time_format; |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * @throws InvalidArgumentException |
|
44 | + * @throws InvalidInterfaceException |
|
45 | + * @throws InvalidDataTypeException |
|
46 | + */ |
|
47 | + protected function _set_hooks_properties() |
|
48 | + { |
|
49 | + $this->_name = 'pricing'; |
|
50 | + // capability check |
|
51 | + if ( |
|
52 | + $this->_adminpage_obj->adminConfig()->useAdvancedEditor() |
|
53 | + || ! EE_Registry::instance()->CAP->current_user_can( |
|
54 | + 'ee_read_default_prices', |
|
55 | + 'advanced_ticket_datetime_metabox' |
|
56 | + ) |
|
57 | + ) { |
|
58 | + $this->_metaboxes = []; |
|
59 | + $this->_scripts_styles = []; |
|
60 | + return; |
|
61 | + } |
|
62 | + $this->_setup_metaboxes(); |
|
63 | + $this->_set_date_time_formats(); |
|
64 | + $this->_validate_format_strings(); |
|
65 | + $this->_set_scripts_styles(); |
|
66 | + add_filter( |
|
67 | + 'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks', |
|
68 | + [$this, 'caf_updates'] |
|
69 | + ); |
|
70 | + } |
|
71 | + |
|
72 | + |
|
73 | + /** |
|
74 | + * @return void |
|
75 | + */ |
|
76 | + protected function _setup_metaboxes() |
|
77 | + { |
|
78 | + // if we were going to add our own metaboxes we'd use the below. |
|
79 | + $this->_metaboxes = [ |
|
80 | + 0 => [ |
|
81 | + 'page_route' => ['edit', 'create_new'], |
|
82 | + 'func' => [$this, 'pricing_metabox'], |
|
83 | + 'label' => esc_html__('Event Tickets & Datetimes', 'event_espresso'), |
|
84 | + 'priority' => 'high', |
|
85 | + 'context' => 'normal', |
|
86 | + ], |
|
87 | + ]; |
|
88 | + $this->_remove_metaboxes = [ |
|
89 | + 0 => [ |
|
90 | + 'page_route' => ['edit', 'create_new'], |
|
91 | + 'id' => 'espresso_event_editor_tickets', |
|
92 | + 'context' => 'normal', |
|
93 | + ], |
|
94 | + ]; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * @return void |
|
100 | + */ |
|
101 | + protected function _set_date_time_formats() |
|
102 | + { |
|
103 | + /** |
|
104 | + * Format strings for date and time. Defaults are existing behaviour from 4.1. |
|
105 | + * Note, that if you return null as the value for 'date', and 'time' in the array, then |
|
106 | + * EE will automatically use the set wp_options, 'date_format', and 'time_format'. |
|
107 | + * |
|
108 | + * @since 4.6.7 |
|
109 | + * @var array Expected an array returned with 'date' and 'time' keys. |
|
110 | + */ |
|
111 | + $this->_date_format_strings = apply_filters( |
|
112 | + 'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings', |
|
113 | + [ |
|
114 | + 'date' => 'Y-m-d', |
|
115 | + 'time' => 'h:i a', |
|
116 | + ] |
|
117 | + ); |
|
118 | + // validate |
|
119 | + $this->_date_format_strings['date'] = $this->_date_format_strings['date'] ?? ''; |
|
120 | + $this->_date_format_strings['time'] = $this->_date_format_strings['time'] ?? ''; |
|
121 | + |
|
122 | + $this->_date_time_format = $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time']; |
|
123 | + } |
|
124 | + |
|
125 | + |
|
126 | + /** |
|
127 | + * @return void |
|
128 | + */ |
|
129 | + protected function _validate_format_strings() |
|
130 | + { |
|
131 | + // validate format strings |
|
132 | + $format_validation = EEH_DTT_Helper::validate_format_string( |
|
133 | + $this->_date_time_format |
|
134 | + ); |
|
135 | + if (is_array($format_validation)) { |
|
136 | + $msg = '<p>'; |
|
137 | + $msg .= sprintf( |
|
138 | + esc_html__( |
|
139 | + 'The format "%s" was likely added via a filter and is invalid for the following reasons:', |
|
140 | + 'event_espresso' |
|
141 | + ), |
|
142 | + $this->_date_time_format |
|
143 | + ); |
|
144 | + $msg .= '</p><ul>'; |
|
145 | + foreach ($format_validation as $error) { |
|
146 | + $msg .= '<li>' . $error . '</li>'; |
|
147 | + } |
|
148 | + $msg .= '</ul><p>'; |
|
149 | + $msg .= sprintf( |
|
150 | + esc_html__( |
|
151 | + '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s', |
|
152 | + 'event_espresso' |
|
153 | + ), |
|
154 | + '<span style="color:#D54E21;">', |
|
155 | + '</span>' |
|
156 | + ); |
|
157 | + $msg .= '</p>'; |
|
158 | + EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__); |
|
159 | + $this->_date_format_strings = [ |
|
160 | + 'date' => 'Y-m-d', |
|
161 | + 'time' => 'h:i a', |
|
162 | + ]; |
|
163 | + } |
|
164 | + } |
|
165 | + |
|
166 | + |
|
167 | + /** |
|
168 | + * @return void |
|
169 | + */ |
|
170 | + protected function _set_scripts_styles() |
|
171 | + { |
|
172 | + $this->_scripts_styles = [ |
|
173 | + 'registers' => [ |
|
174 | + 'ee-tickets-datetimes-css' => [ |
|
175 | + 'url' => PRICING_ASSETS_URL . 'event-tickets-datetimes.css', |
|
176 | + 'type' => 'css', |
|
177 | + ], |
|
178 | + 'ee-dtt-ticket-metabox' => [ |
|
179 | + 'url' => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js', |
|
180 | + 'depends' => ['ee-datepicker', 'ee-dialog', 'underscore'], |
|
181 | + ], |
|
182 | + ], |
|
183 | + 'deregisters' => [ |
|
184 | + 'event-editor-css' => ['type' => 'css'], |
|
185 | + 'event-datetime-metabox' => ['type' => 'js'], |
|
186 | + ], |
|
187 | + 'enqueues' => [ |
|
188 | + 'ee-tickets-datetimes-css' => ['edit', 'create_new'], |
|
189 | + 'ee-dtt-ticket-metabox' => ['edit', 'create_new'], |
|
190 | + ], |
|
191 | + 'localize' => [ |
|
192 | + 'ee-dtt-ticket-metabox' => [ |
|
193 | + 'DTT_TRASH_BLOCK' => [ |
|
194 | + 'main_warning' => esc_html__( |
|
195 | + 'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):', |
|
196 | + 'event_espresso' |
|
197 | + ), |
|
198 | + 'after_warning' => esc_html__( |
|
199 | + 'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.', |
|
200 | + 'event_espresso' |
|
201 | + ), |
|
202 | + 'cancel_button' => ' |
|
203 | 203 | <button class="button--secondary ee-modal-cancel"> |
204 | 204 | ' . esc_html__('Cancel', 'event_espresso') . ' |
205 | 205 | </button>', |
206 | - 'close_button' => ' |
|
206 | + 'close_button' => ' |
|
207 | 207 | <button class="button--secondary ee-modal-cancel"> |
208 | 208 | ' . esc_html__('Close', 'event_espresso') . ' |
209 | 209 | </button>', |
210 | - 'single_warning_from_tkt' => esc_html__( |
|
211 | - 'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.', |
|
212 | - 'event_espresso' |
|
213 | - ), |
|
214 | - 'single_warning_from_dtt' => esc_html__( |
|
215 | - 'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket. Tickets must always have at least one datetime assigned to them.', |
|
216 | - 'event_espresso' |
|
217 | - ), |
|
218 | - 'dismiss_button' => ' |
|
210 | + 'single_warning_from_tkt' => esc_html__( |
|
211 | + 'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.', |
|
212 | + 'event_espresso' |
|
213 | + ), |
|
214 | + 'single_warning_from_dtt' => esc_html__( |
|
215 | + 'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket. Tickets must always have at least one datetime assigned to them.', |
|
216 | + 'event_espresso' |
|
217 | + ), |
|
218 | + 'dismiss_button' => ' |
|
219 | 219 | <button class="button--secondary ee-modal-cancel"> |
220 | 220 | ' . esc_html__('Dismiss', 'event_espresso') . ' |
221 | 221 | </button>', |
222 | - ], |
|
223 | - 'DTT_ERROR_MSG' => [ |
|
224 | - 'no_ticket_name' => esc_html__('General Admission', 'event_espresso'), |
|
225 | - 'dismiss_button' => ' |
|
222 | + ], |
|
223 | + 'DTT_ERROR_MSG' => [ |
|
224 | + 'no_ticket_name' => esc_html__('General Admission', 'event_espresso'), |
|
225 | + 'dismiss_button' => ' |
|
226 | 226 | <div class="save-cancel-button-container"> |
227 | 227 | <button class="button--secondary ee-modal-cancel"> |
228 | 228 | ' . esc_html__('Dismiss', 'event_espresso') . ' |
229 | 229 | </button> |
230 | 230 | </div>', |
231 | - ], |
|
232 | - 'DTT_OVERSELL_WARNING' => [ |
|
233 | - 'datetime_ticket' => esc_html__( |
|
234 | - 'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.', |
|
235 | - 'event_espresso' |
|
236 | - ), |
|
237 | - 'ticket_datetime' => esc_html__( |
|
238 | - 'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.', |
|
239 | - 'event_espresso' |
|
240 | - ), |
|
241 | - ], |
|
242 | - 'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats( |
|
243 | - $this->_date_format_strings['date'], |
|
244 | - $this->_date_format_strings['time'] |
|
245 | - ), |
|
246 | - 'DTT_START_OF_WEEK' => ['dayValue' => (int) get_option('start_of_week')], |
|
247 | - ], |
|
248 | - ], |
|
249 | - ]; |
|
250 | - } |
|
251 | - |
|
252 | - |
|
253 | - /** |
|
254 | - * @param array $update_callbacks |
|
255 | - * @return array |
|
256 | - */ |
|
257 | - public function caf_updates(array $update_callbacks): array |
|
258 | - { |
|
259 | - unset($update_callbacks['_default_tickets_update']); |
|
260 | - $update_callbacks['datetime_and_tickets_caf_update'] = [$this, 'datetime_and_tickets_caf_update']; |
|
261 | - return $update_callbacks; |
|
262 | - } |
|
263 | - |
|
264 | - |
|
265 | - /** |
|
266 | - * Handles saving everything related to Tickets (datetimes, tickets, prices) |
|
267 | - * |
|
268 | - * @param EE_Event $event The Event object we're attaching data to |
|
269 | - * @param array $data The request data from the form |
|
270 | - * @throws ReflectionException |
|
271 | - * @throws Exception |
|
272 | - * @throws InvalidInterfaceException |
|
273 | - * @throws InvalidDataTypeException |
|
274 | - * @throws EE_Error |
|
275 | - * @throws InvalidArgumentException |
|
276 | - */ |
|
277 | - public function datetime_and_tickets_caf_update(EE_Event $event, array $data) |
|
278 | - { |
|
279 | - // first we need to start with datetimes cause they are the "root" items attached to events. |
|
280 | - $saved_datetimes = $this->_update_datetimes($event, $data); |
|
281 | - // next tackle the tickets (and prices?) |
|
282 | - $this->_update_tickets($event, $saved_datetimes, $data); |
|
283 | - } |
|
284 | - |
|
285 | - |
|
286 | - /** |
|
287 | - * update event_datetimes |
|
288 | - * |
|
289 | - * @param EE_Event $event Event being updated |
|
290 | - * @param array $data the request data from the form |
|
291 | - * @return EE_Datetime[] |
|
292 | - * @throws Exception |
|
293 | - * @throws ReflectionException |
|
294 | - * @throws InvalidInterfaceException |
|
295 | - * @throws InvalidDataTypeException |
|
296 | - * @throws InvalidArgumentException |
|
297 | - * @throws EE_Error |
|
298 | - */ |
|
299 | - protected function _update_datetimes(EE_Event $event, array $data): array |
|
300 | - { |
|
301 | - $timezone = $data['timezone_string'] ?? null; |
|
302 | - $saved_datetime_ids = []; |
|
303 | - $saved_datetime_objs = []; |
|
304 | - if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) { |
|
305 | - throw new InvalidArgumentException( |
|
306 | - esc_html__( |
|
307 | - 'The "edit_event_datetimes" array is invalid therefore the event can not be updated.', |
|
308 | - 'event_espresso' |
|
309 | - ) |
|
310 | - ); |
|
311 | - } |
|
312 | - foreach ($data['edit_event_datetimes'] as $row => $datetime_data) { |
|
313 | - // trim all values to ensure any excess whitespace is removed. |
|
314 | - $datetime_data = array_map( |
|
315 | - function ($datetime_data) { |
|
316 | - return is_array($datetime_data) ? $datetime_data : trim($datetime_data); |
|
317 | - }, |
|
318 | - $datetime_data |
|
319 | - ); |
|
320 | - |
|
321 | - $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end']) |
|
322 | - && ! empty($datetime_data['DTT_EVT_end']) |
|
323 | - ? $datetime_data['DTT_EVT_end'] |
|
324 | - : $datetime_data['DTT_EVT_start']; |
|
325 | - |
|
326 | - $datetime_values = [ |
|
327 | - 'DTT_ID' => ! empty($datetime_data['DTT_ID']) |
|
328 | - ? $datetime_data['DTT_ID'] |
|
329 | - : null, |
|
330 | - 'DTT_name' => ! empty($datetime_data['DTT_name']) |
|
331 | - ? $datetime_data['DTT_name'] |
|
332 | - : '', |
|
333 | - 'DTT_description' => ! empty($datetime_data['DTT_description']) |
|
334 | - ? $datetime_data['DTT_description'] |
|
335 | - : '', |
|
336 | - 'DTT_EVT_start' => $datetime_data['DTT_EVT_start'], |
|
337 | - 'DTT_EVT_end' => $datetime_data['DTT_EVT_end'], |
|
338 | - 'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) |
|
339 | - ? EE_INF |
|
340 | - : $datetime_data['DTT_reg_limit'], |
|
341 | - 'DTT_order' => ! isset($datetime_data['DTT_order']) |
|
342 | - ? $row |
|
343 | - : $datetime_data['DTT_order'], |
|
344 | - ]; |
|
345 | - |
|
346 | - // if we have an id then let's get existing object first and then set the new values. |
|
347 | - // Otherwise we instantiate a new object for save. |
|
348 | - if (! empty($datetime_data['DTT_ID'])) { |
|
349 | - $datetime = EEM_Datetime::instance($timezone)->get_one_by_ID($datetime_data['DTT_ID']); |
|
350 | - // set date and time format according to what is set in this class. |
|
351 | - $datetime->set_date_format($this->_date_format_strings['date']); |
|
352 | - $datetime->set_time_format($this->_date_format_strings['time']); |
|
353 | - foreach ($datetime_values as $field => $value) { |
|
354 | - $datetime->set($field, $value); |
|
355 | - } |
|
356 | - |
|
357 | - // make sure the $datetime_id here is saved just in case |
|
358 | - // after the add_relation_to() the autosave replaces it. |
|
359 | - // We need to do this so we dont' TRASH the parent DTT. |
|
360 | - // (save the ID for both key and value to avoid duplications) |
|
361 | - $saved_datetime_ids[ $datetime->ID() ] = $datetime->ID(); |
|
362 | - } else { |
|
363 | - $datetime = EE_Datetime::new_instance( |
|
364 | - $datetime_values, |
|
365 | - $timezone, |
|
366 | - [$this->_date_format_strings['date'], $this->_date_format_strings['time']] |
|
367 | - ); |
|
368 | - foreach ($datetime_values as $field => $value) { |
|
369 | - $datetime->set($field, $value); |
|
370 | - } |
|
371 | - } |
|
372 | - $datetime->save(); |
|
373 | - do_action( |
|
374 | - 'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save', |
|
375 | - $datetime, |
|
376 | - $row, |
|
377 | - $datetime_data, |
|
378 | - $data |
|
379 | - ); |
|
380 | - $datetime = $event->_add_relation_to($datetime, 'Datetime'); |
|
381 | - // before going any further make sure our dates are setup correctly |
|
382 | - // so that the end date is always equal or greater than the start date. |
|
383 | - if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) { |
|
384 | - $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start')); |
|
385 | - $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days'); |
|
386 | - $datetime->save(); |
|
387 | - } |
|
388 | - // now we have to make sure we add the new DTT_ID to the $saved_datetime_ids array |
|
389 | - // because it is possible there was a new one created for the autosave. |
|
390 | - // (save the ID for both key and value to avoid duplications) |
|
391 | - $DTT_ID = $datetime->ID(); |
|
392 | - $saved_datetime_ids[ $DTT_ID ] = $DTT_ID; |
|
393 | - $saved_datetime_objs[ $row ] = $datetime; |
|
394 | - // @todo if ANY of these updates fail then we want the appropriate global error message. |
|
395 | - } |
|
396 | - $event->save(); |
|
397 | - // now we need to REMOVE any datetimes that got deleted. |
|
398 | - // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them. |
|
399 | - // So its safe to permanently delete at this point. |
|
400 | - $old_datetimes = explode(',', $data['datetime_IDs']); |
|
401 | - $old_datetimes = $old_datetimes[0] === '' ? [] : $old_datetimes; |
|
402 | - if (is_array($old_datetimes)) { |
|
403 | - $datetimes_to_delete = array_diff($old_datetimes, $saved_datetime_ids); |
|
404 | - foreach ($datetimes_to_delete as $id) { |
|
405 | - $id = absint($id); |
|
406 | - if (empty($id)) { |
|
407 | - continue; |
|
408 | - } |
|
409 | - $datetime_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id); |
|
410 | - // remove ticket relationships. |
|
411 | - $related_tickets = $datetime_to_remove->get_many_related('Ticket'); |
|
412 | - foreach ($related_tickets as $ticket) { |
|
413 | - $datetime_to_remove->_remove_relation_to($ticket, 'Ticket'); |
|
414 | - } |
|
415 | - $event->_remove_relation_to($id, 'Datetime'); |
|
416 | - $datetime_to_remove->refresh_cache_of_related_objects(); |
|
417 | - } |
|
418 | - } |
|
419 | - return $saved_datetime_objs; |
|
420 | - } |
|
421 | - |
|
422 | - |
|
423 | - /** |
|
424 | - * update tickets |
|
425 | - * |
|
426 | - * @param EE_Event $event Event object being updated |
|
427 | - * @param EE_Datetime[] $saved_datetimes an array of datetime ids being updated |
|
428 | - * @param array $data incoming request data |
|
429 | - * @return EE_Ticket[] |
|
430 | - * @throws Exception |
|
431 | - * @throws ReflectionException |
|
432 | - * @throws InvalidInterfaceException |
|
433 | - * @throws InvalidDataTypeException |
|
434 | - * @throws InvalidArgumentException |
|
435 | - * @throws EE_Error |
|
436 | - */ |
|
437 | - protected function _update_tickets(EE_Event $event, array $saved_datetimes, array $data): array |
|
438 | - { |
|
439 | - $new_ticket = null; |
|
440 | - // stripslashes because WP filtered the $_POST ($data) array to add slashes |
|
441 | - $data = stripslashes_deep($data); |
|
442 | - $timezone = $data['timezone_string'] ?? null; |
|
443 | - $saved_tickets = []; |
|
444 | - $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : []; |
|
445 | - if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) { |
|
446 | - throw new InvalidArgumentException( |
|
447 | - esc_html__( |
|
448 | - 'The "edit_tickets" array is invalid therefore the event can not be updated.', |
|
449 | - 'event_espresso' |
|
450 | - ) |
|
451 | - ); |
|
452 | - } |
|
453 | - foreach ($data['edit_tickets'] as $row => $ticket_data) { |
|
454 | - $update_prices = $create_new_TKT = false; |
|
455 | - // figure out what datetimes were added to the ticket |
|
456 | - // and what datetimes were removed from the ticket in the session. |
|
457 | - $starting_ticket_datetime_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]); |
|
458 | - $ticket_datetime_rows = explode(',', $data['ticket_datetime_rows'][ $row ]); |
|
459 | - $datetimes_added = array_diff($ticket_datetime_rows, $starting_ticket_datetime_rows); |
|
460 | - $datetimes_removed = array_diff($starting_ticket_datetime_rows, $ticket_datetime_rows); |
|
461 | - // trim inputs to ensure any excess whitespace is removed. |
|
462 | - $ticket_data = array_map( |
|
463 | - function ($ticket_data) { |
|
464 | - return is_array($ticket_data) ? $ticket_data : trim($ticket_data); |
|
465 | - }, |
|
466 | - $ticket_data |
|
467 | - ); |
|
468 | - // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle |
|
469 | - // because we're doing calculations prior to using the models. |
|
470 | - // note incoming ['TKT_price'] value is already in standard notation (via js). |
|
471 | - $ticket_price = isset($ticket_data['TKT_price']) |
|
472 | - ? round((float) $ticket_data['TKT_price'], 3) |
|
473 | - : 0; |
|
474 | - // note incoming base price needs converted from localized value. |
|
475 | - $base_price = isset($ticket_data['TKT_base_price']) |
|
476 | - ? EEH_Money::convert_to_float_from_localized_money($ticket_data['TKT_base_price']) |
|
477 | - : 0; |
|
478 | - // if ticket price == 0 and $base_price != 0 then ticket price == base_price |
|
479 | - $ticket_price = $ticket_price === 0 && $base_price !== 0 |
|
480 | - ? $base_price |
|
481 | - : $ticket_price; |
|
482 | - $base_price_id = $ticket_data['TKT_base_price_ID'] ?? 0; |
|
483 | - $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ]) |
|
484 | - ? $data['edit_prices'][ $row ] |
|
485 | - : []; |
|
486 | - $now = null; |
|
487 | - if (empty($ticket_data['TKT_start_date'])) { |
|
488 | - // lets' use now in the set timezone. |
|
489 | - $now = new DateTime('now', new DateTimeZone($event->get_timezone())); |
|
490 | - $ticket_data['TKT_start_date'] = $now->format($this->_date_time_format); |
|
491 | - } |
|
492 | - if (empty($ticket_data['TKT_end_date'])) { |
|
493 | - /** |
|
494 | - * set the TKT_end_date to the first datetime attached to the ticket. |
|
495 | - */ |
|
496 | - $first_datetime = $saved_datetimes[ reset($ticket_datetime_rows) ]; |
|
497 | - $ticket_data['TKT_end_date'] = $first_datetime->start_date_and_time($this->_date_time_format); |
|
498 | - } |
|
499 | - $TKT_values = [ |
|
500 | - 'TKT_ID' => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null, |
|
501 | - 'TTM_ID' => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0, |
|
502 | - 'TKT_name' => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '', |
|
503 | - 'TKT_description' => ! empty($ticket_data['TKT_description']) |
|
504 | - && $ticket_data['TKT_description'] !== esc_html__( |
|
505 | - 'You can modify this description', |
|
506 | - 'event_espresso' |
|
507 | - ) |
|
508 | - ? $ticket_data['TKT_description'] |
|
509 | - : '', |
|
510 | - 'TKT_start_date' => $ticket_data['TKT_start_date'], |
|
511 | - 'TKT_end_date' => $ticket_data['TKT_end_date'], |
|
512 | - 'TKT_qty' => ! isset($ticket_data['TKT_qty']) || $ticket_data['TKT_qty'] === '' |
|
513 | - ? EE_INF |
|
514 | - : $ticket_data['TKT_qty'], |
|
515 | - 'TKT_uses' => ! isset($ticket_data['TKT_uses']) || $ticket_data['TKT_uses'] === '' |
|
516 | - ? EE_INF |
|
517 | - : $ticket_data['TKT_uses'], |
|
518 | - 'TKT_min' => empty($ticket_data['TKT_min']) ? 0 : $ticket_data['TKT_min'], |
|
519 | - 'TKT_max' => empty($ticket_data['TKT_max']) ? EE_INF : $ticket_data['TKT_max'], |
|
520 | - 'TKT_row' => $row, |
|
521 | - 'TKT_order' => $ticket_data['TKT_order'] ?? 0, |
|
522 | - 'TKT_taxable' => ! empty($ticket_data['TKT_taxable']) ? 1 : 0, |
|
523 | - 'TKT_required' => ! empty($ticket_data['TKT_required']) ? 1 : 0, |
|
524 | - 'TKT_price' => $ticket_price, |
|
525 | - ]; |
|
526 | - // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, |
|
527 | - // which means in turn that the prices will become new prices as well. |
|
528 | - if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) { |
|
529 | - $TKT_values['TKT_ID'] = 0; |
|
530 | - $TKT_values['TKT_is_default'] = 0; |
|
531 | - $update_prices = true; |
|
532 | - } |
|
533 | - // if we have a TKT_ID then we need to get that existing TKT_obj and update it |
|
534 | - // we actually do our saves ahead of doing any add_relations to |
|
535 | - // because its entirely possible that this ticket wasn't removed or added to any datetime in the session |
|
536 | - // but DID have it's items modified. |
|
537 | - // keep in mind that if the TKT has been sold (and we have changed pricing information), |
|
538 | - // then we won't be updating the ticket but instead a new ticket will be created and the old one archived. |
|
539 | - if (absint($TKT_values['TKT_ID'])) { |
|
540 | - $ticket = EEM_Ticket::instance($timezone)->get_one_by_ID($ticket_data['TKT_ID']); |
|
541 | - if ($ticket instanceof EE_Ticket) { |
|
542 | - $ticket = $this->_update_ticket_datetimes( |
|
543 | - $ticket, |
|
544 | - $saved_datetimes, |
|
545 | - $datetimes_added, |
|
546 | - $datetimes_removed |
|
547 | - ); |
|
548 | - // are there any registrations using this ticket ? |
|
549 | - $tickets_sold = $ticket->count_related( |
|
550 | - 'Registration', |
|
551 | - [ |
|
552 | - [ |
|
553 | - 'STS_ID' => ['NOT IN', [EEM_Registration::status_id_incomplete]], |
|
554 | - ], |
|
555 | - ] |
|
556 | - ); |
|
557 | - // set ticket formats |
|
558 | - $ticket->set_date_format($this->_date_format_strings['date']); |
|
559 | - $ticket->set_time_format($this->_date_format_strings['time']); |
|
560 | - // let's just check the total price for the existing ticket |
|
561 | - // and determine if it matches the new total price. |
|
562 | - // if they are different then we create a new ticket (if tickets sold) |
|
563 | - // if they aren't different then we go ahead and modify existing ticket. |
|
564 | - $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted(); |
|
565 | - // set new values |
|
566 | - foreach ($TKT_values as $field => $value) { |
|
567 | - if ($field === 'TKT_qty') { |
|
568 | - $ticket->set_qty($value); |
|
569 | - } else { |
|
570 | - $ticket->set($field, $value); |
|
571 | - } |
|
572 | - } |
|
573 | - // if $create_new_TKT is false then we can safely update the existing ticket. |
|
574 | - // Otherwise we have to create a new ticket. |
|
575 | - if ($create_new_TKT) { |
|
576 | - $new_ticket = $this->_duplicate_ticket( |
|
577 | - $ticket, |
|
578 | - $price_rows, |
|
579 | - $ticket_price, |
|
580 | - $base_price, |
|
581 | - $base_price_id |
|
582 | - ); |
|
583 | - } |
|
584 | - } |
|
585 | - } else { |
|
586 | - // no TKT_id so a new TKT |
|
587 | - $ticket = EE_Ticket::new_instance( |
|
588 | - $TKT_values, |
|
589 | - $timezone, |
|
590 | - [$this->_date_format_strings['date'], $this->_date_format_strings['time']] |
|
591 | - ); |
|
592 | - if ($ticket instanceof EE_Ticket) { |
|
593 | - // make sure ticket has an ID of setting relations won't work |
|
594 | - $ticket->save(); |
|
595 | - $ticket = $this->_update_ticket_datetimes( |
|
596 | - $ticket, |
|
597 | - $saved_datetimes, |
|
598 | - $datetimes_added, |
|
599 | - $datetimes_removed |
|
600 | - ); |
|
601 | - $update_prices = true; |
|
602 | - } |
|
603 | - } |
|
604 | - // make sure any current values have been saved. |
|
605 | - // $ticket->save(); |
|
606 | - // before going any further make sure our dates are setup correctly |
|
607 | - // so that the end date is always equal or greater than the start date. |
|
608 | - if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) { |
|
609 | - $ticket->set('TKT_end_date', $ticket->get('TKT_start_date')); |
|
610 | - $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days'); |
|
611 | - } |
|
612 | - // let's make sure the base price is handled |
|
613 | - $ticket = ! $create_new_TKT |
|
614 | - ? $this->_add_prices_to_ticket( |
|
615 | - [], |
|
616 | - $ticket, |
|
617 | - $update_prices, |
|
618 | - $base_price, |
|
619 | - $base_price_id |
|
620 | - ) |
|
621 | - : $ticket; |
|
622 | - // add/update price_modifiers |
|
623 | - $ticket = ! $create_new_TKT |
|
624 | - ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices) |
|
625 | - : $ticket; |
|
626 | - // need to make sue that the TKT_price is accurate after saving the prices. |
|
627 | - $ticket->ensure_TKT_Price_correct(); |
|
628 | - // handle CREATING a default ticket from the incoming ticket but ONLY if this isn't an autosave. |
|
629 | - if (! defined('DOING_AUTOSAVE') && ! empty($ticket_data['TKT_is_default_selector'])) { |
|
630 | - $new_default = clone $ticket; |
|
631 | - $new_default->set('TKT_ID', 0); |
|
632 | - $new_default->set('TKT_is_default', 1); |
|
633 | - $new_default->set('TKT_row', 1); |
|
634 | - $new_default->set('TKT_price', $ticket_price); |
|
635 | - // remove any datetime relations cause we DON'T want datetime relations attached |
|
636 | - // (note this is just removing the cached relations in the object) |
|
637 | - $new_default->_remove_relations('Datetime'); |
|
638 | - // @todo we need to add the current attached prices as new prices to the new default ticket. |
|
639 | - $new_default = $this->_add_prices_to_ticket( |
|
640 | - $price_rows, |
|
641 | - $new_default, |
|
642 | - true |
|
643 | - ); |
|
644 | - // don't forget the base price! |
|
645 | - $new_default = $this->_add_prices_to_ticket( |
|
646 | - [], |
|
647 | - $new_default, |
|
648 | - true, |
|
649 | - $base_price, |
|
650 | - $base_price_id |
|
651 | - ); |
|
652 | - $new_default->save(); |
|
653 | - do_action( |
|
654 | - 'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket', |
|
655 | - $new_default, |
|
656 | - $row, |
|
657 | - $ticket, |
|
658 | - $data |
|
659 | - ); |
|
660 | - } |
|
661 | - // DO ALL datetime relationships for both current tickets and any archived tickets |
|
662 | - // for the given datetime that are related to the current ticket. |
|
663 | - // TODO... not sure exactly how we're going to do this considering we don't know |
|
664 | - // what current ticket the archived tickets are related to |
|
665 | - // (and TKT_parent is used for autosaves so that's not a field we can reliably use). |
|
666 | - // let's assign any tickets that have been setup to the saved_tickets tracker |
|
667 | - // save existing TKT |
|
668 | - $ticket->save(); |
|
669 | - if ($create_new_TKT && $new_ticket instanceof EE_Ticket) { |
|
670 | - // save new TKT |
|
671 | - $new_ticket->save(); |
|
672 | - // add new ticket to array |
|
673 | - $saved_tickets[ $new_ticket->ID() ] = $new_ticket; |
|
674 | - do_action( |
|
675 | - 'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket', |
|
676 | - $new_ticket, |
|
677 | - $row, |
|
678 | - $ticket_data, |
|
679 | - $data |
|
680 | - ); |
|
681 | - } else { |
|
682 | - // add ticket to saved tickets |
|
683 | - $saved_tickets[ $ticket->ID() ] = $ticket; |
|
684 | - do_action( |
|
685 | - 'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket', |
|
686 | - $ticket, |
|
687 | - $row, |
|
688 | - $ticket_data, |
|
689 | - $data |
|
690 | - ); |
|
691 | - } |
|
692 | - } |
|
693 | - // now we need to handle tickets actually "deleted permanently". |
|
694 | - // There are cases where we'd want this to happen |
|
695 | - // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket). |
|
696 | - // Or a draft event was saved and in the process of editing a ticket is trashed. |
|
697 | - // No sense in keeping all the related data in the db! |
|
698 | - $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets; |
|
699 | - $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets)); |
|
700 | - foreach ($tickets_removed as $id) { |
|
701 | - $id = absint($id); |
|
702 | - // get the ticket for this id |
|
703 | - $ticket_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id); |
|
704 | - // if this ticket is a default ticket we leave it alone cause it won't be attached to the datetime |
|
705 | - if ($ticket_to_remove->get('TKT_is_default')) { |
|
706 | - continue; |
|
707 | - } |
|
708 | - // if this ticket has any registrations attached so then we just ARCHIVE |
|
709 | - // because we don't actually permanently delete these tickets. |
|
710 | - if ($ticket_to_remove->count_related('Registration') > 0) { |
|
711 | - $ticket_to_remove->delete(); |
|
712 | - continue; |
|
713 | - } |
|
714 | - // need to get all the related datetimes on this ticket and remove from every single one of them |
|
715 | - // (remember this process can ONLY kick off if there are NO tickets_sold) |
|
716 | - $datetimes = $ticket_to_remove->get_many_related('Datetime'); |
|
717 | - foreach ($datetimes as $datetime) { |
|
718 | - $ticket_to_remove->_remove_relation_to($datetime, 'Datetime'); |
|
719 | - } |
|
720 | - // need to do the same for prices (except these prices can also be deleted because again, |
|
721 | - // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived)) |
|
722 | - $ticket_to_remove->delete_related_permanently('Price'); |
|
723 | - do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $ticket_to_remove); |
|
724 | - // finally let's delete this ticket |
|
725 | - // (which should not be blocked at this point b/c we've removed all our relationships) |
|
726 | - $ticket_to_remove->delete_permanently(); |
|
727 | - } |
|
728 | - return $saved_tickets; |
|
729 | - } |
|
730 | - |
|
731 | - |
|
732 | - /** |
|
733 | - * @access protected |
|
734 | - * @param EE_Ticket $ticket |
|
735 | - * @param EE_Datetime[] $saved_datetimes |
|
736 | - * @param int[] $added_datetimes |
|
737 | - * @param int[] $removed_datetimes |
|
738 | - * @return EE_Ticket |
|
739 | - * @throws EE_Error |
|
740 | - * @throws ReflectionException |
|
741 | - */ |
|
742 | - protected function _update_ticket_datetimes( |
|
743 | - EE_Ticket $ticket, |
|
744 | - array $saved_datetimes = [], |
|
745 | - array $added_datetimes = [], |
|
746 | - array $removed_datetimes = [] |
|
747 | - ): EE_Ticket { |
|
748 | - // to start we have to add the ticket to all the datetimes its supposed to be with, |
|
749 | - // and removing the ticket from datetimes it got removed from. |
|
750 | - // first let's add datetimes |
|
751 | - if (! empty($added_datetimes) && is_array($added_datetimes)) { |
|
752 | - foreach ($added_datetimes as $row_id) { |
|
753 | - if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
754 | - $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
755 | - } |
|
756 | - } |
|
757 | - } |
|
758 | - // then remove datetimes |
|
759 | - if (! empty($removed_datetimes) && is_array($removed_datetimes)) { |
|
760 | - foreach ($removed_datetimes as $row_id) { |
|
761 | - // its entirely possible that a datetime got deleted (instead of just removed from relationship. |
|
762 | - // So make sure we skip over this if the datetime isn't in the $saved_datetimes array) |
|
763 | - if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
764 | - $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
765 | - } |
|
766 | - } |
|
767 | - } |
|
768 | - // cap ticket qty by datetime reg limits |
|
769 | - $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit'))); |
|
770 | - return $ticket; |
|
771 | - } |
|
772 | - |
|
773 | - |
|
774 | - /** |
|
775 | - * @access protected |
|
776 | - * @param EE_Ticket $ticket |
|
777 | - * @param array $price_rows |
|
778 | - * @param int|float $ticket_price |
|
779 | - * @param int|float $base_price |
|
780 | - * @param int $base_price_id |
|
781 | - * @return EE_Ticket |
|
782 | - * @throws ReflectionException |
|
783 | - * @throws InvalidArgumentException |
|
784 | - * @throws InvalidInterfaceException |
|
785 | - * @throws InvalidDataTypeException |
|
786 | - * @throws EE_Error |
|
787 | - */ |
|
788 | - protected function _duplicate_ticket( |
|
789 | - EE_Ticket $ticket, |
|
790 | - array $price_rows = [], |
|
791 | - $ticket_price = 0, |
|
792 | - $base_price = 0, |
|
793 | - int $base_price_id = 0 |
|
794 | - ): EE_Ticket { |
|
795 | - // create new ticket that's a copy of the existing |
|
796 | - // except a new id of course (and not archived) |
|
797 | - // AND has the new TKT_price associated with it. |
|
798 | - $new_ticket = clone $ticket; |
|
799 | - $new_ticket->set('TKT_ID', 0); |
|
800 | - $new_ticket->set_deleted(0); |
|
801 | - $new_ticket->set_price($ticket_price); |
|
802 | - $new_ticket->set_sold(0); |
|
803 | - // let's get a new ID for this ticket |
|
804 | - $new_ticket->save(); |
|
805 | - // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket |
|
806 | - $datetimes_on_existing = $ticket->datetimes(); |
|
807 | - $new_ticket = $this->_update_ticket_datetimes( |
|
808 | - $new_ticket, |
|
809 | - $datetimes_on_existing, |
|
810 | - array_keys($datetimes_on_existing) |
|
811 | - ); |
|
812 | - // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array. |
|
813 | - // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining |
|
814 | - // available. |
|
815 | - if ($ticket->sold() > 0) { |
|
816 | - $new_qty = $ticket->qty() - $ticket->sold(); |
|
817 | - $new_ticket->set_qty($new_qty); |
|
818 | - } |
|
819 | - // now we update the prices just for this ticket |
|
820 | - $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true); |
|
821 | - // and we update the base price |
|
822 | - return $this->_add_prices_to_ticket( |
|
823 | - [], |
|
824 | - $new_ticket, |
|
825 | - true, |
|
826 | - $base_price, |
|
827 | - $base_price_id |
|
828 | - ); |
|
829 | - } |
|
830 | - |
|
831 | - |
|
832 | - /** |
|
833 | - * This attaches a list of given prices to a ticket. |
|
834 | - * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change |
|
835 | - * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old |
|
836 | - * price info and prices are automatically "archived" via the ticket. |
|
837 | - * |
|
838 | - * @access private |
|
839 | - * @param array $prices Array of prices from the form. |
|
840 | - * @param EE_Ticket $ticket EE_Ticket object that prices are being attached to. |
|
841 | - * @param bool $new_prices Whether attach existing incoming prices or create new ones. |
|
842 | - * @param int|bool $base_price if FALSE then NOT doing a base price add. |
|
843 | - * @param int|bool $base_price_id if present then this is the base_price_id being updated. |
|
844 | - * @return EE_Ticket |
|
845 | - * @throws ReflectionException |
|
846 | - * @throws InvalidArgumentException |
|
847 | - * @throws InvalidInterfaceException |
|
848 | - * @throws InvalidDataTypeException |
|
849 | - * @throws EE_Error |
|
850 | - */ |
|
851 | - protected function _add_prices_to_ticket( |
|
852 | - array $prices, |
|
853 | - EE_Ticket $ticket, |
|
854 | - bool $new_prices = false, |
|
855 | - $base_price = false, |
|
856 | - $base_price_id = false |
|
857 | - ): EE_Ticket { |
|
858 | - // let's just get any current prices that may exist on the given ticket |
|
859 | - // so we can remove any prices that got trashed in this session. |
|
860 | - $current_prices_on_ticket = $base_price !== false |
|
861 | - ? $ticket->base_price(true) |
|
862 | - : $ticket->price_modifiers(); |
|
863 | - $updated_prices = []; |
|
864 | - // if $base_price ! FALSE then updating a base price. |
|
865 | - if ($base_price !== false) { |
|
866 | - $prices[1] = [ |
|
867 | - 'PRC_ID' => $new_prices || $base_price_id === 1 ? null : $base_price_id, |
|
868 | - 'PRT_ID' => 1, |
|
869 | - 'PRC_amount' => $base_price, |
|
870 | - 'PRC_name' => $ticket->get('TKT_name'), |
|
871 | - 'PRC_desc' => $ticket->get('TKT_description'), |
|
872 | - ]; |
|
873 | - } |
|
874 | - // possibly need to save ticket |
|
875 | - if (! $ticket->ID()) { |
|
876 | - $ticket->save(); |
|
877 | - } |
|
878 | - foreach ($prices as $row => $prc) { |
|
879 | - $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null; |
|
880 | - if (empty($prt_id)) { |
|
881 | - continue; |
|
882 | - } //prices MUST have a price type id. |
|
883 | - $PRC_values = [ |
|
884 | - 'PRC_ID' => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null, |
|
885 | - 'PRT_ID' => $prt_id, |
|
886 | - 'PRC_amount' => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0, |
|
887 | - 'PRC_name' => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '', |
|
888 | - 'PRC_desc' => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '', |
|
889 | - 'PRC_is_default' => false, |
|
890 | - // make sure we set PRC_is_default to false for all ticket saves from event_editor |
|
891 | - 'PRC_order' => $row, |
|
892 | - ]; |
|
893 | - if ($new_prices || empty($PRC_values['PRC_ID'])) { |
|
894 | - $PRC_values['PRC_ID'] = 0; |
|
895 | - $price = EE_Registry::instance()->load_class( |
|
896 | - 'Price', |
|
897 | - [$PRC_values], |
|
898 | - false, |
|
899 | - false |
|
900 | - ); |
|
901 | - } else { |
|
902 | - $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']); |
|
903 | - // update this price with new values |
|
904 | - foreach ($PRC_values as $field => $value) { |
|
905 | - $price->set($field, $value); |
|
906 | - } |
|
907 | - } |
|
908 | - $price->save(); |
|
909 | - $updated_prices[ $price->ID() ] = $price; |
|
910 | - $ticket->_add_relation_to($price, 'Price'); |
|
911 | - } |
|
912 | - // now let's remove any prices that got removed from the ticket |
|
913 | - if (! empty($current_prices_on_ticket)) { |
|
914 | - $current = array_keys($current_prices_on_ticket); |
|
915 | - $updated = array_keys($updated_prices); |
|
916 | - $prices_to_remove = array_diff($current, $updated); |
|
917 | - if (! empty($prices_to_remove)) { |
|
918 | - foreach ($prices_to_remove as $prc_id) { |
|
919 | - $p = $current_prices_on_ticket[ $prc_id ]; |
|
920 | - $ticket->_remove_relation_to($p, 'Price'); |
|
921 | - // delete permanently the price |
|
922 | - $p->delete_permanently(); |
|
923 | - } |
|
924 | - } |
|
925 | - } |
|
926 | - return $ticket; |
|
927 | - } |
|
928 | - |
|
929 | - |
|
930 | - /** |
|
931 | - * @throws ReflectionException |
|
932 | - * @throws InvalidArgumentException |
|
933 | - * @throws InvalidInterfaceException |
|
934 | - * @throws InvalidDataTypeException |
|
935 | - * @throws DomainException |
|
936 | - * @throws EE_Error |
|
937 | - */ |
|
938 | - public function pricing_metabox() |
|
939 | - { |
|
940 | - $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = []; |
|
941 | - $event = $this->_adminpage_obj->get_cpt_model_obj(); |
|
942 | - |
|
943 | - // set is_creating_event property. |
|
944 | - $EVT_ID = $event->ID(); |
|
945 | - $this->_is_creating_event = empty($this->_req_data['post']); |
|
946 | - |
|
947 | - // default main template args |
|
948 | - $main_template_args = [ |
|
949 | - 'event_datetime_help_link' => EEH_Template::get_help_tab_link( |
|
950 | - 'event_editor_event_datetimes_help_tab', |
|
951 | - $this->_adminpage_obj->page_slug, |
|
952 | - $this->_adminpage_obj->get_req_action() |
|
953 | - ), |
|
954 | - |
|
955 | - // todo need to add a filter to the template for the help text |
|
956 | - // in the Events_Admin_Page core file so we can add further help |
|
957 | - 'add_new_dtt_help_link' => EEH_Template::get_help_tab_link( |
|
958 | - 'add_new_dtt_info', |
|
959 | - $this->_adminpage_obj->page_slug, |
|
960 | - $this->_adminpage_obj->get_req_action() |
|
961 | - ), |
|
962 | - // todo need to add this help info id to the Events_Admin_Page core file so we can access it here. |
|
963 | - 'datetime_rows' => '', |
|
964 | - 'show_tickets_container' => '', |
|
965 | - 'ticket_rows' => '', |
|
966 | - 'ee_collapsible_status' => ' ee-collapsible-open', |
|
967 | - ]; |
|
968 | - $timezone = $event instanceof EE_Event ? $event->timezone_string() : null; |
|
969 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
970 | - |
|
971 | - /** |
|
972 | - * 1. Start with retrieving Datetimes |
|
973 | - * 2. For each datetime get related tickets |
|
974 | - * 3. For each ticket get related prices |
|
975 | - */ |
|
976 | - /** @var EEM_Datetime $datetime_model */ |
|
977 | - $datetime_model = EE_Registry::instance()->load_model('Datetime', [$timezone]); |
|
978 | - $datetimes = $datetime_model->get_all_event_dates($EVT_ID); |
|
979 | - $main_template_args['total_dtt_rows'] = count($datetimes); |
|
980 | - |
|
981 | - /** |
|
982 | - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486 |
|
983 | - * for why we are counting $datetime_row and then setting that on the Datetime object |
|
984 | - */ |
|
985 | - $datetime_row = 1; |
|
986 | - foreach ($datetimes as $datetime) { |
|
987 | - $DTT_ID = $datetime->get('DTT_ID'); |
|
988 | - $datetime->set('DTT_order', $datetime_row); |
|
989 | - $existing_datetime_ids[] = $DTT_ID; |
|
990 | - // tickets attached |
|
991 | - $related_tickets = $datetime->ID() > 0 |
|
992 | - ? $datetime->get_many_related( |
|
993 | - 'Ticket', |
|
994 | - [ |
|
995 | - [ |
|
996 | - 'OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0], |
|
997 | - ], |
|
998 | - 'default_where_conditions' => 'none', |
|
999 | - 'order_by' => ['TKT_order' => 'ASC'], |
|
1000 | - ] |
|
1001 | - ) |
|
1002 | - : []; |
|
1003 | - // if there are no related tickets this is likely a new event OR auto-draft |
|
1004 | - // event so we need to generate the default tickets because datetimes |
|
1005 | - // ALWAYS have at least one related ticket!!. EXCEPT, we dont' do this if there is already more than one |
|
1006 | - // datetime on the event. |
|
1007 | - if (empty($related_tickets) && count($datetimes) < 2) { |
|
1008 | - /** @var EEM_Ticket $ticket_model */ |
|
1009 | - $ticket_model = EE_Registry::instance()->load_model('Ticket'); |
|
1010 | - $related_tickets = $ticket_model->get_all_default_tickets(); |
|
1011 | - // this should be ordered by TKT_ID, so let's grab the first default ticket |
|
1012 | - // (which will be the main default) and ensure it has any default prices added to it (but do NOT save). |
|
1013 | - $default_prices = EEM_Price::instance()->get_all_default_prices(); |
|
1014 | - $main_default_ticket = reset($related_tickets); |
|
1015 | - if ($main_default_ticket instanceof EE_Ticket) { |
|
1016 | - foreach ($default_prices as $default_price) { |
|
1017 | - if ($default_price instanceof EE_Price && $default_price->is_base_price()) { |
|
1018 | - continue; |
|
1019 | - } |
|
1020 | - $main_default_ticket->cache('Price', $default_price); |
|
1021 | - } |
|
1022 | - } |
|
1023 | - } |
|
1024 | - // we can't actually setup rows in this loop yet cause we don't know all |
|
1025 | - // the unique tickets for this event yet (tickets are linked through all datetimes). |
|
1026 | - // So we're going to temporarily cache some of that information. |
|
1027 | - // loop through and setup the ticket rows and make sure the order is set. |
|
1028 | - foreach ($related_tickets as $ticket) { |
|
1029 | - $TKT_ID = $ticket->get('TKT_ID'); |
|
1030 | - $ticket_row = $ticket->get('TKT_row'); |
|
1031 | - // we only want unique tickets in our final display!! |
|
1032 | - if (! in_array($TKT_ID, $existing_ticket_ids, true)) { |
|
1033 | - $existing_ticket_ids[] = $TKT_ID; |
|
1034 | - $all_tickets[] = $ticket; |
|
1035 | - } |
|
1036 | - // temporary cache of this ticket info for this datetime for later processing of datetime rows. |
|
1037 | - $datetime_tickets[ $DTT_ID ][] = $ticket_row; |
|
1038 | - // temporary cache of this datetime info for this ticket for later processing of ticket rows. |
|
1039 | - if ( |
|
1040 | - ! isset($ticket_datetimes[ $TKT_ID ]) |
|
1041 | - || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true) |
|
1042 | - ) { |
|
1043 | - $ticket_datetimes[ $TKT_ID ][] = $datetime_row; |
|
1044 | - } |
|
1045 | - } |
|
1046 | - $datetime_row++; |
|
1047 | - } |
|
1048 | - $main_template_args['total_ticket_rows'] = count($existing_ticket_ids); |
|
1049 | - $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids); |
|
1050 | - $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids); |
|
1051 | - // sort $all_tickets by order |
|
1052 | - usort( |
|
1053 | - $all_tickets, |
|
1054 | - function (EE_Ticket $a, EE_Ticket $b) { |
|
1055 | - $a_order = (int) $a->get('TKT_order'); |
|
1056 | - $b_order = (int) $b->get('TKT_order'); |
|
1057 | - if ($a_order === $b_order) { |
|
1058 | - return 0; |
|
1059 | - } |
|
1060 | - return ($a_order < $b_order) ? -1 : 1; |
|
1061 | - } |
|
1062 | - ); |
|
1063 | - // k NOW we have all the data we need for setting up the datetime rows |
|
1064 | - // and ticket rows so we start our datetime loop again. |
|
1065 | - $datetime_row = 1; |
|
1066 | - foreach ($datetimes as $datetime) { |
|
1067 | - $main_template_args['datetime_rows'] .= $this->_get_datetime_row( |
|
1068 | - $datetime_row, |
|
1069 | - $datetime, |
|
1070 | - $datetime_tickets, |
|
1071 | - $all_tickets, |
|
1072 | - false, |
|
1073 | - $datetimes |
|
1074 | - ); |
|
1075 | - $datetime_row++; |
|
1076 | - } |
|
1077 | - // then loop through all tickets for the ticket rows. |
|
1078 | - $ticket_row = 1; |
|
1079 | - foreach ($all_tickets as $ticket) { |
|
1080 | - $main_template_args['ticket_rows'] .= $this->_get_ticket_row( |
|
1081 | - $ticket_row, |
|
1082 | - $ticket, |
|
1083 | - $ticket_datetimes, |
|
1084 | - $datetimes, |
|
1085 | - false, |
|
1086 | - $all_tickets |
|
1087 | - ); |
|
1088 | - $ticket_row++; |
|
1089 | - } |
|
1090 | - $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets); |
|
1091 | - |
|
1092 | - $status_change_notice = LoaderFactory::getLoader()->getShared( |
|
1093 | - 'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice' |
|
1094 | - ); |
|
1095 | - |
|
1096 | - $main_template_args['status_change_notice'] = $status_change_notice->display( |
|
1097 | - '__event-editor', |
|
1098 | - 'espresso-events' |
|
1099 | - ); |
|
1100 | - |
|
1101 | - EEH_Template::display_template( |
|
1102 | - PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php', |
|
1103 | - $main_template_args |
|
1104 | - ); |
|
1105 | - } |
|
1106 | - |
|
1107 | - |
|
1108 | - /** |
|
1109 | - * @param int $datetime_row |
|
1110 | - * @param EE_Datetime $datetime |
|
1111 | - * @param array $datetime_tickets |
|
1112 | - * @param array $all_tickets |
|
1113 | - * @param bool $default |
|
1114 | - * @param array $all_datetimes |
|
1115 | - * @return string |
|
1116 | - * @throws DomainException |
|
1117 | - * @throws EE_Error |
|
1118 | - * @throws ReflectionException |
|
1119 | - */ |
|
1120 | - protected function _get_datetime_row( |
|
1121 | - int $datetime_row, |
|
1122 | - EE_Datetime $datetime, |
|
1123 | - array $datetime_tickets = [], |
|
1124 | - array $all_tickets = [], |
|
1125 | - bool $default = false, |
|
1126 | - array $all_datetimes = [] |
|
1127 | - ): string { |
|
1128 | - return EEH_Template::display_template( |
|
1129 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php', |
|
1130 | - [ |
|
1131 | - 'dtt_edit_row' => $this->_get_dtt_edit_row( |
|
1132 | - $datetime_row, |
|
1133 | - $datetime, |
|
1134 | - $default, |
|
1135 | - $all_datetimes |
|
1136 | - ), |
|
1137 | - 'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row( |
|
1138 | - $datetime_row, |
|
1139 | - $datetime, |
|
1140 | - $datetime_tickets, |
|
1141 | - $all_tickets, |
|
1142 | - $default |
|
1143 | - ), |
|
1144 | - 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1145 | - ], |
|
1146 | - true |
|
1147 | - ); |
|
1148 | - } |
|
1149 | - |
|
1150 | - |
|
1151 | - /** |
|
1152 | - * This method is used to generate a datetime fields edit row. |
|
1153 | - * The same row is used to generate a row with valid DTT objects |
|
1154 | - * and the default row that is used as the skeleton by the js. |
|
1155 | - * |
|
1156 | - * @param int $datetime_row The row number for the row being generated. |
|
1157 | - * @param EE_Datetime|null $datetime |
|
1158 | - * @param bool $default Whether a default row is being generated or not. |
|
1159 | - * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor. |
|
1160 | - * @return string |
|
1161 | - * @throws EE_Error |
|
1162 | - * @throws ReflectionException |
|
1163 | - */ |
|
1164 | - protected function _get_dtt_edit_row( |
|
1165 | - int $datetime_row, |
|
1166 | - ?EE_Datetime $datetime, |
|
1167 | - bool $default, |
|
1168 | - array $all_datetimes |
|
1169 | - ): string { |
|
1170 | - // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true. |
|
1171 | - $default = ! $datetime instanceof EE_Datetime ? true : $default; |
|
1172 | - $template_args = [ |
|
1173 | - 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1174 | - 'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes', |
|
1175 | - 'edit_dtt_expanded' => '', |
|
1176 | - 'DTT_ID' => $default ? '' : $datetime->ID(), |
|
1177 | - 'DTT_name' => $default ? '' : $datetime->get_f('DTT_name'), |
|
1178 | - 'DTT_description' => $default ? '' : $datetime->get_f('DTT_description'), |
|
1179 | - 'DTT_EVT_start' => $default ? '' : $datetime->start_date($this->_date_time_format), |
|
1180 | - 'DTT_EVT_end' => $default ? '' : $datetime->end_date($this->_date_time_format), |
|
1181 | - 'DTT_reg_limit' => $default |
|
1182 | - ? '' |
|
1183 | - : $datetime->get_pretty( |
|
1184 | - 'DTT_reg_limit', |
|
1185 | - 'input' |
|
1186 | - ), |
|
1187 | - 'DTT_order' => $default ? 'DTTNUM' : $datetime_row, |
|
1188 | - 'dtt_sold' => $default ? '0' : $datetime->get('DTT_sold'), |
|
1189 | - 'dtt_reserved' => $default ? '0' : $datetime->reserved(), |
|
1190 | - 'clone_icon' => ! empty($datetime) && $datetime->get('DTT_sold') > 0 |
|
1191 | - ? '' |
|
1192 | - : 'clone-icon ee-icon ee-icon-clone clickable', |
|
1193 | - 'trash_icon' => ! empty($datetime) && $datetime->get('DTT_sold') > 0 |
|
1194 | - ? 'dashicons dashicons-lock' |
|
1195 | - : 'trash-icon dashicons dashicons-post-trash clickable', |
|
1196 | - 'reg_list_url' => $default || ! $datetime->event() instanceof EE_Event |
|
1197 | - ? '' |
|
1198 | - : EE_Admin_Page::add_query_args_and_nonce( |
|
1199 | - ['event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()], |
|
1200 | - REG_ADMIN_URL |
|
1201 | - ), |
|
1202 | - ]; |
|
1203 | - $template_args['show_trash'] = count($all_datetimes) === 1 |
|
1204 | - && $template_args['trash_icon'] !== 'dashicons dashicons-lock' |
|
1205 | - ? 'display:none' |
|
1206 | - : ''; |
|
1207 | - // allow filtering of template args at this point. |
|
1208 | - $template_args = apply_filters( |
|
1209 | - 'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args', |
|
1210 | - $template_args, |
|
1211 | - $datetime_row, |
|
1212 | - $datetime, |
|
1213 | - $default, |
|
1214 | - $all_datetimes, |
|
1215 | - $this->_is_creating_event |
|
1216 | - ); |
|
1217 | - return EEH_Template::display_template( |
|
1218 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php', |
|
1219 | - $template_args, |
|
1220 | - true |
|
1221 | - ); |
|
1222 | - } |
|
1223 | - |
|
1224 | - |
|
1225 | - /** |
|
1226 | - * @param int $datetime_row |
|
1227 | - * @param EE_Datetime $datetime |
|
1228 | - * @param array $datetime_tickets |
|
1229 | - * @param array $all_tickets |
|
1230 | - * @param bool $default |
|
1231 | - * @return string |
|
1232 | - * @throws DomainException |
|
1233 | - * @throws EE_Error |
|
1234 | - * @throws ReflectionException |
|
1235 | - */ |
|
1236 | - protected function _get_dtt_attached_tickets_row( |
|
1237 | - int $datetime_row, |
|
1238 | - EE_Datetime $datetime, |
|
1239 | - array $datetime_tickets = [], |
|
1240 | - array $all_tickets = [], |
|
1241 | - bool $default = false |
|
1242 | - ): string { |
|
1243 | - $template_args = [ |
|
1244 | - 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1245 | - 'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes', |
|
1246 | - 'DTT_description' => $default ? '' : $datetime->get_f('DTT_description'), |
|
1247 | - 'datetime_tickets_list' => $default ? '<li class="hidden"></li>' : '', |
|
1248 | - 'show_tickets_row' => 'display:none;', |
|
1249 | - 'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link( |
|
1250 | - 'add_new_ticket_via_datetime', |
|
1251 | - $this->_adminpage_obj->page_slug, |
|
1252 | - $this->_adminpage_obj->get_req_action() |
|
1253 | - ), |
|
1254 | - // todo need to add this help info id to the Events_Admin_Page core file so we can access it here. |
|
1255 | - 'DTT_ID' => $default ? '' : $datetime->ID(), |
|
1256 | - ]; |
|
1257 | - // need to setup the list items (but only if this isn't a default skeleton setup) |
|
1258 | - if (! $default) { |
|
1259 | - $ticket_row = 1; |
|
1260 | - foreach ($all_tickets as $ticket) { |
|
1261 | - $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
|
1262 | - $datetime_row, |
|
1263 | - $ticket_row, |
|
1264 | - $datetime, |
|
1265 | - $ticket, |
|
1266 | - $datetime_tickets, |
|
1267 | - $default |
|
1268 | - ); |
|
1269 | - $ticket_row++; |
|
1270 | - } |
|
1271 | - } |
|
1272 | - // filter template args at this point |
|
1273 | - $template_args = apply_filters( |
|
1274 | - 'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args', |
|
1275 | - $template_args, |
|
1276 | - $datetime_row, |
|
1277 | - $datetime, |
|
1278 | - $datetime_tickets, |
|
1279 | - $all_tickets, |
|
1280 | - $default, |
|
1281 | - $this->_is_creating_event |
|
1282 | - ); |
|
1283 | - return EEH_Template::display_template( |
|
1284 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php', |
|
1285 | - $template_args, |
|
1286 | - true |
|
1287 | - ); |
|
1288 | - } |
|
1289 | - |
|
1290 | - |
|
1291 | - /** |
|
1292 | - * @param int $datetime_row |
|
1293 | - * @param int $ticket_row |
|
1294 | - * @param EE_Datetime|null $datetime |
|
1295 | - * @param EE_Ticket|null $ticket |
|
1296 | - * @param array $datetime_tickets |
|
1297 | - * @param bool $default |
|
1298 | - * @return string |
|
1299 | - * @throws EE_Error |
|
1300 | - * @throws ReflectionException |
|
1301 | - */ |
|
1302 | - protected function _get_datetime_tickets_list_item( |
|
1303 | - int $datetime_row, |
|
1304 | - int $ticket_row, |
|
1305 | - ?EE_Datetime $datetime, |
|
1306 | - ?EE_Ticket $ticket, |
|
1307 | - array $datetime_tickets = [], |
|
1308 | - bool $default = false |
|
1309 | - ): string { |
|
1310 | - $datetime_tickets = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ]) |
|
1311 | - ? $datetime_tickets[ $datetime->ID() ] |
|
1312 | - : []; |
|
1313 | - $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0; |
|
1314 | - $no_ticket = $default && empty($ticket); |
|
1315 | - $template_args = [ |
|
1316 | - 'dtt_row' => $default |
|
1317 | - ? 'DTTNUM' |
|
1318 | - : $datetime_row, |
|
1319 | - 'tkt_row' => $no_ticket |
|
1320 | - ? 'TICKETNUM' |
|
1321 | - : $ticket_row, |
|
1322 | - 'datetime_ticket_checked' => in_array($display_row, $datetime_tickets, true) |
|
1323 | - ? ' checked' |
|
1324 | - : '', |
|
1325 | - 'ticket_selected' => in_array($display_row, $datetime_tickets, true) |
|
1326 | - ? ' ticket-selected' |
|
1327 | - : '', |
|
1328 | - 'TKT_name' => $no_ticket |
|
1329 | - ? 'TKTNAME' |
|
1330 | - : $ticket->get('TKT_name'), |
|
1331 | - 'tkt_status_class' => $no_ticket || $this->_is_creating_event |
|
1332 | - ? ' tkt-status-' . EE_Ticket::onsale |
|
1333 | - : ' tkt-status-' . $ticket->ticket_status(), |
|
1334 | - ]; |
|
1335 | - // filter template args |
|
1336 | - $template_args = apply_filters( |
|
1337 | - 'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args', |
|
1338 | - $template_args, |
|
1339 | - $datetime_row, |
|
1340 | - $ticket_row, |
|
1341 | - $datetime, |
|
1342 | - $ticket, |
|
1343 | - $datetime_tickets, |
|
1344 | - $default, |
|
1345 | - $this->_is_creating_event |
|
1346 | - ); |
|
1347 | - return EEH_Template::display_template( |
|
1348 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php', |
|
1349 | - $template_args, |
|
1350 | - true |
|
1351 | - ); |
|
1352 | - } |
|
1353 | - |
|
1354 | - |
|
1355 | - /** |
|
1356 | - * This generates the ticket row for tickets. |
|
1357 | - * This same method is used to generate both the actual rows and the js skeleton row |
|
1358 | - * (when default === true) |
|
1359 | - * |
|
1360 | - * @param int $ticket_row Represents the row number being generated. |
|
1361 | - * @param EE_Ticket|null $ticket |
|
1362 | - * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket |
|
1363 | - * or empty for default |
|
1364 | - * @param EE_Datetime[] $all_datetimes All Datetimes on the event or empty for default. |
|
1365 | - * @param bool $default Whether default row being generated or not. |
|
1366 | - * @param EE_Ticket[] $all_tickets This is an array of all tickets attached to the event |
|
1367 | - * (or empty in the case of defaults) |
|
1368 | - * @return string |
|
1369 | - * @throws InvalidArgumentException |
|
1370 | - * @throws InvalidInterfaceException |
|
1371 | - * @throws InvalidDataTypeException |
|
1372 | - * @throws DomainException |
|
1373 | - * @throws EE_Error |
|
1374 | - * @throws ReflectionException |
|
1375 | - */ |
|
1376 | - protected function _get_ticket_row( |
|
1377 | - int $ticket_row, |
|
1378 | - ?EE_Ticket $ticket, |
|
1379 | - array $ticket_datetimes, |
|
1380 | - array $all_datetimes, |
|
1381 | - bool $default = false, |
|
1382 | - array $all_tickets = [] |
|
1383 | - ): string { |
|
1384 | - // if $ticket is not an instance of EE_Ticket then force default to true. |
|
1385 | - $default = ! $ticket instanceof EE_Ticket ? true : $default; |
|
1386 | - $prices = ! empty($ticket) && ! $default |
|
1387 | - ? $ticket->get_many_related( |
|
1388 | - 'Price', |
|
1389 | - ['default_where_conditions' => 'none', 'order_by' => ['PRC_order' => 'ASC']] |
|
1390 | - ) |
|
1391 | - : []; |
|
1392 | - // if there is only one price (which would be the base price) |
|
1393 | - // or NO prices and this ticket is a default ticket, |
|
1394 | - // let's just make sure there are no cached default prices on the object. |
|
1395 | - // This is done by not including any query_params. |
|
1396 | - if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) { |
|
1397 | - $prices = $ticket->prices(); |
|
1398 | - } |
|
1399 | - // check if we're dealing with a default ticket in which case |
|
1400 | - // we don't want any starting_ticket_datetime_row values set |
|
1401 | - // (otherwise there won't be any new relationships created for tickets based off of the default ticket). |
|
1402 | - // This will future proof in case there is ever any behaviour change between what the primary_key defaults to. |
|
1403 | - $default_datetime = $default || ($ticket instanceof EE_Ticket && $ticket->is_default()); |
|
1404 | - $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
1405 | - ? $ticket_datetimes[ $ticket->ID() ] |
|
1406 | - : []; |
|
1407 | - $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal(); |
|
1408 | - $base_price = $default ? null : $ticket->base_price(); |
|
1409 | - $count_price_mods = EEM_Price::instance()->get_all_default_prices(true); |
|
1410 | - // breaking out complicated condition for ticket_status |
|
1411 | - if ($default) { |
|
1412 | - $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale; |
|
1413 | - } else { |
|
1414 | - $ticket_status_class = $ticket->is_default() |
|
1415 | - ? ' tkt-status-' . EE_Ticket::onsale |
|
1416 | - : ' tkt-status-' . $ticket->ticket_status(); |
|
1417 | - } |
|
1418 | - // breaking out complicated condition for TKT_taxable |
|
1419 | - if ($default) { |
|
1420 | - $TKT_taxable = ''; |
|
1421 | - } else { |
|
1422 | - $TKT_taxable = $ticket->taxable() |
|
1423 | - ? 'checked' |
|
1424 | - : ''; |
|
1425 | - } |
|
1426 | - if ($default) { |
|
1427 | - $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence'); |
|
1428 | - } elseif ($ticket->is_default()) { |
|
1429 | - $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence'); |
|
1430 | - } else { |
|
1431 | - $TKT_status = $ticket->ticket_status(true); |
|
1432 | - } |
|
1433 | - if ($default) { |
|
1434 | - $TKT_min = ''; |
|
1435 | - } else { |
|
1436 | - $TKT_min = $ticket->min(); |
|
1437 | - if ($TKT_min === -1 || $TKT_min === 0) { |
|
1438 | - $TKT_min = ''; |
|
1439 | - } |
|
1440 | - } |
|
1441 | - $template_args = [ |
|
1442 | - 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1443 | - 'TKT_order' => $default ? 'TICKETNUM' : $ticket_row, |
|
1444 | - // on initial page load this will always be the correct order. |
|
1445 | - 'tkt_status_class' => $ticket_status_class, |
|
1446 | - 'display_edit_tkt_row' => 'display:none;', |
|
1447 | - 'edit_tkt_expanded' => '', |
|
1448 | - 'edit_tickets_name' => $default ? 'TICKETNAMEATTR' : 'edit_tickets', |
|
1449 | - 'TKT_name' => $default ? '' : $ticket->get_f('TKT_name'), |
|
1450 | - 'TKT_start_date' => $default |
|
1451 | - ? '' |
|
1452 | - : $ticket->get_date('TKT_start_date', $this->_date_time_format), |
|
1453 | - 'TKT_end_date' => $default |
|
1454 | - ? '' |
|
1455 | - : $ticket->get_date('TKT_end_date', $this->_date_time_format), |
|
1456 | - 'TKT_status' => $TKT_status, |
|
1457 | - 'TKT_price' => $default |
|
1458 | - ? '' |
|
1459 | - : EEH_Template::format_currency( |
|
1460 | - $ticket->get_ticket_total_with_taxes(), |
|
1461 | - false, |
|
1462 | - false |
|
1463 | - ), |
|
1464 | - 'TKT_price_code' => EE_Registry::instance()->CFG->currency->code, |
|
1465 | - 'TKT_price_amount' => $default ? 0 : $ticket_subtotal, |
|
1466 | - 'TKT_qty' => $default |
|
1467 | - ? '' |
|
1468 | - : $ticket->get_pretty('TKT_qty', 'symbol'), |
|
1469 | - 'TKT_qty_for_input' => $default |
|
1470 | - ? '' |
|
1471 | - : $ticket->get_pretty('TKT_qty', 'input'), |
|
1472 | - 'TKT_uses' => $default |
|
1473 | - ? '' |
|
1474 | - : $ticket->get_pretty('TKT_uses', 'input'), |
|
1475 | - 'TKT_min' => $TKT_min, |
|
1476 | - 'TKT_max' => $default |
|
1477 | - ? '' |
|
1478 | - : $ticket->get_pretty('TKT_max', 'input'), |
|
1479 | - 'TKT_sold' => $default ? 0 : $ticket->tickets_sold(), |
|
1480 | - 'TKT_reserved' => $default ? 0 : $ticket->reserved(), |
|
1481 | - 'TKT_registrations' => $default |
|
1482 | - ? 0 |
|
1483 | - : $ticket->count_registrations( |
|
1484 | - [ |
|
1485 | - [ |
|
1486 | - 'STS_ID' => [ |
|
1487 | - '!=', |
|
1488 | - EEM_Registration::status_id_incomplete, |
|
1489 | - ], |
|
1490 | - ], |
|
1491 | - ] |
|
1492 | - ), |
|
1493 | - 'TKT_ID' => $default ? 0 : $ticket->ID(), |
|
1494 | - 'TKT_description' => $default ? '' : $ticket->get_f('TKT_description'), |
|
1495 | - 'TKT_is_default' => $default ? 0 : $ticket->is_default(), |
|
1496 | - 'TKT_required' => $default ? 0 : $ticket->required(), |
|
1497 | - 'TKT_is_default_selector' => '', |
|
1498 | - 'ticket_price_rows' => '', |
|
1499 | - 'TKT_base_price' => $default || ! $base_price instanceof EE_Price |
|
1500 | - ? '' |
|
1501 | - : $base_price->get_pretty('PRC_amount', 'localized_float'), |
|
1502 | - 'TKT_base_price_ID' => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(), |
|
1503 | - 'show_price_modifier' => count($prices) > 1 || ($default && $count_price_mods > 0) |
|
1504 | - ? '' |
|
1505 | - : 'display:none;', |
|
1506 | - 'show_price_mod_button' => count($prices) > 1 |
|
1507 | - || ($default && $count_price_mods > 0) |
|
1508 | - || (! $default && $ticket->deleted()) |
|
1509 | - ? 'display:none;' |
|
1510 | - : '', |
|
1511 | - 'total_price_rows' => count($prices) > 1 ? count($prices) : 1, |
|
1512 | - 'ticket_datetimes_list' => $default ? '<li class="hidden"></li>' : '', |
|
1513 | - 'starting_ticket_datetime_rows' => $default || $default_datetime ? '' : implode(',', $ticket_datetimes), |
|
1514 | - 'ticket_datetime_rows' => $default ? '' : implode(',', $ticket_datetimes), |
|
1515 | - 'existing_ticket_price_ids' => $default ? '' : implode(',', array_keys($prices)), |
|
1516 | - 'ticket_template_id' => $default ? 0 : $ticket->get('TTM_ID'), |
|
1517 | - 'TKT_taxable' => $TKT_taxable, |
|
1518 | - 'display_subtotal' => $ticket instanceof EE_Ticket && $ticket->taxable() |
|
1519 | - ? '' |
|
1520 | - : 'display:none;', |
|
1521 | - 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
1522 | - 'TKT_subtotal_amount_display' => EEH_Template::format_currency( |
|
1523 | - $ticket_subtotal, |
|
1524 | - false, |
|
1525 | - false |
|
1526 | - ), |
|
1527 | - 'TKT_subtotal_amount' => $ticket_subtotal, |
|
1528 | - 'tax_rows' => $this->_get_tax_rows($ticket_row, $ticket), |
|
1529 | - 'disabled' => $ticket instanceof EE_Ticket && $ticket->deleted(), |
|
1530 | - 'ticket_archive_class' => $ticket instanceof EE_Ticket && $ticket->deleted() |
|
1531 | - ? ' ticket-archived' |
|
1532 | - : '', |
|
1533 | - 'trash_icon' => $ticket instanceof EE_Ticket |
|
1534 | - && $ticket->deleted() |
|
1535 | - && ! $ticket->is_permanently_deleteable() |
|
1536 | - ? 'dashicons dashicons-lock ' |
|
1537 | - : 'trash-icon dashicons dashicons-post-trash clickable', |
|
1538 | - 'clone_icon' => $ticket instanceof EE_Ticket && $ticket->deleted() |
|
1539 | - ? '' |
|
1540 | - : 'clone-icon ee-icon ee-icon-clone clickable', |
|
1541 | - ]; |
|
1542 | - $template_args['trash_hidden'] = count($all_tickets) === 1 |
|
1543 | - && $template_args['trash_icon'] !== 'dashicons dashicons-lock' |
|
1544 | - ? 'display:none' |
|
1545 | - : ''; |
|
1546 | - // handle rows that should NOT be empty |
|
1547 | - if (empty($template_args['TKT_start_date'])) { |
|
1548 | - // if empty then the start date will be now. |
|
1549 | - $template_args['TKT_start_date'] = date( |
|
1550 | - $this->_date_time_format, |
|
1551 | - current_time('timestamp') |
|
1552 | - ); |
|
1553 | - $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1554 | - } |
|
1555 | - if (empty($template_args['TKT_end_date'])) { |
|
1556 | - // get the earliest datetime (if present); |
|
1557 | - $earliest_datetime = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 |
|
1558 | - ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related( |
|
1559 | - 'Datetime', |
|
1560 | - ['order_by' => ['DTT_EVT_start' => 'ASC']] |
|
1561 | - ) |
|
1562 | - : null; |
|
1563 | - if (! empty($earliest_datetime)) { |
|
1564 | - $template_args['TKT_end_date'] = $earliest_datetime->get_datetime( |
|
1565 | - 'DTT_EVT_start', |
|
1566 | - $this->_date_time_format |
|
1567 | - ); |
|
1568 | - } else { |
|
1569 | - // default so let's just use what's been set for the default date-time which is 30 days from now. |
|
1570 | - $template_args['TKT_end_date'] = date( |
|
1571 | - $this->_date_time_format, |
|
1572 | - mktime( |
|
1573 | - 24, |
|
1574 | - 0, |
|
1575 | - 0, |
|
1576 | - date('m'), |
|
1577 | - date('d') + 29, |
|
1578 | - date('Y') |
|
1579 | - ) |
|
1580 | - ); |
|
1581 | - } |
|
1582 | - $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1583 | - } |
|
1584 | - // generate ticket_datetime items |
|
1585 | - if (! $default) { |
|
1586 | - $datetime_row = 1; |
|
1587 | - foreach ($all_datetimes as $datetime) { |
|
1588 | - $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item( |
|
1589 | - $datetime_row, |
|
1590 | - $ticket_row, |
|
1591 | - $datetime, |
|
1592 | - $ticket, |
|
1593 | - $ticket_datetimes, |
|
1594 | - $default |
|
1595 | - ); |
|
1596 | - $datetime_row++; |
|
1597 | - } |
|
1598 | - } |
|
1599 | - $price_row = 1; |
|
1600 | - foreach ($prices as $price) { |
|
1601 | - if (! $price instanceof EE_Price) { |
|
1602 | - continue; |
|
1603 | - } |
|
1604 | - if ($price->is_base_price()) { |
|
1605 | - $price_row++; |
|
1606 | - continue; |
|
1607 | - } |
|
1608 | - |
|
1609 | - $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1); |
|
1610 | - $show_create = ! (count($prices) > 1 && count($prices) !== $price_row); |
|
1611 | - |
|
1612 | - $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row( |
|
1613 | - $ticket_row, |
|
1614 | - $price_row, |
|
1615 | - $price, |
|
1616 | - $default, |
|
1617 | - $ticket, |
|
1618 | - $show_trash, |
|
1619 | - $show_create |
|
1620 | - ); |
|
1621 | - $price_row++; |
|
1622 | - } |
|
1623 | - // filter $template_args |
|
1624 | - $template_args = apply_filters( |
|
1625 | - 'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args', |
|
1626 | - $template_args, |
|
1627 | - $ticket_row, |
|
1628 | - $ticket, |
|
1629 | - $ticket_datetimes, |
|
1630 | - $all_datetimes, |
|
1631 | - $default, |
|
1632 | - $all_tickets, |
|
1633 | - $this->_is_creating_event |
|
1634 | - ); |
|
1635 | - return EEH_Template::display_template( |
|
1636 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php', |
|
1637 | - $template_args, |
|
1638 | - true |
|
1639 | - ); |
|
1640 | - } |
|
1641 | - |
|
1642 | - |
|
1643 | - /** |
|
1644 | - * @param int $ticket_row |
|
1645 | - * @param EE_Ticket|null $ticket |
|
1646 | - * @return string |
|
1647 | - * @throws DomainException |
|
1648 | - * @throws EE_Error |
|
1649 | - * @throws ReflectionException |
|
1650 | - */ |
|
1651 | - protected function _get_tax_rows(int $ticket_row, ?EE_Ticket $ticket): string |
|
1652 | - { |
|
1653 | - $tax_rows = ''; |
|
1654 | - /** @var EE_Price[] $taxes */ |
|
1655 | - $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin(); |
|
1656 | - foreach ($taxes as $tax) { |
|
1657 | - $tax_added = $this->_get_tax_added($tax, $ticket); |
|
1658 | - $template_args = [ |
|
1659 | - 'display_tax' => ! empty($ticket) && $ticket->get('TKT_taxable') |
|
1660 | - ? '' |
|
1661 | - : 'display:none;', |
|
1662 | - 'tax_id' => $tax->ID(), |
|
1663 | - 'tkt_row' => $ticket_row, |
|
1664 | - 'tax_label' => $tax->get('PRC_name'), |
|
1665 | - 'tax_added' => $tax_added, |
|
1666 | - 'tax_added_display' => EEH_Template::format_currency($tax_added, false, false), |
|
1667 | - 'tax_amount' => $tax->get('PRC_amount'), |
|
1668 | - ]; |
|
1669 | - $template_args = apply_filters( |
|
1670 | - 'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args', |
|
1671 | - $template_args, |
|
1672 | - $ticket_row, |
|
1673 | - $ticket, |
|
1674 | - $this->_is_creating_event |
|
1675 | - ); |
|
1676 | - $tax_rows .= EEH_Template::display_template( |
|
1677 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php', |
|
1678 | - $template_args, |
|
1679 | - true |
|
1680 | - ); |
|
1681 | - } |
|
1682 | - return $tax_rows; |
|
1683 | - } |
|
1684 | - |
|
1685 | - |
|
1686 | - /** |
|
1687 | - * @param EE_Price $tax |
|
1688 | - * @param EE_Ticket|null $ticket |
|
1689 | - * @return float|int |
|
1690 | - * @throws EE_Error |
|
1691 | - * @throws ReflectionException |
|
1692 | - */ |
|
1693 | - protected function _get_tax_added(EE_Price $tax, ?EE_Ticket $ticket) |
|
1694 | - { |
|
1695 | - $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal(); |
|
1696 | - return $subtotal * $tax->get('PRC_amount') / 100; |
|
1697 | - } |
|
1698 | - |
|
1699 | - |
|
1700 | - /** |
|
1701 | - * @param int $ticket_row |
|
1702 | - * @param int $price_row |
|
1703 | - * @param EE_Price|null $price |
|
1704 | - * @param bool $default |
|
1705 | - * @param EE_Ticket|null $ticket |
|
1706 | - * @param bool $show_trash |
|
1707 | - * @param bool $show_create |
|
1708 | - * @return string |
|
1709 | - * @throws InvalidArgumentException |
|
1710 | - * @throws InvalidInterfaceException |
|
1711 | - * @throws InvalidDataTypeException |
|
1712 | - * @throws DomainException |
|
1713 | - * @throws EE_Error |
|
1714 | - * @throws ReflectionException |
|
1715 | - */ |
|
1716 | - protected function _get_ticket_price_row( |
|
1717 | - int $ticket_row, |
|
1718 | - int $price_row, |
|
1719 | - ?EE_Price $price, |
|
1720 | - bool $default, |
|
1721 | - ?EE_Ticket $ticket, |
|
1722 | - bool $show_trash = true, |
|
1723 | - bool $show_create = true |
|
1724 | - ): string { |
|
1725 | - $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted'); |
|
1726 | - $template_args = [ |
|
1727 | - 'tkt_row' => $default && empty($ticket) |
|
1728 | - ? 'TICKETNUM' |
|
1729 | - : $ticket_row, |
|
1730 | - 'PRC_order' => $default && empty($price) |
|
1731 | - ? 'PRICENUM' |
|
1732 | - : $price_row, |
|
1733 | - 'edit_prices_name' => $default && empty($price) |
|
1734 | - ? 'PRICENAMEATTR' |
|
1735 | - : 'edit_prices', |
|
1736 | - 'price_type_selector' => $default && empty($price) |
|
1737 | - ? $this->_get_base_price_template($ticket_row, $price_row, $price, true) |
|
1738 | - : $this->_get_price_type_selector( |
|
1739 | - $ticket_row, |
|
1740 | - $price_row, |
|
1741 | - $price, |
|
1742 | - $default, |
|
1743 | - $send_disabled |
|
1744 | - ), |
|
1745 | - 'PRC_ID' => $default && empty($price) |
|
1746 | - ? 0 |
|
1747 | - : $price->ID(), |
|
1748 | - 'PRC_is_default' => $default && empty($price) |
|
1749 | - ? 0 |
|
1750 | - : $price->get('PRC_is_default'), |
|
1751 | - 'PRC_name' => $default && empty($price) |
|
1752 | - ? '' |
|
1753 | - : $price->get('PRC_name'), |
|
1754 | - 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
1755 | - 'show_plus_or_minus' => $default && empty($price) |
|
1756 | - ? '' |
|
1757 | - : 'display:none;', |
|
1758 | - 'show_plus' => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price()) |
|
1759 | - ? 'display:none;' |
|
1760 | - : '', |
|
1761 | - 'show_minus' => ($default && empty($price)) || ! $price->is_discount() |
|
1762 | - ? 'display:none;' |
|
1763 | - : '', |
|
1764 | - 'show_currency_symbol' => ($default && empty($price)) || $price->is_percent() |
|
1765 | - ? 'display:none' |
|
1766 | - : '', |
|
1767 | - 'PRC_amount' => $default && empty($price) |
|
1768 | - ? 0 |
|
1769 | - : $price->get_pretty('PRC_amount', 'localized_float'), |
|
1770 | - 'show_percentage' => ($default && empty($price)) || ! $price->is_percent() |
|
1771 | - ? 'display:none;' |
|
1772 | - : '', |
|
1773 | - 'show_trash_icon' => $show_trash |
|
1774 | - ? '' |
|
1775 | - : ' style="display:none;"', |
|
1776 | - 'show_create_button' => $show_create |
|
1777 | - ? '' |
|
1778 | - : ' style="display:none;"', |
|
1779 | - 'PRC_desc' => $default && empty($price) |
|
1780 | - ? '' |
|
1781 | - : $price->get('PRC_desc'), |
|
1782 | - 'disabled' => ! empty($ticket) && $ticket->get('TKT_deleted'), |
|
1783 | - ]; |
|
1784 | - $template_args = apply_filters( |
|
1785 | - 'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args', |
|
1786 | - $template_args, |
|
1787 | - $ticket_row, |
|
1788 | - $price_row, |
|
1789 | - $price, |
|
1790 | - $default, |
|
1791 | - $ticket, |
|
1792 | - $show_trash, |
|
1793 | - $show_create, |
|
1794 | - $this->_is_creating_event |
|
1795 | - ); |
|
1796 | - return EEH_Template::display_template( |
|
1797 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php', |
|
1798 | - $template_args, |
|
1799 | - true |
|
1800 | - ); |
|
1801 | - } |
|
1802 | - |
|
1803 | - |
|
1804 | - /** |
|
1805 | - * @param int $ticket_row |
|
1806 | - * @param int $price_row |
|
1807 | - * @param EE_Price|null $price |
|
1808 | - * @param bool $default |
|
1809 | - * @param bool $disabled |
|
1810 | - * @return string |
|
1811 | - * @throws ReflectionException |
|
1812 | - * @throws InvalidArgumentException |
|
1813 | - * @throws InvalidInterfaceException |
|
1814 | - * @throws InvalidDataTypeException |
|
1815 | - * @throws DomainException |
|
1816 | - * @throws EE_Error |
|
1817 | - */ |
|
1818 | - protected function _get_price_type_selector( |
|
1819 | - int $ticket_row, |
|
1820 | - int $price_row, |
|
1821 | - ?EE_Price $price, |
|
1822 | - bool $default, |
|
1823 | - bool $disabled = false |
|
1824 | - ): string { |
|
1825 | - if ($price->is_base_price()) { |
|
1826 | - return $this->_get_base_price_template( |
|
1827 | - $ticket_row, |
|
1828 | - $price_row, |
|
1829 | - $price, |
|
1830 | - $default |
|
1831 | - ); |
|
1832 | - } |
|
1833 | - return $this->_get_price_modifier_template( |
|
1834 | - $ticket_row, |
|
1835 | - $price_row, |
|
1836 | - $price, |
|
1837 | - $default, |
|
1838 | - $disabled |
|
1839 | - ); |
|
1840 | - } |
|
1841 | - |
|
1842 | - |
|
1843 | - /** |
|
1844 | - * @param int $ticket_row |
|
1845 | - * @param int $price_row |
|
1846 | - * @param EE_Price|null $price |
|
1847 | - * @param bool $default |
|
1848 | - * @return string |
|
1849 | - * @throws DomainException |
|
1850 | - * @throws EE_Error |
|
1851 | - * @throws ReflectionException |
|
1852 | - */ |
|
1853 | - protected function _get_base_price_template( |
|
1854 | - int $ticket_row, |
|
1855 | - int $price_row, |
|
1856 | - ?EE_Price $price, |
|
1857 | - bool $default |
|
1858 | - ): string { |
|
1859 | - $template_args = [ |
|
1860 | - 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1861 | - 'PRC_order' => $default && empty($price) ? 'PRICENUM' : $price_row, |
|
1862 | - 'PRT_ID' => $default && empty($price) ? 1 : $price->get('PRT_ID'), |
|
1863 | - 'PRT_name' => esc_html__('Price', 'event_espresso'), |
|
1864 | - 'price_selected_operator' => '+', |
|
1865 | - 'price_selected_is_percent' => 0, |
|
1866 | - ]; |
|
1867 | - $template_args = apply_filters( |
|
1868 | - 'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args', |
|
1869 | - $template_args, |
|
1870 | - $ticket_row, |
|
1871 | - $price_row, |
|
1872 | - $price, |
|
1873 | - $default, |
|
1874 | - $this->_is_creating_event |
|
1875 | - ); |
|
1876 | - return EEH_Template::display_template( |
|
1877 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php', |
|
1878 | - $template_args, |
|
1879 | - true |
|
1880 | - ); |
|
1881 | - } |
|
1882 | - |
|
1883 | - |
|
1884 | - /** |
|
1885 | - * @param int $ticket_row |
|
1886 | - * @param int $price_row |
|
1887 | - * @param EE_Price|null $price |
|
1888 | - * @param bool $default |
|
1889 | - * @param bool $disabled |
|
1890 | - * @return string |
|
1891 | - * @throws ReflectionException |
|
1892 | - * @throws InvalidArgumentException |
|
1893 | - * @throws InvalidInterfaceException |
|
1894 | - * @throws InvalidDataTypeException |
|
1895 | - * @throws DomainException |
|
1896 | - * @throws EE_Error |
|
1897 | - */ |
|
1898 | - protected function _get_price_modifier_template( |
|
1899 | - int $ticket_row, |
|
1900 | - int $price_row, |
|
1901 | - ?EE_Price $price, |
|
1902 | - bool $default, |
|
1903 | - bool $disabled = false |
|
1904 | - ): string { |
|
1905 | - $select_name = $default && ! $price instanceof EE_Price |
|
1906 | - ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]' |
|
1907 | - : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]'; |
|
1908 | - /** @var EEM_Price_Type $price_type_model */ |
|
1909 | - $price_type_model = EE_Registry::instance()->load_model('Price_Type'); |
|
1910 | - $price_types = $price_type_model->get_all( |
|
1911 | - [ |
|
1912 | - [ |
|
1913 | - 'OR' => [ |
|
1914 | - 'PBT_ID' => '2', |
|
1915 | - 'PBT_ID*' => '3', |
|
1916 | - ], |
|
1917 | - ], |
|
1918 | - ] |
|
1919 | - ); |
|
1920 | - $all_price_types = $default && ! $price instanceof EE_Price |
|
1921 | - ? [esc_html__('Select Modifier', 'event_espresso')] |
|
1922 | - : []; |
|
1923 | - $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type(); |
|
1924 | - $price_option_spans = ''; |
|
1925 | - // setup price types for selector |
|
1926 | - foreach ($price_types as $price_type) { |
|
1927 | - if (! $price_type instanceof EE_Price_Type) { |
|
1928 | - continue; |
|
1929 | - } |
|
1930 | - $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name'); |
|
1931 | - // while we're in the loop let's setup the option spans used by js |
|
1932 | - $span_args = [ |
|
1933 | - 'PRT_ID' => $price_type->ID(), |
|
1934 | - 'PRT_operator' => $price_type->is_discount() ? '-' : '+', |
|
1935 | - 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0, |
|
1936 | - ]; |
|
1937 | - $price_option_spans .= EEH_Template::display_template( |
|
1938 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php', |
|
1939 | - $span_args, |
|
1940 | - true |
|
1941 | - ); |
|
1942 | - } |
|
1943 | - |
|
1944 | - $select_name = $disabled |
|
1945 | - ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]' |
|
1946 | - : $select_name; |
|
1947 | - |
|
1948 | - $select_input = new EE_Select_Input( |
|
1949 | - $all_price_types, |
|
1950 | - [ |
|
1951 | - 'default' => $selected_price_type_id, |
|
1952 | - 'html_name' => $select_name, |
|
1953 | - 'html_class' => 'edit-price-PRT_ID', |
|
1954 | - 'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"', |
|
1955 | - ] |
|
1956 | - ); |
|
1957 | - |
|
1958 | - $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+'; |
|
1959 | - $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator; |
|
1960 | - $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0; |
|
1961 | - $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent; |
|
1962 | - $template_args = [ |
|
1963 | - 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1964 | - 'PRC_order' => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row, |
|
1965 | - 'price_modifier_selector' => $select_input->get_html_for_input(), |
|
1966 | - 'main_name' => $select_name, |
|
1967 | - 'selected_price_type_id' => $selected_price_type_id, |
|
1968 | - 'price_option_spans' => $price_option_spans, |
|
1969 | - 'price_selected_operator' => $price_selected_operator, |
|
1970 | - 'price_selected_is_percent' => $price_selected_is_percent, |
|
1971 | - 'disabled' => $disabled, |
|
1972 | - ]; |
|
1973 | - $template_args = apply_filters( |
|
1974 | - 'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args', |
|
1975 | - $template_args, |
|
1976 | - $ticket_row, |
|
1977 | - $price_row, |
|
1978 | - $price, |
|
1979 | - $default, |
|
1980 | - $disabled, |
|
1981 | - $this->_is_creating_event |
|
1982 | - ); |
|
1983 | - return EEH_Template::display_template( |
|
1984 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php', |
|
1985 | - $template_args, |
|
1986 | - true |
|
1987 | - ); |
|
1988 | - } |
|
1989 | - |
|
1990 | - |
|
1991 | - /** |
|
1992 | - * @param int $datetime_row |
|
1993 | - * @param int $ticket_row |
|
1994 | - * @param EE_Datetime|null $datetime |
|
1995 | - * @param EE_Ticket|null $ticket |
|
1996 | - * @param array $ticket_datetimes |
|
1997 | - * @param bool $default |
|
1998 | - * @return string |
|
1999 | - * @throws DomainException |
|
2000 | - * @throws EE_Error |
|
2001 | - * @throws ReflectionException |
|
2002 | - */ |
|
2003 | - protected function _get_ticket_datetime_list_item( |
|
2004 | - int $datetime_row, |
|
2005 | - int $ticket_row, |
|
2006 | - ?EE_Datetime $datetime, |
|
2007 | - ?EE_Ticket $ticket, |
|
2008 | - array $ticket_datetimes = [], |
|
2009 | - bool $default = false |
|
2010 | - ): string { |
|
2011 | - $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
2012 | - ? $ticket_datetimes[ $ticket->ID() ] |
|
2013 | - : []; |
|
2014 | - $template_args = [ |
|
2015 | - 'dtt_row' => $default && ! $datetime instanceof EE_Datetime |
|
2016 | - ? 'DTTNUM' |
|
2017 | - : $datetime_row, |
|
2018 | - 'tkt_row' => $default |
|
2019 | - ? 'TICKETNUM' |
|
2020 | - : $ticket_row, |
|
2021 | - 'ticket_datetime_selected' => in_array($datetime_row, $ticket_datetimes, true) |
|
2022 | - ? ' ticket-selected' |
|
2023 | - : '', |
|
2024 | - 'ticket_datetime_checked' => in_array($datetime_row, $ticket_datetimes, true) |
|
2025 | - ? ' checked' |
|
2026 | - : '', |
|
2027 | - 'DTT_name' => $default && empty($datetime) |
|
2028 | - ? 'DTTNAME' |
|
2029 | - : $datetime->get_dtt_display_name(true), |
|
2030 | - 'tkt_status_class' => '', |
|
2031 | - ]; |
|
2032 | - $template_args = apply_filters( |
|
2033 | - 'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args', |
|
2034 | - $template_args, |
|
2035 | - $datetime_row, |
|
2036 | - $ticket_row, |
|
2037 | - $datetime, |
|
2038 | - $ticket, |
|
2039 | - $ticket_datetimes, |
|
2040 | - $default, |
|
2041 | - $this->_is_creating_event |
|
2042 | - ); |
|
2043 | - return EEH_Template::display_template( |
|
2044 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php', |
|
2045 | - $template_args, |
|
2046 | - true |
|
2047 | - ); |
|
2048 | - } |
|
2049 | - |
|
2050 | - |
|
2051 | - /** |
|
2052 | - * @param array $all_datetimes |
|
2053 | - * @param array $all_tickets |
|
2054 | - * @return string |
|
2055 | - * @throws ReflectionException |
|
2056 | - * @throws InvalidArgumentException |
|
2057 | - * @throws InvalidInterfaceException |
|
2058 | - * @throws InvalidDataTypeException |
|
2059 | - * @throws DomainException |
|
2060 | - * @throws EE_Error |
|
2061 | - */ |
|
2062 | - protected function _get_ticket_js_structure(array $all_datetimes = [], array $all_tickets = []): string |
|
2063 | - { |
|
2064 | - $template_args = [ |
|
2065 | - 'default_datetime_edit_row' => $this->_get_dtt_edit_row( |
|
2066 | - 'DTTNUM', |
|
2067 | - null, |
|
2068 | - true, |
|
2069 | - $all_datetimes |
|
2070 | - ), |
|
2071 | - 'default_ticket_row' => $this->_get_ticket_row( |
|
2072 | - 'TICKETNUM', |
|
2073 | - null, |
|
2074 | - [], |
|
2075 | - [], |
|
2076 | - true |
|
2077 | - ), |
|
2078 | - 'default_price_row' => $this->_get_ticket_price_row( |
|
2079 | - 'TICKETNUM', |
|
2080 | - 'PRICENUM', |
|
2081 | - null, |
|
2082 | - true, |
|
2083 | - null |
|
2084 | - ), |
|
2085 | - |
|
2086 | - 'default_price_rows' => '', |
|
2087 | - 'default_base_price_amount' => 0, |
|
2088 | - 'default_base_price_name' => '', |
|
2089 | - 'default_base_price_description' => '', |
|
2090 | - 'default_price_modifier_selector_row' => $this->_get_price_modifier_template( |
|
2091 | - 'TICKETNUM', |
|
2092 | - 'PRICENUM', |
|
2093 | - null, |
|
2094 | - true |
|
2095 | - ), |
|
2096 | - 'default_available_tickets_for_datetime' => $this->_get_dtt_attached_tickets_row( |
|
2097 | - 'DTTNUM', |
|
2098 | - null, |
|
2099 | - [], |
|
2100 | - [], |
|
2101 | - true |
|
2102 | - ), |
|
2103 | - 'existing_available_datetime_tickets_list' => '', |
|
2104 | - 'existing_available_ticket_datetimes_list' => '', |
|
2105 | - 'new_available_datetime_ticket_list_item' => $this->_get_datetime_tickets_list_item( |
|
2106 | - 'DTTNUM', |
|
2107 | - 'TICKETNUM', |
|
2108 | - null, |
|
2109 | - null, |
|
2110 | - [], |
|
2111 | - true |
|
2112 | - ), |
|
2113 | - 'new_available_ticket_datetime_list_item' => $this->_get_ticket_datetime_list_item( |
|
2114 | - 'DTTNUM', |
|
2115 | - 'TICKETNUM', |
|
2116 | - null, |
|
2117 | - null, |
|
2118 | - [], |
|
2119 | - true |
|
2120 | - ), |
|
2121 | - ]; |
|
2122 | - $ticket_row = 1; |
|
2123 | - foreach ($all_tickets as $ticket) { |
|
2124 | - $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
|
2125 | - 'DTTNUM', |
|
2126 | - $ticket_row, |
|
2127 | - null, |
|
2128 | - $ticket, |
|
2129 | - [], |
|
2130 | - true |
|
2131 | - ); |
|
2132 | - $ticket_row++; |
|
2133 | - } |
|
2134 | - $datetime_row = 1; |
|
2135 | - foreach ($all_datetimes as $datetime) { |
|
2136 | - $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item( |
|
2137 | - $datetime_row, |
|
2138 | - 'TICKETNUM', |
|
2139 | - $datetime, |
|
2140 | - null, |
|
2141 | - [], |
|
2142 | - true |
|
2143 | - ); |
|
2144 | - $datetime_row++; |
|
2145 | - } |
|
2146 | - /** @var EEM_Price $price_model */ |
|
2147 | - $price_model = EE_Registry::instance()->load_model('Price'); |
|
2148 | - $default_prices = $price_model->get_all_default_prices(); |
|
2149 | - $price_row = 1; |
|
2150 | - foreach ($default_prices as $price) { |
|
2151 | - if (! $price instanceof EE_Price) { |
|
2152 | - continue; |
|
2153 | - } |
|
2154 | - if ($price->is_base_price()) { |
|
2155 | - $template_args['default_base_price_amount'] = $price->get_pretty( |
|
2156 | - 'PRC_amount', |
|
2157 | - 'localized_float' |
|
2158 | - ); |
|
2159 | - $template_args['default_base_price_name'] = $price->get('PRC_name'); |
|
2160 | - $template_args['default_base_price_description'] = $price->get('PRC_desc'); |
|
2161 | - $price_row++; |
|
2162 | - continue; |
|
2163 | - } |
|
2164 | - |
|
2165 | - $show_trash = ! ((count($default_prices) > 1 && $price_row === 1) || count($default_prices) === 1); |
|
2166 | - $show_create = ! (count($default_prices) > 1 && count($default_prices) !== $price_row); |
|
2167 | - |
|
2168 | - $template_args['default_price_rows'] .= $this->_get_ticket_price_row( |
|
2169 | - 'TICKETNUM', |
|
2170 | - $price_row, |
|
2171 | - $price, |
|
2172 | - true, |
|
2173 | - null, |
|
2174 | - $show_trash, |
|
2175 | - $show_create |
|
2176 | - ); |
|
2177 | - $price_row++; |
|
2178 | - } |
|
2179 | - $template_args = apply_filters( |
|
2180 | - 'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args', |
|
2181 | - $template_args, |
|
2182 | - $all_datetimes, |
|
2183 | - $all_tickets, |
|
2184 | - $this->_is_creating_event |
|
2185 | - ); |
|
2186 | - return EEH_Template::display_template( |
|
2187 | - PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php', |
|
2188 | - $template_args, |
|
2189 | - true |
|
2190 | - ); |
|
2191 | - } |
|
231 | + ], |
|
232 | + 'DTT_OVERSELL_WARNING' => [ |
|
233 | + 'datetime_ticket' => esc_html__( |
|
234 | + 'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.', |
|
235 | + 'event_espresso' |
|
236 | + ), |
|
237 | + 'ticket_datetime' => esc_html__( |
|
238 | + 'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.', |
|
239 | + 'event_espresso' |
|
240 | + ), |
|
241 | + ], |
|
242 | + 'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats( |
|
243 | + $this->_date_format_strings['date'], |
|
244 | + $this->_date_format_strings['time'] |
|
245 | + ), |
|
246 | + 'DTT_START_OF_WEEK' => ['dayValue' => (int) get_option('start_of_week')], |
|
247 | + ], |
|
248 | + ], |
|
249 | + ]; |
|
250 | + } |
|
251 | + |
|
252 | + |
|
253 | + /** |
|
254 | + * @param array $update_callbacks |
|
255 | + * @return array |
|
256 | + */ |
|
257 | + public function caf_updates(array $update_callbacks): array |
|
258 | + { |
|
259 | + unset($update_callbacks['_default_tickets_update']); |
|
260 | + $update_callbacks['datetime_and_tickets_caf_update'] = [$this, 'datetime_and_tickets_caf_update']; |
|
261 | + return $update_callbacks; |
|
262 | + } |
|
263 | + |
|
264 | + |
|
265 | + /** |
|
266 | + * Handles saving everything related to Tickets (datetimes, tickets, prices) |
|
267 | + * |
|
268 | + * @param EE_Event $event The Event object we're attaching data to |
|
269 | + * @param array $data The request data from the form |
|
270 | + * @throws ReflectionException |
|
271 | + * @throws Exception |
|
272 | + * @throws InvalidInterfaceException |
|
273 | + * @throws InvalidDataTypeException |
|
274 | + * @throws EE_Error |
|
275 | + * @throws InvalidArgumentException |
|
276 | + */ |
|
277 | + public function datetime_and_tickets_caf_update(EE_Event $event, array $data) |
|
278 | + { |
|
279 | + // first we need to start with datetimes cause they are the "root" items attached to events. |
|
280 | + $saved_datetimes = $this->_update_datetimes($event, $data); |
|
281 | + // next tackle the tickets (and prices?) |
|
282 | + $this->_update_tickets($event, $saved_datetimes, $data); |
|
283 | + } |
|
284 | + |
|
285 | + |
|
286 | + /** |
|
287 | + * update event_datetimes |
|
288 | + * |
|
289 | + * @param EE_Event $event Event being updated |
|
290 | + * @param array $data the request data from the form |
|
291 | + * @return EE_Datetime[] |
|
292 | + * @throws Exception |
|
293 | + * @throws ReflectionException |
|
294 | + * @throws InvalidInterfaceException |
|
295 | + * @throws InvalidDataTypeException |
|
296 | + * @throws InvalidArgumentException |
|
297 | + * @throws EE_Error |
|
298 | + */ |
|
299 | + protected function _update_datetimes(EE_Event $event, array $data): array |
|
300 | + { |
|
301 | + $timezone = $data['timezone_string'] ?? null; |
|
302 | + $saved_datetime_ids = []; |
|
303 | + $saved_datetime_objs = []; |
|
304 | + if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) { |
|
305 | + throw new InvalidArgumentException( |
|
306 | + esc_html__( |
|
307 | + 'The "edit_event_datetimes" array is invalid therefore the event can not be updated.', |
|
308 | + 'event_espresso' |
|
309 | + ) |
|
310 | + ); |
|
311 | + } |
|
312 | + foreach ($data['edit_event_datetimes'] as $row => $datetime_data) { |
|
313 | + // trim all values to ensure any excess whitespace is removed. |
|
314 | + $datetime_data = array_map( |
|
315 | + function ($datetime_data) { |
|
316 | + return is_array($datetime_data) ? $datetime_data : trim($datetime_data); |
|
317 | + }, |
|
318 | + $datetime_data |
|
319 | + ); |
|
320 | + |
|
321 | + $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end']) |
|
322 | + && ! empty($datetime_data['DTT_EVT_end']) |
|
323 | + ? $datetime_data['DTT_EVT_end'] |
|
324 | + : $datetime_data['DTT_EVT_start']; |
|
325 | + |
|
326 | + $datetime_values = [ |
|
327 | + 'DTT_ID' => ! empty($datetime_data['DTT_ID']) |
|
328 | + ? $datetime_data['DTT_ID'] |
|
329 | + : null, |
|
330 | + 'DTT_name' => ! empty($datetime_data['DTT_name']) |
|
331 | + ? $datetime_data['DTT_name'] |
|
332 | + : '', |
|
333 | + 'DTT_description' => ! empty($datetime_data['DTT_description']) |
|
334 | + ? $datetime_data['DTT_description'] |
|
335 | + : '', |
|
336 | + 'DTT_EVT_start' => $datetime_data['DTT_EVT_start'], |
|
337 | + 'DTT_EVT_end' => $datetime_data['DTT_EVT_end'], |
|
338 | + 'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) |
|
339 | + ? EE_INF |
|
340 | + : $datetime_data['DTT_reg_limit'], |
|
341 | + 'DTT_order' => ! isset($datetime_data['DTT_order']) |
|
342 | + ? $row |
|
343 | + : $datetime_data['DTT_order'], |
|
344 | + ]; |
|
345 | + |
|
346 | + // if we have an id then let's get existing object first and then set the new values. |
|
347 | + // Otherwise we instantiate a new object for save. |
|
348 | + if (! empty($datetime_data['DTT_ID'])) { |
|
349 | + $datetime = EEM_Datetime::instance($timezone)->get_one_by_ID($datetime_data['DTT_ID']); |
|
350 | + // set date and time format according to what is set in this class. |
|
351 | + $datetime->set_date_format($this->_date_format_strings['date']); |
|
352 | + $datetime->set_time_format($this->_date_format_strings['time']); |
|
353 | + foreach ($datetime_values as $field => $value) { |
|
354 | + $datetime->set($field, $value); |
|
355 | + } |
|
356 | + |
|
357 | + // make sure the $datetime_id here is saved just in case |
|
358 | + // after the add_relation_to() the autosave replaces it. |
|
359 | + // We need to do this so we dont' TRASH the parent DTT. |
|
360 | + // (save the ID for both key and value to avoid duplications) |
|
361 | + $saved_datetime_ids[ $datetime->ID() ] = $datetime->ID(); |
|
362 | + } else { |
|
363 | + $datetime = EE_Datetime::new_instance( |
|
364 | + $datetime_values, |
|
365 | + $timezone, |
|
366 | + [$this->_date_format_strings['date'], $this->_date_format_strings['time']] |
|
367 | + ); |
|
368 | + foreach ($datetime_values as $field => $value) { |
|
369 | + $datetime->set($field, $value); |
|
370 | + } |
|
371 | + } |
|
372 | + $datetime->save(); |
|
373 | + do_action( |
|
374 | + 'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save', |
|
375 | + $datetime, |
|
376 | + $row, |
|
377 | + $datetime_data, |
|
378 | + $data |
|
379 | + ); |
|
380 | + $datetime = $event->_add_relation_to($datetime, 'Datetime'); |
|
381 | + // before going any further make sure our dates are setup correctly |
|
382 | + // so that the end date is always equal or greater than the start date. |
|
383 | + if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) { |
|
384 | + $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start')); |
|
385 | + $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days'); |
|
386 | + $datetime->save(); |
|
387 | + } |
|
388 | + // now we have to make sure we add the new DTT_ID to the $saved_datetime_ids array |
|
389 | + // because it is possible there was a new one created for the autosave. |
|
390 | + // (save the ID for both key and value to avoid duplications) |
|
391 | + $DTT_ID = $datetime->ID(); |
|
392 | + $saved_datetime_ids[ $DTT_ID ] = $DTT_ID; |
|
393 | + $saved_datetime_objs[ $row ] = $datetime; |
|
394 | + // @todo if ANY of these updates fail then we want the appropriate global error message. |
|
395 | + } |
|
396 | + $event->save(); |
|
397 | + // now we need to REMOVE any datetimes that got deleted. |
|
398 | + // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them. |
|
399 | + // So its safe to permanently delete at this point. |
|
400 | + $old_datetimes = explode(',', $data['datetime_IDs']); |
|
401 | + $old_datetimes = $old_datetimes[0] === '' ? [] : $old_datetimes; |
|
402 | + if (is_array($old_datetimes)) { |
|
403 | + $datetimes_to_delete = array_diff($old_datetimes, $saved_datetime_ids); |
|
404 | + foreach ($datetimes_to_delete as $id) { |
|
405 | + $id = absint($id); |
|
406 | + if (empty($id)) { |
|
407 | + continue; |
|
408 | + } |
|
409 | + $datetime_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id); |
|
410 | + // remove ticket relationships. |
|
411 | + $related_tickets = $datetime_to_remove->get_many_related('Ticket'); |
|
412 | + foreach ($related_tickets as $ticket) { |
|
413 | + $datetime_to_remove->_remove_relation_to($ticket, 'Ticket'); |
|
414 | + } |
|
415 | + $event->_remove_relation_to($id, 'Datetime'); |
|
416 | + $datetime_to_remove->refresh_cache_of_related_objects(); |
|
417 | + } |
|
418 | + } |
|
419 | + return $saved_datetime_objs; |
|
420 | + } |
|
421 | + |
|
422 | + |
|
423 | + /** |
|
424 | + * update tickets |
|
425 | + * |
|
426 | + * @param EE_Event $event Event object being updated |
|
427 | + * @param EE_Datetime[] $saved_datetimes an array of datetime ids being updated |
|
428 | + * @param array $data incoming request data |
|
429 | + * @return EE_Ticket[] |
|
430 | + * @throws Exception |
|
431 | + * @throws ReflectionException |
|
432 | + * @throws InvalidInterfaceException |
|
433 | + * @throws InvalidDataTypeException |
|
434 | + * @throws InvalidArgumentException |
|
435 | + * @throws EE_Error |
|
436 | + */ |
|
437 | + protected function _update_tickets(EE_Event $event, array $saved_datetimes, array $data): array |
|
438 | + { |
|
439 | + $new_ticket = null; |
|
440 | + // stripslashes because WP filtered the $_POST ($data) array to add slashes |
|
441 | + $data = stripslashes_deep($data); |
|
442 | + $timezone = $data['timezone_string'] ?? null; |
|
443 | + $saved_tickets = []; |
|
444 | + $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : []; |
|
445 | + if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) { |
|
446 | + throw new InvalidArgumentException( |
|
447 | + esc_html__( |
|
448 | + 'The "edit_tickets" array is invalid therefore the event can not be updated.', |
|
449 | + 'event_espresso' |
|
450 | + ) |
|
451 | + ); |
|
452 | + } |
|
453 | + foreach ($data['edit_tickets'] as $row => $ticket_data) { |
|
454 | + $update_prices = $create_new_TKT = false; |
|
455 | + // figure out what datetimes were added to the ticket |
|
456 | + // and what datetimes were removed from the ticket in the session. |
|
457 | + $starting_ticket_datetime_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]); |
|
458 | + $ticket_datetime_rows = explode(',', $data['ticket_datetime_rows'][ $row ]); |
|
459 | + $datetimes_added = array_diff($ticket_datetime_rows, $starting_ticket_datetime_rows); |
|
460 | + $datetimes_removed = array_diff($starting_ticket_datetime_rows, $ticket_datetime_rows); |
|
461 | + // trim inputs to ensure any excess whitespace is removed. |
|
462 | + $ticket_data = array_map( |
|
463 | + function ($ticket_data) { |
|
464 | + return is_array($ticket_data) ? $ticket_data : trim($ticket_data); |
|
465 | + }, |
|
466 | + $ticket_data |
|
467 | + ); |
|
468 | + // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle |
|
469 | + // because we're doing calculations prior to using the models. |
|
470 | + // note incoming ['TKT_price'] value is already in standard notation (via js). |
|
471 | + $ticket_price = isset($ticket_data['TKT_price']) |
|
472 | + ? round((float) $ticket_data['TKT_price'], 3) |
|
473 | + : 0; |
|
474 | + // note incoming base price needs converted from localized value. |
|
475 | + $base_price = isset($ticket_data['TKT_base_price']) |
|
476 | + ? EEH_Money::convert_to_float_from_localized_money($ticket_data['TKT_base_price']) |
|
477 | + : 0; |
|
478 | + // if ticket price == 0 and $base_price != 0 then ticket price == base_price |
|
479 | + $ticket_price = $ticket_price === 0 && $base_price !== 0 |
|
480 | + ? $base_price |
|
481 | + : $ticket_price; |
|
482 | + $base_price_id = $ticket_data['TKT_base_price_ID'] ?? 0; |
|
483 | + $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ]) |
|
484 | + ? $data['edit_prices'][ $row ] |
|
485 | + : []; |
|
486 | + $now = null; |
|
487 | + if (empty($ticket_data['TKT_start_date'])) { |
|
488 | + // lets' use now in the set timezone. |
|
489 | + $now = new DateTime('now', new DateTimeZone($event->get_timezone())); |
|
490 | + $ticket_data['TKT_start_date'] = $now->format($this->_date_time_format); |
|
491 | + } |
|
492 | + if (empty($ticket_data['TKT_end_date'])) { |
|
493 | + /** |
|
494 | + * set the TKT_end_date to the first datetime attached to the ticket. |
|
495 | + */ |
|
496 | + $first_datetime = $saved_datetimes[ reset($ticket_datetime_rows) ]; |
|
497 | + $ticket_data['TKT_end_date'] = $first_datetime->start_date_and_time($this->_date_time_format); |
|
498 | + } |
|
499 | + $TKT_values = [ |
|
500 | + 'TKT_ID' => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null, |
|
501 | + 'TTM_ID' => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0, |
|
502 | + 'TKT_name' => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '', |
|
503 | + 'TKT_description' => ! empty($ticket_data['TKT_description']) |
|
504 | + && $ticket_data['TKT_description'] !== esc_html__( |
|
505 | + 'You can modify this description', |
|
506 | + 'event_espresso' |
|
507 | + ) |
|
508 | + ? $ticket_data['TKT_description'] |
|
509 | + : '', |
|
510 | + 'TKT_start_date' => $ticket_data['TKT_start_date'], |
|
511 | + 'TKT_end_date' => $ticket_data['TKT_end_date'], |
|
512 | + 'TKT_qty' => ! isset($ticket_data['TKT_qty']) || $ticket_data['TKT_qty'] === '' |
|
513 | + ? EE_INF |
|
514 | + : $ticket_data['TKT_qty'], |
|
515 | + 'TKT_uses' => ! isset($ticket_data['TKT_uses']) || $ticket_data['TKT_uses'] === '' |
|
516 | + ? EE_INF |
|
517 | + : $ticket_data['TKT_uses'], |
|
518 | + 'TKT_min' => empty($ticket_data['TKT_min']) ? 0 : $ticket_data['TKT_min'], |
|
519 | + 'TKT_max' => empty($ticket_data['TKT_max']) ? EE_INF : $ticket_data['TKT_max'], |
|
520 | + 'TKT_row' => $row, |
|
521 | + 'TKT_order' => $ticket_data['TKT_order'] ?? 0, |
|
522 | + 'TKT_taxable' => ! empty($ticket_data['TKT_taxable']) ? 1 : 0, |
|
523 | + 'TKT_required' => ! empty($ticket_data['TKT_required']) ? 1 : 0, |
|
524 | + 'TKT_price' => $ticket_price, |
|
525 | + ]; |
|
526 | + // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, |
|
527 | + // which means in turn that the prices will become new prices as well. |
|
528 | + if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) { |
|
529 | + $TKT_values['TKT_ID'] = 0; |
|
530 | + $TKT_values['TKT_is_default'] = 0; |
|
531 | + $update_prices = true; |
|
532 | + } |
|
533 | + // if we have a TKT_ID then we need to get that existing TKT_obj and update it |
|
534 | + // we actually do our saves ahead of doing any add_relations to |
|
535 | + // because its entirely possible that this ticket wasn't removed or added to any datetime in the session |
|
536 | + // but DID have it's items modified. |
|
537 | + // keep in mind that if the TKT has been sold (and we have changed pricing information), |
|
538 | + // then we won't be updating the ticket but instead a new ticket will be created and the old one archived. |
|
539 | + if (absint($TKT_values['TKT_ID'])) { |
|
540 | + $ticket = EEM_Ticket::instance($timezone)->get_one_by_ID($ticket_data['TKT_ID']); |
|
541 | + if ($ticket instanceof EE_Ticket) { |
|
542 | + $ticket = $this->_update_ticket_datetimes( |
|
543 | + $ticket, |
|
544 | + $saved_datetimes, |
|
545 | + $datetimes_added, |
|
546 | + $datetimes_removed |
|
547 | + ); |
|
548 | + // are there any registrations using this ticket ? |
|
549 | + $tickets_sold = $ticket->count_related( |
|
550 | + 'Registration', |
|
551 | + [ |
|
552 | + [ |
|
553 | + 'STS_ID' => ['NOT IN', [EEM_Registration::status_id_incomplete]], |
|
554 | + ], |
|
555 | + ] |
|
556 | + ); |
|
557 | + // set ticket formats |
|
558 | + $ticket->set_date_format($this->_date_format_strings['date']); |
|
559 | + $ticket->set_time_format($this->_date_format_strings['time']); |
|
560 | + // let's just check the total price for the existing ticket |
|
561 | + // and determine if it matches the new total price. |
|
562 | + // if they are different then we create a new ticket (if tickets sold) |
|
563 | + // if they aren't different then we go ahead and modify existing ticket. |
|
564 | + $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted(); |
|
565 | + // set new values |
|
566 | + foreach ($TKT_values as $field => $value) { |
|
567 | + if ($field === 'TKT_qty') { |
|
568 | + $ticket->set_qty($value); |
|
569 | + } else { |
|
570 | + $ticket->set($field, $value); |
|
571 | + } |
|
572 | + } |
|
573 | + // if $create_new_TKT is false then we can safely update the existing ticket. |
|
574 | + // Otherwise we have to create a new ticket. |
|
575 | + if ($create_new_TKT) { |
|
576 | + $new_ticket = $this->_duplicate_ticket( |
|
577 | + $ticket, |
|
578 | + $price_rows, |
|
579 | + $ticket_price, |
|
580 | + $base_price, |
|
581 | + $base_price_id |
|
582 | + ); |
|
583 | + } |
|
584 | + } |
|
585 | + } else { |
|
586 | + // no TKT_id so a new TKT |
|
587 | + $ticket = EE_Ticket::new_instance( |
|
588 | + $TKT_values, |
|
589 | + $timezone, |
|
590 | + [$this->_date_format_strings['date'], $this->_date_format_strings['time']] |
|
591 | + ); |
|
592 | + if ($ticket instanceof EE_Ticket) { |
|
593 | + // make sure ticket has an ID of setting relations won't work |
|
594 | + $ticket->save(); |
|
595 | + $ticket = $this->_update_ticket_datetimes( |
|
596 | + $ticket, |
|
597 | + $saved_datetimes, |
|
598 | + $datetimes_added, |
|
599 | + $datetimes_removed |
|
600 | + ); |
|
601 | + $update_prices = true; |
|
602 | + } |
|
603 | + } |
|
604 | + // make sure any current values have been saved. |
|
605 | + // $ticket->save(); |
|
606 | + // before going any further make sure our dates are setup correctly |
|
607 | + // so that the end date is always equal or greater than the start date. |
|
608 | + if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) { |
|
609 | + $ticket->set('TKT_end_date', $ticket->get('TKT_start_date')); |
|
610 | + $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days'); |
|
611 | + } |
|
612 | + // let's make sure the base price is handled |
|
613 | + $ticket = ! $create_new_TKT |
|
614 | + ? $this->_add_prices_to_ticket( |
|
615 | + [], |
|
616 | + $ticket, |
|
617 | + $update_prices, |
|
618 | + $base_price, |
|
619 | + $base_price_id |
|
620 | + ) |
|
621 | + : $ticket; |
|
622 | + // add/update price_modifiers |
|
623 | + $ticket = ! $create_new_TKT |
|
624 | + ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices) |
|
625 | + : $ticket; |
|
626 | + // need to make sue that the TKT_price is accurate after saving the prices. |
|
627 | + $ticket->ensure_TKT_Price_correct(); |
|
628 | + // handle CREATING a default ticket from the incoming ticket but ONLY if this isn't an autosave. |
|
629 | + if (! defined('DOING_AUTOSAVE') && ! empty($ticket_data['TKT_is_default_selector'])) { |
|
630 | + $new_default = clone $ticket; |
|
631 | + $new_default->set('TKT_ID', 0); |
|
632 | + $new_default->set('TKT_is_default', 1); |
|
633 | + $new_default->set('TKT_row', 1); |
|
634 | + $new_default->set('TKT_price', $ticket_price); |
|
635 | + // remove any datetime relations cause we DON'T want datetime relations attached |
|
636 | + // (note this is just removing the cached relations in the object) |
|
637 | + $new_default->_remove_relations('Datetime'); |
|
638 | + // @todo we need to add the current attached prices as new prices to the new default ticket. |
|
639 | + $new_default = $this->_add_prices_to_ticket( |
|
640 | + $price_rows, |
|
641 | + $new_default, |
|
642 | + true |
|
643 | + ); |
|
644 | + // don't forget the base price! |
|
645 | + $new_default = $this->_add_prices_to_ticket( |
|
646 | + [], |
|
647 | + $new_default, |
|
648 | + true, |
|
649 | + $base_price, |
|
650 | + $base_price_id |
|
651 | + ); |
|
652 | + $new_default->save(); |
|
653 | + do_action( |
|
654 | + 'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket', |
|
655 | + $new_default, |
|
656 | + $row, |
|
657 | + $ticket, |
|
658 | + $data |
|
659 | + ); |
|
660 | + } |
|
661 | + // DO ALL datetime relationships for both current tickets and any archived tickets |
|
662 | + // for the given datetime that are related to the current ticket. |
|
663 | + // TODO... not sure exactly how we're going to do this considering we don't know |
|
664 | + // what current ticket the archived tickets are related to |
|
665 | + // (and TKT_parent is used for autosaves so that's not a field we can reliably use). |
|
666 | + // let's assign any tickets that have been setup to the saved_tickets tracker |
|
667 | + // save existing TKT |
|
668 | + $ticket->save(); |
|
669 | + if ($create_new_TKT && $new_ticket instanceof EE_Ticket) { |
|
670 | + // save new TKT |
|
671 | + $new_ticket->save(); |
|
672 | + // add new ticket to array |
|
673 | + $saved_tickets[ $new_ticket->ID() ] = $new_ticket; |
|
674 | + do_action( |
|
675 | + 'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket', |
|
676 | + $new_ticket, |
|
677 | + $row, |
|
678 | + $ticket_data, |
|
679 | + $data |
|
680 | + ); |
|
681 | + } else { |
|
682 | + // add ticket to saved tickets |
|
683 | + $saved_tickets[ $ticket->ID() ] = $ticket; |
|
684 | + do_action( |
|
685 | + 'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket', |
|
686 | + $ticket, |
|
687 | + $row, |
|
688 | + $ticket_data, |
|
689 | + $data |
|
690 | + ); |
|
691 | + } |
|
692 | + } |
|
693 | + // now we need to handle tickets actually "deleted permanently". |
|
694 | + // There are cases where we'd want this to happen |
|
695 | + // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket). |
|
696 | + // Or a draft event was saved and in the process of editing a ticket is trashed. |
|
697 | + // No sense in keeping all the related data in the db! |
|
698 | + $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets; |
|
699 | + $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets)); |
|
700 | + foreach ($tickets_removed as $id) { |
|
701 | + $id = absint($id); |
|
702 | + // get the ticket for this id |
|
703 | + $ticket_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id); |
|
704 | + // if this ticket is a default ticket we leave it alone cause it won't be attached to the datetime |
|
705 | + if ($ticket_to_remove->get('TKT_is_default')) { |
|
706 | + continue; |
|
707 | + } |
|
708 | + // if this ticket has any registrations attached so then we just ARCHIVE |
|
709 | + // because we don't actually permanently delete these tickets. |
|
710 | + if ($ticket_to_remove->count_related('Registration') > 0) { |
|
711 | + $ticket_to_remove->delete(); |
|
712 | + continue; |
|
713 | + } |
|
714 | + // need to get all the related datetimes on this ticket and remove from every single one of them |
|
715 | + // (remember this process can ONLY kick off if there are NO tickets_sold) |
|
716 | + $datetimes = $ticket_to_remove->get_many_related('Datetime'); |
|
717 | + foreach ($datetimes as $datetime) { |
|
718 | + $ticket_to_remove->_remove_relation_to($datetime, 'Datetime'); |
|
719 | + } |
|
720 | + // need to do the same for prices (except these prices can also be deleted because again, |
|
721 | + // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived)) |
|
722 | + $ticket_to_remove->delete_related_permanently('Price'); |
|
723 | + do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $ticket_to_remove); |
|
724 | + // finally let's delete this ticket |
|
725 | + // (which should not be blocked at this point b/c we've removed all our relationships) |
|
726 | + $ticket_to_remove->delete_permanently(); |
|
727 | + } |
|
728 | + return $saved_tickets; |
|
729 | + } |
|
730 | + |
|
731 | + |
|
732 | + /** |
|
733 | + * @access protected |
|
734 | + * @param EE_Ticket $ticket |
|
735 | + * @param EE_Datetime[] $saved_datetimes |
|
736 | + * @param int[] $added_datetimes |
|
737 | + * @param int[] $removed_datetimes |
|
738 | + * @return EE_Ticket |
|
739 | + * @throws EE_Error |
|
740 | + * @throws ReflectionException |
|
741 | + */ |
|
742 | + protected function _update_ticket_datetimes( |
|
743 | + EE_Ticket $ticket, |
|
744 | + array $saved_datetimes = [], |
|
745 | + array $added_datetimes = [], |
|
746 | + array $removed_datetimes = [] |
|
747 | + ): EE_Ticket { |
|
748 | + // to start we have to add the ticket to all the datetimes its supposed to be with, |
|
749 | + // and removing the ticket from datetimes it got removed from. |
|
750 | + // first let's add datetimes |
|
751 | + if (! empty($added_datetimes) && is_array($added_datetimes)) { |
|
752 | + foreach ($added_datetimes as $row_id) { |
|
753 | + if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
754 | + $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
755 | + } |
|
756 | + } |
|
757 | + } |
|
758 | + // then remove datetimes |
|
759 | + if (! empty($removed_datetimes) && is_array($removed_datetimes)) { |
|
760 | + foreach ($removed_datetimes as $row_id) { |
|
761 | + // its entirely possible that a datetime got deleted (instead of just removed from relationship. |
|
762 | + // So make sure we skip over this if the datetime isn't in the $saved_datetimes array) |
|
763 | + if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) { |
|
764 | + $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime'); |
|
765 | + } |
|
766 | + } |
|
767 | + } |
|
768 | + // cap ticket qty by datetime reg limits |
|
769 | + $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit'))); |
|
770 | + return $ticket; |
|
771 | + } |
|
772 | + |
|
773 | + |
|
774 | + /** |
|
775 | + * @access protected |
|
776 | + * @param EE_Ticket $ticket |
|
777 | + * @param array $price_rows |
|
778 | + * @param int|float $ticket_price |
|
779 | + * @param int|float $base_price |
|
780 | + * @param int $base_price_id |
|
781 | + * @return EE_Ticket |
|
782 | + * @throws ReflectionException |
|
783 | + * @throws InvalidArgumentException |
|
784 | + * @throws InvalidInterfaceException |
|
785 | + * @throws InvalidDataTypeException |
|
786 | + * @throws EE_Error |
|
787 | + */ |
|
788 | + protected function _duplicate_ticket( |
|
789 | + EE_Ticket $ticket, |
|
790 | + array $price_rows = [], |
|
791 | + $ticket_price = 0, |
|
792 | + $base_price = 0, |
|
793 | + int $base_price_id = 0 |
|
794 | + ): EE_Ticket { |
|
795 | + // create new ticket that's a copy of the existing |
|
796 | + // except a new id of course (and not archived) |
|
797 | + // AND has the new TKT_price associated with it. |
|
798 | + $new_ticket = clone $ticket; |
|
799 | + $new_ticket->set('TKT_ID', 0); |
|
800 | + $new_ticket->set_deleted(0); |
|
801 | + $new_ticket->set_price($ticket_price); |
|
802 | + $new_ticket->set_sold(0); |
|
803 | + // let's get a new ID for this ticket |
|
804 | + $new_ticket->save(); |
|
805 | + // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket |
|
806 | + $datetimes_on_existing = $ticket->datetimes(); |
|
807 | + $new_ticket = $this->_update_ticket_datetimes( |
|
808 | + $new_ticket, |
|
809 | + $datetimes_on_existing, |
|
810 | + array_keys($datetimes_on_existing) |
|
811 | + ); |
|
812 | + // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array. |
|
813 | + // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining |
|
814 | + // available. |
|
815 | + if ($ticket->sold() > 0) { |
|
816 | + $new_qty = $ticket->qty() - $ticket->sold(); |
|
817 | + $new_ticket->set_qty($new_qty); |
|
818 | + } |
|
819 | + // now we update the prices just for this ticket |
|
820 | + $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true); |
|
821 | + // and we update the base price |
|
822 | + return $this->_add_prices_to_ticket( |
|
823 | + [], |
|
824 | + $new_ticket, |
|
825 | + true, |
|
826 | + $base_price, |
|
827 | + $base_price_id |
|
828 | + ); |
|
829 | + } |
|
830 | + |
|
831 | + |
|
832 | + /** |
|
833 | + * This attaches a list of given prices to a ticket. |
|
834 | + * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change |
|
835 | + * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old |
|
836 | + * price info and prices are automatically "archived" via the ticket. |
|
837 | + * |
|
838 | + * @access private |
|
839 | + * @param array $prices Array of prices from the form. |
|
840 | + * @param EE_Ticket $ticket EE_Ticket object that prices are being attached to. |
|
841 | + * @param bool $new_prices Whether attach existing incoming prices or create new ones. |
|
842 | + * @param int|bool $base_price if FALSE then NOT doing a base price add. |
|
843 | + * @param int|bool $base_price_id if present then this is the base_price_id being updated. |
|
844 | + * @return EE_Ticket |
|
845 | + * @throws ReflectionException |
|
846 | + * @throws InvalidArgumentException |
|
847 | + * @throws InvalidInterfaceException |
|
848 | + * @throws InvalidDataTypeException |
|
849 | + * @throws EE_Error |
|
850 | + */ |
|
851 | + protected function _add_prices_to_ticket( |
|
852 | + array $prices, |
|
853 | + EE_Ticket $ticket, |
|
854 | + bool $new_prices = false, |
|
855 | + $base_price = false, |
|
856 | + $base_price_id = false |
|
857 | + ): EE_Ticket { |
|
858 | + // let's just get any current prices that may exist on the given ticket |
|
859 | + // so we can remove any prices that got trashed in this session. |
|
860 | + $current_prices_on_ticket = $base_price !== false |
|
861 | + ? $ticket->base_price(true) |
|
862 | + : $ticket->price_modifiers(); |
|
863 | + $updated_prices = []; |
|
864 | + // if $base_price ! FALSE then updating a base price. |
|
865 | + if ($base_price !== false) { |
|
866 | + $prices[1] = [ |
|
867 | + 'PRC_ID' => $new_prices || $base_price_id === 1 ? null : $base_price_id, |
|
868 | + 'PRT_ID' => 1, |
|
869 | + 'PRC_amount' => $base_price, |
|
870 | + 'PRC_name' => $ticket->get('TKT_name'), |
|
871 | + 'PRC_desc' => $ticket->get('TKT_description'), |
|
872 | + ]; |
|
873 | + } |
|
874 | + // possibly need to save ticket |
|
875 | + if (! $ticket->ID()) { |
|
876 | + $ticket->save(); |
|
877 | + } |
|
878 | + foreach ($prices as $row => $prc) { |
|
879 | + $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null; |
|
880 | + if (empty($prt_id)) { |
|
881 | + continue; |
|
882 | + } //prices MUST have a price type id. |
|
883 | + $PRC_values = [ |
|
884 | + 'PRC_ID' => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null, |
|
885 | + 'PRT_ID' => $prt_id, |
|
886 | + 'PRC_amount' => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0, |
|
887 | + 'PRC_name' => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '', |
|
888 | + 'PRC_desc' => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '', |
|
889 | + 'PRC_is_default' => false, |
|
890 | + // make sure we set PRC_is_default to false for all ticket saves from event_editor |
|
891 | + 'PRC_order' => $row, |
|
892 | + ]; |
|
893 | + if ($new_prices || empty($PRC_values['PRC_ID'])) { |
|
894 | + $PRC_values['PRC_ID'] = 0; |
|
895 | + $price = EE_Registry::instance()->load_class( |
|
896 | + 'Price', |
|
897 | + [$PRC_values], |
|
898 | + false, |
|
899 | + false |
|
900 | + ); |
|
901 | + } else { |
|
902 | + $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']); |
|
903 | + // update this price with new values |
|
904 | + foreach ($PRC_values as $field => $value) { |
|
905 | + $price->set($field, $value); |
|
906 | + } |
|
907 | + } |
|
908 | + $price->save(); |
|
909 | + $updated_prices[ $price->ID() ] = $price; |
|
910 | + $ticket->_add_relation_to($price, 'Price'); |
|
911 | + } |
|
912 | + // now let's remove any prices that got removed from the ticket |
|
913 | + if (! empty($current_prices_on_ticket)) { |
|
914 | + $current = array_keys($current_prices_on_ticket); |
|
915 | + $updated = array_keys($updated_prices); |
|
916 | + $prices_to_remove = array_diff($current, $updated); |
|
917 | + if (! empty($prices_to_remove)) { |
|
918 | + foreach ($prices_to_remove as $prc_id) { |
|
919 | + $p = $current_prices_on_ticket[ $prc_id ]; |
|
920 | + $ticket->_remove_relation_to($p, 'Price'); |
|
921 | + // delete permanently the price |
|
922 | + $p->delete_permanently(); |
|
923 | + } |
|
924 | + } |
|
925 | + } |
|
926 | + return $ticket; |
|
927 | + } |
|
928 | + |
|
929 | + |
|
930 | + /** |
|
931 | + * @throws ReflectionException |
|
932 | + * @throws InvalidArgumentException |
|
933 | + * @throws InvalidInterfaceException |
|
934 | + * @throws InvalidDataTypeException |
|
935 | + * @throws DomainException |
|
936 | + * @throws EE_Error |
|
937 | + */ |
|
938 | + public function pricing_metabox() |
|
939 | + { |
|
940 | + $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = []; |
|
941 | + $event = $this->_adminpage_obj->get_cpt_model_obj(); |
|
942 | + |
|
943 | + // set is_creating_event property. |
|
944 | + $EVT_ID = $event->ID(); |
|
945 | + $this->_is_creating_event = empty($this->_req_data['post']); |
|
946 | + |
|
947 | + // default main template args |
|
948 | + $main_template_args = [ |
|
949 | + 'event_datetime_help_link' => EEH_Template::get_help_tab_link( |
|
950 | + 'event_editor_event_datetimes_help_tab', |
|
951 | + $this->_adminpage_obj->page_slug, |
|
952 | + $this->_adminpage_obj->get_req_action() |
|
953 | + ), |
|
954 | + |
|
955 | + // todo need to add a filter to the template for the help text |
|
956 | + // in the Events_Admin_Page core file so we can add further help |
|
957 | + 'add_new_dtt_help_link' => EEH_Template::get_help_tab_link( |
|
958 | + 'add_new_dtt_info', |
|
959 | + $this->_adminpage_obj->page_slug, |
|
960 | + $this->_adminpage_obj->get_req_action() |
|
961 | + ), |
|
962 | + // todo need to add this help info id to the Events_Admin_Page core file so we can access it here. |
|
963 | + 'datetime_rows' => '', |
|
964 | + 'show_tickets_container' => '', |
|
965 | + 'ticket_rows' => '', |
|
966 | + 'ee_collapsible_status' => ' ee-collapsible-open', |
|
967 | + ]; |
|
968 | + $timezone = $event instanceof EE_Event ? $event->timezone_string() : null; |
|
969 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
970 | + |
|
971 | + /** |
|
972 | + * 1. Start with retrieving Datetimes |
|
973 | + * 2. For each datetime get related tickets |
|
974 | + * 3. For each ticket get related prices |
|
975 | + */ |
|
976 | + /** @var EEM_Datetime $datetime_model */ |
|
977 | + $datetime_model = EE_Registry::instance()->load_model('Datetime', [$timezone]); |
|
978 | + $datetimes = $datetime_model->get_all_event_dates($EVT_ID); |
|
979 | + $main_template_args['total_dtt_rows'] = count($datetimes); |
|
980 | + |
|
981 | + /** |
|
982 | + * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486 |
|
983 | + * for why we are counting $datetime_row and then setting that on the Datetime object |
|
984 | + */ |
|
985 | + $datetime_row = 1; |
|
986 | + foreach ($datetimes as $datetime) { |
|
987 | + $DTT_ID = $datetime->get('DTT_ID'); |
|
988 | + $datetime->set('DTT_order', $datetime_row); |
|
989 | + $existing_datetime_ids[] = $DTT_ID; |
|
990 | + // tickets attached |
|
991 | + $related_tickets = $datetime->ID() > 0 |
|
992 | + ? $datetime->get_many_related( |
|
993 | + 'Ticket', |
|
994 | + [ |
|
995 | + [ |
|
996 | + 'OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0], |
|
997 | + ], |
|
998 | + 'default_where_conditions' => 'none', |
|
999 | + 'order_by' => ['TKT_order' => 'ASC'], |
|
1000 | + ] |
|
1001 | + ) |
|
1002 | + : []; |
|
1003 | + // if there are no related tickets this is likely a new event OR auto-draft |
|
1004 | + // event so we need to generate the default tickets because datetimes |
|
1005 | + // ALWAYS have at least one related ticket!!. EXCEPT, we dont' do this if there is already more than one |
|
1006 | + // datetime on the event. |
|
1007 | + if (empty($related_tickets) && count($datetimes) < 2) { |
|
1008 | + /** @var EEM_Ticket $ticket_model */ |
|
1009 | + $ticket_model = EE_Registry::instance()->load_model('Ticket'); |
|
1010 | + $related_tickets = $ticket_model->get_all_default_tickets(); |
|
1011 | + // this should be ordered by TKT_ID, so let's grab the first default ticket |
|
1012 | + // (which will be the main default) and ensure it has any default prices added to it (but do NOT save). |
|
1013 | + $default_prices = EEM_Price::instance()->get_all_default_prices(); |
|
1014 | + $main_default_ticket = reset($related_tickets); |
|
1015 | + if ($main_default_ticket instanceof EE_Ticket) { |
|
1016 | + foreach ($default_prices as $default_price) { |
|
1017 | + if ($default_price instanceof EE_Price && $default_price->is_base_price()) { |
|
1018 | + continue; |
|
1019 | + } |
|
1020 | + $main_default_ticket->cache('Price', $default_price); |
|
1021 | + } |
|
1022 | + } |
|
1023 | + } |
|
1024 | + // we can't actually setup rows in this loop yet cause we don't know all |
|
1025 | + // the unique tickets for this event yet (tickets are linked through all datetimes). |
|
1026 | + // So we're going to temporarily cache some of that information. |
|
1027 | + // loop through and setup the ticket rows and make sure the order is set. |
|
1028 | + foreach ($related_tickets as $ticket) { |
|
1029 | + $TKT_ID = $ticket->get('TKT_ID'); |
|
1030 | + $ticket_row = $ticket->get('TKT_row'); |
|
1031 | + // we only want unique tickets in our final display!! |
|
1032 | + if (! in_array($TKT_ID, $existing_ticket_ids, true)) { |
|
1033 | + $existing_ticket_ids[] = $TKT_ID; |
|
1034 | + $all_tickets[] = $ticket; |
|
1035 | + } |
|
1036 | + // temporary cache of this ticket info for this datetime for later processing of datetime rows. |
|
1037 | + $datetime_tickets[ $DTT_ID ][] = $ticket_row; |
|
1038 | + // temporary cache of this datetime info for this ticket for later processing of ticket rows. |
|
1039 | + if ( |
|
1040 | + ! isset($ticket_datetimes[ $TKT_ID ]) |
|
1041 | + || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true) |
|
1042 | + ) { |
|
1043 | + $ticket_datetimes[ $TKT_ID ][] = $datetime_row; |
|
1044 | + } |
|
1045 | + } |
|
1046 | + $datetime_row++; |
|
1047 | + } |
|
1048 | + $main_template_args['total_ticket_rows'] = count($existing_ticket_ids); |
|
1049 | + $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids); |
|
1050 | + $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids); |
|
1051 | + // sort $all_tickets by order |
|
1052 | + usort( |
|
1053 | + $all_tickets, |
|
1054 | + function (EE_Ticket $a, EE_Ticket $b) { |
|
1055 | + $a_order = (int) $a->get('TKT_order'); |
|
1056 | + $b_order = (int) $b->get('TKT_order'); |
|
1057 | + if ($a_order === $b_order) { |
|
1058 | + return 0; |
|
1059 | + } |
|
1060 | + return ($a_order < $b_order) ? -1 : 1; |
|
1061 | + } |
|
1062 | + ); |
|
1063 | + // k NOW we have all the data we need for setting up the datetime rows |
|
1064 | + // and ticket rows so we start our datetime loop again. |
|
1065 | + $datetime_row = 1; |
|
1066 | + foreach ($datetimes as $datetime) { |
|
1067 | + $main_template_args['datetime_rows'] .= $this->_get_datetime_row( |
|
1068 | + $datetime_row, |
|
1069 | + $datetime, |
|
1070 | + $datetime_tickets, |
|
1071 | + $all_tickets, |
|
1072 | + false, |
|
1073 | + $datetimes |
|
1074 | + ); |
|
1075 | + $datetime_row++; |
|
1076 | + } |
|
1077 | + // then loop through all tickets for the ticket rows. |
|
1078 | + $ticket_row = 1; |
|
1079 | + foreach ($all_tickets as $ticket) { |
|
1080 | + $main_template_args['ticket_rows'] .= $this->_get_ticket_row( |
|
1081 | + $ticket_row, |
|
1082 | + $ticket, |
|
1083 | + $ticket_datetimes, |
|
1084 | + $datetimes, |
|
1085 | + false, |
|
1086 | + $all_tickets |
|
1087 | + ); |
|
1088 | + $ticket_row++; |
|
1089 | + } |
|
1090 | + $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets); |
|
1091 | + |
|
1092 | + $status_change_notice = LoaderFactory::getLoader()->getShared( |
|
1093 | + 'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice' |
|
1094 | + ); |
|
1095 | + |
|
1096 | + $main_template_args['status_change_notice'] = $status_change_notice->display( |
|
1097 | + '__event-editor', |
|
1098 | + 'espresso-events' |
|
1099 | + ); |
|
1100 | + |
|
1101 | + EEH_Template::display_template( |
|
1102 | + PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php', |
|
1103 | + $main_template_args |
|
1104 | + ); |
|
1105 | + } |
|
1106 | + |
|
1107 | + |
|
1108 | + /** |
|
1109 | + * @param int $datetime_row |
|
1110 | + * @param EE_Datetime $datetime |
|
1111 | + * @param array $datetime_tickets |
|
1112 | + * @param array $all_tickets |
|
1113 | + * @param bool $default |
|
1114 | + * @param array $all_datetimes |
|
1115 | + * @return string |
|
1116 | + * @throws DomainException |
|
1117 | + * @throws EE_Error |
|
1118 | + * @throws ReflectionException |
|
1119 | + */ |
|
1120 | + protected function _get_datetime_row( |
|
1121 | + int $datetime_row, |
|
1122 | + EE_Datetime $datetime, |
|
1123 | + array $datetime_tickets = [], |
|
1124 | + array $all_tickets = [], |
|
1125 | + bool $default = false, |
|
1126 | + array $all_datetimes = [] |
|
1127 | + ): string { |
|
1128 | + return EEH_Template::display_template( |
|
1129 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php', |
|
1130 | + [ |
|
1131 | + 'dtt_edit_row' => $this->_get_dtt_edit_row( |
|
1132 | + $datetime_row, |
|
1133 | + $datetime, |
|
1134 | + $default, |
|
1135 | + $all_datetimes |
|
1136 | + ), |
|
1137 | + 'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row( |
|
1138 | + $datetime_row, |
|
1139 | + $datetime, |
|
1140 | + $datetime_tickets, |
|
1141 | + $all_tickets, |
|
1142 | + $default |
|
1143 | + ), |
|
1144 | + 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1145 | + ], |
|
1146 | + true |
|
1147 | + ); |
|
1148 | + } |
|
1149 | + |
|
1150 | + |
|
1151 | + /** |
|
1152 | + * This method is used to generate a datetime fields edit row. |
|
1153 | + * The same row is used to generate a row with valid DTT objects |
|
1154 | + * and the default row that is used as the skeleton by the js. |
|
1155 | + * |
|
1156 | + * @param int $datetime_row The row number for the row being generated. |
|
1157 | + * @param EE_Datetime|null $datetime |
|
1158 | + * @param bool $default Whether a default row is being generated or not. |
|
1159 | + * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor. |
|
1160 | + * @return string |
|
1161 | + * @throws EE_Error |
|
1162 | + * @throws ReflectionException |
|
1163 | + */ |
|
1164 | + protected function _get_dtt_edit_row( |
|
1165 | + int $datetime_row, |
|
1166 | + ?EE_Datetime $datetime, |
|
1167 | + bool $default, |
|
1168 | + array $all_datetimes |
|
1169 | + ): string { |
|
1170 | + // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true. |
|
1171 | + $default = ! $datetime instanceof EE_Datetime ? true : $default; |
|
1172 | + $template_args = [ |
|
1173 | + 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1174 | + 'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes', |
|
1175 | + 'edit_dtt_expanded' => '', |
|
1176 | + 'DTT_ID' => $default ? '' : $datetime->ID(), |
|
1177 | + 'DTT_name' => $default ? '' : $datetime->get_f('DTT_name'), |
|
1178 | + 'DTT_description' => $default ? '' : $datetime->get_f('DTT_description'), |
|
1179 | + 'DTT_EVT_start' => $default ? '' : $datetime->start_date($this->_date_time_format), |
|
1180 | + 'DTT_EVT_end' => $default ? '' : $datetime->end_date($this->_date_time_format), |
|
1181 | + 'DTT_reg_limit' => $default |
|
1182 | + ? '' |
|
1183 | + : $datetime->get_pretty( |
|
1184 | + 'DTT_reg_limit', |
|
1185 | + 'input' |
|
1186 | + ), |
|
1187 | + 'DTT_order' => $default ? 'DTTNUM' : $datetime_row, |
|
1188 | + 'dtt_sold' => $default ? '0' : $datetime->get('DTT_sold'), |
|
1189 | + 'dtt_reserved' => $default ? '0' : $datetime->reserved(), |
|
1190 | + 'clone_icon' => ! empty($datetime) && $datetime->get('DTT_sold') > 0 |
|
1191 | + ? '' |
|
1192 | + : 'clone-icon ee-icon ee-icon-clone clickable', |
|
1193 | + 'trash_icon' => ! empty($datetime) && $datetime->get('DTT_sold') > 0 |
|
1194 | + ? 'dashicons dashicons-lock' |
|
1195 | + : 'trash-icon dashicons dashicons-post-trash clickable', |
|
1196 | + 'reg_list_url' => $default || ! $datetime->event() instanceof EE_Event |
|
1197 | + ? '' |
|
1198 | + : EE_Admin_Page::add_query_args_and_nonce( |
|
1199 | + ['event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()], |
|
1200 | + REG_ADMIN_URL |
|
1201 | + ), |
|
1202 | + ]; |
|
1203 | + $template_args['show_trash'] = count($all_datetimes) === 1 |
|
1204 | + && $template_args['trash_icon'] !== 'dashicons dashicons-lock' |
|
1205 | + ? 'display:none' |
|
1206 | + : ''; |
|
1207 | + // allow filtering of template args at this point. |
|
1208 | + $template_args = apply_filters( |
|
1209 | + 'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args', |
|
1210 | + $template_args, |
|
1211 | + $datetime_row, |
|
1212 | + $datetime, |
|
1213 | + $default, |
|
1214 | + $all_datetimes, |
|
1215 | + $this->_is_creating_event |
|
1216 | + ); |
|
1217 | + return EEH_Template::display_template( |
|
1218 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php', |
|
1219 | + $template_args, |
|
1220 | + true |
|
1221 | + ); |
|
1222 | + } |
|
1223 | + |
|
1224 | + |
|
1225 | + /** |
|
1226 | + * @param int $datetime_row |
|
1227 | + * @param EE_Datetime $datetime |
|
1228 | + * @param array $datetime_tickets |
|
1229 | + * @param array $all_tickets |
|
1230 | + * @param bool $default |
|
1231 | + * @return string |
|
1232 | + * @throws DomainException |
|
1233 | + * @throws EE_Error |
|
1234 | + * @throws ReflectionException |
|
1235 | + */ |
|
1236 | + protected function _get_dtt_attached_tickets_row( |
|
1237 | + int $datetime_row, |
|
1238 | + EE_Datetime $datetime, |
|
1239 | + array $datetime_tickets = [], |
|
1240 | + array $all_tickets = [], |
|
1241 | + bool $default = false |
|
1242 | + ): string { |
|
1243 | + $template_args = [ |
|
1244 | + 'dtt_row' => $default ? 'DTTNUM' : $datetime_row, |
|
1245 | + 'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes', |
|
1246 | + 'DTT_description' => $default ? '' : $datetime->get_f('DTT_description'), |
|
1247 | + 'datetime_tickets_list' => $default ? '<li class="hidden"></li>' : '', |
|
1248 | + 'show_tickets_row' => 'display:none;', |
|
1249 | + 'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link( |
|
1250 | + 'add_new_ticket_via_datetime', |
|
1251 | + $this->_adminpage_obj->page_slug, |
|
1252 | + $this->_adminpage_obj->get_req_action() |
|
1253 | + ), |
|
1254 | + // todo need to add this help info id to the Events_Admin_Page core file so we can access it here. |
|
1255 | + 'DTT_ID' => $default ? '' : $datetime->ID(), |
|
1256 | + ]; |
|
1257 | + // need to setup the list items (but only if this isn't a default skeleton setup) |
|
1258 | + if (! $default) { |
|
1259 | + $ticket_row = 1; |
|
1260 | + foreach ($all_tickets as $ticket) { |
|
1261 | + $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
|
1262 | + $datetime_row, |
|
1263 | + $ticket_row, |
|
1264 | + $datetime, |
|
1265 | + $ticket, |
|
1266 | + $datetime_tickets, |
|
1267 | + $default |
|
1268 | + ); |
|
1269 | + $ticket_row++; |
|
1270 | + } |
|
1271 | + } |
|
1272 | + // filter template args at this point |
|
1273 | + $template_args = apply_filters( |
|
1274 | + 'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args', |
|
1275 | + $template_args, |
|
1276 | + $datetime_row, |
|
1277 | + $datetime, |
|
1278 | + $datetime_tickets, |
|
1279 | + $all_tickets, |
|
1280 | + $default, |
|
1281 | + $this->_is_creating_event |
|
1282 | + ); |
|
1283 | + return EEH_Template::display_template( |
|
1284 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php', |
|
1285 | + $template_args, |
|
1286 | + true |
|
1287 | + ); |
|
1288 | + } |
|
1289 | + |
|
1290 | + |
|
1291 | + /** |
|
1292 | + * @param int $datetime_row |
|
1293 | + * @param int $ticket_row |
|
1294 | + * @param EE_Datetime|null $datetime |
|
1295 | + * @param EE_Ticket|null $ticket |
|
1296 | + * @param array $datetime_tickets |
|
1297 | + * @param bool $default |
|
1298 | + * @return string |
|
1299 | + * @throws EE_Error |
|
1300 | + * @throws ReflectionException |
|
1301 | + */ |
|
1302 | + protected function _get_datetime_tickets_list_item( |
|
1303 | + int $datetime_row, |
|
1304 | + int $ticket_row, |
|
1305 | + ?EE_Datetime $datetime, |
|
1306 | + ?EE_Ticket $ticket, |
|
1307 | + array $datetime_tickets = [], |
|
1308 | + bool $default = false |
|
1309 | + ): string { |
|
1310 | + $datetime_tickets = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ]) |
|
1311 | + ? $datetime_tickets[ $datetime->ID() ] |
|
1312 | + : []; |
|
1313 | + $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0; |
|
1314 | + $no_ticket = $default && empty($ticket); |
|
1315 | + $template_args = [ |
|
1316 | + 'dtt_row' => $default |
|
1317 | + ? 'DTTNUM' |
|
1318 | + : $datetime_row, |
|
1319 | + 'tkt_row' => $no_ticket |
|
1320 | + ? 'TICKETNUM' |
|
1321 | + : $ticket_row, |
|
1322 | + 'datetime_ticket_checked' => in_array($display_row, $datetime_tickets, true) |
|
1323 | + ? ' checked' |
|
1324 | + : '', |
|
1325 | + 'ticket_selected' => in_array($display_row, $datetime_tickets, true) |
|
1326 | + ? ' ticket-selected' |
|
1327 | + : '', |
|
1328 | + 'TKT_name' => $no_ticket |
|
1329 | + ? 'TKTNAME' |
|
1330 | + : $ticket->get('TKT_name'), |
|
1331 | + 'tkt_status_class' => $no_ticket || $this->_is_creating_event |
|
1332 | + ? ' tkt-status-' . EE_Ticket::onsale |
|
1333 | + : ' tkt-status-' . $ticket->ticket_status(), |
|
1334 | + ]; |
|
1335 | + // filter template args |
|
1336 | + $template_args = apply_filters( |
|
1337 | + 'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args', |
|
1338 | + $template_args, |
|
1339 | + $datetime_row, |
|
1340 | + $ticket_row, |
|
1341 | + $datetime, |
|
1342 | + $ticket, |
|
1343 | + $datetime_tickets, |
|
1344 | + $default, |
|
1345 | + $this->_is_creating_event |
|
1346 | + ); |
|
1347 | + return EEH_Template::display_template( |
|
1348 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php', |
|
1349 | + $template_args, |
|
1350 | + true |
|
1351 | + ); |
|
1352 | + } |
|
1353 | + |
|
1354 | + |
|
1355 | + /** |
|
1356 | + * This generates the ticket row for tickets. |
|
1357 | + * This same method is used to generate both the actual rows and the js skeleton row |
|
1358 | + * (when default === true) |
|
1359 | + * |
|
1360 | + * @param int $ticket_row Represents the row number being generated. |
|
1361 | + * @param EE_Ticket|null $ticket |
|
1362 | + * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket |
|
1363 | + * or empty for default |
|
1364 | + * @param EE_Datetime[] $all_datetimes All Datetimes on the event or empty for default. |
|
1365 | + * @param bool $default Whether default row being generated or not. |
|
1366 | + * @param EE_Ticket[] $all_tickets This is an array of all tickets attached to the event |
|
1367 | + * (or empty in the case of defaults) |
|
1368 | + * @return string |
|
1369 | + * @throws InvalidArgumentException |
|
1370 | + * @throws InvalidInterfaceException |
|
1371 | + * @throws InvalidDataTypeException |
|
1372 | + * @throws DomainException |
|
1373 | + * @throws EE_Error |
|
1374 | + * @throws ReflectionException |
|
1375 | + */ |
|
1376 | + protected function _get_ticket_row( |
|
1377 | + int $ticket_row, |
|
1378 | + ?EE_Ticket $ticket, |
|
1379 | + array $ticket_datetimes, |
|
1380 | + array $all_datetimes, |
|
1381 | + bool $default = false, |
|
1382 | + array $all_tickets = [] |
|
1383 | + ): string { |
|
1384 | + // if $ticket is not an instance of EE_Ticket then force default to true. |
|
1385 | + $default = ! $ticket instanceof EE_Ticket ? true : $default; |
|
1386 | + $prices = ! empty($ticket) && ! $default |
|
1387 | + ? $ticket->get_many_related( |
|
1388 | + 'Price', |
|
1389 | + ['default_where_conditions' => 'none', 'order_by' => ['PRC_order' => 'ASC']] |
|
1390 | + ) |
|
1391 | + : []; |
|
1392 | + // if there is only one price (which would be the base price) |
|
1393 | + // or NO prices and this ticket is a default ticket, |
|
1394 | + // let's just make sure there are no cached default prices on the object. |
|
1395 | + // This is done by not including any query_params. |
|
1396 | + if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) { |
|
1397 | + $prices = $ticket->prices(); |
|
1398 | + } |
|
1399 | + // check if we're dealing with a default ticket in which case |
|
1400 | + // we don't want any starting_ticket_datetime_row values set |
|
1401 | + // (otherwise there won't be any new relationships created for tickets based off of the default ticket). |
|
1402 | + // This will future proof in case there is ever any behaviour change between what the primary_key defaults to. |
|
1403 | + $default_datetime = $default || ($ticket instanceof EE_Ticket && $ticket->is_default()); |
|
1404 | + $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
1405 | + ? $ticket_datetimes[ $ticket->ID() ] |
|
1406 | + : []; |
|
1407 | + $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal(); |
|
1408 | + $base_price = $default ? null : $ticket->base_price(); |
|
1409 | + $count_price_mods = EEM_Price::instance()->get_all_default_prices(true); |
|
1410 | + // breaking out complicated condition for ticket_status |
|
1411 | + if ($default) { |
|
1412 | + $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale; |
|
1413 | + } else { |
|
1414 | + $ticket_status_class = $ticket->is_default() |
|
1415 | + ? ' tkt-status-' . EE_Ticket::onsale |
|
1416 | + : ' tkt-status-' . $ticket->ticket_status(); |
|
1417 | + } |
|
1418 | + // breaking out complicated condition for TKT_taxable |
|
1419 | + if ($default) { |
|
1420 | + $TKT_taxable = ''; |
|
1421 | + } else { |
|
1422 | + $TKT_taxable = $ticket->taxable() |
|
1423 | + ? 'checked' |
|
1424 | + : ''; |
|
1425 | + } |
|
1426 | + if ($default) { |
|
1427 | + $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence'); |
|
1428 | + } elseif ($ticket->is_default()) { |
|
1429 | + $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence'); |
|
1430 | + } else { |
|
1431 | + $TKT_status = $ticket->ticket_status(true); |
|
1432 | + } |
|
1433 | + if ($default) { |
|
1434 | + $TKT_min = ''; |
|
1435 | + } else { |
|
1436 | + $TKT_min = $ticket->min(); |
|
1437 | + if ($TKT_min === -1 || $TKT_min === 0) { |
|
1438 | + $TKT_min = ''; |
|
1439 | + } |
|
1440 | + } |
|
1441 | + $template_args = [ |
|
1442 | + 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1443 | + 'TKT_order' => $default ? 'TICKETNUM' : $ticket_row, |
|
1444 | + // on initial page load this will always be the correct order. |
|
1445 | + 'tkt_status_class' => $ticket_status_class, |
|
1446 | + 'display_edit_tkt_row' => 'display:none;', |
|
1447 | + 'edit_tkt_expanded' => '', |
|
1448 | + 'edit_tickets_name' => $default ? 'TICKETNAMEATTR' : 'edit_tickets', |
|
1449 | + 'TKT_name' => $default ? '' : $ticket->get_f('TKT_name'), |
|
1450 | + 'TKT_start_date' => $default |
|
1451 | + ? '' |
|
1452 | + : $ticket->get_date('TKT_start_date', $this->_date_time_format), |
|
1453 | + 'TKT_end_date' => $default |
|
1454 | + ? '' |
|
1455 | + : $ticket->get_date('TKT_end_date', $this->_date_time_format), |
|
1456 | + 'TKT_status' => $TKT_status, |
|
1457 | + 'TKT_price' => $default |
|
1458 | + ? '' |
|
1459 | + : EEH_Template::format_currency( |
|
1460 | + $ticket->get_ticket_total_with_taxes(), |
|
1461 | + false, |
|
1462 | + false |
|
1463 | + ), |
|
1464 | + 'TKT_price_code' => EE_Registry::instance()->CFG->currency->code, |
|
1465 | + 'TKT_price_amount' => $default ? 0 : $ticket_subtotal, |
|
1466 | + 'TKT_qty' => $default |
|
1467 | + ? '' |
|
1468 | + : $ticket->get_pretty('TKT_qty', 'symbol'), |
|
1469 | + 'TKT_qty_for_input' => $default |
|
1470 | + ? '' |
|
1471 | + : $ticket->get_pretty('TKT_qty', 'input'), |
|
1472 | + 'TKT_uses' => $default |
|
1473 | + ? '' |
|
1474 | + : $ticket->get_pretty('TKT_uses', 'input'), |
|
1475 | + 'TKT_min' => $TKT_min, |
|
1476 | + 'TKT_max' => $default |
|
1477 | + ? '' |
|
1478 | + : $ticket->get_pretty('TKT_max', 'input'), |
|
1479 | + 'TKT_sold' => $default ? 0 : $ticket->tickets_sold(), |
|
1480 | + 'TKT_reserved' => $default ? 0 : $ticket->reserved(), |
|
1481 | + 'TKT_registrations' => $default |
|
1482 | + ? 0 |
|
1483 | + : $ticket->count_registrations( |
|
1484 | + [ |
|
1485 | + [ |
|
1486 | + 'STS_ID' => [ |
|
1487 | + '!=', |
|
1488 | + EEM_Registration::status_id_incomplete, |
|
1489 | + ], |
|
1490 | + ], |
|
1491 | + ] |
|
1492 | + ), |
|
1493 | + 'TKT_ID' => $default ? 0 : $ticket->ID(), |
|
1494 | + 'TKT_description' => $default ? '' : $ticket->get_f('TKT_description'), |
|
1495 | + 'TKT_is_default' => $default ? 0 : $ticket->is_default(), |
|
1496 | + 'TKT_required' => $default ? 0 : $ticket->required(), |
|
1497 | + 'TKT_is_default_selector' => '', |
|
1498 | + 'ticket_price_rows' => '', |
|
1499 | + 'TKT_base_price' => $default || ! $base_price instanceof EE_Price |
|
1500 | + ? '' |
|
1501 | + : $base_price->get_pretty('PRC_amount', 'localized_float'), |
|
1502 | + 'TKT_base_price_ID' => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(), |
|
1503 | + 'show_price_modifier' => count($prices) > 1 || ($default && $count_price_mods > 0) |
|
1504 | + ? '' |
|
1505 | + : 'display:none;', |
|
1506 | + 'show_price_mod_button' => count($prices) > 1 |
|
1507 | + || ($default && $count_price_mods > 0) |
|
1508 | + || (! $default && $ticket->deleted()) |
|
1509 | + ? 'display:none;' |
|
1510 | + : '', |
|
1511 | + 'total_price_rows' => count($prices) > 1 ? count($prices) : 1, |
|
1512 | + 'ticket_datetimes_list' => $default ? '<li class="hidden"></li>' : '', |
|
1513 | + 'starting_ticket_datetime_rows' => $default || $default_datetime ? '' : implode(',', $ticket_datetimes), |
|
1514 | + 'ticket_datetime_rows' => $default ? '' : implode(',', $ticket_datetimes), |
|
1515 | + 'existing_ticket_price_ids' => $default ? '' : implode(',', array_keys($prices)), |
|
1516 | + 'ticket_template_id' => $default ? 0 : $ticket->get('TTM_ID'), |
|
1517 | + 'TKT_taxable' => $TKT_taxable, |
|
1518 | + 'display_subtotal' => $ticket instanceof EE_Ticket && $ticket->taxable() |
|
1519 | + ? '' |
|
1520 | + : 'display:none;', |
|
1521 | + 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
1522 | + 'TKT_subtotal_amount_display' => EEH_Template::format_currency( |
|
1523 | + $ticket_subtotal, |
|
1524 | + false, |
|
1525 | + false |
|
1526 | + ), |
|
1527 | + 'TKT_subtotal_amount' => $ticket_subtotal, |
|
1528 | + 'tax_rows' => $this->_get_tax_rows($ticket_row, $ticket), |
|
1529 | + 'disabled' => $ticket instanceof EE_Ticket && $ticket->deleted(), |
|
1530 | + 'ticket_archive_class' => $ticket instanceof EE_Ticket && $ticket->deleted() |
|
1531 | + ? ' ticket-archived' |
|
1532 | + : '', |
|
1533 | + 'trash_icon' => $ticket instanceof EE_Ticket |
|
1534 | + && $ticket->deleted() |
|
1535 | + && ! $ticket->is_permanently_deleteable() |
|
1536 | + ? 'dashicons dashicons-lock ' |
|
1537 | + : 'trash-icon dashicons dashicons-post-trash clickable', |
|
1538 | + 'clone_icon' => $ticket instanceof EE_Ticket && $ticket->deleted() |
|
1539 | + ? '' |
|
1540 | + : 'clone-icon ee-icon ee-icon-clone clickable', |
|
1541 | + ]; |
|
1542 | + $template_args['trash_hidden'] = count($all_tickets) === 1 |
|
1543 | + && $template_args['trash_icon'] !== 'dashicons dashicons-lock' |
|
1544 | + ? 'display:none' |
|
1545 | + : ''; |
|
1546 | + // handle rows that should NOT be empty |
|
1547 | + if (empty($template_args['TKT_start_date'])) { |
|
1548 | + // if empty then the start date will be now. |
|
1549 | + $template_args['TKT_start_date'] = date( |
|
1550 | + $this->_date_time_format, |
|
1551 | + current_time('timestamp') |
|
1552 | + ); |
|
1553 | + $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1554 | + } |
|
1555 | + if (empty($template_args['TKT_end_date'])) { |
|
1556 | + // get the earliest datetime (if present); |
|
1557 | + $earliest_datetime = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 |
|
1558 | + ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related( |
|
1559 | + 'Datetime', |
|
1560 | + ['order_by' => ['DTT_EVT_start' => 'ASC']] |
|
1561 | + ) |
|
1562 | + : null; |
|
1563 | + if (! empty($earliest_datetime)) { |
|
1564 | + $template_args['TKT_end_date'] = $earliest_datetime->get_datetime( |
|
1565 | + 'DTT_EVT_start', |
|
1566 | + $this->_date_time_format |
|
1567 | + ); |
|
1568 | + } else { |
|
1569 | + // default so let's just use what's been set for the default date-time which is 30 days from now. |
|
1570 | + $template_args['TKT_end_date'] = date( |
|
1571 | + $this->_date_time_format, |
|
1572 | + mktime( |
|
1573 | + 24, |
|
1574 | + 0, |
|
1575 | + 0, |
|
1576 | + date('m'), |
|
1577 | + date('d') + 29, |
|
1578 | + date('Y') |
|
1579 | + ) |
|
1580 | + ); |
|
1581 | + } |
|
1582 | + $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale; |
|
1583 | + } |
|
1584 | + // generate ticket_datetime items |
|
1585 | + if (! $default) { |
|
1586 | + $datetime_row = 1; |
|
1587 | + foreach ($all_datetimes as $datetime) { |
|
1588 | + $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item( |
|
1589 | + $datetime_row, |
|
1590 | + $ticket_row, |
|
1591 | + $datetime, |
|
1592 | + $ticket, |
|
1593 | + $ticket_datetimes, |
|
1594 | + $default |
|
1595 | + ); |
|
1596 | + $datetime_row++; |
|
1597 | + } |
|
1598 | + } |
|
1599 | + $price_row = 1; |
|
1600 | + foreach ($prices as $price) { |
|
1601 | + if (! $price instanceof EE_Price) { |
|
1602 | + continue; |
|
1603 | + } |
|
1604 | + if ($price->is_base_price()) { |
|
1605 | + $price_row++; |
|
1606 | + continue; |
|
1607 | + } |
|
1608 | + |
|
1609 | + $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1); |
|
1610 | + $show_create = ! (count($prices) > 1 && count($prices) !== $price_row); |
|
1611 | + |
|
1612 | + $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row( |
|
1613 | + $ticket_row, |
|
1614 | + $price_row, |
|
1615 | + $price, |
|
1616 | + $default, |
|
1617 | + $ticket, |
|
1618 | + $show_trash, |
|
1619 | + $show_create |
|
1620 | + ); |
|
1621 | + $price_row++; |
|
1622 | + } |
|
1623 | + // filter $template_args |
|
1624 | + $template_args = apply_filters( |
|
1625 | + 'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args', |
|
1626 | + $template_args, |
|
1627 | + $ticket_row, |
|
1628 | + $ticket, |
|
1629 | + $ticket_datetimes, |
|
1630 | + $all_datetimes, |
|
1631 | + $default, |
|
1632 | + $all_tickets, |
|
1633 | + $this->_is_creating_event |
|
1634 | + ); |
|
1635 | + return EEH_Template::display_template( |
|
1636 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php', |
|
1637 | + $template_args, |
|
1638 | + true |
|
1639 | + ); |
|
1640 | + } |
|
1641 | + |
|
1642 | + |
|
1643 | + /** |
|
1644 | + * @param int $ticket_row |
|
1645 | + * @param EE_Ticket|null $ticket |
|
1646 | + * @return string |
|
1647 | + * @throws DomainException |
|
1648 | + * @throws EE_Error |
|
1649 | + * @throws ReflectionException |
|
1650 | + */ |
|
1651 | + protected function _get_tax_rows(int $ticket_row, ?EE_Ticket $ticket): string |
|
1652 | + { |
|
1653 | + $tax_rows = ''; |
|
1654 | + /** @var EE_Price[] $taxes */ |
|
1655 | + $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin(); |
|
1656 | + foreach ($taxes as $tax) { |
|
1657 | + $tax_added = $this->_get_tax_added($tax, $ticket); |
|
1658 | + $template_args = [ |
|
1659 | + 'display_tax' => ! empty($ticket) && $ticket->get('TKT_taxable') |
|
1660 | + ? '' |
|
1661 | + : 'display:none;', |
|
1662 | + 'tax_id' => $tax->ID(), |
|
1663 | + 'tkt_row' => $ticket_row, |
|
1664 | + 'tax_label' => $tax->get('PRC_name'), |
|
1665 | + 'tax_added' => $tax_added, |
|
1666 | + 'tax_added_display' => EEH_Template::format_currency($tax_added, false, false), |
|
1667 | + 'tax_amount' => $tax->get('PRC_amount'), |
|
1668 | + ]; |
|
1669 | + $template_args = apply_filters( |
|
1670 | + 'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args', |
|
1671 | + $template_args, |
|
1672 | + $ticket_row, |
|
1673 | + $ticket, |
|
1674 | + $this->_is_creating_event |
|
1675 | + ); |
|
1676 | + $tax_rows .= EEH_Template::display_template( |
|
1677 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php', |
|
1678 | + $template_args, |
|
1679 | + true |
|
1680 | + ); |
|
1681 | + } |
|
1682 | + return $tax_rows; |
|
1683 | + } |
|
1684 | + |
|
1685 | + |
|
1686 | + /** |
|
1687 | + * @param EE_Price $tax |
|
1688 | + * @param EE_Ticket|null $ticket |
|
1689 | + * @return float|int |
|
1690 | + * @throws EE_Error |
|
1691 | + * @throws ReflectionException |
|
1692 | + */ |
|
1693 | + protected function _get_tax_added(EE_Price $tax, ?EE_Ticket $ticket) |
|
1694 | + { |
|
1695 | + $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal(); |
|
1696 | + return $subtotal * $tax->get('PRC_amount') / 100; |
|
1697 | + } |
|
1698 | + |
|
1699 | + |
|
1700 | + /** |
|
1701 | + * @param int $ticket_row |
|
1702 | + * @param int $price_row |
|
1703 | + * @param EE_Price|null $price |
|
1704 | + * @param bool $default |
|
1705 | + * @param EE_Ticket|null $ticket |
|
1706 | + * @param bool $show_trash |
|
1707 | + * @param bool $show_create |
|
1708 | + * @return string |
|
1709 | + * @throws InvalidArgumentException |
|
1710 | + * @throws InvalidInterfaceException |
|
1711 | + * @throws InvalidDataTypeException |
|
1712 | + * @throws DomainException |
|
1713 | + * @throws EE_Error |
|
1714 | + * @throws ReflectionException |
|
1715 | + */ |
|
1716 | + protected function _get_ticket_price_row( |
|
1717 | + int $ticket_row, |
|
1718 | + int $price_row, |
|
1719 | + ?EE_Price $price, |
|
1720 | + bool $default, |
|
1721 | + ?EE_Ticket $ticket, |
|
1722 | + bool $show_trash = true, |
|
1723 | + bool $show_create = true |
|
1724 | + ): string { |
|
1725 | + $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted'); |
|
1726 | + $template_args = [ |
|
1727 | + 'tkt_row' => $default && empty($ticket) |
|
1728 | + ? 'TICKETNUM' |
|
1729 | + : $ticket_row, |
|
1730 | + 'PRC_order' => $default && empty($price) |
|
1731 | + ? 'PRICENUM' |
|
1732 | + : $price_row, |
|
1733 | + 'edit_prices_name' => $default && empty($price) |
|
1734 | + ? 'PRICENAMEATTR' |
|
1735 | + : 'edit_prices', |
|
1736 | + 'price_type_selector' => $default && empty($price) |
|
1737 | + ? $this->_get_base_price_template($ticket_row, $price_row, $price, true) |
|
1738 | + : $this->_get_price_type_selector( |
|
1739 | + $ticket_row, |
|
1740 | + $price_row, |
|
1741 | + $price, |
|
1742 | + $default, |
|
1743 | + $send_disabled |
|
1744 | + ), |
|
1745 | + 'PRC_ID' => $default && empty($price) |
|
1746 | + ? 0 |
|
1747 | + : $price->ID(), |
|
1748 | + 'PRC_is_default' => $default && empty($price) |
|
1749 | + ? 0 |
|
1750 | + : $price->get('PRC_is_default'), |
|
1751 | + 'PRC_name' => $default && empty($price) |
|
1752 | + ? '' |
|
1753 | + : $price->get('PRC_name'), |
|
1754 | + 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
1755 | + 'show_plus_or_minus' => $default && empty($price) |
|
1756 | + ? '' |
|
1757 | + : 'display:none;', |
|
1758 | + 'show_plus' => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price()) |
|
1759 | + ? 'display:none;' |
|
1760 | + : '', |
|
1761 | + 'show_minus' => ($default && empty($price)) || ! $price->is_discount() |
|
1762 | + ? 'display:none;' |
|
1763 | + : '', |
|
1764 | + 'show_currency_symbol' => ($default && empty($price)) || $price->is_percent() |
|
1765 | + ? 'display:none' |
|
1766 | + : '', |
|
1767 | + 'PRC_amount' => $default && empty($price) |
|
1768 | + ? 0 |
|
1769 | + : $price->get_pretty('PRC_amount', 'localized_float'), |
|
1770 | + 'show_percentage' => ($default && empty($price)) || ! $price->is_percent() |
|
1771 | + ? 'display:none;' |
|
1772 | + : '', |
|
1773 | + 'show_trash_icon' => $show_trash |
|
1774 | + ? '' |
|
1775 | + : ' style="display:none;"', |
|
1776 | + 'show_create_button' => $show_create |
|
1777 | + ? '' |
|
1778 | + : ' style="display:none;"', |
|
1779 | + 'PRC_desc' => $default && empty($price) |
|
1780 | + ? '' |
|
1781 | + : $price->get('PRC_desc'), |
|
1782 | + 'disabled' => ! empty($ticket) && $ticket->get('TKT_deleted'), |
|
1783 | + ]; |
|
1784 | + $template_args = apply_filters( |
|
1785 | + 'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args', |
|
1786 | + $template_args, |
|
1787 | + $ticket_row, |
|
1788 | + $price_row, |
|
1789 | + $price, |
|
1790 | + $default, |
|
1791 | + $ticket, |
|
1792 | + $show_trash, |
|
1793 | + $show_create, |
|
1794 | + $this->_is_creating_event |
|
1795 | + ); |
|
1796 | + return EEH_Template::display_template( |
|
1797 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php', |
|
1798 | + $template_args, |
|
1799 | + true |
|
1800 | + ); |
|
1801 | + } |
|
1802 | + |
|
1803 | + |
|
1804 | + /** |
|
1805 | + * @param int $ticket_row |
|
1806 | + * @param int $price_row |
|
1807 | + * @param EE_Price|null $price |
|
1808 | + * @param bool $default |
|
1809 | + * @param bool $disabled |
|
1810 | + * @return string |
|
1811 | + * @throws ReflectionException |
|
1812 | + * @throws InvalidArgumentException |
|
1813 | + * @throws InvalidInterfaceException |
|
1814 | + * @throws InvalidDataTypeException |
|
1815 | + * @throws DomainException |
|
1816 | + * @throws EE_Error |
|
1817 | + */ |
|
1818 | + protected function _get_price_type_selector( |
|
1819 | + int $ticket_row, |
|
1820 | + int $price_row, |
|
1821 | + ?EE_Price $price, |
|
1822 | + bool $default, |
|
1823 | + bool $disabled = false |
|
1824 | + ): string { |
|
1825 | + if ($price->is_base_price()) { |
|
1826 | + return $this->_get_base_price_template( |
|
1827 | + $ticket_row, |
|
1828 | + $price_row, |
|
1829 | + $price, |
|
1830 | + $default |
|
1831 | + ); |
|
1832 | + } |
|
1833 | + return $this->_get_price_modifier_template( |
|
1834 | + $ticket_row, |
|
1835 | + $price_row, |
|
1836 | + $price, |
|
1837 | + $default, |
|
1838 | + $disabled |
|
1839 | + ); |
|
1840 | + } |
|
1841 | + |
|
1842 | + |
|
1843 | + /** |
|
1844 | + * @param int $ticket_row |
|
1845 | + * @param int $price_row |
|
1846 | + * @param EE_Price|null $price |
|
1847 | + * @param bool $default |
|
1848 | + * @return string |
|
1849 | + * @throws DomainException |
|
1850 | + * @throws EE_Error |
|
1851 | + * @throws ReflectionException |
|
1852 | + */ |
|
1853 | + protected function _get_base_price_template( |
|
1854 | + int $ticket_row, |
|
1855 | + int $price_row, |
|
1856 | + ?EE_Price $price, |
|
1857 | + bool $default |
|
1858 | + ): string { |
|
1859 | + $template_args = [ |
|
1860 | + 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1861 | + 'PRC_order' => $default && empty($price) ? 'PRICENUM' : $price_row, |
|
1862 | + 'PRT_ID' => $default && empty($price) ? 1 : $price->get('PRT_ID'), |
|
1863 | + 'PRT_name' => esc_html__('Price', 'event_espresso'), |
|
1864 | + 'price_selected_operator' => '+', |
|
1865 | + 'price_selected_is_percent' => 0, |
|
1866 | + ]; |
|
1867 | + $template_args = apply_filters( |
|
1868 | + 'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args', |
|
1869 | + $template_args, |
|
1870 | + $ticket_row, |
|
1871 | + $price_row, |
|
1872 | + $price, |
|
1873 | + $default, |
|
1874 | + $this->_is_creating_event |
|
1875 | + ); |
|
1876 | + return EEH_Template::display_template( |
|
1877 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php', |
|
1878 | + $template_args, |
|
1879 | + true |
|
1880 | + ); |
|
1881 | + } |
|
1882 | + |
|
1883 | + |
|
1884 | + /** |
|
1885 | + * @param int $ticket_row |
|
1886 | + * @param int $price_row |
|
1887 | + * @param EE_Price|null $price |
|
1888 | + * @param bool $default |
|
1889 | + * @param bool $disabled |
|
1890 | + * @return string |
|
1891 | + * @throws ReflectionException |
|
1892 | + * @throws InvalidArgumentException |
|
1893 | + * @throws InvalidInterfaceException |
|
1894 | + * @throws InvalidDataTypeException |
|
1895 | + * @throws DomainException |
|
1896 | + * @throws EE_Error |
|
1897 | + */ |
|
1898 | + protected function _get_price_modifier_template( |
|
1899 | + int $ticket_row, |
|
1900 | + int $price_row, |
|
1901 | + ?EE_Price $price, |
|
1902 | + bool $default, |
|
1903 | + bool $disabled = false |
|
1904 | + ): string { |
|
1905 | + $select_name = $default && ! $price instanceof EE_Price |
|
1906 | + ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]' |
|
1907 | + : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]'; |
|
1908 | + /** @var EEM_Price_Type $price_type_model */ |
|
1909 | + $price_type_model = EE_Registry::instance()->load_model('Price_Type'); |
|
1910 | + $price_types = $price_type_model->get_all( |
|
1911 | + [ |
|
1912 | + [ |
|
1913 | + 'OR' => [ |
|
1914 | + 'PBT_ID' => '2', |
|
1915 | + 'PBT_ID*' => '3', |
|
1916 | + ], |
|
1917 | + ], |
|
1918 | + ] |
|
1919 | + ); |
|
1920 | + $all_price_types = $default && ! $price instanceof EE_Price |
|
1921 | + ? [esc_html__('Select Modifier', 'event_espresso')] |
|
1922 | + : []; |
|
1923 | + $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type(); |
|
1924 | + $price_option_spans = ''; |
|
1925 | + // setup price types for selector |
|
1926 | + foreach ($price_types as $price_type) { |
|
1927 | + if (! $price_type instanceof EE_Price_Type) { |
|
1928 | + continue; |
|
1929 | + } |
|
1930 | + $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name'); |
|
1931 | + // while we're in the loop let's setup the option spans used by js |
|
1932 | + $span_args = [ |
|
1933 | + 'PRT_ID' => $price_type->ID(), |
|
1934 | + 'PRT_operator' => $price_type->is_discount() ? '-' : '+', |
|
1935 | + 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0, |
|
1936 | + ]; |
|
1937 | + $price_option_spans .= EEH_Template::display_template( |
|
1938 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php', |
|
1939 | + $span_args, |
|
1940 | + true |
|
1941 | + ); |
|
1942 | + } |
|
1943 | + |
|
1944 | + $select_name = $disabled |
|
1945 | + ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]' |
|
1946 | + : $select_name; |
|
1947 | + |
|
1948 | + $select_input = new EE_Select_Input( |
|
1949 | + $all_price_types, |
|
1950 | + [ |
|
1951 | + 'default' => $selected_price_type_id, |
|
1952 | + 'html_name' => $select_name, |
|
1953 | + 'html_class' => 'edit-price-PRT_ID', |
|
1954 | + 'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"', |
|
1955 | + ] |
|
1956 | + ); |
|
1957 | + |
|
1958 | + $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+'; |
|
1959 | + $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator; |
|
1960 | + $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0; |
|
1961 | + $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent; |
|
1962 | + $template_args = [ |
|
1963 | + 'tkt_row' => $default ? 'TICKETNUM' : $ticket_row, |
|
1964 | + 'PRC_order' => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row, |
|
1965 | + 'price_modifier_selector' => $select_input->get_html_for_input(), |
|
1966 | + 'main_name' => $select_name, |
|
1967 | + 'selected_price_type_id' => $selected_price_type_id, |
|
1968 | + 'price_option_spans' => $price_option_spans, |
|
1969 | + 'price_selected_operator' => $price_selected_operator, |
|
1970 | + 'price_selected_is_percent' => $price_selected_is_percent, |
|
1971 | + 'disabled' => $disabled, |
|
1972 | + ]; |
|
1973 | + $template_args = apply_filters( |
|
1974 | + 'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args', |
|
1975 | + $template_args, |
|
1976 | + $ticket_row, |
|
1977 | + $price_row, |
|
1978 | + $price, |
|
1979 | + $default, |
|
1980 | + $disabled, |
|
1981 | + $this->_is_creating_event |
|
1982 | + ); |
|
1983 | + return EEH_Template::display_template( |
|
1984 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php', |
|
1985 | + $template_args, |
|
1986 | + true |
|
1987 | + ); |
|
1988 | + } |
|
1989 | + |
|
1990 | + |
|
1991 | + /** |
|
1992 | + * @param int $datetime_row |
|
1993 | + * @param int $ticket_row |
|
1994 | + * @param EE_Datetime|null $datetime |
|
1995 | + * @param EE_Ticket|null $ticket |
|
1996 | + * @param array $ticket_datetimes |
|
1997 | + * @param bool $default |
|
1998 | + * @return string |
|
1999 | + * @throws DomainException |
|
2000 | + * @throws EE_Error |
|
2001 | + * @throws ReflectionException |
|
2002 | + */ |
|
2003 | + protected function _get_ticket_datetime_list_item( |
|
2004 | + int $datetime_row, |
|
2005 | + int $ticket_row, |
|
2006 | + ?EE_Datetime $datetime, |
|
2007 | + ?EE_Ticket $ticket, |
|
2008 | + array $ticket_datetimes = [], |
|
2009 | + bool $default = false |
|
2010 | + ): string { |
|
2011 | + $ticket_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ]) |
|
2012 | + ? $ticket_datetimes[ $ticket->ID() ] |
|
2013 | + : []; |
|
2014 | + $template_args = [ |
|
2015 | + 'dtt_row' => $default && ! $datetime instanceof EE_Datetime |
|
2016 | + ? 'DTTNUM' |
|
2017 | + : $datetime_row, |
|
2018 | + 'tkt_row' => $default |
|
2019 | + ? 'TICKETNUM' |
|
2020 | + : $ticket_row, |
|
2021 | + 'ticket_datetime_selected' => in_array($datetime_row, $ticket_datetimes, true) |
|
2022 | + ? ' ticket-selected' |
|
2023 | + : '', |
|
2024 | + 'ticket_datetime_checked' => in_array($datetime_row, $ticket_datetimes, true) |
|
2025 | + ? ' checked' |
|
2026 | + : '', |
|
2027 | + 'DTT_name' => $default && empty($datetime) |
|
2028 | + ? 'DTTNAME' |
|
2029 | + : $datetime->get_dtt_display_name(true), |
|
2030 | + 'tkt_status_class' => '', |
|
2031 | + ]; |
|
2032 | + $template_args = apply_filters( |
|
2033 | + 'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args', |
|
2034 | + $template_args, |
|
2035 | + $datetime_row, |
|
2036 | + $ticket_row, |
|
2037 | + $datetime, |
|
2038 | + $ticket, |
|
2039 | + $ticket_datetimes, |
|
2040 | + $default, |
|
2041 | + $this->_is_creating_event |
|
2042 | + ); |
|
2043 | + return EEH_Template::display_template( |
|
2044 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php', |
|
2045 | + $template_args, |
|
2046 | + true |
|
2047 | + ); |
|
2048 | + } |
|
2049 | + |
|
2050 | + |
|
2051 | + /** |
|
2052 | + * @param array $all_datetimes |
|
2053 | + * @param array $all_tickets |
|
2054 | + * @return string |
|
2055 | + * @throws ReflectionException |
|
2056 | + * @throws InvalidArgumentException |
|
2057 | + * @throws InvalidInterfaceException |
|
2058 | + * @throws InvalidDataTypeException |
|
2059 | + * @throws DomainException |
|
2060 | + * @throws EE_Error |
|
2061 | + */ |
|
2062 | + protected function _get_ticket_js_structure(array $all_datetimes = [], array $all_tickets = []): string |
|
2063 | + { |
|
2064 | + $template_args = [ |
|
2065 | + 'default_datetime_edit_row' => $this->_get_dtt_edit_row( |
|
2066 | + 'DTTNUM', |
|
2067 | + null, |
|
2068 | + true, |
|
2069 | + $all_datetimes |
|
2070 | + ), |
|
2071 | + 'default_ticket_row' => $this->_get_ticket_row( |
|
2072 | + 'TICKETNUM', |
|
2073 | + null, |
|
2074 | + [], |
|
2075 | + [], |
|
2076 | + true |
|
2077 | + ), |
|
2078 | + 'default_price_row' => $this->_get_ticket_price_row( |
|
2079 | + 'TICKETNUM', |
|
2080 | + 'PRICENUM', |
|
2081 | + null, |
|
2082 | + true, |
|
2083 | + null |
|
2084 | + ), |
|
2085 | + |
|
2086 | + 'default_price_rows' => '', |
|
2087 | + 'default_base_price_amount' => 0, |
|
2088 | + 'default_base_price_name' => '', |
|
2089 | + 'default_base_price_description' => '', |
|
2090 | + 'default_price_modifier_selector_row' => $this->_get_price_modifier_template( |
|
2091 | + 'TICKETNUM', |
|
2092 | + 'PRICENUM', |
|
2093 | + null, |
|
2094 | + true |
|
2095 | + ), |
|
2096 | + 'default_available_tickets_for_datetime' => $this->_get_dtt_attached_tickets_row( |
|
2097 | + 'DTTNUM', |
|
2098 | + null, |
|
2099 | + [], |
|
2100 | + [], |
|
2101 | + true |
|
2102 | + ), |
|
2103 | + 'existing_available_datetime_tickets_list' => '', |
|
2104 | + 'existing_available_ticket_datetimes_list' => '', |
|
2105 | + 'new_available_datetime_ticket_list_item' => $this->_get_datetime_tickets_list_item( |
|
2106 | + 'DTTNUM', |
|
2107 | + 'TICKETNUM', |
|
2108 | + null, |
|
2109 | + null, |
|
2110 | + [], |
|
2111 | + true |
|
2112 | + ), |
|
2113 | + 'new_available_ticket_datetime_list_item' => $this->_get_ticket_datetime_list_item( |
|
2114 | + 'DTTNUM', |
|
2115 | + 'TICKETNUM', |
|
2116 | + null, |
|
2117 | + null, |
|
2118 | + [], |
|
2119 | + true |
|
2120 | + ), |
|
2121 | + ]; |
|
2122 | + $ticket_row = 1; |
|
2123 | + foreach ($all_tickets as $ticket) { |
|
2124 | + $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item( |
|
2125 | + 'DTTNUM', |
|
2126 | + $ticket_row, |
|
2127 | + null, |
|
2128 | + $ticket, |
|
2129 | + [], |
|
2130 | + true |
|
2131 | + ); |
|
2132 | + $ticket_row++; |
|
2133 | + } |
|
2134 | + $datetime_row = 1; |
|
2135 | + foreach ($all_datetimes as $datetime) { |
|
2136 | + $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item( |
|
2137 | + $datetime_row, |
|
2138 | + 'TICKETNUM', |
|
2139 | + $datetime, |
|
2140 | + null, |
|
2141 | + [], |
|
2142 | + true |
|
2143 | + ); |
|
2144 | + $datetime_row++; |
|
2145 | + } |
|
2146 | + /** @var EEM_Price $price_model */ |
|
2147 | + $price_model = EE_Registry::instance()->load_model('Price'); |
|
2148 | + $default_prices = $price_model->get_all_default_prices(); |
|
2149 | + $price_row = 1; |
|
2150 | + foreach ($default_prices as $price) { |
|
2151 | + if (! $price instanceof EE_Price) { |
|
2152 | + continue; |
|
2153 | + } |
|
2154 | + if ($price->is_base_price()) { |
|
2155 | + $template_args['default_base_price_amount'] = $price->get_pretty( |
|
2156 | + 'PRC_amount', |
|
2157 | + 'localized_float' |
|
2158 | + ); |
|
2159 | + $template_args['default_base_price_name'] = $price->get('PRC_name'); |
|
2160 | + $template_args['default_base_price_description'] = $price->get('PRC_desc'); |
|
2161 | + $price_row++; |
|
2162 | + continue; |
|
2163 | + } |
|
2164 | + |
|
2165 | + $show_trash = ! ((count($default_prices) > 1 && $price_row === 1) || count($default_prices) === 1); |
|
2166 | + $show_create = ! (count($default_prices) > 1 && count($default_prices) !== $price_row); |
|
2167 | + |
|
2168 | + $template_args['default_price_rows'] .= $this->_get_ticket_price_row( |
|
2169 | + 'TICKETNUM', |
|
2170 | + $price_row, |
|
2171 | + $price, |
|
2172 | + true, |
|
2173 | + null, |
|
2174 | + $show_trash, |
|
2175 | + $show_create |
|
2176 | + ); |
|
2177 | + $price_row++; |
|
2178 | + } |
|
2179 | + $template_args = apply_filters( |
|
2180 | + 'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args', |
|
2181 | + $template_args, |
|
2182 | + $all_datetimes, |
|
2183 | + $all_tickets, |
|
2184 | + $this->_is_creating_event |
|
2185 | + ); |
|
2186 | + return EEH_Template::display_template( |
|
2187 | + PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php', |
|
2188 | + $template_args, |
|
2189 | + true |
|
2190 | + ); |
|
2191 | + } |
|
2192 | 2192 | } |