Completed
Branch master (876dd2)
by
unknown
02:51
created
admin_pages/messages/Messages_Admin_Page.core.php 1 patch
Indentation   +4650 added lines, -4650 removed lines patch added patch discarded remove patch
@@ -18,2689 +18,2689 @@  discard block
 block discarded – undo
18 18
  */
19 19
 class Messages_Admin_Page extends EE_Admin_Page
20 20
 {
21
-    /**
22
-     * @var EEM_Message
23
-     */
24
-    private $MSG_MODEL;
25
-
26
-    /**
27
-     * @var EEM_Message_Template
28
-     */
29
-    private $MTP_MODEL;
30
-
31
-    /**
32
-     * @var EEM_Message_Template_Group
33
-     */
34
-    private $MTG_MODEL;
35
-
36
-    /**
37
-     * @var EE_Message_Resource_Manager $_message_resource_manager
38
-     */
39
-    protected $_message_resource_manager;
40
-
41
-    /**
42
-     * @var string
43
-     */
44
-    protected $_active_message_type_name = '';
45
-
46
-    /**
47
-     * @var string
48
-     */
49
-    protected $_active_messenger_name = '';
50
-
51
-    /**
52
-     * @var EE_messenger $_active_messenger
53
-     */
54
-    protected $_active_messenger;
55
-
56
-    protected $_activate_meta_box_type;
57
-
58
-    protected $_current_message_meta_box;
59
-
60
-    protected $_current_message_meta_box_object;
61
-
62
-    protected $_context_switcher;
63
-
64
-    protected $_shortcodes           = [];
65
-
66
-    protected $_active_messengers    = [];
67
-
68
-    protected $_active_message_types = [];
69
-
70
-    /**
71
-     * @var EE_Message_Template_Group $_message_template_group
72
-     */
73
-    protected $_message_template_group;
74
-
75
-    protected $_m_mt_settings = [];
76
-
77
-
78
-    /**
79
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
80
-     * IF there is no group then it gets automatically set to the Default template pack.
81
-     *
82
-     * @since 4.5.0
83
-     *
84
-     * @var EE_Messages_Template_Pack
85
-     */
86
-    protected $_template_pack;
87
-
88
-
89
-    /**
90
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
91
-     * group is.  If there is no group then it automatically gets set to default.
92
-     *
93
-     * @since 4.5.0
94
-     *
95
-     * @var string
96
-     */
97
-    protected $_variation;
98
-
99
-
100
-    /**
101
-     * @param bool $routing
102
-     * @throws EE_Error
103
-     * @throws ReflectionException
104
-     */
105
-    public function __construct($routing = true)
106
-    {
107
-        // make sure messages autoloader is running
108
-        EED_Messages::set_autoloaders();
109
-        parent::__construct($routing);
110
-    }
111
-
112
-
113
-    /**
114
-     * @return EEM_Message
115
-     * @throws EE_Error
116
-     */
117
-    public function getMsgModel()
118
-    {
119
-        if (! $this->MSG_MODEL instanceof EEM_Message) {
120
-            $this->MSG_MODEL = EEM_Message::instance();
121
-        }
122
-        return $this->MSG_MODEL;
123
-    }
124
-
125
-
126
-    /**
127
-     * @return EEM_Message_Template
128
-     * @throws EE_Error
129
-     */
130
-    public function getMtpModel()
131
-    {
132
-        if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
133
-            $this->MTP_MODEL = EEM_Message_Template::instance();
134
-        }
135
-        return $this->MTP_MODEL;
136
-    }
137
-
138
-
139
-    /**
140
-     * @return EEM_Message_Template_Group
141
-     * @throws EE_Error
142
-     */
143
-    public function getMtgModel()
144
-    {
145
-        if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
146
-            $this->MTG_MODEL = EEM_Message_Template_Group::instance();
147
-        }
148
-        return $this->MTG_MODEL;
149
-    }
150
-
151
-
152
-    /**
153
-     * @throws EE_Error
154
-     * @throws ReflectionException
155
-     */
156
-    protected function _init_page_props()
157
-    {
158
-        $this->page_slug        = EE_MSG_PG_SLUG;
159
-        $this->page_label       = esc_html__('Messages Settings', 'event_espresso');
160
-        $this->_admin_base_url  = EE_MSG_ADMIN_URL;
161
-        $this->_admin_base_path = EE_MSG_ADMIN;
162
-
163
-        $messenger    = $this->request->getRequestParam('messenger', '');
164
-        $message_type = $this->request->getRequestParam('message_type', '');
165
-        $this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
166
-        $this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
167
-
168
-        $this->_load_message_resource_manager();
169
-    }
170
-
171
-
172
-    /**
173
-     * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
174
-     *
175
-     * @throws EE_Error
176
-     * @throws InvalidDataTypeException
177
-     * @throws InvalidInterfaceException
178
-     * @throws InvalidArgumentException
179
-     * @throws ReflectionException
180
-     */
181
-    protected function _load_message_resource_manager()
182
-    {
183
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
184
-    }
185
-
186
-
187
-    /**
188
-     * @return array
189
-     * @throws EE_Error
190
-     * @throws InvalidArgumentException
191
-     * @throws InvalidDataTypeException
192
-     * @throws InvalidInterfaceException
193
-     * @deprecated 4.9.9.rc.014
194
-     */
195
-    public function get_messengers_for_list_table()
196
-    {
197
-        EE_Error::doing_it_wrong(
198
-            __METHOD__,
199
-            sprintf(
200
-                esc_html__(
201
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
202
-                    'event_espresso'
203
-                ),
204
-                'Messages_Admin_Page::get_messengers_select_input()'
205
-            ),
206
-            '4.9.9.rc.014'
207
-        );
208
-
209
-        $m_values          = [];
210
-        $active_messengers = $this->getMsgModel()->get_all(['group_by' => 'MSG_messenger']);
211
-        // setup messengers for selects
212
-        $i = 1;
213
-        foreach ($active_messengers as $active_messenger) {
214
-            if ($active_messenger instanceof EE_Message) {
215
-                $m_values[ $i ]['id']   = $active_messenger->messenger();
216
-                $m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
217
-                $i++;
218
-            }
219
-        }
220
-
221
-        return $m_values;
222
-    }
223
-
224
-
225
-    /**
226
-     * @return array
227
-     * @throws EE_Error
228
-     * @throws InvalidArgumentException
229
-     * @throws InvalidDataTypeException
230
-     * @throws InvalidInterfaceException
231
-     * @deprecated 4.9.9.rc.014
232
-     */
233
-    public function get_message_types_for_list_table()
234
-    {
235
-        EE_Error::doing_it_wrong(
236
-            __METHOD__,
237
-            sprintf(
238
-                esc_html__(
239
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
240
-                    'event_espresso'
241
-                ),
242
-                'Messages_Admin_Page::get_message_types_select_input()'
243
-            ),
244
-            '4.9.9.rc.014'
245
-        );
246
-
247
-        $mt_values       = [];
248
-        $active_messages = $this->getMsgModel()->get_all(['group_by' => 'MSG_message_type']);
249
-        $i               = 1;
250
-        foreach ($active_messages as $active_message) {
251
-            if ($active_message instanceof EE_Message) {
252
-                $mt_values[ $i ]['id']   = $active_message->message_type();
253
-                $mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
254
-                $i++;
255
-            }
256
-        }
257
-
258
-        return $mt_values;
259
-    }
260
-
261
-
262
-    /**
263
-     * @return array
264
-     * @throws EE_Error
265
-     * @throws InvalidArgumentException
266
-     * @throws InvalidDataTypeException
267
-     * @throws InvalidInterfaceException
268
-     * @deprecated 4.9.9.rc.014
269
-     */
270
-    public function get_contexts_for_message_types_for_list_table()
271
-    {
272
-        EE_Error::doing_it_wrong(
273
-            __METHOD__,
274
-            sprintf(
275
-                esc_html__(
276
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
277
-                    'event_espresso'
278
-                ),
279
-                'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
280
-            ),
281
-            '4.9.9.rc.014'
282
-        );
283
-
284
-        $contexts                = [];
285
-        $active_message_contexts = $this->getMsgModel()->get_all(['group_by' => 'MSG_context']);
286
-        foreach ($active_message_contexts as $active_message) {
287
-            if ($active_message instanceof EE_Message) {
288
-                $message_type = $active_message->message_type_object();
289
-                if ($message_type instanceof EE_message_type) {
290
-                    $message_type_contexts = $message_type->get_contexts();
291
-                    foreach ($message_type_contexts as $context => $context_details) {
292
-                        $contexts[ $context ] = $context_details['label'];
293
-                    }
294
-                }
295
-            }
296
-        }
297
-
298
-        return $contexts;
299
-    }
300
-
301
-
302
-    /**
303
-     * Generate select input with provided messenger options array.
304
-     *
305
-     * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
306
-     *                                 labels.
307
-     * @return string
308
-     * @throws EE_Error
309
-     */
310
-    public function get_messengers_select_input($messenger_options)
311
-    {
312
-        // if empty or just one value then just return an empty string
313
-        if (
314
-            empty($messenger_options)
315
-            || ! is_array($messenger_options)
316
-            || count($messenger_options) === 1
317
-        ) {
318
-            return '';
319
-        }
320
-        // merge in default
321
-        $messenger_options = array_merge(
322
-            ['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
323
-            $messenger_options
324
-        );
325
-        $input             = new EE_Select_Input(
326
-            $messenger_options,
327
-            [
328
-                'html_name'  => 'ee_messenger_filter_by',
329
-                'html_id'    => 'ee_messenger_filter_by',
330
-                'html_class' => 'wide',
331
-                'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
332
-            ]
333
-        );
334
-
335
-        return $input->get_html_for_input();
336
-    }
337
-
338
-
339
-    /**
340
-     * Generate select input with provided message type options array.
341
-     *
342
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
343
-     *                                    message type labels
344
-     * @return string
345
-     * @throws EE_Error
346
-     */
347
-    public function get_message_types_select_input($message_type_options)
348
-    {
349
-        // if empty or count of options is 1 then just return an empty string
350
-        if (
351
-            empty($message_type_options)
352
-            || ! is_array($message_type_options)
353
-            || count($message_type_options) === 1
354
-        ) {
355
-            return '';
356
-        }
357
-        // merge in default
358
-        $message_type_options = array_merge(
359
-            ['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
360
-            $message_type_options
361
-        );
362
-        $input                = new EE_Select_Input(
363
-            $message_type_options,
364
-            [
365
-                'html_name'  => 'ee_message_type_filter_by',
366
-                'html_id'    => 'ee_message_type_filter_by',
367
-                'html_class' => 'wide',
368
-                'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
369
-            ]
370
-        );
371
-
372
-        return $input->get_html_for_input();
373
-    }
374
-
375
-
376
-    /**
377
-     * Generate select input with provide message type contexts array.
378
-     *
379
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
380
-     *                               context label.
381
-     * @return string
382
-     * @throws EE_Error
383
-     */
384
-    public function get_contexts_for_message_types_select_input($context_options)
385
-    {
386
-        // if empty or count of options is one then just return empty string
387
-        if (
388
-            empty($context_options)
389
-            || ! is_array($context_options)
390
-            || count($context_options) === 1
391
-        ) {
392
-            return '';
393
-        }
394
-        // merge in default
395
-        $context_options = array_merge(
396
-            ['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
397
-            $context_options
398
-        );
399
-        $input           = new EE_Select_Input(
400
-            $context_options,
401
-            [
402
-                'html_name'  => 'ee_context_filter_by',
403
-                'html_id'    => 'ee_context_filter_by',
404
-                'html_class' => 'wide',
405
-                'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
406
-            ]
407
-        );
408
-
409
-        return $input->get_html_for_input();
410
-    }
411
-
412
-
413
-    protected function _ajax_hooks()
414
-    {
415
-        add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
416
-        add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
417
-        add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
418
-        add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
419
-        add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
420
-        add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
421
-    }
422
-
423
-
424
-    protected function _define_page_props()
425
-    {
426
-        $this->_admin_page_title = $this->page_label;
427
-        $this->_labels           = [
428
-            'buttons'    => [
429
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
430
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
431
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
432
-            ],
433
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
434
-        ];
435
-    }
436
-
437
-
438
-    /**
439
-     *        an array for storing key => value pairs of request actions and their corresponding methods
440
-     *
441
-     * @access protected
442
-     * @return void
443
-     */
444
-    protected function _set_page_routes()
445
-    {
446
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
447
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
448
-        $MSG_ID = $this->request->getRequestParam('MSG_ID', 0, 'int');
449
-
450
-        $this->_page_routes = [
451
-            'default'                          => [
452
-                'func'       => '_message_queue_list_table',
453
-                'capability' => 'ee_read_global_messages',
454
-            ],
455
-            'global_mtps'                      => [
456
-                'func'       => '_ee_default_messages_overview_list_table',
457
-                'capability' => 'ee_read_global_messages',
458
-            ],
459
-            'custom_mtps'                      => [
460
-                'func'       => '_custom_mtps_preview',
461
-                'capability' => 'ee_read_messages',
462
-            ],
463
-            'add_new_message_template'         => [
464
-                'func'       => 'add_message_template',
465
-                'capability' => 'ee_edit_messages',
466
-                'noheader'   => true,
467
-            ],
468
-            'edit_message_template'            => [
469
-                'func'       => '_edit_message_template',
470
-                'capability' => 'ee_edit_message',
471
-                'obj_id'     => $GRP_ID,
472
-            ],
473
-            'preview_message'                  => [
474
-                'func'               => '_preview_message',
475
-                'capability'         => 'ee_read_message',
476
-                'obj_id'             => $GRP_ID,
477
-                'noheader'           => true,
478
-                'headers_sent_route' => 'display_preview_message',
479
-            ],
480
-            'display_preview_message'          => [
481
-                'func'       => '_display_preview_message',
482
-                'capability' => 'ee_read_message',
483
-                'obj_id'     => $GRP_ID,
484
-            ],
485
-            'insert_message_template'          => [
486
-                'func'       => '_insert_or_update_message_template',
487
-                'capability' => 'ee_edit_messages',
488
-                'args'       => ['new' => true],
489
-                'noheader'   => true,
490
-            ],
491
-            'update_message_template'          => [
492
-                'func'       => '_insert_or_update_message_template',
493
-                'capability' => 'ee_edit_message',
494
-                'obj_id'     => $GRP_ID,
495
-                'args'       => ['new' => false],
496
-                'noheader'   => true,
497
-            ],
498
-            'trash_message_template'           => [
499
-                'func'       => '_trash_or_restore_message_template',
500
-                'capability' => 'ee_delete_message',
501
-                'obj_id'     => $GRP_ID,
502
-                'args'       => ['trash' => true, 'all' => true],
503
-                'noheader'   => true,
504
-            ],
505
-            'trash_message_template_context'   => [
506
-                'func'       => '_trash_or_restore_message_template',
507
-                'capability' => 'ee_delete_message',
508
-                'obj_id'     => $GRP_ID,
509
-                'args'       => ['trash' => true],
510
-                'noheader'   => true,
511
-            ],
512
-            'restore_message_template'         => [
513
-                'func'       => '_trash_or_restore_message_template',
514
-                'capability' => 'ee_delete_message',
515
-                'obj_id'     => $GRP_ID,
516
-                'args'       => ['trash' => false, 'all' => true],
517
-                'noheader'   => true,
518
-            ],
519
-            'restore_message_template_context' => [
520
-                'func'       => '_trash_or_restore_message_template',
521
-                'capability' => 'ee_delete_message',
522
-                'obj_id'     => $GRP_ID,
523
-                'args'       => ['trash' => false],
524
-                'noheader'   => true,
525
-            ],
526
-            'delete_message_template'          => [
527
-                'func'       => '_delete_message_template',
528
-                'capability' => 'ee_delete_message',
529
-                'obj_id'     => $GRP_ID,
530
-                'noheader'   => true,
531
-            ],
532
-            'reset_to_default'                 => [
533
-                'func'       => '_reset_to_default_template',
534
-                'capability' => 'ee_edit_message',
535
-                'obj_id'     => $GRP_ID,
536
-                'noheader'   => true,
537
-            ],
538
-            'settings'                         => [
539
-                'func'       => '_settings',
540
-                'capability' => 'manage_options',
541
-            ],
542
-            'update_global_settings'           => [
543
-                'func'       => '_update_global_settings',
544
-                'capability' => 'manage_options',
545
-                'noheader'   => true,
546
-            ],
547
-            'generate_now'                     => [
548
-                'func'       => '_generate_now',
549
-                'capability' => 'ee_send_message',
550
-                'noheader'   => true,
551
-            ],
552
-            'generate_and_send_now'            => [
553
-                'func'       => '_generate_and_send_now',
554
-                'capability' => 'ee_send_message',
555
-                'noheader'   => true,
556
-            ],
557
-            'queue_for_resending'              => [
558
-                'func'       => '_queue_for_resending',
559
-                'capability' => 'ee_send_message',
560
-                'noheader'   => true,
561
-            ],
562
-            'send_now'                         => [
563
-                'func'       => '_send_now',
564
-                'capability' => 'ee_send_message',
565
-                'noheader'   => true,
566
-            ],
567
-            'delete_ee_message'                => [
568
-                'func'       => '_delete_ee_messages',
569
-                'capability' => 'ee_delete_messages',
570
-                'noheader'   => true,
571
-            ],
572
-            'delete_ee_messages'               => [
573
-                'func'       => '_delete_ee_messages',
574
-                'capability' => 'ee_delete_messages',
575
-                'noheader'   => true,
576
-                'obj_id'     => $MSG_ID,
577
-            ],
578
-        ];
579
-    }
580
-
581
-
582
-    protected function _set_page_config()
583
-    {
584
-        $this->_page_config = [
585
-            'default'                  => [
586
-                'nav'           => [
587
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
588
-                    'icon' => 'dashicons-email',
589
-                    'order' => 10,
590
-                ],
591
-                'list_table'    => 'EE_Message_List_Table',
592
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
593
-                'require_nonce' => false,
594
-            ],
595
-            'global_mtps'              => [
596
-                'nav'           => [
597
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
598
-                    'icon' => 'dashicons-layout',
599
-                    'order' => 20,
600
-                ],
601
-                'list_table'    => 'Messages_Template_List_Table',
602
-                'help_tabs'     => [
603
-                    'messages_overview_help_tab'                                => [
604
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
605
-                        'filename' => 'messages_overview',
606
-                    ],
607
-                    'messages_overview_messages_table_column_headings_help_tab' => [
608
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
609
-                        'filename' => 'messages_overview_table_column_headings',
610
-                    ],
611
-                    'messages_overview_messages_filters_help_tab'               => [
612
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
613
-                        'filename' => 'messages_overview_filters',
614
-                    ],
615
-                    'messages_overview_messages_views_help_tab'                 => [
616
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
617
-                        'filename' => 'messages_overview_views',
618
-                    ],
619
-                    'message_overview_message_types_help_tab'                   => [
620
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
621
-                        'filename' => 'messages_overview_types',
622
-                    ],
623
-                    'messages_overview_messengers_help_tab'                     => [
624
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
625
-                        'filename' => 'messages_overview_messengers',
626
-                    ],
627
-                ],
628
-                'require_nonce' => false,
629
-            ],
630
-            'custom_mtps'              => [
631
-                'nav'           => [
632
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
633
-                    'icon' => 'dashicons-admin-customizer',
634
-                    'order' => 30,
635
-                ],
636
-                'help_tabs'     => [],
637
-                'require_nonce' => false,
638
-            ],
639
-            'add_new_message_template' => [
640
-                'nav'           => [
641
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
642
-                    'icon' => 'dashicons-plus-alt',
643
-                    'order'      => 5,
644
-                    'persistent' => false,
645
-                ],
646
-                'require_nonce' => false,
647
-            ],
648
-            'edit_message_template'    => [
649
-                'labels'        => [
650
-                    'buttons'    => [
651
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
652
-                    ],
653
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
654
-                ],
655
-                'nav'           => [
656
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
657
-                    'icon' => 'dashicons-edit-large',
658
-                    'order'      => 5,
659
-                    'persistent' => false,
660
-                    'url'        => '',
661
-                ],
662
-                'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
663
-                'has_metaboxes' => true,
664
-                'help_tabs'     => [
665
-                    'edit_message_template'            => [
666
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
667
-                        'callback' => 'edit_message_template_help_tab',
668
-                    ],
669
-                    'message_templates_help_tab'       => [
670
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
671
-                        'filename' => 'messages_templates',
672
-                    ],
673
-                    'message_template_shortcodes'      => [
674
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
675
-                        'callback' => 'message_template_shortcodes_help_tab',
676
-                    ],
677
-                    'message_preview_help_tab'         => [
678
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
679
-                        'filename' => 'messages_preview',
680
-                    ],
681
-                    'messages_overview_other_help_tab' => [
682
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
683
-                        'filename' => 'messages_overview_other',
684
-                    ],
685
-                ],
686
-                'require_nonce' => false,
687
-            ],
688
-            'display_preview_message'  => [
689
-                'nav'           => [
690
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
691
-                    'icon' => 'dashicons-visibility-bar',
692
-                    'order'      => 5,
693
-                    'url'        => '',
694
-                    'persistent' => false,
695
-                ],
696
-                'help_tabs'     => [
697
-                    'preview_message' => [
698
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
699
-                        'callback' => 'preview_message_help_tab',
700
-                    ],
701
-                ],
702
-                'require_nonce' => false,
703
-            ],
704
-            'settings'                 => [
705
-                'nav'           => [
706
-                    'label' => esc_html__('Settings', 'event_espresso'),
707
-                    'icon' => 'dashicons-admin-generic',
708
-                    'order' => 40,
709
-                ],
710
-                'metaboxes'     => ['_messages_settings_metaboxes'],
711
-                'help_tabs'     => [
712
-                    'messages_settings_help_tab'               => [
713
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
714
-                        'filename' => 'messages_settings',
715
-                    ],
716
-                    'messages_settings_message_types_help_tab' => [
717
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
718
-                        'filename' => 'messages_settings_message_types',
719
-                    ],
720
-                    'messages_settings_messengers_help_tab'    => [
721
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
722
-                        'filename' => 'messages_settings_messengers',
723
-                    ],
724
-                ],
725
-                'require_nonce' => false,
726
-            ],
727
-        ];
728
-    }
729
-
730
-
731
-    protected function _add_screen_options()
732
-    {
733
-        // todo
734
-    }
735
-
736
-
737
-    protected function _add_screen_options_global_mtps()
738
-    {
739
-        /**
740
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
741
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
742
-         */
743
-        $page_title              = $this->_admin_page_title;
744
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
745
-        $this->_per_page_screen_option();
746
-        $this->_admin_page_title = $page_title;
747
-    }
748
-
749
-
750
-    protected function _add_screen_options_default()
751
-    {
752
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
753
-        $this->_per_page_screen_option();
754
-    }
755
-
756
-
757
-    // none of the below group are currently used for Messages
758
-    protected function _add_feature_pointers()
759
-    {
760
-    }
761
-
762
-
763
-    public function admin_init()
764
-    {
765
-    }
766
-
767
-
768
-    public function admin_notices()
769
-    {
770
-    }
771
-
772
-
773
-    public function admin_footer_scripts()
774
-    {
775
-    }
776
-
777
-
778
-    public function messages_help_tab()
779
-    {
780
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
781
-    }
782
-
783
-
784
-    public function messengers_help_tab()
785
-    {
786
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
787
-    }
788
-
789
-
790
-    public function message_types_help_tab()
791
-    {
792
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
793
-    }
794
-
795
-
796
-    public function messages_overview_help_tab()
797
-    {
798
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
799
-    }
800
-
801
-
802
-    public function message_templates_help_tab()
803
-    {
804
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
805
-    }
806
-
807
-
808
-    public function edit_message_template_help_tab()
809
-    {
810
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
811
-                        . esc_attr__('Editor Title', 'event_espresso')
812
-                        . '" />';
813
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
814
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
815
-                        . '" />';
816
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
817
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
818
-                        . '" />';
819
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
820
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
821
-                        . '" />';
822
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
823
-                        . esc_attr__('Publish Metabox', 'event_espresso')
824
-                        . '" />';
825
-        EEH_Template::display_template(
826
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
827
-            $args
828
-        );
829
-    }
830
-
831
-
832
-    /**
833
-     * @throws ReflectionException
834
-     * @throws EE_Error
835
-     */
836
-    public function message_template_shortcodes_help_tab()
837
-    {
838
-        $this->_set_shortcodes();
839
-        $args['shortcodes'] = $this->_shortcodes;
840
-        EEH_Template::display_template(
841
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
842
-            $args
843
-        );
844
-    }
845
-
846
-
847
-    public function preview_message_help_tab()
848
-    {
849
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
850
-    }
851
-
852
-
853
-    public function settings_help_tab()
854
-    {
855
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
856
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
857
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
858
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
859
-        $args['img3'] = '<div class="ee-switch">'
860
-                        . '<input class="ee-switch__input" id="ee-on-off-toggle-on" type="checkbox" checked>'
861
-                        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-on"></label>'
862
-                        . '</div>';
863
-        $args['img4'] = '<div class="switch">'
864
-                        . '<input class="ee-switch__input" id="ee-on-off-toggle-off" type="checkbox">'
865
-                        . '<label class="ee-switch__toggle" for="ee-on-off-toggle-off"></label>'
866
-                        . '</div>';
867
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
868
-    }
869
-
870
-
871
-    public function load_scripts_styles()
872
-    {
873
-        wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
874
-        wp_enqueue_style('espresso_ee_msg');
875
-
876
-        wp_register_script(
877
-            'ee-messages-settings',
878
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
879
-            ['jquery-ui-droppable', 'ee-serialize-full-array'],
880
-            EVENT_ESPRESSO_VERSION,
881
-            true
882
-        );
883
-        wp_register_script(
884
-            'ee-msg-list-table-js',
885
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
886
-            ['ee-dialog'],
887
-            EVENT_ESPRESSO_VERSION
888
-        );
889
-    }
890
-
891
-
892
-    public function load_scripts_styles_default()
893
-    {
894
-        wp_enqueue_script('ee-msg-list-table-js');
895
-    }
896
-
897
-
898
-    public function wp_editor_css($mce_css)
899
-    {
900
-        // if we're on the edit_message_template route
901
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
902
-            $message_type_name = $this->_active_message_type_name;
903
-
904
-            // we're going to REPLACE the existing mce css
905
-            // we need to get the css file location from the active messenger
906
-            $mce_css = $this->_active_messenger->get_variation(
907
-                $this->_template_pack,
908
-                $message_type_name,
909
-                true,
910
-                'wpeditor',
911
-                $this->_variation
912
-            );
913
-        }
914
-
915
-        return $mce_css;
916
-    }
917
-
918
-
919
-    /**
920
-     * @throws EE_Error
921
-     * @throws ReflectionException
922
-     */
923
-    public function load_scripts_styles_edit_message_template()
924
-    {
925
-
926
-        $this->_set_shortcodes();
927
-
928
-        EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
929
-            esc_html__(
930
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
931
-                'event_espresso'
932
-            ),
933
-            $this->_message_template_group->messenger_obj()->label['singular'],
934
-            $this->_message_template_group->message_type_obj()->label['singular']
935
-        );
936
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
937
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
938
-            'event_espresso'
939
-        );
940
-        EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
941
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
942
-            'event_espresso'
943
-        );
944
-
945
-        wp_register_script(
946
-            'ee_msgs_edit_js',
947
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
948
-            ['jquery'],
949
-            EVENT_ESPRESSO_VERSION
950
-        );
951
-
952
-        wp_enqueue_script('ee_admin_js');
953
-        wp_enqueue_script('ee_msgs_edit_js');
954
-
955
-        // add in special css for tiny_mce
956
-        add_filter('mce_css', [$this, 'wp_editor_css']);
957
-    }
958
-
959
-
960
-    /**
961
-     * @throws EE_Error
962
-     * @throws ReflectionException
963
-     */
964
-    public function load_scripts_styles_display_preview_message()
965
-    {
966
-        $this->_set_message_template_group();
967
-        if ($this->_active_messenger_name) {
968
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
969
-                $this->_active_messenger_name
970
-            );
971
-        }
972
-
973
-        wp_enqueue_style(
974
-            'espresso_preview_css',
975
-            $this->_active_messenger->get_variation(
976
-                $this->_template_pack,
977
-                $this->_active_message_type_name,
978
-                true,
979
-                'preview',
980
-                $this->_variation
981
-            )
982
-        );
983
-    }
984
-
985
-
986
-    public function load_scripts_styles_settings()
987
-    {
988
-        wp_register_style(
989
-            'ee-message-settings',
990
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
991
-            [],
992
-            EVENT_ESPRESSO_VERSION
993
-        );
994
-        wp_enqueue_style('ee-text-links');
995
-        wp_enqueue_style('ee-message-settings');
996
-        wp_enqueue_script('ee-messages-settings');
997
-    }
998
-
999
-
1000
-    /**
1001
-     * set views array for List Table
1002
-     */
1003
-    public function _set_list_table_views_global_mtps()
1004
-    {
1005
-        $this->_views = [
1006
-            'in_use' => [
1007
-                'slug'  => 'in_use',
1008
-                'label' => esc_html__('In Use', 'event_espresso'),
1009
-                'count' => 0,
1010
-            ],
1011
-        ];
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     * Set views array for the Custom Template List Table
1017
-     */
1018
-    public function _set_list_table_views_custom_mtps()
1019
-    {
1020
-        $this->_set_list_table_views_global_mtps();
1021
-        $this->_views['in_use']['bulk_action'] = [
1022
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
1023
-        ];
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * set views array for message queue list table
1029
-     *
1030
-     * @throws InvalidDataTypeException
1031
-     * @throws InvalidInterfaceException
1032
-     * @throws InvalidArgumentException
1033
-     * @throws EE_Error
1034
-     * @throws ReflectionException
1035
-     */
1036
-    public function _set_list_table_views_default()
1037
-    {
1038
-        EE_Registry::instance()->load_helper('Template');
1039
-
1040
-        $common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
1041
-            'ee_send_message',
1042
-            'message_list_table_bulk_actions'
1043
-        )
1044
-            ? [
1045
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
1046
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
1047
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
1048
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
1049
-            ]
1050
-            : [];
1051
-
1052
-        $delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
1053
-            'ee_delete_messages',
1054
-            'message_list_table_bulk_actions'
1055
-        )
1056
-            ? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
1057
-            : [];
1058
-
1059
-
1060
-        $this->_views = [
1061
-            'all' => [
1062
-                'slug'        => 'all',
1063
-                'label'       => esc_html__('All', 'event_espresso'),
1064
-                'count'       => 0,
1065
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1066
-            ],
1067
-        ];
1068
-
1069
-
1070
-        foreach ($this->getMsgModel()->all_statuses() as $status) {
1071
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1072
-                continue;
1073
-            }
1074
-            $status_bulk_actions = $common_bulk_actions;
1075
-            // unset bulk actions not applying to status
1076
-            if (! empty($status_bulk_actions)) {
1077
-                switch ($status) {
1078
-                    case EEM_Message::status_idle:
1079
-                    case EEM_Message::status_resend:
1080
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1081
-                        break;
1082
-
1083
-                    case EEM_Message::status_failed:
1084
-                    case EEM_Message::status_debug_only:
1085
-                    case EEM_Message::status_messenger_executing:
1086
-                        $status_bulk_actions = [];
1087
-                        break;
1088
-
1089
-                    case EEM_Message::status_incomplete:
1090
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1091
-                        break;
1092
-
1093
-                    case EEM_Message::status_retry:
1094
-                    case EEM_Message::status_sent:
1095
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1096
-                        break;
1097
-                }
1098
-            }
1099
-
1100
-            // skip adding messenger executing status to views because it will be included with the Failed view.
1101
-            if ($status === EEM_Message::status_messenger_executing) {
1102
-                continue;
1103
-            }
1104
-
1105
-            $this->_views[ strtolower($status) ] = [
1106
-                'slug'        => strtolower($status),
1107
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1108
-                'count'       => 0,
1109
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1110
-            ];
1111
-        }
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * @throws EE_Error
1117
-     */
1118
-    protected function _ee_default_messages_overview_list_table()
1119
-    {
1120
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1121
-        $this->display_admin_list_table_page_with_no_sidebar();
1122
-    }
1123
-
1124
-
1125
-    /**
1126
-     * @throws EE_Error
1127
-     * @throws ReflectionException
1128
-     */
1129
-    protected function _message_queue_list_table()
1130
-    {
1131
-        $this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1132
-        $this->_template_args['per_column']        = 6;
1133
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1134
-        $message_results = trim(EEM_Message::instance()->get_pretty_label_for_results());
1135
-        $this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1136
-        $this->display_admin_list_table_page_with_no_sidebar();
1137
-    }
1138
-
1139
-
1140
-    /**
1141
-     * @throws EE_Error
1142
-     */
1143
-    protected function _message_legend_items()
1144
-    {
1145
-
1146
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1147
-        $action_items       = [];
1148
-
1149
-        foreach ($action_css_classes as $action_item => $action_details) {
1150
-            if ($action_item === 'see_notifications_for') {
1151
-                continue;
1152
-            }
1153
-            $action_items[ $action_item ] = [
1154
-                'class' => $action_details['css_class'],
1155
-                'desc'  => $action_details['label'],
1156
-            ];
1157
-        }
1158
-
1159
-        /** @var array $status_items status legend setup */
1160
-        $status_items = [
1161
-            'sent_status'                => [
1162
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1163
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1164
-            ],
1165
-            'idle_status'                => [
1166
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1167
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1168
-            ],
1169
-            'failed_status'              => [
1170
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1171
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1172
-            ],
1173
-            'messenger_executing_status' => [
1174
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1175
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1176
-            ],
1177
-            'resend_status'              => [
1178
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1179
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1180
-            ],
1181
-            'incomplete_status'          => [
1182
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1183
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1184
-            ],
1185
-            'retry_status'               => [
1186
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1187
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1188
-            ],
1189
-        ];
1190
-        if (EEM_Message::debug()) {
1191
-            $status_items['debug_only_status'] = [
1192
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1193
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1194
-            ];
1195
-        }
1196
-
1197
-        return array_merge($action_items, $status_items);
1198
-    }
1199
-
1200
-
1201
-    /**
1202
-     * @throws EE_Error
1203
-     */
1204
-    protected function _custom_mtps_preview()
1205
-    {
1206
-        $this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1207
-        $this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1208
-                                                . ' alt="' . esc_attr__(
1209
-                                                    'Preview Custom Message Templates screenshot',
1210
-                                                    'event_espresso'
1211
-                                                ) . '" />';
1212
-        $this->_template_args['preview_text'] = '<strong>'
1213
-                                                . esc_html__(
1214
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1215
-                                                    'event_espresso'
1216
-                                                )
1217
-                                                . '</strong>';
1218
-
1219
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * get_message_templates
1225
-     * This gets all the message templates for listing on the overview list.
1226
-     *
1227
-     * @access public
1228
-     * @param int    $per_page the amount of templates groups to show per page
1229
-     * @param string $type     the current _view we're getting templates for
1230
-     * @param bool   $count    return count?
1231
-     * @param bool   $all      disregard any paging info (get all data);
1232
-     * @param bool   $global   whether to return just global (true) or custom templates (false)
1233
-     * @return array
1234
-     * @throws EE_Error
1235
-     * @throws InvalidArgumentException
1236
-     * @throws InvalidDataTypeException
1237
-     * @throws InvalidInterfaceException
1238
-     */
1239
-    public function get_message_templates(
1240
-        $per_page = 10,
1241
-        $type = 'in_use',
1242
-        $count = false,
1243
-        $all = false,
1244
-        $global = true
1245
-    ) {
1246
-        $orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1247
-        $this->request->setRequestParam('orderby', $orderby);
1248
-
1249
-        $order        = $this->request->getRequestParam('order', 'ASC');
1250
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1251
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1252
-
1253
-        $offset = ($current_page - 1) * $per_page;
1254
-        $limit  = $all ? null : [$offset, $per_page];
1255
-
1256
-        // options will match what is in the _views array property
1257
-        return $type === 'in_use'
1258
-            ? $this->getMtgModel()->get_all_active_message_templates(
1259
-                $orderby,
1260
-                $order,
1261
-                $limit,
1262
-                $count,
1263
-                $global,
1264
-                true
1265
-            )
1266
-            : $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1267
-                $orderby,
1268
-                $order,
1269
-                $limit,
1270
-                $count,
1271
-                $global
1272
-            );
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * filters etc might need a list of installed message_types
1278
-     *
1279
-     * @return array an array of message type objects
1280
-     */
1281
-    public function get_installed_message_types()
1282
-    {
1283
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1284
-        $installed               = [];
1285
-
1286
-        foreach ($installed_message_types as $message_type) {
1287
-            $installed[ $message_type->name ] = $message_type;
1288
-        }
1289
-
1290
-        return $installed;
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1296
-     *
1297
-     * @param string $message_type
1298
-     * @param string $messenger
1299
-     * @param string $GRP_ID
1300
-     *
1301
-     * @throws EE_error
1302
-     * @throws ReflectionException
1303
-     */
1304
-    public function add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1305
-    {
1306
-        // set values override any request data
1307
-        $message_type = ! empty($message_type) ? $message_type : $this->_active_message_type_name;
1308
-        $messenger    = ! empty($messenger) ? $messenger : $this->_active_messenger_name;
1309
-        $GRP_ID       = ! empty($GRP_ID) ? $GRP_ID : $this->request->getRequestParam('GRP_ID', 0, 'int');
1310
-
1311
-        // we need messenger and message type.  They should be coming from the event editor. If not here then return error
1312
-        if (empty($message_type) || empty($messenger)) {
1313
-            throw new EE_Error(
1314
-                esc_html__(
1315
-                    'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1316
-                    'event_espresso'
1317
-                )
1318
-            );
1319
-        }
1320
-
1321
-        // we need the GRP_ID for the template being used as the base for the new template
1322
-        if (empty($GRP_ID)) {
1323
-            throw new EE_Error(
1324
-                esc_html__(
1325
-                    'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1326
-                    'event_espresso'
1327
-                )
1328
-            );
1329
-        }
1330
-
1331
-        // let's just make sure the template gets generated!
1332
-
1333
-        // we need to reassign some variables for what the insert is expecting
1334
-        $this->request->setRequestParam('MTP_messenger', $messenger);
1335
-        $this->request->setRequestParam('MTP_message_type', $message_type);
1336
-        $this->request->setRequestParam('GRP_ID', $GRP_ID);
1337
-
1338
-        $this->_insert_or_update_message_template(true);
1339
-    }
1340
-
1341
-
1342
-    /**
1343
-     * @param string $message_type     message type slug
1344
-     * @param string $messenger        messenger slug
1345
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1346
-     *                                 off of.
1347
-     * @throws EE_error
1348
-     * @throws ReflectionException
1349
-     * @deprecated 4.10.29.p
1350
-     */
1351
-    protected function _add_message_template($message_type, $messenger, $GRP_ID)
1352
-    {
1353
-        $this->add_message_template($message_type, $messenger, $GRP_ID);
1354
-    }
1355
-
1356
-
1357
-    /**
1358
-     * _edit_message_template
1359
-     *
1360
-     * @access protected
1361
-     * @return void
1362
-     * @throws InvalidIdentifierException
1363
-     * @throws DomainException
1364
-     * @throws EE_Error
1365
-     * @throws InvalidArgumentException
1366
-     * @throws ReflectionException
1367
-     * @throws InvalidDataTypeException
1368
-     * @throws InvalidInterfaceException
1369
-     */
1370
-    protected function _edit_message_template()
1371
-    {
1372
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1373
-        $template_fields = '';
1374
-        $sidebar_fields  = '';
1375
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1376
-        // valid html in the templates.
1377
-        add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1378
-
1379
-        $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
1380
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
1381
-
1382
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1383
-        $message_template_group = $this->_message_template_group;
1384
-        $c_label                = $message_template_group->context_label();
1385
-        $c_config               = $message_template_group->contexts_config();
1386
-
1387
-        reset($c_config);
1388
-        $context = $this->request->getRequestParam('context', key($c_config));
1389
-        $context = strtolower($context);
1390
-
1391
-        $action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1392
-
1393
-        $edit_message_template_form_url = add_query_arg(
1394
-            ['action' => $action, 'noheader' => true],
1395
-            EE_MSG_ADMIN_URL
1396
-        );
1397
-
1398
-        // set active messenger for this view
1399
-        $this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1400
-            $message_template_group->messenger()
1401
-        );
1402
-        $this->_active_message_type_name = $message_template_group->message_type();
1403
-
1404
-
1405
-        // Do we have any validation errors?
1406
-        $validators = $this->_get_transient();
1407
-        $v_fields   = ! empty($validators) ? array_keys($validators) : [];
1408
-
1409
-
1410
-        // we need to assemble the title from Various details
1411
-        $context_label = sprintf(
1412
-            esc_html__('(%s %s)', 'event_espresso'),
1413
-            $c_config[ $context ]['label'],
1414
-            ucwords($c_label['label'])
1415
-        );
1416
-
1417
-        $title = sprintf(
1418
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1419
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1420
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1421
-            $context_label
1422
-        );
1423
-
1424
-        $this->_template_args['GRP_ID']           = $GRP_ID;
1425
-        $this->_template_args['message_template'] = $message_template_group;
1426
-        $this->_template_args['is_extra_fields']  = false;
1427
-
1428
-
1429
-        // let's get EEH_MSG_Template so we can get template form fields
1430
-        $template_field_structure = EEH_MSG_Template::get_fields(
1431
-            $message_template_group->messenger(),
1432
-            $message_template_group->message_type()
1433
-        );
1434
-
1435
-        if (! $template_field_structure) {
1436
-            $template_field_structure = false;
1437
-            $template_fields          = esc_html__(
1438
-                'There was an error in assembling the fields for this display (you should see an error message)',
1439
-                'event_espresso'
1440
-            );
1441
-        }
1442
-
1443
-
1444
-        $message_templates = $message_template_group->context_templates();
1445
-
1446
-
1447
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1448
-        // will get handled in the "extra" array.
1449
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1450
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1451
-                unset($template_field_structure[ $context ][ $reference_field ]);
1452
-            }
1453
-        }
1454
-
1455
-        // let's loop through the template_field_structure and actually assemble the input fields!
1456
-        if (! empty($template_field_structure)) {
1457
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1458
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1459
-                // the extra array and reset them.
1460
-                if ($template_field === 'extra') {
1461
-                    $this->_template_args['is_extra_fields'] = true;
1462
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1463
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1464
-                        $content          = $message_template instanceof EE_Message_Template
1465
-                            ? $message_template->get('MTP_content')
1466
-                            : '';
1467
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1468
-                            // let's verify if we need this extra field via the shortcodes parameter.
1469
-                            $continue = false;
1470
-                            if (isset($extra_array['shortcodes_required'])) {
1471
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1472
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1473
-                                        $continue = true;
1474
-                                    }
1475
-                                }
1476
-                                if ($continue) {
1477
-                                    continue;
1478
-                                }
1479
-                            }
1480
-
1481
-                            $field_id = $reference_field . '-' . $extra_field . '-content';
1482
-
1483
-                            $template_form_fields[ $field_id ]         = $extra_array;
1484
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1485
-                                                                         . $reference_field
1486
-                                                                         . '][content]['
1487
-                                                                         . $extra_field . ']';
1488
-                            $css_class                                 = isset($extra_array['css_class'])
1489
-                                ? $extra_array['css_class']
1490
-                                : '';
1491
-
1492
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1493
-                                                                              && in_array($extra_field, $v_fields, true)
1494
-                                                                              && (
1495
-                                                                                  is_array($validators[ $extra_field ])
1496
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1497
-                                                                              )
1498
-                                ? 'validate-error ' . $css_class
1499
-                                : $css_class;
1500
-
1501
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1502
-                                                                          && isset($content[ $extra_field ])
1503
-                                ? $content[ $extra_field ]
1504
-                                : '';
1505
-
1506
-                            // do we have a validation error?  if we do then let's use that value instead
1507
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1508
-                                ? $validators[ $extra_field ]['value']
1509
-                                : $template_form_fields[ $field_id ]['value'];
1510
-
1511
-
1512
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1513
-
1514
-                            // shortcode selector
1515
-                            $field_name_to_use                                   = $extra_field === 'main'
1516
-                                ? 'content'
1517
-                                : $extra_field;
1518
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1519
-                                $field_name_to_use,
1520
-                                $field_id
1521
-                            );
1522
-                        }
1523
-                        $template_field_MTP_id           = $reference_field . '-MTP_ID';
1524
-                        $template_field_template_name_id = $reference_field . '-name';
1525
-
1526
-                        $template_form_fields[ $template_field_MTP_id ] = [
1527
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1528
-                            'label'      => null,
1529
-                            'input'      => 'hidden',
1530
-                            'type'       => 'int',
1531
-                            'required'   => false,
1532
-                            'validation' => false,
1533
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1534
-                            'css_class'  => '',
1535
-                            'format'     => '%d',
1536
-                            'db-col'     => 'MTP_ID',
1537
-                        ];
1538
-
1539
-                        $template_form_fields[ $template_field_template_name_id ] = [
1540
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1541
-                            'label'      => null,
1542
-                            'input'      => 'hidden',
1543
-                            'type'       => 'string',
1544
-                            'required'   => false,
1545
-                            'validation' => true,
1546
-                            'value'      => $reference_field,
1547
-                            'css_class'  => '',
1548
-                            'format'     => '%s',
1549
-                            'db-col'     => 'MTP_template_field',
1550
-                        ];
1551
-                    }
1552
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1553
-                } else {
1554
-                    $field_id                                   = $template_field . '-content';
1555
-                    $template_form_fields[ $field_id ]          = $field_setup_array;
1556
-                    $template_form_fields[ $field_id ]['name']  =
1557
-                        'MTP_template_fields[' . $template_field . '][content]';
1558
-                    $message_template                           =
1559
-                        isset($message_templates[ $context ][ $template_field ])
1560
-                            ? $message_templates[ $context ][ $template_field ]
1561
-                            : null;
1562
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1563
-                                                                  && is_array($message_templates[ $context ])
1564
-                                                                  && $message_template instanceof EE_Message_Template
1565
-                        ? $message_template->get('MTP_content')
1566
-                        : '';
1567
-
1568
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1569
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1570
-                        ? $validators[ $template_field ]['value']
1571
-                        : $template_form_fields[ $field_id ]['value'];
1572
-
1573
-
1574
-                    $template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1575
-                    $css_class                                      = isset($field_setup_array['css_class'])
1576
-                        ? $field_setup_array['css_class']
1577
-                        : '';
1578
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1579
-                                                                      && in_array($template_field, $v_fields, true)
1580
-                                                                      && isset($validators[ $template_field ]['msg'])
1581
-                        ? 'validate-error ' . $css_class
1582
-                        : $css_class;
1583
-
1584
-                    // shortcode selector
1585
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1586
-                        $template_field,
1587
-                        $field_id
1588
-                    );
1589
-                }
1590
-
1591
-                // k took care of content field(s) now let's take care of others.
1592
-
1593
-                $template_field_MTP_id                 = $template_field . '-MTP_ID';
1594
-                $template_field_field_template_name_id = $template_field . '-name';
1595
-
1596
-                // foreach template field there are actually two form fields created
1597
-                $template_form_fields[ $template_field_MTP_id ] = [
1598
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1599
-                    'label'      => null,
1600
-                    'input'      => 'hidden',
1601
-                    'type'       => 'int',
1602
-                    'required'   => false,
1603
-                    'validation' => true,
1604
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1605
-                    'css_class'  => '',
1606
-                    'format'     => '%d',
1607
-                    'db-col'     => 'MTP_ID',
1608
-                ];
1609
-
1610
-                $template_form_fields[ $template_field_field_template_name_id ] = [
1611
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1612
-                    'label'      => null,
1613
-                    'input'      => 'hidden',
1614
-                    'type'       => 'string',
1615
-                    'required'   => false,
1616
-                    'validation' => true,
1617
-                    'value'      => $template_field,
1618
-                    'css_class'  => '',
1619
-                    'format'     => '%s',
1620
-                    'db-col'     => 'MTP_template_field',
1621
-                ];
1622
-            }
1623
-
1624
-            // add other fields
1625
-            $template_form_fields['ee-msg-current-context'] = [
1626
-                'name'       => 'MTP_context',
1627
-                'label'      => null,
1628
-                'input'      => 'hidden',
1629
-                'type'       => 'string',
1630
-                'required'   => false,
1631
-                'validation' => true,
1632
-                'value'      => $context,
1633
-                'css_class'  => '',
1634
-                'format'     => '%s',
1635
-                'db-col'     => 'MTP_context',
1636
-            ];
1637
-
1638
-            $template_form_fields['ee-msg-grp-id'] = [
1639
-                'name'       => 'GRP_ID',
1640
-                'label'      => null,
1641
-                'input'      => 'hidden',
1642
-                'type'       => 'int',
1643
-                'required'   => false,
1644
-                'validation' => true,
1645
-                'value'      => $GRP_ID,
1646
-                'css_class'  => '',
1647
-                'format'     => '%d',
1648
-                'db-col'     => 'GRP_ID',
1649
-            ];
1650
-
1651
-            $template_form_fields['ee-msg-messenger'] = [
1652
-                'name'       => 'MTP_messenger',
1653
-                'label'      => null,
1654
-                'input'      => 'hidden',
1655
-                'type'       => 'string',
1656
-                'required'   => false,
1657
-                'validation' => true,
1658
-                'value'      => $message_template_group->messenger(),
1659
-                'css_class'  => '',
1660
-                'format'     => '%s',
1661
-                'db-col'     => 'MTP_messenger',
1662
-            ];
1663
-
1664
-            $template_form_fields['ee-msg-message-type'] = [
1665
-                'name'       => 'MTP_message_type',
1666
-                'label'      => null,
1667
-                'input'      => 'hidden',
1668
-                'type'       => 'string',
1669
-                'required'   => false,
1670
-                'validation' => true,
1671
-                'value'      => $message_template_group->message_type(),
1672
-                'css_class'  => '',
1673
-                'format'     => '%s',
1674
-                'db-col'     => 'MTP_message_type',
1675
-            ];
1676
-
1677
-            $sidebar_form_fields['ee-msg-is-global'] = [
1678
-                'name'       => 'MTP_is_global',
1679
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1680
-                'input'      => 'hidden',
1681
-                'type'       => 'int',
1682
-                'required'   => false,
1683
-                'validation' => true,
1684
-                'value'      => $message_template_group->get('MTP_is_global'),
1685
-                'css_class'  => '',
1686
-                'format'     => '%d',
1687
-                'db-col'     => 'MTP_is_global',
1688
-            ];
1689
-
1690
-            $sidebar_form_fields['ee-msg-is-override'] = [
1691
-                'name'       => 'MTP_is_override',
1692
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1693
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1694
-                'type'       => 'int',
1695
-                'required'   => false,
1696
-                'validation' => true,
1697
-                'value'      => $message_template_group->get('MTP_is_override'),
1698
-                'css_class'  => '',
1699
-                'format'     => '%d',
1700
-                'db-col'     => 'MTP_is_override',
1701
-            ];
1702
-
1703
-            $sidebar_form_fields['ee-msg-is-active'] = [
1704
-                'name'       => 'MTP_is_active',
1705
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1706
-                'input'      => 'hidden',
1707
-                'type'       => 'int',
1708
-                'required'   => false,
1709
-                'validation' => true,
1710
-                'value'      => $message_template_group->is_active(),
1711
-                'css_class'  => '',
1712
-                'format'     => '%d',
1713
-                'db-col'     => 'MTP_is_active',
1714
-            ];
1715
-
1716
-            $sidebar_form_fields['ee-msg-deleted'] = [
1717
-                'name'       => 'MTP_deleted',
1718
-                'label'      => null,
1719
-                'input'      => 'hidden',
1720
-                'type'       => 'int',
1721
-                'required'   => false,
1722
-                'validation' => true,
1723
-                'value'      => $message_template_group->get('MTP_deleted'),
1724
-                'css_class'  => '',
1725
-                'format'     => '%d',
1726
-                'db-col'     => 'MTP_deleted',
1727
-            ];
1728
-            $sidebar_form_fields['ee-msg-author']  = [
1729
-                'name'       => 'MTP_user_id',
1730
-                'label'      => esc_html__('Author', 'event_espresso'),
1731
-                'input'      => 'hidden',
1732
-                'type'       => 'int',
1733
-                'required'   => false,
1734
-                'validation' => false,
1735
-                'value'      => $message_template_group->user(),
1736
-                'format'     => '%d',
1737
-                'db-col'     => 'MTP_user_id',
1738
-            ];
1739
-
1740
-            $sidebar_form_fields['ee-msg-route'] = [
1741
-                'name'  => 'action',
1742
-                'input' => 'hidden',
1743
-                'type'  => 'string',
1744
-                'value' => $action,
1745
-            ];
1746
-
1747
-            $sidebar_form_fields['ee-msg-id']        = [
1748
-                'name'  => 'id',
1749
-                'input' => 'hidden',
1750
-                'type'  => 'int',
1751
-                'value' => $GRP_ID,
1752
-            ];
1753
-            $sidebar_form_fields['ee-msg-evt-nonce'] = [
1754
-                'name'  => $action . '_nonce',
1755
-                'input' => 'hidden',
1756
-                'type'  => 'string',
1757
-                'value' => wp_create_nonce($action . '_nonce'),
1758
-            ];
1759
-
1760
-            $template_switch = $this->request->getRequestParam('template_switch');
1761
-            if ($template_switch) {
1762
-                $sidebar_form_fields['ee-msg-template-switch'] = [
1763
-                    'name'  => 'template_switch',
1764
-                    'input' => 'hidden',
1765
-                    'type'  => 'int',
1766
-                    'value' => 1,
1767
-                ];
1768
-            }
1769
-
1770
-
1771
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1772
-            $sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1773
-        } //end if ( !empty($template_field_structure) )
1774
-
1775
-        // set extra content for publish box
1776
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1777
-        $this->_set_publish_post_box_vars(
1778
-            'id',
1779
-            $GRP_ID,
1780
-            '',
1781
-            add_query_arg(
1782
-                ['action' => $message_template_group->is_global() ? 'global_mtps' : 'custom_mtps'],
1783
-                $this->_admin_base_url
1784
-            ),
1785
-            true
1786
-        );
1787
-
1788
-        // add preview button
1789
-        $preview_url    = parent::add_query_args_and_nonce(
1790
-            [
1791
-                'message_type' => $message_template_group->message_type(),
1792
-                'messenger'    => $message_template_group->messenger(),
1793
-                'context'      => $context,
1794
-                'GRP_ID'       => $GRP_ID,
1795
-                'evt_id'       => $EVT_ID ?: false,
1796
-                'action'       => 'preview_message',
1797
-            ],
1798
-            $this->_admin_base_url
1799
-        );
1800
-        $preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1801
-                          . esc_html__('Preview', 'event_espresso')
1802
-                          . '</a>';
1803
-
1804
-
1805
-        // setup context switcher
1806
-        $this->_set_context_switcher(
1807
-            $message_template_group,
1808
-            [
1809
-                'page'    => 'espresso_messages',
1810
-                'action'  => 'edit_message_template',
1811
-                'id'      => $GRP_ID,
1812
-                'evt_id'  => $EVT_ID,
1813
-                'context' => $context,
1814
-                'extra'   => $preview_button,
1815
-            ]
1816
-        );
1817
-
1818
-
1819
-        // main box
1820
-        $this->_template_args['template_fields']                         = $template_fields;
1821
-        $this->_template_args['sidebar_box_id']                          = 'details';
1822
-        $this->_template_args['action']                                  = $action;
1823
-        $this->_template_args['context']                                 = $context;
1824
-        $this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1825
-        $this->_template_args['learn_more_about_message_templates_link'] =
1826
-            $this->_learn_more_about_message_templates_link();
1827
-
1828
-
1829
-        $this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1830
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1831
-            $message_template_group,
1832
-            $context,
1833
-            $context_label
1834
-        );
1835
-        $this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1836
-        $this->_template_args['before_admin_page_content'] .= '</div>';
1837
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1838
-        $this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1839
-
1840
-        $this->_template_path = $this->_template_args['GRP_ID']
1841
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1842
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1843
-
1844
-        // send along EE_Message_Template_Group object for further template use.
1845
-        $this->_template_args['MTP'] = $message_template_group;
1846
-
1847
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1848
-            $this->_template_path,
1849
-            $this->_template_args,
1850
-            true
1851
-        );
1852
-
1853
-
1854
-        // finally, let's set the admin_page title
1855
-        $this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1856
-
1857
-
1858
-        // we need to take care of setting the shortcodes property for use elsewhere.
1859
-        $this->_set_shortcodes();
1860
-
1861
-
1862
-        // final template wrapper
1863
-        $this->display_admin_page_with_sidebar();
1864
-    }
1865
-
1866
-
1867
-    public function filter_tinymce_init($mceInit, $editor_id)
1868
-    {
1869
-        return $mceInit;
1870
-    }
1871
-
1872
-
1873
-    public function add_context_switcher()
1874
-    {
1875
-        return $this->_context_switcher;
1876
-    }
1877
-
1878
-
1879
-    /**
1880
-     * Adds the activation/deactivation toggle for the message template context.
1881
-     *
1882
-     * @param EE_Message_Template_Group $message_template_group
1883
-     * @param string                    $context
1884
-     * @param string                    $context_label
1885
-     * @return string
1886
-     * @throws DomainException
1887
-     * @throws EE_Error
1888
-     * @throws InvalidIdentifierException
1889
-     * @throws ReflectionException
1890
-     */
1891
-    protected function add_active_context_element(
1892
-        EE_Message_Template_Group $message_template_group,
1893
-        $context,
1894
-        $context_label
1895
-    ) {
1896
-        $template_args = [
1897
-            'context'                   => $context,
1898
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1899
-            'is_active'                 => $message_template_group->is_context_active($context),
1900
-            'on_off_action'             => $message_template_group->is_context_active($context)
1901
-                ? 'context-off'
1902
-                : 'context-on',
1903
-            'context_label'             => str_replace(['(', ')'], '', $context_label),
1904
-            'message_template_group_id' => $message_template_group->ID(),
1905
-        ];
1906
-        return EEH_Template::display_template(
1907
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1908
-            $template_args,
1909
-            true
1910
-        );
1911
-    }
1912
-
1913
-
1914
-    /**
1915
-     * Ajax callback for `toggle_context_template` ajax action.
1916
-     * Handles toggling the message context on or off.
1917
-     *
1918
-     * @throws EE_Error
1919
-     * @throws InvalidArgumentException
1920
-     * @throws InvalidDataTypeException
1921
-     * @throws InvalidIdentifierException
1922
-     * @throws InvalidInterfaceException
1923
-     */
1924
-    public function toggle_context_template()
1925
-    {
1926
-        $success = true;
1927
-        // check for required data
1928
-        if (
1929
-            ! (
1930
-                $this->request->requestParamIsSet('message_template_group_id')
1931
-                && $this->request->requestParamIsSet('context')
1932
-                && $this->request->requestParamIsSet('status')
1933
-            )
1934
-        ) {
1935
-            EE_Error::add_error(
1936
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1937
-                __FILE__,
1938
-                __FUNCTION__,
1939
-                __LINE__
1940
-            );
1941
-            $success = false;
1942
-        }
1943
-
1944
-        $nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1945
-        $context = $this->request->getRequestParam('context', '');
1946
-        $status  = $this->request->getRequestParam('status', '');
1947
-
1948
-        $this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1949
-
1950
-        if ($status !== 'off' && $status !== 'on') {
1951
-            EE_Error::add_error(
1952
-                sprintf(
1953
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1954
-                    $status
1955
-                ),
1956
-                __FILE__,
1957
-                __FUNCTION__,
1958
-                __LINE__
1959
-            );
1960
-            $success = false;
1961
-        }
1962
-        $message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, 'int');
1963
-        $message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1964
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1965
-            EE_Error::add_error(
1966
-                sprintf(
1967
-                    esc_html__(
1968
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1969
-                        'event_espresso'
1970
-                    ),
1971
-                    $message_template_group_id,
1972
-                    'EE_Message_Template_Group'
1973
-                ),
1974
-                __FILE__,
1975
-                __FUNCTION__,
1976
-                __LINE__
1977
-            );
1978
-            $success = false;
1979
-        }
1980
-        if ($success) {
1981
-            $success = $status === 'off'
1982
-                ? $message_template_group->deactivate_context($context)
1983
-                : $message_template_group->activate_context($context);
1984
-        }
1985
-        $this->_template_args['success'] = $success;
1986
-        $this->_return_json();
1987
-    }
1988
-
1989
-
1990
-    public function _add_form_element_before()
1991
-    {
1992
-        return '<form method="post" action="'
1993
-               . $this->_template_args['edit_message_template_form_url']
1994
-               . '" id="ee-msg-edit-frm">';
1995
-    }
1996
-
1997
-
1998
-    public function _add_form_element_after()
1999
-    {
2000
-        return '</form>';
2001
-    }
2002
-
2003
-
2004
-    /**
2005
-     * This executes switching the template pack for a message template.
2006
-     *
2007
-     * @throws EE_Error
2008
-     * @throws InvalidDataTypeException
2009
-     * @throws InvalidInterfaceException
2010
-     * @throws InvalidArgumentException
2011
-     * @throws ReflectionException
2012
-     * @since 4.5.0
2013
-     */
2014
-    public function switch_template_pack()
2015
-    {
2016
-
2017
-        $GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, 'int');
2018
-        $template_pack = $this->request->getRequestParam('template_pack', '');
2019
-
2020
-        // verify we have needed values.
2021
-        if (empty($GRP_ID) || empty($template_pack)) {
2022
-            $this->_template_args['error'] = true;
2023
-            EE_Error::add_error(
2024
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
2025
-                __FILE__,
2026
-                __FUNCTION__,
2027
-                __LINE__
2028
-            );
2029
-        } else {
2030
-            // get template, set the new template_pack and then reset to default
2031
-            /** @var EE_Message_Template_Group $message_template_group */
2032
-            $message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
2033
-
2034
-            $message_template_group->set_template_pack_name($template_pack);
2035
-            $this->request->setRequestParam('msgr', $message_template_group->messenger());
2036
-            $this->request->setRequestParam('mt', $message_template_group->message_type());
2037
-
2038
-            $query_args = $this->_reset_to_default_template();
2039
-
2040
-            if (empty($query_args['id'])) {
2041
-                EE_Error::add_error(
2042
-                    esc_html__(
2043
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
2044
-                        'event_espresso'
2045
-                    ),
2046
-                    __FILE__,
2047
-                    __FUNCTION__,
2048
-                    __LINE__
2049
-                );
2050
-                $this->_template_args['error'] = true;
2051
-            } else {
2052
-                $template_label       = $message_template_group->get_template_pack()->label;
2053
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2054
-                EE_Error::add_success(
2055
-                    sprintf(
2056
-                        esc_html__(
2057
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2058
-                            'event_espresso'
2059
-                        ),
2060
-                        $template_label,
2061
-                        $template_pack_labels->template_pack
2062
-                    )
2063
-                );
2064
-                // generate the redirect url for js.
2065
-                $url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2066
-
2067
-                $this->_template_args['data']['redirect_url'] = $url;
2068
-                $this->_template_args['success']              = true;
2069
-            }
2070
-
2071
-            $this->_return_json();
2072
-        }
2073
-    }
2074
-
2075
-
2076
-    /**
2077
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2078
-     * they want.
2079
-     *
2080
-     * @access protected
2081
-     * @return array|void
2082
-     * @throws EE_Error
2083
-     * @throws InvalidArgumentException
2084
-     * @throws InvalidDataTypeException
2085
-     * @throws InvalidInterfaceException
2086
-     * @throws ReflectionException
2087
-     */
2088
-    protected function _reset_to_default_template()
2089
-    {
2090
-        $templates    = [];
2091
-        $GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, 'int');
2092
-        $messenger    = $this->request->getRequestParam('msgr');
2093
-        $message_type = $this->request->getRequestParam('mt');
2094
-        // we need to make sure we've got the info we need.
2095
-        if (! ($GRP_ID && $messenger && $message_type)) {
2096
-            EE_Error::add_error(
2097
-                esc_html__(
2098
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2099
-                    'event_espresso'
2100
-                ),
2101
-                __FILE__,
2102
-                __FUNCTION__,
2103
-                __LINE__
2104
-            );
2105
-        }
2106
-
2107
-        // all templates will be reset to whatever the defaults are
2108
-        // for the global template matching the messenger and message type.
2109
-        $success = ! empty($GRP_ID);
2110
-
2111
-        if ($success) {
2112
-            // let's first determine if the incoming template is a global template,
2113
-            // if it isn't then we need to get the global template matching messenger and message type.
2114
-            // $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
2115
-
2116
-
2117
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2118
-            $success = $this->_delete_mtp_permanently($GRP_ID, false);
2119
-
2120
-            if ($success) {
2121
-                // if successfully deleted, lets generate the new ones.
2122
-                // Note. We set GLOBAL to true, because resets on ANY template
2123
-                // will use the related global template defaults for regeneration.
2124
-                // This means that if a custom template is reset it resets to whatever the related global template is.
2125
-                // HOWEVER, we DO keep the template pack and template variation set
2126
-                // for the current custom template when resetting.
2127
-                $templates = $this->_generate_new_templates($messenger, $message_type, $GRP_ID, true);
2128
-            }
2129
-        }
2130
-
2131
-        // any error messages?
2132
-        if (! $success) {
2133
-            EE_Error::add_error(
2134
-                esc_html__(
2135
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
2136
-                    'event_espresso'
2137
-                ),
2138
-                __FILE__,
2139
-                __FUNCTION__,
2140
-                __LINE__
2141
-            );
2142
-        }
2143
-
2144
-        // all good, let's add a success message!
2145
-        if ($success && ! empty($templates)) {
2146
-            // the info for the template we generated is the first element in the returned array
2147
-            EE_Error::overwrite_success();
2148
-            EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
2149
-        }
2150
-
2151
-
2152
-        $query_args = [
2153
-            'id'      => isset($templates['GRP_ID']) ? $templates['GRP_ID'] : null,
2154
-            'context' => isset($templates['MTP_context']) ? $templates['MTP_context'] : null,
2155
-            'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2156
-        ];
2157
-
2158
-        // if called via ajax then we return query args otherwise redirect
2159
-        if ($this->request->isAjax()) {
2160
-            return $query_args;
2161
-        }
2162
-        $this->_redirect_after_action(false, '', '', $query_args, true);
2163
-    }
2164
-
2165
-
2166
-    /**
2167
-     * Retrieve and set the message preview for display.
2168
-     *
2169
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2170
-     * @return string
2171
-     * @throws ReflectionException
2172
-     * @throws EE_Error
2173
-     * @throws InvalidArgumentException
2174
-     * @throws InvalidDataTypeException
2175
-     * @throws InvalidInterfaceException
2176
-     */
2177
-    public function _preview_message($send = false)
2178
-    {
2179
-        // first make sure we've got the necessary parameters
2180
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2181
-        if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2182
-            EE_Error::add_error(
2183
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2184
-                __FILE__,
2185
-                __FUNCTION__,
2186
-                __LINE__
2187
-            );
2188
-        }
2189
-
2190
-        $context = $this->request->getRequestParam('context');
2191
-        // get the preview!
2192
-        $preview = EED_Messages::preview_message(
2193
-            $this->_active_message_type_name,
2194
-            $context,
2195
-            $this->_active_messenger_name,
2196
-            $send
2197
-        );
2198
-
2199
-        if ($send) {
2200
-            return $preview;
2201
-        }
2202
-
2203
-        // if we have an evt_id set on the request, use it.
2204
-        $EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
2205
-
2206
-        // let's add a button to go back to the edit view
2207
-        $query_args             = [
2208
-            'id'      => $GRP_ID,
2209
-            'evt_id'  => $EVT_ID,
2210
-            'context' => $context,
2211
-            'action'  => 'edit_message_template',
2212
-        ];
2213
-        $go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2214
-        $preview_button         = '<a href="'
2215
-                                  . $go_back_url
2216
-                                  . '" class="button--secondary messages-preview-go-back-button">'
2217
-                                  . esc_html__('Go Back to Edit', 'event_espresso')
2218
-                                  . '</a>';
2219
-        $message_types          = $this->get_installed_message_types();
2220
-        $active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2221
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2222
-            ? ucwords($active_messenger->label['singular'])
2223
-            : esc_html__('Unknown Messenger', 'event_espresso');
2224
-        // let's provide a helpful title for context
2225
-        $preview_title = sprintf(
2226
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2227
-            $active_messenger_label,
2228
-            ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2229
-        );
2230
-        if (empty($preview)) {
2231
-            $this->noEventsErrorMessage();
2232
-        }
2233
-        // setup display of preview.
2234
-        $this->_admin_page_title                    = $preview_title;
2235
-        $this->_template_args['admin_page_title']   = $preview_title;
2236
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2237
-        $this->_template_args['data']['force_json'] = true;
2238
-
2239
-        return '';
2240
-    }
2241
-
2242
-
2243
-    /**
2244
-     * Used to set an error if there are no events available for generating a preview/test send.
2245
-     *
2246
-     * @param bool $test_send Whether the error should be generated for the context of a test send.
2247
-     */
2248
-    protected function noEventsErrorMessage($test_send = false)
2249
-    {
2250
-        $events_url = parent::add_query_args_and_nonce(
2251
-            [
2252
-                'action' => 'default',
2253
-                'page'   => 'espresso_events',
2254
-            ],
2255
-            admin_url('admin.php')
2256
-        );
2257
-        $message    = $test_send
2258
-            ? esc_html__(
2259
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2260
-                'event_espresso'
2261
-            )
2262
-            : esc_html__(
2263
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2264
-                'event_espresso'
2265
-            );
2266
-
2267
-        EE_Error::add_attention(
2268
-            sprintf(
2269
-                $message,
2270
-                "<a href='{$events_url}'>",
2271
-                '</a>'
2272
-            )
2273
-        );
2274
-    }
2275
-
2276
-
2277
-    /**
2278
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2279
-     * gets called automatically.
2280
-     *
2281
-     * @return void
2282
-     * @throws EE_Error
2283
-     * @since 4.5.0
2284
-     *
2285
-     */
2286
-    protected function _display_preview_message()
2287
-    {
2288
-        $this->display_admin_page_with_no_sidebar();
2289
-    }
2290
-
2291
-
2292
-    /**
2293
-     * registers metaboxes that should show up on the "edit_message_template" page
2294
-     *
2295
-     * @access protected
2296
-     * @return void
2297
-     */
2298
-    protected function _register_edit_meta_boxes()
2299
-    {
2300
-        $this->addMetaBox(
2301
-            'mtp_valid_shortcodes',
2302
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2303
-            [$this, 'shortcode_meta_box'],
2304
-            $this->_current_screen->id,
2305
-            'side'
2306
-        );
2307
-        $this->addMetaBox(
2308
-            'mtp_extra_actions',
2309
-            esc_html__('Extra Actions', 'event_espresso'),
2310
-            [$this, 'extra_actions_meta_box'],
2311
-            $this->_current_screen->id,
2312
-            'side',
2313
-            'high'
2314
-        );
2315
-        $this->addMetaBox(
2316
-            'mtp_templates',
2317
-            esc_html__('Template Styles', 'event_espresso'),
2318
-            [$this, 'template_pack_meta_box'],
2319
-            $this->_current_screen->id,
2320
-            'side',
2321
-            'high'
2322
-        );
2323
-    }
2324
-
2325
-
2326
-    /**
2327
-     * metabox content for all template pack and variation selection.
2328
-     *
2329
-     * @return void
2330
-     * @throws DomainException
2331
-     * @throws EE_Error
2332
-     * @throws InvalidArgumentException
2333
-     * @throws ReflectionException
2334
-     * @throws InvalidDataTypeException
2335
-     * @throws InvalidInterfaceException
2336
-     * @since 4.5.0
2337
-     */
2338
-    public function template_pack_meta_box()
2339
-    {
2340
-        $this->_set_message_template_group();
2341
-
2342
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2343
-
2344
-        $tp_select_values = [];
2345
-
2346
-        foreach ($tp_collection as $tp) {
2347
-            // only include template packs that support this messenger and message type!
2348
-            $supports = $tp->get_supports();
2349
-            if (
2350
-                ! isset($supports[ $this->_message_template_group->messenger() ])
2351
-                || ! in_array(
2352
-                    $this->_message_template_group->message_type(),
2353
-                    $supports[ $this->_message_template_group->messenger() ],
2354
-                    true
2355
-                )
2356
-            ) {
2357
-                // not supported
2358
-                continue;
2359
-            }
2360
-
2361
-            $tp_select_values[] = [
2362
-                'text' => $tp->label,
2363
-                'id'   => $tp->dbref,
2364
-            ];
2365
-        }
2366
-
2367
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2368
-        // the default template pack.  This still allows for the odd template pack to override.
2369
-        if (empty($tp_select_values)) {
2370
-            $tp_select_values[] = [
2371
-                'text' => esc_html__('Default', 'event_espresso'),
2372
-                'id'   => 'default',
2373
-            ];
2374
-        }
2375
-
2376
-        // setup variation select values for the currently selected template.
2377
-        $variations               = $this->_message_template_group->get_template_pack()->get_variations(
2378
-            $this->_message_template_group->messenger(),
2379
-            $this->_message_template_group->message_type()
2380
-        );
2381
-        $variations_select_values = [];
2382
-        foreach ($variations as $variation => $label) {
2383
-            $variations_select_values[] = [
2384
-                'text' => $label,
2385
-                'id'   => $variation,
2386
-            ];
2387
-        }
2388
-
2389
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2390
-
2391
-        $template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2392
-            'MTP_template_pack',
2393
-            $tp_select_values,
2394
-            $this->_message_template_group->get_template_pack_name()
2395
-        );
2396
-        $template_args['variations_selector']            = EEH_Form_Fields::select_input(
2397
-            'MTP_template_variation',
2398
-            $variations_select_values,
2399
-            $this->_message_template_group->get_template_pack_variation()
2400
-        );
2401
-        $template_args['template_pack_label']            = $template_pack_labels->template_pack;
2402
-        $template_args['template_variation_label']       = $template_pack_labels->template_variation;
2403
-        $template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2404
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2405
-
2406
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2407
-
2408
-        EEH_Template::display_template($template, $template_args);
2409
-    }
2410
-
2411
-
2412
-    /**
2413
-     * This meta box holds any extra actions related to Message Templates
2414
-     * For now, this includes Resetting templates to defaults and sending a test email.
2415
-     *
2416
-     * @access  public
2417
-     * @return void
2418
-     * @throws EE_Error
2419
-     */
2420
-    public function extra_actions_meta_box()
2421
-    {
2422
-        $template_form_fields = [];
2423
-
2424
-        $extra_args = [
2425
-            'msgr'   => $this->_message_template_group->messenger(),
2426
-            'mt'     => $this->_message_template_group->message_type(),
2427
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2428
-        ];
2429
-        // first we need to see if there are any fields
2430
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2431
-
2432
-        if (! empty($fields)) {
2433
-            // yup there be fields
2434
-            foreach ($fields as $field => $config) {
2435
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2436
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2437
-                $default  = isset($config['default']) ? $config['default'] : '';
2438
-                $default  = isset($config['value']) ? $config['value'] : $default;
2439
-
2440
-                // if type is hidden and the value is empty
2441
-                // something may have gone wrong so let's correct with the defaults
2442
-                $fix                = $config['input'] === 'hidden'
2443
-                                      && isset($existing[ $field ])
2444
-                                      && empty($existing[ $field ])
2445
-                    ? $default
2446
-                    : '';
2447
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2448
-                    ? $existing[ $field ]
2449
-                    : $fix;
2450
-
2451
-                $template_form_fields[ $field_id ] = [
2452
-                    'name'       => 'test_settings_fld[' . $field . ']',
2453
-                    'label'      => $config['label'],
2454
-                    'input'      => $config['input'],
2455
-                    'type'       => $config['type'],
2456
-                    'required'   => $config['required'],
2457
-                    'validation' => $config['validation'],
2458
-                    'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2459
-                    'css_class'  => $config['css_class'],
2460
-                    'options'    => isset($config['options']) ? $config['options'] : [],
2461
-                    'default'    => $default,
2462
-                    'format'     => $config['format'],
2463
-                ];
2464
-            }
2465
-        }
2466
-
2467
-        $test_settings_html = ! empty($template_form_fields)
2468
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2469
-            : '';
2470
-
2471
-        // print out $test_settings_fields
2472
-        if (! empty($test_settings_html)) {
2473
-            $test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2474
-            $test_settings_html .= 'name="test_button" value="';
2475
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2476
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2477
-        }
2478
-
2479
-        // and button
2480
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2481
-        $test_settings_html .= '<p>';
2482
-        $test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2483
-        $test_settings_html .= '</p>';
2484
-        $test_settings_html .= $this->get_action_link_or_button(
2485
-            'reset_to_default',
2486
-            'reset',
2487
-            $extra_args,
2488
-            'button--primary reset-default-button'
2489
-        );
2490
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2491
-        echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2492
-    }
2493
-
2494
-
2495
-    /**
2496
-     * This returns the shortcode selector skeleton for a given context and field.
2497
-     *
2498
-     * @param string $field           The name of the field retrieving shortcodes for.
2499
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2500
-     * @return string
2501
-     * @throws DomainException
2502
-     * @throws EE_Error
2503
-     * @throws InvalidArgumentException
2504
-     * @throws ReflectionException
2505
-     * @throws InvalidDataTypeException
2506
-     * @throws InvalidInterfaceException
2507
-     * @since 4.9.rc.000
2508
-     */
2509
-    protected function _get_shortcode_selector($field, $linked_input_id)
2510
-    {
2511
-        $template_args = [
2512
-            'shortcodes'      => $this->_get_shortcodes([$field]),
2513
-            'fieldname'       => $field,
2514
-            'linked_input_id' => $linked_input_id,
2515
-        ];
2516
-
2517
-        return EEH_Template::display_template(
2518
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2519
-            $template_args,
2520
-            true
2521
-        );
2522
-    }
2523
-
2524
-
2525
-    /**
2526
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2527
-     * page)
2528
-     *
2529
-     * @access public
2530
-     * @return void
2531
-     * @throws EE_Error
2532
-     * @throws InvalidArgumentException
2533
-     * @throws ReflectionException
2534
-     * @throws InvalidDataTypeException
2535
-     * @throws InvalidInterfaceException
2536
-     */
2537
-    public function shortcode_meta_box()
2538
-    {
2539
-        $shortcodes = $this->_get_shortcodes([], false);
2540
-        // just make sure the shortcodes property is set
2541
-        // $messenger = $this->_message_template_group->messenger_obj();
2542
-        // now let's set the content depending on the status of the shortcodes array
2543
-        if (empty($shortcodes)) {
2544
-            echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2545
-            return;
2546
-        }
2547
-        ?>
21
+	/**
22
+	 * @var EEM_Message
23
+	 */
24
+	private $MSG_MODEL;
25
+
26
+	/**
27
+	 * @var EEM_Message_Template
28
+	 */
29
+	private $MTP_MODEL;
30
+
31
+	/**
32
+	 * @var EEM_Message_Template_Group
33
+	 */
34
+	private $MTG_MODEL;
35
+
36
+	/**
37
+	 * @var EE_Message_Resource_Manager $_message_resource_manager
38
+	 */
39
+	protected $_message_resource_manager;
40
+
41
+	/**
42
+	 * @var string
43
+	 */
44
+	protected $_active_message_type_name = '';
45
+
46
+	/**
47
+	 * @var string
48
+	 */
49
+	protected $_active_messenger_name = '';
50
+
51
+	/**
52
+	 * @var EE_messenger $_active_messenger
53
+	 */
54
+	protected $_active_messenger;
55
+
56
+	protected $_activate_meta_box_type;
57
+
58
+	protected $_current_message_meta_box;
59
+
60
+	protected $_current_message_meta_box_object;
61
+
62
+	protected $_context_switcher;
63
+
64
+	protected $_shortcodes           = [];
65
+
66
+	protected $_active_messengers    = [];
67
+
68
+	protected $_active_message_types = [];
69
+
70
+	/**
71
+	 * @var EE_Message_Template_Group $_message_template_group
72
+	 */
73
+	protected $_message_template_group;
74
+
75
+	protected $_m_mt_settings = [];
76
+
77
+
78
+	/**
79
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
80
+	 * IF there is no group then it gets automatically set to the Default template pack.
81
+	 *
82
+	 * @since 4.5.0
83
+	 *
84
+	 * @var EE_Messages_Template_Pack
85
+	 */
86
+	protected $_template_pack;
87
+
88
+
89
+	/**
90
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
91
+	 * group is.  If there is no group then it automatically gets set to default.
92
+	 *
93
+	 * @since 4.5.0
94
+	 *
95
+	 * @var string
96
+	 */
97
+	protected $_variation;
98
+
99
+
100
+	/**
101
+	 * @param bool $routing
102
+	 * @throws EE_Error
103
+	 * @throws ReflectionException
104
+	 */
105
+	public function __construct($routing = true)
106
+	{
107
+		// make sure messages autoloader is running
108
+		EED_Messages::set_autoloaders();
109
+		parent::__construct($routing);
110
+	}
111
+
112
+
113
+	/**
114
+	 * @return EEM_Message
115
+	 * @throws EE_Error
116
+	 */
117
+	public function getMsgModel()
118
+	{
119
+		if (! $this->MSG_MODEL instanceof EEM_Message) {
120
+			$this->MSG_MODEL = EEM_Message::instance();
121
+		}
122
+		return $this->MSG_MODEL;
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return EEM_Message_Template
128
+	 * @throws EE_Error
129
+	 */
130
+	public function getMtpModel()
131
+	{
132
+		if (! $this->MTP_MODEL instanceof EEM_Message_Template) {
133
+			$this->MTP_MODEL = EEM_Message_Template::instance();
134
+		}
135
+		return $this->MTP_MODEL;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return EEM_Message_Template_Group
141
+	 * @throws EE_Error
142
+	 */
143
+	public function getMtgModel()
144
+	{
145
+		if (! $this->MTG_MODEL instanceof EEM_Message_Template_Group) {
146
+			$this->MTG_MODEL = EEM_Message_Template_Group::instance();
147
+		}
148
+		return $this->MTG_MODEL;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @throws EE_Error
154
+	 * @throws ReflectionException
155
+	 */
156
+	protected function _init_page_props()
157
+	{
158
+		$this->page_slug        = EE_MSG_PG_SLUG;
159
+		$this->page_label       = esc_html__('Messages Settings', 'event_espresso');
160
+		$this->_admin_base_url  = EE_MSG_ADMIN_URL;
161
+		$this->_admin_base_path = EE_MSG_ADMIN;
162
+
163
+		$messenger    = $this->request->getRequestParam('messenger', '');
164
+		$message_type = $this->request->getRequestParam('message_type', '');
165
+		$this->_active_messenger_name    = $this->request->getRequestParam('MTP_messenger', $messenger);
166
+		$this->_active_message_type_name = $this->request->getRequestParam('MTP_message_type', $message_type);
167
+
168
+		$this->_load_message_resource_manager();
169
+	}
170
+
171
+
172
+	/**
173
+	 * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
174
+	 *
175
+	 * @throws EE_Error
176
+	 * @throws InvalidDataTypeException
177
+	 * @throws InvalidInterfaceException
178
+	 * @throws InvalidArgumentException
179
+	 * @throws ReflectionException
180
+	 */
181
+	protected function _load_message_resource_manager()
182
+	{
183
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
184
+	}
185
+
186
+
187
+	/**
188
+	 * @return array
189
+	 * @throws EE_Error
190
+	 * @throws InvalidArgumentException
191
+	 * @throws InvalidDataTypeException
192
+	 * @throws InvalidInterfaceException
193
+	 * @deprecated 4.9.9.rc.014
194
+	 */
195
+	public function get_messengers_for_list_table()
196
+	{
197
+		EE_Error::doing_it_wrong(
198
+			__METHOD__,
199
+			sprintf(
200
+				esc_html__(
201
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
202
+					'event_espresso'
203
+				),
204
+				'Messages_Admin_Page::get_messengers_select_input()'
205
+			),
206
+			'4.9.9.rc.014'
207
+		);
208
+
209
+		$m_values          = [];
210
+		$active_messengers = $this->getMsgModel()->get_all(['group_by' => 'MSG_messenger']);
211
+		// setup messengers for selects
212
+		$i = 1;
213
+		foreach ($active_messengers as $active_messenger) {
214
+			if ($active_messenger instanceof EE_Message) {
215
+				$m_values[ $i ]['id']   = $active_messenger->messenger();
216
+				$m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
217
+				$i++;
218
+			}
219
+		}
220
+
221
+		return $m_values;
222
+	}
223
+
224
+
225
+	/**
226
+	 * @return array
227
+	 * @throws EE_Error
228
+	 * @throws InvalidArgumentException
229
+	 * @throws InvalidDataTypeException
230
+	 * @throws InvalidInterfaceException
231
+	 * @deprecated 4.9.9.rc.014
232
+	 */
233
+	public function get_message_types_for_list_table()
234
+	{
235
+		EE_Error::doing_it_wrong(
236
+			__METHOD__,
237
+			sprintf(
238
+				esc_html__(
239
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
240
+					'event_espresso'
241
+				),
242
+				'Messages_Admin_Page::get_message_types_select_input()'
243
+			),
244
+			'4.9.9.rc.014'
245
+		);
246
+
247
+		$mt_values       = [];
248
+		$active_messages = $this->getMsgModel()->get_all(['group_by' => 'MSG_message_type']);
249
+		$i               = 1;
250
+		foreach ($active_messages as $active_message) {
251
+			if ($active_message instanceof EE_Message) {
252
+				$mt_values[ $i ]['id']   = $active_message->message_type();
253
+				$mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
254
+				$i++;
255
+			}
256
+		}
257
+
258
+		return $mt_values;
259
+	}
260
+
261
+
262
+	/**
263
+	 * @return array
264
+	 * @throws EE_Error
265
+	 * @throws InvalidArgumentException
266
+	 * @throws InvalidDataTypeException
267
+	 * @throws InvalidInterfaceException
268
+	 * @deprecated 4.9.9.rc.014
269
+	 */
270
+	public function get_contexts_for_message_types_for_list_table()
271
+	{
272
+		EE_Error::doing_it_wrong(
273
+			__METHOD__,
274
+			sprintf(
275
+				esc_html__(
276
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
277
+					'event_espresso'
278
+				),
279
+				'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
280
+			),
281
+			'4.9.9.rc.014'
282
+		);
283
+
284
+		$contexts                = [];
285
+		$active_message_contexts = $this->getMsgModel()->get_all(['group_by' => 'MSG_context']);
286
+		foreach ($active_message_contexts as $active_message) {
287
+			if ($active_message instanceof EE_Message) {
288
+				$message_type = $active_message->message_type_object();
289
+				if ($message_type instanceof EE_message_type) {
290
+					$message_type_contexts = $message_type->get_contexts();
291
+					foreach ($message_type_contexts as $context => $context_details) {
292
+						$contexts[ $context ] = $context_details['label'];
293
+					}
294
+				}
295
+			}
296
+		}
297
+
298
+		return $contexts;
299
+	}
300
+
301
+
302
+	/**
303
+	 * Generate select input with provided messenger options array.
304
+	 *
305
+	 * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
306
+	 *                                 labels.
307
+	 * @return string
308
+	 * @throws EE_Error
309
+	 */
310
+	public function get_messengers_select_input($messenger_options)
311
+	{
312
+		// if empty or just one value then just return an empty string
313
+		if (
314
+			empty($messenger_options)
315
+			|| ! is_array($messenger_options)
316
+			|| count($messenger_options) === 1
317
+		) {
318
+			return '';
319
+		}
320
+		// merge in default
321
+		$messenger_options = array_merge(
322
+			['none_selected' => esc_html__('Show All Messengers', 'event_espresso')],
323
+			$messenger_options
324
+		);
325
+		$input             = new EE_Select_Input(
326
+			$messenger_options,
327
+			[
328
+				'html_name'  => 'ee_messenger_filter_by',
329
+				'html_id'    => 'ee_messenger_filter_by',
330
+				'html_class' => 'wide',
331
+				'default'    => $this->request->getRequestParam('ee_messenger_filter_by', 'none_selected', 'title'),
332
+			]
333
+		);
334
+
335
+		return $input->get_html_for_input();
336
+	}
337
+
338
+
339
+	/**
340
+	 * Generate select input with provided message type options array.
341
+	 *
342
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
343
+	 *                                    message type labels
344
+	 * @return string
345
+	 * @throws EE_Error
346
+	 */
347
+	public function get_message_types_select_input($message_type_options)
348
+	{
349
+		// if empty or count of options is 1 then just return an empty string
350
+		if (
351
+			empty($message_type_options)
352
+			|| ! is_array($message_type_options)
353
+			|| count($message_type_options) === 1
354
+		) {
355
+			return '';
356
+		}
357
+		// merge in default
358
+		$message_type_options = array_merge(
359
+			['none_selected' => esc_html__('Show All Message Types', 'event_espresso')],
360
+			$message_type_options
361
+		);
362
+		$input                = new EE_Select_Input(
363
+			$message_type_options,
364
+			[
365
+				'html_name'  => 'ee_message_type_filter_by',
366
+				'html_id'    => 'ee_message_type_filter_by',
367
+				'html_class' => 'wide',
368
+				'default'    => $this->request->getRequestParam('ee_message_type_filter_by', 'none_selected', 'title'),
369
+			]
370
+		);
371
+
372
+		return $input->get_html_for_input();
373
+	}
374
+
375
+
376
+	/**
377
+	 * Generate select input with provide message type contexts array.
378
+	 *
379
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
380
+	 *                               context label.
381
+	 * @return string
382
+	 * @throws EE_Error
383
+	 */
384
+	public function get_contexts_for_message_types_select_input($context_options)
385
+	{
386
+		// if empty or count of options is one then just return empty string
387
+		if (
388
+			empty($context_options)
389
+			|| ! is_array($context_options)
390
+			|| count($context_options) === 1
391
+		) {
392
+			return '';
393
+		}
394
+		// merge in default
395
+		$context_options = array_merge(
396
+			['none_selected' => esc_html__('Show all Contexts', 'event_espresso')],
397
+			$context_options
398
+		);
399
+		$input           = new EE_Select_Input(
400
+			$context_options,
401
+			[
402
+				'html_name'  => 'ee_context_filter_by',
403
+				'html_id'    => 'ee_context_filter_by',
404
+				'html_class' => 'wide',
405
+				'default'    => $this->request->getRequestParam('ee_context_filter_by', 'none_selected', 'title'),
406
+			]
407
+		);
408
+
409
+		return $input->get_html_for_input();
410
+	}
411
+
412
+
413
+	protected function _ajax_hooks()
414
+	{
415
+		add_action('wp_ajax_activate_messenger', [$this, 'activate_messenger_toggle']);
416
+		add_action('wp_ajax_activate_mt', [$this, 'activate_mt_toggle']);
417
+		add_action('wp_ajax_ee_msgs_save_settings', [$this, 'save_settings']);
418
+		add_action('wp_ajax_ee_msgs_update_mt_form', [$this, 'update_mt_form']);
419
+		add_action('wp_ajax_switch_template_pack', [$this, 'switch_template_pack']);
420
+		add_action('wp_ajax_toggle_context_template', [$this, 'toggle_context_template']);
421
+	}
422
+
423
+
424
+	protected function _define_page_props()
425
+	{
426
+		$this->_admin_page_title = $this->page_label;
427
+		$this->_labels           = [
428
+			'buttons'    => [
429
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
430
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
431
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
432
+			],
433
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
434
+		];
435
+	}
436
+
437
+
438
+	/**
439
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
440
+	 *
441
+	 * @access protected
442
+	 * @return void
443
+	 */
444
+	protected function _set_page_routes()
445
+	{
446
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
447
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
448
+		$MSG_ID = $this->request->getRequestParam('MSG_ID', 0, 'int');
449
+
450
+		$this->_page_routes = [
451
+			'default'                          => [
452
+				'func'       => '_message_queue_list_table',
453
+				'capability' => 'ee_read_global_messages',
454
+			],
455
+			'global_mtps'                      => [
456
+				'func'       => '_ee_default_messages_overview_list_table',
457
+				'capability' => 'ee_read_global_messages',
458
+			],
459
+			'custom_mtps'                      => [
460
+				'func'       => '_custom_mtps_preview',
461
+				'capability' => 'ee_read_messages',
462
+			],
463
+			'add_new_message_template'         => [
464
+				'func'       => 'add_message_template',
465
+				'capability' => 'ee_edit_messages',
466
+				'noheader'   => true,
467
+			],
468
+			'edit_message_template'            => [
469
+				'func'       => '_edit_message_template',
470
+				'capability' => 'ee_edit_message',
471
+				'obj_id'     => $GRP_ID,
472
+			],
473
+			'preview_message'                  => [
474
+				'func'               => '_preview_message',
475
+				'capability'         => 'ee_read_message',
476
+				'obj_id'             => $GRP_ID,
477
+				'noheader'           => true,
478
+				'headers_sent_route' => 'display_preview_message',
479
+			],
480
+			'display_preview_message'          => [
481
+				'func'       => '_display_preview_message',
482
+				'capability' => 'ee_read_message',
483
+				'obj_id'     => $GRP_ID,
484
+			],
485
+			'insert_message_template'          => [
486
+				'func'       => '_insert_or_update_message_template',
487
+				'capability' => 'ee_edit_messages',
488
+				'args'       => ['new' => true],
489
+				'noheader'   => true,
490
+			],
491
+			'update_message_template'          => [
492
+				'func'       => '_insert_or_update_message_template',
493
+				'capability' => 'ee_edit_message',
494
+				'obj_id'     => $GRP_ID,
495
+				'args'       => ['new' => false],
496
+				'noheader'   => true,
497
+			],
498
+			'trash_message_template'           => [
499
+				'func'       => '_trash_or_restore_message_template',
500
+				'capability' => 'ee_delete_message',
501
+				'obj_id'     => $GRP_ID,
502
+				'args'       => ['trash' => true, 'all' => true],
503
+				'noheader'   => true,
504
+			],
505
+			'trash_message_template_context'   => [
506
+				'func'       => '_trash_or_restore_message_template',
507
+				'capability' => 'ee_delete_message',
508
+				'obj_id'     => $GRP_ID,
509
+				'args'       => ['trash' => true],
510
+				'noheader'   => true,
511
+			],
512
+			'restore_message_template'         => [
513
+				'func'       => '_trash_or_restore_message_template',
514
+				'capability' => 'ee_delete_message',
515
+				'obj_id'     => $GRP_ID,
516
+				'args'       => ['trash' => false, 'all' => true],
517
+				'noheader'   => true,
518
+			],
519
+			'restore_message_template_context' => [
520
+				'func'       => '_trash_or_restore_message_template',
521
+				'capability' => 'ee_delete_message',
522
+				'obj_id'     => $GRP_ID,
523
+				'args'       => ['trash' => false],
524
+				'noheader'   => true,
525
+			],
526
+			'delete_message_template'          => [
527
+				'func'       => '_delete_message_template',
528
+				'capability' => 'ee_delete_message',
529
+				'obj_id'     => $GRP_ID,
530
+				'noheader'   => true,
531
+			],
532
+			'reset_to_default'                 => [
533
+				'func'       => '_reset_to_default_template',
534
+				'capability' => 'ee_edit_message',
535
+				'obj_id'     => $GRP_ID,
536
+				'noheader'   => true,
537
+			],
538
+			'settings'                         => [
539
+				'func'       => '_settings',
540
+				'capability' => 'manage_options',
541
+			],
542
+			'update_global_settings'           => [
543
+				'func'       => '_update_global_settings',
544
+				'capability' => 'manage_options',
545
+				'noheader'   => true,
546
+			],
547
+			'generate_now'                     => [
548
+				'func'       => '_generate_now',
549
+				'capability' => 'ee_send_message',
550
+				'noheader'   => true,
551
+			],
552
+			'generate_and_send_now'            => [
553
+				'func'       => '_generate_and_send_now',
554
+				'capability' => 'ee_send_message',
555
+				'noheader'   => true,
556
+			],
557
+			'queue_for_resending'              => [
558
+				'func'       => '_queue_for_resending',
559
+				'capability' => 'ee_send_message',
560
+				'noheader'   => true,
561
+			],
562
+			'send_now'                         => [
563
+				'func'       => '_send_now',
564
+				'capability' => 'ee_send_message',
565
+				'noheader'   => true,
566
+			],
567
+			'delete_ee_message'                => [
568
+				'func'       => '_delete_ee_messages',
569
+				'capability' => 'ee_delete_messages',
570
+				'noheader'   => true,
571
+			],
572
+			'delete_ee_messages'               => [
573
+				'func'       => '_delete_ee_messages',
574
+				'capability' => 'ee_delete_messages',
575
+				'noheader'   => true,
576
+				'obj_id'     => $MSG_ID,
577
+			],
578
+		];
579
+	}
580
+
581
+
582
+	protected function _set_page_config()
583
+	{
584
+		$this->_page_config = [
585
+			'default'                  => [
586
+				'nav'           => [
587
+					'label' => esc_html__('Message Activity', 'event_espresso'),
588
+					'icon' => 'dashicons-email',
589
+					'order' => 10,
590
+				],
591
+				'list_table'    => 'EE_Message_List_Table',
592
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
593
+				'require_nonce' => false,
594
+			],
595
+			'global_mtps'              => [
596
+				'nav'           => [
597
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
598
+					'icon' => 'dashicons-layout',
599
+					'order' => 20,
600
+				],
601
+				'list_table'    => 'Messages_Template_List_Table',
602
+				'help_tabs'     => [
603
+					'messages_overview_help_tab'                                => [
604
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
605
+						'filename' => 'messages_overview',
606
+					],
607
+					'messages_overview_messages_table_column_headings_help_tab' => [
608
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
609
+						'filename' => 'messages_overview_table_column_headings',
610
+					],
611
+					'messages_overview_messages_filters_help_tab'               => [
612
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
613
+						'filename' => 'messages_overview_filters',
614
+					],
615
+					'messages_overview_messages_views_help_tab'                 => [
616
+						'title'    => esc_html__('Message Views', 'event_espresso'),
617
+						'filename' => 'messages_overview_views',
618
+					],
619
+					'message_overview_message_types_help_tab'                   => [
620
+						'title'    => esc_html__('Message Types', 'event_espresso'),
621
+						'filename' => 'messages_overview_types',
622
+					],
623
+					'messages_overview_messengers_help_tab'                     => [
624
+						'title'    => esc_html__('Messengers', 'event_espresso'),
625
+						'filename' => 'messages_overview_messengers',
626
+					],
627
+				],
628
+				'require_nonce' => false,
629
+			],
630
+			'custom_mtps'              => [
631
+				'nav'           => [
632
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
633
+					'icon' => 'dashicons-admin-customizer',
634
+					'order' => 30,
635
+				],
636
+				'help_tabs'     => [],
637
+				'require_nonce' => false,
638
+			],
639
+			'add_new_message_template' => [
640
+				'nav'           => [
641
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
642
+					'icon' => 'dashicons-plus-alt',
643
+					'order'      => 5,
644
+					'persistent' => false,
645
+				],
646
+				'require_nonce' => false,
647
+			],
648
+			'edit_message_template'    => [
649
+				'labels'        => [
650
+					'buttons'    => [
651
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
652
+					],
653
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
654
+				],
655
+				'nav'           => [
656
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
657
+					'icon' => 'dashicons-edit-large',
658
+					'order'      => 5,
659
+					'persistent' => false,
660
+					'url'        => '',
661
+				],
662
+				'metaboxes'     => ['_publish_post_box', '_register_edit_meta_boxes'],
663
+				'has_metaboxes' => true,
664
+				'help_tabs'     => [
665
+					'edit_message_template'            => [
666
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
667
+						'callback' => 'edit_message_template_help_tab',
668
+					],
669
+					'message_templates_help_tab'       => [
670
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
671
+						'filename' => 'messages_templates',
672
+					],
673
+					'message_template_shortcodes'      => [
674
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
675
+						'callback' => 'message_template_shortcodes_help_tab',
676
+					],
677
+					'message_preview_help_tab'         => [
678
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
679
+						'filename' => 'messages_preview',
680
+					],
681
+					'messages_overview_other_help_tab' => [
682
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
683
+						'filename' => 'messages_overview_other',
684
+					],
685
+				],
686
+				'require_nonce' => false,
687
+			],
688
+			'display_preview_message'  => [
689
+				'nav'           => [
690
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
691
+					'icon' => 'dashicons-visibility-bar',
692
+					'order'      => 5,
693
+					'url'        => '',
694
+					'persistent' => false,
695
+				],
696
+				'help_tabs'     => [
697
+					'preview_message' => [
698
+						'title'    => esc_html__('About Previews', 'event_espresso'),
699
+						'callback' => 'preview_message_help_tab',
700
+					],
701
+				],
702
+				'require_nonce' => false,
703
+			],
704
+			'settings'                 => [
705
+				'nav'           => [
706
+					'label' => esc_html__('Settings', 'event_espresso'),
707
+					'icon' => 'dashicons-admin-generic',
708
+					'order' => 40,
709
+				],
710
+				'metaboxes'     => ['_messages_settings_metaboxes'],
711
+				'help_tabs'     => [
712
+					'messages_settings_help_tab'               => [
713
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
714
+						'filename' => 'messages_settings',
715
+					],
716
+					'messages_settings_message_types_help_tab' => [
717
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
718
+						'filename' => 'messages_settings_message_types',
719
+					],
720
+					'messages_settings_messengers_help_tab'    => [
721
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
722
+						'filename' => 'messages_settings_messengers',
723
+					],
724
+				],
725
+				'require_nonce' => false,
726
+			],
727
+		];
728
+	}
729
+
730
+
731
+	protected function _add_screen_options()
732
+	{
733
+		// todo
734
+	}
735
+
736
+
737
+	protected function _add_screen_options_global_mtps()
738
+	{
739
+		/**
740
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
741
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
742
+		 */
743
+		$page_title              = $this->_admin_page_title;
744
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
745
+		$this->_per_page_screen_option();
746
+		$this->_admin_page_title = $page_title;
747
+	}
748
+
749
+
750
+	protected function _add_screen_options_default()
751
+	{
752
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
753
+		$this->_per_page_screen_option();
754
+	}
755
+
756
+
757
+	// none of the below group are currently used for Messages
758
+	protected function _add_feature_pointers()
759
+	{
760
+	}
761
+
762
+
763
+	public function admin_init()
764
+	{
765
+	}
766
+
767
+
768
+	public function admin_notices()
769
+	{
770
+	}
771
+
772
+
773
+	public function admin_footer_scripts()
774
+	{
775
+	}
776
+
777
+
778
+	public function messages_help_tab()
779
+	{
780
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
781
+	}
782
+
783
+
784
+	public function messengers_help_tab()
785
+	{
786
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
787
+	}
788
+
789
+
790
+	public function message_types_help_tab()
791
+	{
792
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
793
+	}
794
+
795
+
796
+	public function messages_overview_help_tab()
797
+	{
798
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
799
+	}
800
+
801
+
802
+	public function message_templates_help_tab()
803
+	{
804
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
805
+	}
806
+
807
+
808
+	public function edit_message_template_help_tab()
809
+	{
810
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
811
+						. esc_attr__('Editor Title', 'event_espresso')
812
+						. '" />';
813
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
814
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
815
+						. '" />';
816
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
817
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
818
+						. '" />';
819
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
820
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
821
+						. '" />';
822
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
823
+						. esc_attr__('Publish Metabox', 'event_espresso')
824
+						. '" />';
825
+		EEH_Template::display_template(
826
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
827
+			$args
828
+		);
829
+	}
830
+
831
+
832
+	/**
833
+	 * @throws ReflectionException
834
+	 * @throws EE_Error
835
+	 */
836
+	public function message_template_shortcodes_help_tab()
837
+	{
838
+		$this->_set_shortcodes();
839
+		$args['shortcodes'] = $this->_shortcodes;
840
+		EEH_Template::display_template(
841
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
842
+			$args
843
+		);
844
+	}
845
+
846
+
847
+	public function preview_message_help_tab()
848
+	{
849
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
850
+	}
851
+
852
+
853
+	public function settings_help_tab()
854
+	{
855
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
856
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
857
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
858
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
859
+		$args['img3'] = '<div class="ee-switch">'
860
+						. '<input class="ee-switch__input" id="ee-on-off-toggle-on" type="checkbox" checked>'
861
+						. '<label class="ee-switch__toggle" for="ee-on-off-toggle-on"></label>'
862
+						. '</div>';
863
+		$args['img4'] = '<div class="switch">'
864
+						. '<input class="ee-switch__input" id="ee-on-off-toggle-off" type="checkbox">'
865
+						. '<label class="ee-switch__toggle" for="ee-on-off-toggle-off"></label>'
866
+						. '</div>';
867
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
868
+	}
869
+
870
+
871
+	public function load_scripts_styles()
872
+	{
873
+		wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
874
+		wp_enqueue_style('espresso_ee_msg');
875
+
876
+		wp_register_script(
877
+			'ee-messages-settings',
878
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
879
+			['jquery-ui-droppable', 'ee-serialize-full-array'],
880
+			EVENT_ESPRESSO_VERSION,
881
+			true
882
+		);
883
+		wp_register_script(
884
+			'ee-msg-list-table-js',
885
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
886
+			['ee-dialog'],
887
+			EVENT_ESPRESSO_VERSION
888
+		);
889
+	}
890
+
891
+
892
+	public function load_scripts_styles_default()
893
+	{
894
+		wp_enqueue_script('ee-msg-list-table-js');
895
+	}
896
+
897
+
898
+	public function wp_editor_css($mce_css)
899
+	{
900
+		// if we're on the edit_message_template route
901
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
902
+			$message_type_name = $this->_active_message_type_name;
903
+
904
+			// we're going to REPLACE the existing mce css
905
+			// we need to get the css file location from the active messenger
906
+			$mce_css = $this->_active_messenger->get_variation(
907
+				$this->_template_pack,
908
+				$message_type_name,
909
+				true,
910
+				'wpeditor',
911
+				$this->_variation
912
+			);
913
+		}
914
+
915
+		return $mce_css;
916
+	}
917
+
918
+
919
+	/**
920
+	 * @throws EE_Error
921
+	 * @throws ReflectionException
922
+	 */
923
+	public function load_scripts_styles_edit_message_template()
924
+	{
925
+
926
+		$this->_set_shortcodes();
927
+
928
+		EE_Registry::$i18n_js_strings['confirm_default_reset']        = sprintf(
929
+			esc_html__(
930
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
931
+				'event_espresso'
932
+			),
933
+			$this->_message_template_group->messenger_obj()->label['singular'],
934
+			$this->_message_template_group->message_type_obj()->label['singular']
935
+		);
936
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
937
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
938
+			'event_espresso'
939
+		);
940
+		EE_Registry::$i18n_js_strings['server_error']                 = esc_html__(
941
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
942
+			'event_espresso'
943
+		);
944
+
945
+		wp_register_script(
946
+			'ee_msgs_edit_js',
947
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
948
+			['jquery'],
949
+			EVENT_ESPRESSO_VERSION
950
+		);
951
+
952
+		wp_enqueue_script('ee_admin_js');
953
+		wp_enqueue_script('ee_msgs_edit_js');
954
+
955
+		// add in special css for tiny_mce
956
+		add_filter('mce_css', [$this, 'wp_editor_css']);
957
+	}
958
+
959
+
960
+	/**
961
+	 * @throws EE_Error
962
+	 * @throws ReflectionException
963
+	 */
964
+	public function load_scripts_styles_display_preview_message()
965
+	{
966
+		$this->_set_message_template_group();
967
+		if ($this->_active_messenger_name) {
968
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
969
+				$this->_active_messenger_name
970
+			);
971
+		}
972
+
973
+		wp_enqueue_style(
974
+			'espresso_preview_css',
975
+			$this->_active_messenger->get_variation(
976
+				$this->_template_pack,
977
+				$this->_active_message_type_name,
978
+				true,
979
+				'preview',
980
+				$this->_variation
981
+			)
982
+		);
983
+	}
984
+
985
+
986
+	public function load_scripts_styles_settings()
987
+	{
988
+		wp_register_style(
989
+			'ee-message-settings',
990
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
991
+			[],
992
+			EVENT_ESPRESSO_VERSION
993
+		);
994
+		wp_enqueue_style('ee-text-links');
995
+		wp_enqueue_style('ee-message-settings');
996
+		wp_enqueue_script('ee-messages-settings');
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * set views array for List Table
1002
+	 */
1003
+	public function _set_list_table_views_global_mtps()
1004
+	{
1005
+		$this->_views = [
1006
+			'in_use' => [
1007
+				'slug'  => 'in_use',
1008
+				'label' => esc_html__('In Use', 'event_espresso'),
1009
+				'count' => 0,
1010
+			],
1011
+		];
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 * Set views array for the Custom Template List Table
1017
+	 */
1018
+	public function _set_list_table_views_custom_mtps()
1019
+	{
1020
+		$this->_set_list_table_views_global_mtps();
1021
+		$this->_views['in_use']['bulk_action'] = [
1022
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
1023
+		];
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * set views array for message queue list table
1029
+	 *
1030
+	 * @throws InvalidDataTypeException
1031
+	 * @throws InvalidInterfaceException
1032
+	 * @throws InvalidArgumentException
1033
+	 * @throws EE_Error
1034
+	 * @throws ReflectionException
1035
+	 */
1036
+	public function _set_list_table_views_default()
1037
+	{
1038
+		EE_Registry::instance()->load_helper('Template');
1039
+
1040
+		$common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
1041
+			'ee_send_message',
1042
+			'message_list_table_bulk_actions'
1043
+		)
1044
+			? [
1045
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
1046
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
1047
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
1048
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
1049
+			]
1050
+			: [];
1051
+
1052
+		$delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
1053
+			'ee_delete_messages',
1054
+			'message_list_table_bulk_actions'
1055
+		)
1056
+			? ['delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso')]
1057
+			: [];
1058
+
1059
+
1060
+		$this->_views = [
1061
+			'all' => [
1062
+				'slug'        => 'all',
1063
+				'label'       => esc_html__('All', 'event_espresso'),
1064
+				'count'       => 0,
1065
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1066
+			],
1067
+		];
1068
+
1069
+
1070
+		foreach ($this->getMsgModel()->all_statuses() as $status) {
1071
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1072
+				continue;
1073
+			}
1074
+			$status_bulk_actions = $common_bulk_actions;
1075
+			// unset bulk actions not applying to status
1076
+			if (! empty($status_bulk_actions)) {
1077
+				switch ($status) {
1078
+					case EEM_Message::status_idle:
1079
+					case EEM_Message::status_resend:
1080
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1081
+						break;
1082
+
1083
+					case EEM_Message::status_failed:
1084
+					case EEM_Message::status_debug_only:
1085
+					case EEM_Message::status_messenger_executing:
1086
+						$status_bulk_actions = [];
1087
+						break;
1088
+
1089
+					case EEM_Message::status_incomplete:
1090
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1091
+						break;
1092
+
1093
+					case EEM_Message::status_retry:
1094
+					case EEM_Message::status_sent:
1095
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1096
+						break;
1097
+				}
1098
+			}
1099
+
1100
+			// skip adding messenger executing status to views because it will be included with the Failed view.
1101
+			if ($status === EEM_Message::status_messenger_executing) {
1102
+				continue;
1103
+			}
1104
+
1105
+			$this->_views[ strtolower($status) ] = [
1106
+				'slug'        => strtolower($status),
1107
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1108
+				'count'       => 0,
1109
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1110
+			];
1111
+		}
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * @throws EE_Error
1117
+	 */
1118
+	protected function _ee_default_messages_overview_list_table()
1119
+	{
1120
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1121
+		$this->display_admin_list_table_page_with_no_sidebar();
1122
+	}
1123
+
1124
+
1125
+	/**
1126
+	 * @throws EE_Error
1127
+	 * @throws ReflectionException
1128
+	 */
1129
+	protected function _message_queue_list_table()
1130
+	{
1131
+		$this->_search_btn_label                   = esc_html__('Message Activity', 'event_espresso');
1132
+		$this->_template_args['per_column']        = 6;
1133
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_message_legend_items());
1134
+		$message_results = trim(EEM_Message::instance()->get_pretty_label_for_results());
1135
+		$this->_template_args['before_list_table'] = ! empty($message_results) ? "<h3>{$message_results}</h3>" : '';
1136
+		$this->display_admin_list_table_page_with_no_sidebar();
1137
+	}
1138
+
1139
+
1140
+	/**
1141
+	 * @throws EE_Error
1142
+	 */
1143
+	protected function _message_legend_items()
1144
+	{
1145
+
1146
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1147
+		$action_items       = [];
1148
+
1149
+		foreach ($action_css_classes as $action_item => $action_details) {
1150
+			if ($action_item === 'see_notifications_for') {
1151
+				continue;
1152
+			}
1153
+			$action_items[ $action_item ] = [
1154
+				'class' => $action_details['css_class'],
1155
+				'desc'  => $action_details['label'],
1156
+			];
1157
+		}
1158
+
1159
+		/** @var array $status_items status legend setup */
1160
+		$status_items = [
1161
+			'sent_status'                => [
1162
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_sent,
1163
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1164
+			],
1165
+			'idle_status'                => [
1166
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_idle,
1167
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1168
+			],
1169
+			'failed_status'              => [
1170
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_failed,
1171
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1172
+			],
1173
+			'messenger_executing_status' => [
1174
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_messenger_executing,
1175
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1176
+			],
1177
+			'resend_status'              => [
1178
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_resend,
1179
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1180
+			],
1181
+			'incomplete_status'          => [
1182
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_incomplete,
1183
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1184
+			],
1185
+			'retry_status'               => [
1186
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_retry,
1187
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1188
+			],
1189
+		];
1190
+		if (EEM_Message::debug()) {
1191
+			$status_items['debug_only_status'] = [
1192
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Message::status_debug_only,
1193
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1194
+			];
1195
+		}
1196
+
1197
+		return array_merge($action_items, $status_items);
1198
+	}
1199
+
1200
+
1201
+	/**
1202
+	 * @throws EE_Error
1203
+	 */
1204
+	protected function _custom_mtps_preview()
1205
+	{
1206
+		$this->_admin_page_title              = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1207
+		$this->_template_args['preview_img']  = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1208
+												. ' alt="' . esc_attr__(
1209
+													'Preview Custom Message Templates screenshot',
1210
+													'event_espresso'
1211
+												) . '" />';
1212
+		$this->_template_args['preview_text'] = '<strong>'
1213
+												. esc_html__(
1214
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1215
+													'event_espresso'
1216
+												)
1217
+												. '</strong>';
1218
+
1219
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * get_message_templates
1225
+	 * This gets all the message templates for listing on the overview list.
1226
+	 *
1227
+	 * @access public
1228
+	 * @param int    $per_page the amount of templates groups to show per page
1229
+	 * @param string $type     the current _view we're getting templates for
1230
+	 * @param bool   $count    return count?
1231
+	 * @param bool   $all      disregard any paging info (get all data);
1232
+	 * @param bool   $global   whether to return just global (true) or custom templates (false)
1233
+	 * @return array
1234
+	 * @throws EE_Error
1235
+	 * @throws InvalidArgumentException
1236
+	 * @throws InvalidDataTypeException
1237
+	 * @throws InvalidInterfaceException
1238
+	 */
1239
+	public function get_message_templates(
1240
+		$per_page = 10,
1241
+		$type = 'in_use',
1242
+		$count = false,
1243
+		$all = false,
1244
+		$global = true
1245
+	) {
1246
+		$orderby = $this->request->getRequestParam('orderby', 'GRP_ID');
1247
+		$this->request->setRequestParam('orderby', $orderby);
1248
+
1249
+		$order        = $this->request->getRequestParam('order', 'ASC');
1250
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1251
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1252
+
1253
+		$offset = ($current_page - 1) * $per_page;
1254
+		$limit  = $all ? null : [$offset, $per_page];
1255
+
1256
+		// options will match what is in the _views array property
1257
+		return $type === 'in_use'
1258
+			? $this->getMtgModel()->get_all_active_message_templates(
1259
+				$orderby,
1260
+				$order,
1261
+				$limit,
1262
+				$count,
1263
+				$global,
1264
+				true
1265
+			)
1266
+			: $this->getMtgModel()->get_all_trashed_grouped_message_templates(
1267
+				$orderby,
1268
+				$order,
1269
+				$limit,
1270
+				$count,
1271
+				$global
1272
+			);
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * filters etc might need a list of installed message_types
1278
+	 *
1279
+	 * @return array an array of message type objects
1280
+	 */
1281
+	public function get_installed_message_types()
1282
+	{
1283
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1284
+		$installed               = [];
1285
+
1286
+		foreach ($installed_message_types as $message_type) {
1287
+			$installed[ $message_type->name ] = $message_type;
1288
+		}
1289
+
1290
+		return $installed;
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1296
+	 *
1297
+	 * @param string $message_type
1298
+	 * @param string $messenger
1299
+	 * @param string $GRP_ID
1300
+	 *
1301
+	 * @throws EE_error
1302
+	 * @throws ReflectionException
1303
+	 */
1304
+	public function add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1305
+	{
1306
+		// set values override any request data
1307
+		$message_type = ! empty($message_type) ? $message_type : $this->_active_message_type_name;
1308
+		$messenger    = ! empty($messenger) ? $messenger : $this->_active_messenger_name;
1309
+		$GRP_ID       = ! empty($GRP_ID) ? $GRP_ID : $this->request->getRequestParam('GRP_ID', 0, 'int');
1310
+
1311
+		// we need messenger and message type.  They should be coming from the event editor. If not here then return error
1312
+		if (empty($message_type) || empty($messenger)) {
1313
+			throw new EE_Error(
1314
+				esc_html__(
1315
+					'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1316
+					'event_espresso'
1317
+				)
1318
+			);
1319
+		}
1320
+
1321
+		// we need the GRP_ID for the template being used as the base for the new template
1322
+		if (empty($GRP_ID)) {
1323
+			throw new EE_Error(
1324
+				esc_html__(
1325
+					'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1326
+					'event_espresso'
1327
+				)
1328
+			);
1329
+		}
1330
+
1331
+		// let's just make sure the template gets generated!
1332
+
1333
+		// we need to reassign some variables for what the insert is expecting
1334
+		$this->request->setRequestParam('MTP_messenger', $messenger);
1335
+		$this->request->setRequestParam('MTP_message_type', $message_type);
1336
+		$this->request->setRequestParam('GRP_ID', $GRP_ID);
1337
+
1338
+		$this->_insert_or_update_message_template(true);
1339
+	}
1340
+
1341
+
1342
+	/**
1343
+	 * @param string $message_type     message type slug
1344
+	 * @param string $messenger        messenger slug
1345
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1346
+	 *                                 off of.
1347
+	 * @throws EE_error
1348
+	 * @throws ReflectionException
1349
+	 * @deprecated 4.10.29.p
1350
+	 */
1351
+	protected function _add_message_template($message_type, $messenger, $GRP_ID)
1352
+	{
1353
+		$this->add_message_template($message_type, $messenger, $GRP_ID);
1354
+	}
1355
+
1356
+
1357
+	/**
1358
+	 * _edit_message_template
1359
+	 *
1360
+	 * @access protected
1361
+	 * @return void
1362
+	 * @throws InvalidIdentifierException
1363
+	 * @throws DomainException
1364
+	 * @throws EE_Error
1365
+	 * @throws InvalidArgumentException
1366
+	 * @throws ReflectionException
1367
+	 * @throws InvalidDataTypeException
1368
+	 * @throws InvalidInterfaceException
1369
+	 */
1370
+	protected function _edit_message_template()
1371
+	{
1372
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1373
+		$template_fields = '';
1374
+		$sidebar_fields  = '';
1375
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1376
+		// valid html in the templates.
1377
+		add_filter('tiny_mce_before_init', [$this, 'filter_tinymce_init'], 10, 2);
1378
+
1379
+		$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
1380
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
1381
+
1382
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1383
+		$message_template_group = $this->_message_template_group;
1384
+		$c_label                = $message_template_group->context_label();
1385
+		$c_config               = $message_template_group->contexts_config();
1386
+
1387
+		reset($c_config);
1388
+		$context = $this->request->getRequestParam('context', key($c_config));
1389
+		$context = strtolower($context);
1390
+
1391
+		$action = empty($GRP_ID) ? 'insert_message_template' : 'update_message_template';
1392
+
1393
+		$edit_message_template_form_url = add_query_arg(
1394
+			['action' => $action, 'noheader' => true],
1395
+			EE_MSG_ADMIN_URL
1396
+		);
1397
+
1398
+		// set active messenger for this view
1399
+		$this->_active_messenger         = $this->_message_resource_manager->get_active_messenger(
1400
+			$message_template_group->messenger()
1401
+		);
1402
+		$this->_active_message_type_name = $message_template_group->message_type();
1403
+
1404
+
1405
+		// Do we have any validation errors?
1406
+		$validators = $this->_get_transient();
1407
+		$v_fields   = ! empty($validators) ? array_keys($validators) : [];
1408
+
1409
+
1410
+		// we need to assemble the title from Various details
1411
+		$context_label = sprintf(
1412
+			esc_html__('(%s %s)', 'event_espresso'),
1413
+			$c_config[ $context ]['label'],
1414
+			ucwords($c_label['label'])
1415
+		);
1416
+
1417
+		$title = sprintf(
1418
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1419
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1420
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1421
+			$context_label
1422
+		);
1423
+
1424
+		$this->_template_args['GRP_ID']           = $GRP_ID;
1425
+		$this->_template_args['message_template'] = $message_template_group;
1426
+		$this->_template_args['is_extra_fields']  = false;
1427
+
1428
+
1429
+		// let's get EEH_MSG_Template so we can get template form fields
1430
+		$template_field_structure = EEH_MSG_Template::get_fields(
1431
+			$message_template_group->messenger(),
1432
+			$message_template_group->message_type()
1433
+		);
1434
+
1435
+		if (! $template_field_structure) {
1436
+			$template_field_structure = false;
1437
+			$template_fields          = esc_html__(
1438
+				'There was an error in assembling the fields for this display (you should see an error message)',
1439
+				'event_espresso'
1440
+			);
1441
+		}
1442
+
1443
+
1444
+		$message_templates = $message_template_group->context_templates();
1445
+
1446
+
1447
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1448
+		// will get handled in the "extra" array.
1449
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1450
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1451
+				unset($template_field_structure[ $context ][ $reference_field ]);
1452
+			}
1453
+		}
1454
+
1455
+		// let's loop through the template_field_structure and actually assemble the input fields!
1456
+		if (! empty($template_field_structure)) {
1457
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1458
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1459
+				// the extra array and reset them.
1460
+				if ($template_field === 'extra') {
1461
+					$this->_template_args['is_extra_fields'] = true;
1462
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1463
+						$message_template = $message_templates[ $context ][ $reference_field ];
1464
+						$content          = $message_template instanceof EE_Message_Template
1465
+							? $message_template->get('MTP_content')
1466
+							: '';
1467
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1468
+							// let's verify if we need this extra field via the shortcodes parameter.
1469
+							$continue = false;
1470
+							if (isset($extra_array['shortcodes_required'])) {
1471
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1472
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1473
+										$continue = true;
1474
+									}
1475
+								}
1476
+								if ($continue) {
1477
+									continue;
1478
+								}
1479
+							}
1480
+
1481
+							$field_id = $reference_field . '-' . $extra_field . '-content';
1482
+
1483
+							$template_form_fields[ $field_id ]         = $extra_array;
1484
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1485
+																		 . $reference_field
1486
+																		 . '][content]['
1487
+																		 . $extra_field . ']';
1488
+							$css_class                                 = isset($extra_array['css_class'])
1489
+								? $extra_array['css_class']
1490
+								: '';
1491
+
1492
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1493
+																			  && in_array($extra_field, $v_fields, true)
1494
+																			  && (
1495
+																				  is_array($validators[ $extra_field ])
1496
+																				  && isset($validators[ $extra_field ]['msg'])
1497
+																			  )
1498
+								? 'validate-error ' . $css_class
1499
+								: $css_class;
1500
+
1501
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1502
+																		  && isset($content[ $extra_field ])
1503
+								? $content[ $extra_field ]
1504
+								: '';
1505
+
1506
+							// do we have a validation error?  if we do then let's use that value instead
1507
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1508
+								? $validators[ $extra_field ]['value']
1509
+								: $template_form_fields[ $field_id ]['value'];
1510
+
1511
+
1512
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1513
+
1514
+							// shortcode selector
1515
+							$field_name_to_use                                   = $extra_field === 'main'
1516
+								? 'content'
1517
+								: $extra_field;
1518
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1519
+								$field_name_to_use,
1520
+								$field_id
1521
+							);
1522
+						}
1523
+						$template_field_MTP_id           = $reference_field . '-MTP_ID';
1524
+						$template_field_template_name_id = $reference_field . '-name';
1525
+
1526
+						$template_form_fields[ $template_field_MTP_id ] = [
1527
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1528
+							'label'      => null,
1529
+							'input'      => 'hidden',
1530
+							'type'       => 'int',
1531
+							'required'   => false,
1532
+							'validation' => false,
1533
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1534
+							'css_class'  => '',
1535
+							'format'     => '%d',
1536
+							'db-col'     => 'MTP_ID',
1537
+						];
1538
+
1539
+						$template_form_fields[ $template_field_template_name_id ] = [
1540
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1541
+							'label'      => null,
1542
+							'input'      => 'hidden',
1543
+							'type'       => 'string',
1544
+							'required'   => false,
1545
+							'validation' => true,
1546
+							'value'      => $reference_field,
1547
+							'css_class'  => '',
1548
+							'format'     => '%s',
1549
+							'db-col'     => 'MTP_template_field',
1550
+						];
1551
+					}
1552
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1553
+				} else {
1554
+					$field_id                                   = $template_field . '-content';
1555
+					$template_form_fields[ $field_id ]          = $field_setup_array;
1556
+					$template_form_fields[ $field_id ]['name']  =
1557
+						'MTP_template_fields[' . $template_field . '][content]';
1558
+					$message_template                           =
1559
+						isset($message_templates[ $context ][ $template_field ])
1560
+							? $message_templates[ $context ][ $template_field ]
1561
+							: null;
1562
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1563
+																  && is_array($message_templates[ $context ])
1564
+																  && $message_template instanceof EE_Message_Template
1565
+						? $message_template->get('MTP_content')
1566
+						: '';
1567
+
1568
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1569
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1570
+						? $validators[ $template_field ]['value']
1571
+						: $template_form_fields[ $field_id ]['value'];
1572
+
1573
+
1574
+					$template_form_fields[ $field_id ]['db-col']    = 'MTP_content';
1575
+					$css_class                                      = isset($field_setup_array['css_class'])
1576
+						? $field_setup_array['css_class']
1577
+						: '';
1578
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1579
+																	  && in_array($template_field, $v_fields, true)
1580
+																	  && isset($validators[ $template_field ]['msg'])
1581
+						? 'validate-error ' . $css_class
1582
+						: $css_class;
1583
+
1584
+					// shortcode selector
1585
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1586
+						$template_field,
1587
+						$field_id
1588
+					);
1589
+				}
1590
+
1591
+				// k took care of content field(s) now let's take care of others.
1592
+
1593
+				$template_field_MTP_id                 = $template_field . '-MTP_ID';
1594
+				$template_field_field_template_name_id = $template_field . '-name';
1595
+
1596
+				// foreach template field there are actually two form fields created
1597
+				$template_form_fields[ $template_field_MTP_id ] = [
1598
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1599
+					'label'      => null,
1600
+					'input'      => 'hidden',
1601
+					'type'       => 'int',
1602
+					'required'   => false,
1603
+					'validation' => true,
1604
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1605
+					'css_class'  => '',
1606
+					'format'     => '%d',
1607
+					'db-col'     => 'MTP_ID',
1608
+				];
1609
+
1610
+				$template_form_fields[ $template_field_field_template_name_id ] = [
1611
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1612
+					'label'      => null,
1613
+					'input'      => 'hidden',
1614
+					'type'       => 'string',
1615
+					'required'   => false,
1616
+					'validation' => true,
1617
+					'value'      => $template_field,
1618
+					'css_class'  => '',
1619
+					'format'     => '%s',
1620
+					'db-col'     => 'MTP_template_field',
1621
+				];
1622
+			}
1623
+
1624
+			// add other fields
1625
+			$template_form_fields['ee-msg-current-context'] = [
1626
+				'name'       => 'MTP_context',
1627
+				'label'      => null,
1628
+				'input'      => 'hidden',
1629
+				'type'       => 'string',
1630
+				'required'   => false,
1631
+				'validation' => true,
1632
+				'value'      => $context,
1633
+				'css_class'  => '',
1634
+				'format'     => '%s',
1635
+				'db-col'     => 'MTP_context',
1636
+			];
1637
+
1638
+			$template_form_fields['ee-msg-grp-id'] = [
1639
+				'name'       => 'GRP_ID',
1640
+				'label'      => null,
1641
+				'input'      => 'hidden',
1642
+				'type'       => 'int',
1643
+				'required'   => false,
1644
+				'validation' => true,
1645
+				'value'      => $GRP_ID,
1646
+				'css_class'  => '',
1647
+				'format'     => '%d',
1648
+				'db-col'     => 'GRP_ID',
1649
+			];
1650
+
1651
+			$template_form_fields['ee-msg-messenger'] = [
1652
+				'name'       => 'MTP_messenger',
1653
+				'label'      => null,
1654
+				'input'      => 'hidden',
1655
+				'type'       => 'string',
1656
+				'required'   => false,
1657
+				'validation' => true,
1658
+				'value'      => $message_template_group->messenger(),
1659
+				'css_class'  => '',
1660
+				'format'     => '%s',
1661
+				'db-col'     => 'MTP_messenger',
1662
+			];
1663
+
1664
+			$template_form_fields['ee-msg-message-type'] = [
1665
+				'name'       => 'MTP_message_type',
1666
+				'label'      => null,
1667
+				'input'      => 'hidden',
1668
+				'type'       => 'string',
1669
+				'required'   => false,
1670
+				'validation' => true,
1671
+				'value'      => $message_template_group->message_type(),
1672
+				'css_class'  => '',
1673
+				'format'     => '%s',
1674
+				'db-col'     => 'MTP_message_type',
1675
+			];
1676
+
1677
+			$sidebar_form_fields['ee-msg-is-global'] = [
1678
+				'name'       => 'MTP_is_global',
1679
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1680
+				'input'      => 'hidden',
1681
+				'type'       => 'int',
1682
+				'required'   => false,
1683
+				'validation' => true,
1684
+				'value'      => $message_template_group->get('MTP_is_global'),
1685
+				'css_class'  => '',
1686
+				'format'     => '%d',
1687
+				'db-col'     => 'MTP_is_global',
1688
+			];
1689
+
1690
+			$sidebar_form_fields['ee-msg-is-override'] = [
1691
+				'name'       => 'MTP_is_override',
1692
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1693
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1694
+				'type'       => 'int',
1695
+				'required'   => false,
1696
+				'validation' => true,
1697
+				'value'      => $message_template_group->get('MTP_is_override'),
1698
+				'css_class'  => '',
1699
+				'format'     => '%d',
1700
+				'db-col'     => 'MTP_is_override',
1701
+			];
1702
+
1703
+			$sidebar_form_fields['ee-msg-is-active'] = [
1704
+				'name'       => 'MTP_is_active',
1705
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1706
+				'input'      => 'hidden',
1707
+				'type'       => 'int',
1708
+				'required'   => false,
1709
+				'validation' => true,
1710
+				'value'      => $message_template_group->is_active(),
1711
+				'css_class'  => '',
1712
+				'format'     => '%d',
1713
+				'db-col'     => 'MTP_is_active',
1714
+			];
1715
+
1716
+			$sidebar_form_fields['ee-msg-deleted'] = [
1717
+				'name'       => 'MTP_deleted',
1718
+				'label'      => null,
1719
+				'input'      => 'hidden',
1720
+				'type'       => 'int',
1721
+				'required'   => false,
1722
+				'validation' => true,
1723
+				'value'      => $message_template_group->get('MTP_deleted'),
1724
+				'css_class'  => '',
1725
+				'format'     => '%d',
1726
+				'db-col'     => 'MTP_deleted',
1727
+			];
1728
+			$sidebar_form_fields['ee-msg-author']  = [
1729
+				'name'       => 'MTP_user_id',
1730
+				'label'      => esc_html__('Author', 'event_espresso'),
1731
+				'input'      => 'hidden',
1732
+				'type'       => 'int',
1733
+				'required'   => false,
1734
+				'validation' => false,
1735
+				'value'      => $message_template_group->user(),
1736
+				'format'     => '%d',
1737
+				'db-col'     => 'MTP_user_id',
1738
+			];
1739
+
1740
+			$sidebar_form_fields['ee-msg-route'] = [
1741
+				'name'  => 'action',
1742
+				'input' => 'hidden',
1743
+				'type'  => 'string',
1744
+				'value' => $action,
1745
+			];
1746
+
1747
+			$sidebar_form_fields['ee-msg-id']        = [
1748
+				'name'  => 'id',
1749
+				'input' => 'hidden',
1750
+				'type'  => 'int',
1751
+				'value' => $GRP_ID,
1752
+			];
1753
+			$sidebar_form_fields['ee-msg-evt-nonce'] = [
1754
+				'name'  => $action . '_nonce',
1755
+				'input' => 'hidden',
1756
+				'type'  => 'string',
1757
+				'value' => wp_create_nonce($action . '_nonce'),
1758
+			];
1759
+
1760
+			$template_switch = $this->request->getRequestParam('template_switch');
1761
+			if ($template_switch) {
1762
+				$sidebar_form_fields['ee-msg-template-switch'] = [
1763
+					'name'  => 'template_switch',
1764
+					'input' => 'hidden',
1765
+					'type'  => 'int',
1766
+					'value' => 1,
1767
+				];
1768
+			}
1769
+
1770
+
1771
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1772
+			$sidebar_fields  = $this->_generate_admin_form_fields($sidebar_form_fields);
1773
+		} //end if ( !empty($template_field_structure) )
1774
+
1775
+		// set extra content for publish box
1776
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1777
+		$this->_set_publish_post_box_vars(
1778
+			'id',
1779
+			$GRP_ID,
1780
+			'',
1781
+			add_query_arg(
1782
+				['action' => $message_template_group->is_global() ? 'global_mtps' : 'custom_mtps'],
1783
+				$this->_admin_base_url
1784
+			),
1785
+			true
1786
+		);
1787
+
1788
+		// add preview button
1789
+		$preview_url    = parent::add_query_args_and_nonce(
1790
+			[
1791
+				'message_type' => $message_template_group->message_type(),
1792
+				'messenger'    => $message_template_group->messenger(),
1793
+				'context'      => $context,
1794
+				'GRP_ID'       => $GRP_ID,
1795
+				'evt_id'       => $EVT_ID ?: false,
1796
+				'action'       => 'preview_message',
1797
+			],
1798
+			$this->_admin_base_url
1799
+		);
1800
+		$preview_button = '<a href="' . $preview_url . '" class="button--secondary messages-preview-button">'
1801
+						  . esc_html__('Preview', 'event_espresso')
1802
+						  . '</a>';
1803
+
1804
+
1805
+		// setup context switcher
1806
+		$this->_set_context_switcher(
1807
+			$message_template_group,
1808
+			[
1809
+				'page'    => 'espresso_messages',
1810
+				'action'  => 'edit_message_template',
1811
+				'id'      => $GRP_ID,
1812
+				'evt_id'  => $EVT_ID,
1813
+				'context' => $context,
1814
+				'extra'   => $preview_button,
1815
+			]
1816
+		);
1817
+
1818
+
1819
+		// main box
1820
+		$this->_template_args['template_fields']                         = $template_fields;
1821
+		$this->_template_args['sidebar_box_id']                          = 'details';
1822
+		$this->_template_args['action']                                  = $action;
1823
+		$this->_template_args['context']                                 = $context;
1824
+		$this->_template_args['edit_message_template_form_url']          = $edit_message_template_form_url;
1825
+		$this->_template_args['learn_more_about_message_templates_link'] =
1826
+			$this->_learn_more_about_message_templates_link();
1827
+
1828
+
1829
+		$this->_template_args['before_admin_page_content'] = '<div class="ee-msg-admin-header">';
1830
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1831
+			$message_template_group,
1832
+			$context,
1833
+			$context_label
1834
+		);
1835
+		$this->_template_args['before_admin_page_content'] .= $this->add_context_switcher();
1836
+		$this->_template_args['before_admin_page_content'] .= '</div>';
1837
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1838
+		$this->_template_args['after_admin_page_content']  = $this->_add_form_element_after();
1839
+
1840
+		$this->_template_path = $this->_template_args['GRP_ID']
1841
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1842
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1843
+
1844
+		// send along EE_Message_Template_Group object for further template use.
1845
+		$this->_template_args['MTP'] = $message_template_group;
1846
+
1847
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1848
+			$this->_template_path,
1849
+			$this->_template_args,
1850
+			true
1851
+		);
1852
+
1853
+
1854
+		// finally, let's set the admin_page title
1855
+		$this->_admin_page_title = sprintf(esc_html__('Editing %s', 'event_espresso'), $title);
1856
+
1857
+
1858
+		// we need to take care of setting the shortcodes property for use elsewhere.
1859
+		$this->_set_shortcodes();
1860
+
1861
+
1862
+		// final template wrapper
1863
+		$this->display_admin_page_with_sidebar();
1864
+	}
1865
+
1866
+
1867
+	public function filter_tinymce_init($mceInit, $editor_id)
1868
+	{
1869
+		return $mceInit;
1870
+	}
1871
+
1872
+
1873
+	public function add_context_switcher()
1874
+	{
1875
+		return $this->_context_switcher;
1876
+	}
1877
+
1878
+
1879
+	/**
1880
+	 * Adds the activation/deactivation toggle for the message template context.
1881
+	 *
1882
+	 * @param EE_Message_Template_Group $message_template_group
1883
+	 * @param string                    $context
1884
+	 * @param string                    $context_label
1885
+	 * @return string
1886
+	 * @throws DomainException
1887
+	 * @throws EE_Error
1888
+	 * @throws InvalidIdentifierException
1889
+	 * @throws ReflectionException
1890
+	 */
1891
+	protected function add_active_context_element(
1892
+		EE_Message_Template_Group $message_template_group,
1893
+		$context,
1894
+		$context_label
1895
+	) {
1896
+		$template_args = [
1897
+			'context'                   => $context,
1898
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1899
+			'is_active'                 => $message_template_group->is_context_active($context),
1900
+			'on_off_action'             => $message_template_group->is_context_active($context)
1901
+				? 'context-off'
1902
+				: 'context-on',
1903
+			'context_label'             => str_replace(['(', ')'], '', $context_label),
1904
+			'message_template_group_id' => $message_template_group->ID(),
1905
+		];
1906
+		return EEH_Template::display_template(
1907
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1908
+			$template_args,
1909
+			true
1910
+		);
1911
+	}
1912
+
1913
+
1914
+	/**
1915
+	 * Ajax callback for `toggle_context_template` ajax action.
1916
+	 * Handles toggling the message context on or off.
1917
+	 *
1918
+	 * @throws EE_Error
1919
+	 * @throws InvalidArgumentException
1920
+	 * @throws InvalidDataTypeException
1921
+	 * @throws InvalidIdentifierException
1922
+	 * @throws InvalidInterfaceException
1923
+	 */
1924
+	public function toggle_context_template()
1925
+	{
1926
+		$success = true;
1927
+		// check for required data
1928
+		if (
1929
+			! (
1930
+				$this->request->requestParamIsSet('message_template_group_id')
1931
+				&& $this->request->requestParamIsSet('context')
1932
+				&& $this->request->requestParamIsSet('status')
1933
+			)
1934
+		) {
1935
+			EE_Error::add_error(
1936
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1937
+				__FILE__,
1938
+				__FUNCTION__,
1939
+				__LINE__
1940
+			);
1941
+			$success = false;
1942
+		}
1943
+
1944
+		$nonce   = $this->request->getRequestParam('toggle_context_nonce', '');
1945
+		$context = $this->request->getRequestParam('context', '');
1946
+		$status  = $this->request->getRequestParam('status', '');
1947
+
1948
+		$this->_verify_nonce($nonce, "activate_{$context}_toggle_nonce");
1949
+
1950
+		if ($status !== 'off' && $status !== 'on') {
1951
+			EE_Error::add_error(
1952
+				sprintf(
1953
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1954
+					$status
1955
+				),
1956
+				__FILE__,
1957
+				__FUNCTION__,
1958
+				__LINE__
1959
+			);
1960
+			$success = false;
1961
+		}
1962
+		$message_template_group_id = $this->request->getRequestParam('message_template_group_id', 0, 'int');
1963
+		$message_template_group    = $this->getMtgModel()->get_one_by_ID($message_template_group_id);
1964
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1965
+			EE_Error::add_error(
1966
+				sprintf(
1967
+					esc_html__(
1968
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1969
+						'event_espresso'
1970
+					),
1971
+					$message_template_group_id,
1972
+					'EE_Message_Template_Group'
1973
+				),
1974
+				__FILE__,
1975
+				__FUNCTION__,
1976
+				__LINE__
1977
+			);
1978
+			$success = false;
1979
+		}
1980
+		if ($success) {
1981
+			$success = $status === 'off'
1982
+				? $message_template_group->deactivate_context($context)
1983
+				: $message_template_group->activate_context($context);
1984
+		}
1985
+		$this->_template_args['success'] = $success;
1986
+		$this->_return_json();
1987
+	}
1988
+
1989
+
1990
+	public function _add_form_element_before()
1991
+	{
1992
+		return '<form method="post" action="'
1993
+			   . $this->_template_args['edit_message_template_form_url']
1994
+			   . '" id="ee-msg-edit-frm">';
1995
+	}
1996
+
1997
+
1998
+	public function _add_form_element_after()
1999
+	{
2000
+		return '</form>';
2001
+	}
2002
+
2003
+
2004
+	/**
2005
+	 * This executes switching the template pack for a message template.
2006
+	 *
2007
+	 * @throws EE_Error
2008
+	 * @throws InvalidDataTypeException
2009
+	 * @throws InvalidInterfaceException
2010
+	 * @throws InvalidArgumentException
2011
+	 * @throws ReflectionException
2012
+	 * @since 4.5.0
2013
+	 */
2014
+	public function switch_template_pack()
2015
+	{
2016
+
2017
+		$GRP_ID        = $this->request->getRequestParam('GRP_ID', 0, 'int');
2018
+		$template_pack = $this->request->getRequestParam('template_pack', '');
2019
+
2020
+		// verify we have needed values.
2021
+		if (empty($GRP_ID) || empty($template_pack)) {
2022
+			$this->_template_args['error'] = true;
2023
+			EE_Error::add_error(
2024
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
2025
+				__FILE__,
2026
+				__FUNCTION__,
2027
+				__LINE__
2028
+			);
2029
+		} else {
2030
+			// get template, set the new template_pack and then reset to default
2031
+			/** @var EE_Message_Template_Group $message_template_group */
2032
+			$message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
2033
+
2034
+			$message_template_group->set_template_pack_name($template_pack);
2035
+			$this->request->setRequestParam('msgr', $message_template_group->messenger());
2036
+			$this->request->setRequestParam('mt', $message_template_group->message_type());
2037
+
2038
+			$query_args = $this->_reset_to_default_template();
2039
+
2040
+			if (empty($query_args['id'])) {
2041
+				EE_Error::add_error(
2042
+					esc_html__(
2043
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
2044
+						'event_espresso'
2045
+					),
2046
+					__FILE__,
2047
+					__FUNCTION__,
2048
+					__LINE__
2049
+				);
2050
+				$this->_template_args['error'] = true;
2051
+			} else {
2052
+				$template_label       = $message_template_group->get_template_pack()->label;
2053
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2054
+				EE_Error::add_success(
2055
+					sprintf(
2056
+						esc_html__(
2057
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2058
+							'event_espresso'
2059
+						),
2060
+						$template_label,
2061
+						$template_pack_labels->template_pack
2062
+					)
2063
+				);
2064
+				// generate the redirect url for js.
2065
+				$url = self::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2066
+
2067
+				$this->_template_args['data']['redirect_url'] = $url;
2068
+				$this->_template_args['success']              = true;
2069
+			}
2070
+
2071
+			$this->_return_json();
2072
+		}
2073
+	}
2074
+
2075
+
2076
+	/**
2077
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2078
+	 * they want.
2079
+	 *
2080
+	 * @access protected
2081
+	 * @return array|void
2082
+	 * @throws EE_Error
2083
+	 * @throws InvalidArgumentException
2084
+	 * @throws InvalidDataTypeException
2085
+	 * @throws InvalidInterfaceException
2086
+	 * @throws ReflectionException
2087
+	 */
2088
+	protected function _reset_to_default_template()
2089
+	{
2090
+		$templates    = [];
2091
+		$GRP_ID       = $this->request->getRequestParam('GRP_ID', 0, 'int');
2092
+		$messenger    = $this->request->getRequestParam('msgr');
2093
+		$message_type = $this->request->getRequestParam('mt');
2094
+		// we need to make sure we've got the info we need.
2095
+		if (! ($GRP_ID && $messenger && $message_type)) {
2096
+			EE_Error::add_error(
2097
+				esc_html__(
2098
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2099
+					'event_espresso'
2100
+				),
2101
+				__FILE__,
2102
+				__FUNCTION__,
2103
+				__LINE__
2104
+			);
2105
+		}
2106
+
2107
+		// all templates will be reset to whatever the defaults are
2108
+		// for the global template matching the messenger and message type.
2109
+		$success = ! empty($GRP_ID);
2110
+
2111
+		if ($success) {
2112
+			// let's first determine if the incoming template is a global template,
2113
+			// if it isn't then we need to get the global template matching messenger and message type.
2114
+			// $MTPG = $this->getMtgModel()->get_one_by_ID( $GRP_ID );
2115
+
2116
+
2117
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2118
+			$success = $this->_delete_mtp_permanently($GRP_ID, false);
2119
+
2120
+			if ($success) {
2121
+				// if successfully deleted, lets generate the new ones.
2122
+				// Note. We set GLOBAL to true, because resets on ANY template
2123
+				// will use the related global template defaults for regeneration.
2124
+				// This means that if a custom template is reset it resets to whatever the related global template is.
2125
+				// HOWEVER, we DO keep the template pack and template variation set
2126
+				// for the current custom template when resetting.
2127
+				$templates = $this->_generate_new_templates($messenger, $message_type, $GRP_ID, true);
2128
+			}
2129
+		}
2130
+
2131
+		// any error messages?
2132
+		if (! $success) {
2133
+			EE_Error::add_error(
2134
+				esc_html__(
2135
+					'Something went wrong with deleting existing templates. Unable to reset to default',
2136
+					'event_espresso'
2137
+				),
2138
+				__FILE__,
2139
+				__FUNCTION__,
2140
+				__LINE__
2141
+			);
2142
+		}
2143
+
2144
+		// all good, let's add a success message!
2145
+		if ($success && ! empty($templates)) {
2146
+			// the info for the template we generated is the first element in the returned array
2147
+			EE_Error::overwrite_success();
2148
+			EE_Error::add_success(esc_html__('Templates have been reset to defaults.', 'event_espresso'));
2149
+		}
2150
+
2151
+
2152
+		$query_args = [
2153
+			'id'      => isset($templates['GRP_ID']) ? $templates['GRP_ID'] : null,
2154
+			'context' => isset($templates['MTP_context']) ? $templates['MTP_context'] : null,
2155
+			'action'  => isset($templates['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2156
+		];
2157
+
2158
+		// if called via ajax then we return query args otherwise redirect
2159
+		if ($this->request->isAjax()) {
2160
+			return $query_args;
2161
+		}
2162
+		$this->_redirect_after_action(false, '', '', $query_args, true);
2163
+	}
2164
+
2165
+
2166
+	/**
2167
+	 * Retrieve and set the message preview for display.
2168
+	 *
2169
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2170
+	 * @return string
2171
+	 * @throws ReflectionException
2172
+	 * @throws EE_Error
2173
+	 * @throws InvalidArgumentException
2174
+	 * @throws InvalidDataTypeException
2175
+	 * @throws InvalidInterfaceException
2176
+	 */
2177
+	public function _preview_message($send = false)
2178
+	{
2179
+		// first make sure we've got the necessary parameters
2180
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2181
+		if (! ($GRP_ID && $this->_active_messenger_name && $this->_active_message_type_name)) {
2182
+			EE_Error::add_error(
2183
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2184
+				__FILE__,
2185
+				__FUNCTION__,
2186
+				__LINE__
2187
+			);
2188
+		}
2189
+
2190
+		$context = $this->request->getRequestParam('context');
2191
+		// get the preview!
2192
+		$preview = EED_Messages::preview_message(
2193
+			$this->_active_message_type_name,
2194
+			$context,
2195
+			$this->_active_messenger_name,
2196
+			$send
2197
+		);
2198
+
2199
+		if ($send) {
2200
+			return $preview;
2201
+		}
2202
+
2203
+		// if we have an evt_id set on the request, use it.
2204
+		$EVT_ID = $this->request->getRequestParam('evt_id', 0, 'int');
2205
+
2206
+		// let's add a button to go back to the edit view
2207
+		$query_args             = [
2208
+			'id'      => $GRP_ID,
2209
+			'evt_id'  => $EVT_ID,
2210
+			'context' => $context,
2211
+			'action'  => 'edit_message_template',
2212
+		];
2213
+		$go_back_url            = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2214
+		$preview_button         = '<a href="'
2215
+								  . $go_back_url
2216
+								  . '" class="button--secondary messages-preview-go-back-button">'
2217
+								  . esc_html__('Go Back to Edit', 'event_espresso')
2218
+								  . '</a>';
2219
+		$message_types          = $this->get_installed_message_types();
2220
+		$active_messenger       = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
2221
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2222
+			? ucwords($active_messenger->label['singular'])
2223
+			: esc_html__('Unknown Messenger', 'event_espresso');
2224
+		// let's provide a helpful title for context
2225
+		$preview_title = sprintf(
2226
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2227
+			$active_messenger_label,
2228
+			ucwords($message_types[ $this->_active_message_type_name ]->label['singular'])
2229
+		);
2230
+		if (empty($preview)) {
2231
+			$this->noEventsErrorMessage();
2232
+		}
2233
+		// setup display of preview.
2234
+		$this->_admin_page_title                    = $preview_title;
2235
+		$this->_template_args['admin_page_title']   = $preview_title;
2236
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2237
+		$this->_template_args['data']['force_json'] = true;
2238
+
2239
+		return '';
2240
+	}
2241
+
2242
+
2243
+	/**
2244
+	 * Used to set an error if there are no events available for generating a preview/test send.
2245
+	 *
2246
+	 * @param bool $test_send Whether the error should be generated for the context of a test send.
2247
+	 */
2248
+	protected function noEventsErrorMessage($test_send = false)
2249
+	{
2250
+		$events_url = parent::add_query_args_and_nonce(
2251
+			[
2252
+				'action' => 'default',
2253
+				'page'   => 'espresso_events',
2254
+			],
2255
+			admin_url('admin.php')
2256
+		);
2257
+		$message    = $test_send
2258
+			? esc_html__(
2259
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2260
+				'event_espresso'
2261
+			)
2262
+			: esc_html__(
2263
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2264
+				'event_espresso'
2265
+			);
2266
+
2267
+		EE_Error::add_attention(
2268
+			sprintf(
2269
+				$message,
2270
+				"<a href='{$events_url}'>",
2271
+				'</a>'
2272
+			)
2273
+		);
2274
+	}
2275
+
2276
+
2277
+	/**
2278
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2279
+	 * gets called automatically.
2280
+	 *
2281
+	 * @return void
2282
+	 * @throws EE_Error
2283
+	 * @since 4.5.0
2284
+	 *
2285
+	 */
2286
+	protected function _display_preview_message()
2287
+	{
2288
+		$this->display_admin_page_with_no_sidebar();
2289
+	}
2290
+
2291
+
2292
+	/**
2293
+	 * registers metaboxes that should show up on the "edit_message_template" page
2294
+	 *
2295
+	 * @access protected
2296
+	 * @return void
2297
+	 */
2298
+	protected function _register_edit_meta_boxes()
2299
+	{
2300
+		$this->addMetaBox(
2301
+			'mtp_valid_shortcodes',
2302
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2303
+			[$this, 'shortcode_meta_box'],
2304
+			$this->_current_screen->id,
2305
+			'side'
2306
+		);
2307
+		$this->addMetaBox(
2308
+			'mtp_extra_actions',
2309
+			esc_html__('Extra Actions', 'event_espresso'),
2310
+			[$this, 'extra_actions_meta_box'],
2311
+			$this->_current_screen->id,
2312
+			'side',
2313
+			'high'
2314
+		);
2315
+		$this->addMetaBox(
2316
+			'mtp_templates',
2317
+			esc_html__('Template Styles', 'event_espresso'),
2318
+			[$this, 'template_pack_meta_box'],
2319
+			$this->_current_screen->id,
2320
+			'side',
2321
+			'high'
2322
+		);
2323
+	}
2324
+
2325
+
2326
+	/**
2327
+	 * metabox content for all template pack and variation selection.
2328
+	 *
2329
+	 * @return void
2330
+	 * @throws DomainException
2331
+	 * @throws EE_Error
2332
+	 * @throws InvalidArgumentException
2333
+	 * @throws ReflectionException
2334
+	 * @throws InvalidDataTypeException
2335
+	 * @throws InvalidInterfaceException
2336
+	 * @since 4.5.0
2337
+	 */
2338
+	public function template_pack_meta_box()
2339
+	{
2340
+		$this->_set_message_template_group();
2341
+
2342
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2343
+
2344
+		$tp_select_values = [];
2345
+
2346
+		foreach ($tp_collection as $tp) {
2347
+			// only include template packs that support this messenger and message type!
2348
+			$supports = $tp->get_supports();
2349
+			if (
2350
+				! isset($supports[ $this->_message_template_group->messenger() ])
2351
+				|| ! in_array(
2352
+					$this->_message_template_group->message_type(),
2353
+					$supports[ $this->_message_template_group->messenger() ],
2354
+					true
2355
+				)
2356
+			) {
2357
+				// not supported
2358
+				continue;
2359
+			}
2360
+
2361
+			$tp_select_values[] = [
2362
+				'text' => $tp->label,
2363
+				'id'   => $tp->dbref,
2364
+			];
2365
+		}
2366
+
2367
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2368
+		// the default template pack.  This still allows for the odd template pack to override.
2369
+		if (empty($tp_select_values)) {
2370
+			$tp_select_values[] = [
2371
+				'text' => esc_html__('Default', 'event_espresso'),
2372
+				'id'   => 'default',
2373
+			];
2374
+		}
2375
+
2376
+		// setup variation select values for the currently selected template.
2377
+		$variations               = $this->_message_template_group->get_template_pack()->get_variations(
2378
+			$this->_message_template_group->messenger(),
2379
+			$this->_message_template_group->message_type()
2380
+		);
2381
+		$variations_select_values = [];
2382
+		foreach ($variations as $variation => $label) {
2383
+			$variations_select_values[] = [
2384
+				'text' => $label,
2385
+				'id'   => $variation,
2386
+			];
2387
+		}
2388
+
2389
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2390
+
2391
+		$template_args['template_packs_selector']        = EEH_Form_Fields::select_input(
2392
+			'MTP_template_pack',
2393
+			$tp_select_values,
2394
+			$this->_message_template_group->get_template_pack_name()
2395
+		);
2396
+		$template_args['variations_selector']            = EEH_Form_Fields::select_input(
2397
+			'MTP_template_variation',
2398
+			$variations_select_values,
2399
+			$this->_message_template_group->get_template_pack_variation()
2400
+		);
2401
+		$template_args['template_pack_label']            = $template_pack_labels->template_pack;
2402
+		$template_args['template_variation_label']       = $template_pack_labels->template_variation;
2403
+		$template_args['template_pack_description']      = $template_pack_labels->template_pack_description;
2404
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2405
+
2406
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2407
+
2408
+		EEH_Template::display_template($template, $template_args);
2409
+	}
2410
+
2411
+
2412
+	/**
2413
+	 * This meta box holds any extra actions related to Message Templates
2414
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2415
+	 *
2416
+	 * @access  public
2417
+	 * @return void
2418
+	 * @throws EE_Error
2419
+	 */
2420
+	public function extra_actions_meta_box()
2421
+	{
2422
+		$template_form_fields = [];
2423
+
2424
+		$extra_args = [
2425
+			'msgr'   => $this->_message_template_group->messenger(),
2426
+			'mt'     => $this->_message_template_group->message_type(),
2427
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2428
+		];
2429
+		// first we need to see if there are any fields
2430
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2431
+
2432
+		if (! empty($fields)) {
2433
+			// yup there be fields
2434
+			foreach ($fields as $field => $config) {
2435
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2436
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2437
+				$default  = isset($config['default']) ? $config['default'] : '';
2438
+				$default  = isset($config['value']) ? $config['value'] : $default;
2439
+
2440
+				// if type is hidden and the value is empty
2441
+				// something may have gone wrong so let's correct with the defaults
2442
+				$fix                = $config['input'] === 'hidden'
2443
+									  && isset($existing[ $field ])
2444
+									  && empty($existing[ $field ])
2445
+					? $default
2446
+					: '';
2447
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2448
+					? $existing[ $field ]
2449
+					: $fix;
2450
+
2451
+				$template_form_fields[ $field_id ] = [
2452
+					'name'       => 'test_settings_fld[' . $field . ']',
2453
+					'label'      => $config['label'],
2454
+					'input'      => $config['input'],
2455
+					'type'       => $config['type'],
2456
+					'required'   => $config['required'],
2457
+					'validation' => $config['validation'],
2458
+					'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2459
+					'css_class'  => $config['css_class'],
2460
+					'options'    => isset($config['options']) ? $config['options'] : [],
2461
+					'default'    => $default,
2462
+					'format'     => $config['format'],
2463
+				];
2464
+			}
2465
+		}
2466
+
2467
+		$test_settings_html = ! empty($template_form_fields)
2468
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2469
+			: '';
2470
+
2471
+		// print out $test_settings_fields
2472
+		if (! empty($test_settings_html)) {
2473
+			$test_settings_html .= '<input type="submit" class="button--primary mtp-test-button alignright" ';
2474
+			$test_settings_html .= 'name="test_button" value="';
2475
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2476
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2477
+		}
2478
+
2479
+		// and button
2480
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2481
+		$test_settings_html .= '<p>';
2482
+		$test_settings_html .= esc_html__('Need to reset this message type and start over?', 'event_espresso');
2483
+		$test_settings_html .= '</p>';
2484
+		$test_settings_html .= $this->get_action_link_or_button(
2485
+			'reset_to_default',
2486
+			'reset',
2487
+			$extra_args,
2488
+			'button--primary reset-default-button'
2489
+		);
2490
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2491
+		echo wp_kses($test_settings_html, AllowedTags::getWithFormTags());
2492
+	}
2493
+
2494
+
2495
+	/**
2496
+	 * This returns the shortcode selector skeleton for a given context and field.
2497
+	 *
2498
+	 * @param string $field           The name of the field retrieving shortcodes for.
2499
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2500
+	 * @return string
2501
+	 * @throws DomainException
2502
+	 * @throws EE_Error
2503
+	 * @throws InvalidArgumentException
2504
+	 * @throws ReflectionException
2505
+	 * @throws InvalidDataTypeException
2506
+	 * @throws InvalidInterfaceException
2507
+	 * @since 4.9.rc.000
2508
+	 */
2509
+	protected function _get_shortcode_selector($field, $linked_input_id)
2510
+	{
2511
+		$template_args = [
2512
+			'shortcodes'      => $this->_get_shortcodes([$field]),
2513
+			'fieldname'       => $field,
2514
+			'linked_input_id' => $linked_input_id,
2515
+		];
2516
+
2517
+		return EEH_Template::display_template(
2518
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2519
+			$template_args,
2520
+			true
2521
+		);
2522
+	}
2523
+
2524
+
2525
+	/**
2526
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2527
+	 * page)
2528
+	 *
2529
+	 * @access public
2530
+	 * @return void
2531
+	 * @throws EE_Error
2532
+	 * @throws InvalidArgumentException
2533
+	 * @throws ReflectionException
2534
+	 * @throws InvalidDataTypeException
2535
+	 * @throws InvalidInterfaceException
2536
+	 */
2537
+	public function shortcode_meta_box()
2538
+	{
2539
+		$shortcodes = $this->_get_shortcodes([], false);
2540
+		// just make sure the shortcodes property is set
2541
+		// $messenger = $this->_message_template_group->messenger_obj();
2542
+		// now let's set the content depending on the status of the shortcodes array
2543
+		if (empty($shortcodes)) {
2544
+			echo '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2545
+			return;
2546
+		}
2547
+		?>
2548 2548
         <div style="float:right; margin-top:10px">
2549 2549
             <?php echo wp_kses($this->_get_help_tab_link('message_template_shortcodes'), AllowedTags::getAllowedTags());
2550
-            ?>
2550
+			?>
2551 2551
         </div>
2552 2552
         <p class="small-text">
2553 2553
             <?php printf(
2554
-                esc_html__(
2555
-                    'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2556
-                    'event_espresso'
2557
-                ),
2558
-                '<span class="dashicons dashicons-shortcode"></span>'
2559
-            ); ?>
2554
+				esc_html__(
2555
+					'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2556
+					'event_espresso'
2557
+				),
2558
+				'<span class="dashicons dashicons-shortcode"></span>'
2559
+			); ?>
2560 2560
         </p>
2561 2561
         <?php
2562
-    }
2563
-
2564
-
2565
-    /**
2566
-     * used to set the $_shortcodes property for when its needed elsewhere.
2567
-     *
2568
-     * @access protected
2569
-     * @return void
2570
-     * @throws EE_Error
2571
-     * @throws InvalidArgumentException
2572
-     * @throws ReflectionException
2573
-     * @throws InvalidDataTypeException
2574
-     * @throws InvalidInterfaceException
2575
-     */
2576
-    protected function _set_shortcodes()
2577
-    {
2578
-
2579
-        // no need to run this if the property is already set
2580
-        if (! empty($this->_shortcodes)) {
2581
-            return;
2582
-        }
2583
-
2584
-        $this->_shortcodes = $this->_get_shortcodes();
2585
-    }
2586
-
2587
-
2588
-    /**
2589
-     * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2590
-     * property)
2591
-     *
2592
-     * @access  protected
2593
-     * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2594
-     *                         for. Defaults to all (for the given context)
2595
-     * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2596
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2597
-     *                         true just an array of shortcode/label pairs.
2598
-     * @throws EE_Error
2599
-     * @throws InvalidArgumentException
2600
-     * @throws ReflectionException
2601
-     * @throws InvalidDataTypeException
2602
-     * @throws InvalidInterfaceException
2603
-     */
2604
-    protected function _get_shortcodes($fields = [], $merged = true)
2605
-    {
2606
-        $this->_set_message_template_group();
2607
-
2608
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2609
-        $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
2610
-        if (empty($GRP_ID)) {
2611
-            return [];
2612
-        }
2613
-        $context = $this->request->getRequestParam(
2614
-            'messenger',
2615
-            key($this->_message_template_group->contexts_config())
2616
-        );
2617
-        return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2618
-    }
2619
-
2620
-
2621
-    /**
2622
-     * This sets the _message_template property (containing the called message_template object)
2623
-     *
2624
-     * @access protected
2625
-     * @return void
2626
-     * @throws EE_Error
2627
-     * @throws InvalidArgumentException
2628
-     * @throws ReflectionException
2629
-     * @throws InvalidDataTypeException
2630
-     * @throws InvalidInterfaceException
2631
-     */
2632
-    protected function _set_message_template_group()
2633
-    {
2634
-        // get out if this is already set.
2635
-        if (! empty($this->_message_template_group)) {
2636
-            return;
2637
-        }
2638
-
2639
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2640
-        $GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
2641
-
2642
-        // let's get the message templates
2643
-        $this->_message_template_group = ! empty($GRP_ID)
2644
-            ? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2645
-            : $this->getMtgModel()->create_default_object();
2646
-
2647
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2648
-        $this->_variation     = $this->_message_template_group->get_template_pack_variation();
2649
-    }
2650
-
2651
-
2652
-    /**
2653
-     * sets up a context switcher for edit forms
2654
-     *
2655
-     * @access  protected
2656
-     * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2657
-     * @param array                     $args                  various things the context switcher needs.
2658
-     * @throws EE_Error
2659
-     */
2660
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2661
-    {
2662
-        $context_details = $template_group_object->contexts_config();
2663
-        $context_label   = $template_group_object->context_label();
2664
-        ob_start();
2665
-        ?>
2562
+	}
2563
+
2564
+
2565
+	/**
2566
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2567
+	 *
2568
+	 * @access protected
2569
+	 * @return void
2570
+	 * @throws EE_Error
2571
+	 * @throws InvalidArgumentException
2572
+	 * @throws ReflectionException
2573
+	 * @throws InvalidDataTypeException
2574
+	 * @throws InvalidInterfaceException
2575
+	 */
2576
+	protected function _set_shortcodes()
2577
+	{
2578
+
2579
+		// no need to run this if the property is already set
2580
+		if (! empty($this->_shortcodes)) {
2581
+			return;
2582
+		}
2583
+
2584
+		$this->_shortcodes = $this->_get_shortcodes();
2585
+	}
2586
+
2587
+
2588
+	/**
2589
+	 * gets all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2590
+	 * property)
2591
+	 *
2592
+	 * @access  protected
2593
+	 * @param array   $fields  include an array of specific field names that you want to be used to get the shortcodes
2594
+	 *                         for. Defaults to all (for the given context)
2595
+	 * @param boolean $merged  Whether to merge all the shortcodes into one list of unique shortcodes
2596
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2597
+	 *                         true just an array of shortcode/label pairs.
2598
+	 * @throws EE_Error
2599
+	 * @throws InvalidArgumentException
2600
+	 * @throws ReflectionException
2601
+	 * @throws InvalidDataTypeException
2602
+	 * @throws InvalidInterfaceException
2603
+	 */
2604
+	protected function _get_shortcodes($fields = [], $merged = true)
2605
+	{
2606
+		$this->_set_message_template_group();
2607
+
2608
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2609
+		$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
2610
+		if (empty($GRP_ID)) {
2611
+			return [];
2612
+		}
2613
+		$context = $this->request->getRequestParam(
2614
+			'messenger',
2615
+			key($this->_message_template_group->contexts_config())
2616
+		);
2617
+		return $this->_message_template_group->get_shortcodes($context, $fields, $merged);
2618
+	}
2619
+
2620
+
2621
+	/**
2622
+	 * This sets the _message_template property (containing the called message_template object)
2623
+	 *
2624
+	 * @access protected
2625
+	 * @return void
2626
+	 * @throws EE_Error
2627
+	 * @throws InvalidArgumentException
2628
+	 * @throws ReflectionException
2629
+	 * @throws InvalidDataTypeException
2630
+	 * @throws InvalidInterfaceException
2631
+	 */
2632
+	protected function _set_message_template_group()
2633
+	{
2634
+		// get out if this is already set.
2635
+		if (! empty($this->_message_template_group)) {
2636
+			return;
2637
+		}
2638
+
2639
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
2640
+		$GRP_ID = $this->request->getRequestParam('id', $GRP_ID, 'int');
2641
+
2642
+		// let's get the message templates
2643
+		$this->_message_template_group = ! empty($GRP_ID)
2644
+			? $this->getMtgModel()->get_one_by_ID($GRP_ID)
2645
+			: $this->getMtgModel()->create_default_object();
2646
+
2647
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2648
+		$this->_variation     = $this->_message_template_group->get_template_pack_variation();
2649
+	}
2650
+
2651
+
2652
+	/**
2653
+	 * sets up a context switcher for edit forms
2654
+	 *
2655
+	 * @access  protected
2656
+	 * @param EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2657
+	 * @param array                     $args                  various things the context switcher needs.
2658
+	 * @throws EE_Error
2659
+	 */
2660
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2661
+	{
2662
+		$context_details = $template_group_object->contexts_config();
2663
+		$context_label   = $template_group_object->context_label();
2664
+		ob_start();
2665
+		?>
2666 2666
         <div class="ee-msg-switcher-container">
2667 2667
             <form method="get" action="<?php echo esc_url_raw(EE_MSG_ADMIN_URL); ?>" id="ee-msg-context-switcher-frm">
2668 2668
                 <?php
2669
-                foreach ($args as $name => $value) {
2670
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2671
-                        continue;
2672
-                    }
2673
-                    ?>
2669
+				foreach ($args as $name => $value) {
2670
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2671
+						continue;
2672
+					}
2673
+					?>
2674 2674
                     <input type="hidden"
2675 2675
                            name="<?php echo esc_attr($name); ?>"
2676 2676
                            value="<?php echo esc_attr($value); ?>"
2677 2677
                     />
2678 2678
                     <?php
2679
-                }
2680
-                // setup nonce_url
2681
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2682
-                $id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2683
-                ?>
2679
+				}
2680
+				// setup nonce_url
2681
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2682
+				$id = 'ee-' . sanitize_key($context_label['label']) . '-select';
2683
+				?>
2684 2684
                 <label for='<?php echo esc_attr($id); ?>' class='screen-reader-text'>
2685 2685
                     <?php esc_html_e('message context options', 'event_espresso'); ?>
2686 2686
                 </label>
2687 2687
                 <select id="<?php echo esc_attr($id); ?>" name="context">
2688 2688
                     <?php
2689
-                    $context_templates = $template_group_object->context_templates();
2690
-                    if (is_array($context_templates)) :
2691
-                        foreach ($context_templates as $context => $template_fields) :
2692
-                            $checked = ($context === $args['context']) ? 'selected' : '';
2693
-                            ?>
2689
+					$context_templates = $template_group_object->context_templates();
2690
+					if (is_array($context_templates)) :
2691
+						foreach ($context_templates as $context => $template_fields) :
2692
+							$checked = ($context === $args['context']) ? 'selected' : '';
2693
+							?>
2694 2694
                             <option value="<?php echo esc_attr($context); ?>" <?php echo esc_attr($checked); ?>>
2695 2695
                                 <?php echo esc_html($context_details[ $context ]['label']); ?>
2696 2696
                             </option>
2697 2697
                         <?php endforeach;
2698
-                    endif; ?>
2698
+					endif; ?>
2699 2699
                 </select>
2700 2700
                 <?php $button_text = sprintf(
2701
-                    esc_html__('Switch %s', 'event_espresso'),
2702
-                    ucwords($context_label['label'])
2703
-                ); ?>
2701
+					esc_html__('Switch %s', 'event_espresso'),
2702
+					ucwords($context_label['label'])
2703
+				); ?>
2704 2704
                 <input class='button--secondary'
2705 2705
                        id="submit-msg-context-switcher-sbmt"
2706 2706
                        type="submit"
@@ -2710,1997 +2710,1997 @@  discard block
 block discarded – undo
2710 2710
             <?php echo wp_kses($args['extra'], AllowedTags::getWithFormTags()); ?>
2711 2711
         </div> <!-- end .ee-msg-switcher-container -->
2712 2712
         <?php $this->_context_switcher = ob_get_clean();
2713
-    }
2714
-
2715
-
2716
-    /**
2717
-     * @param bool $new
2718
-     * @throws EE_Error
2719
-     * @throws ReflectionException
2720
-     */
2721
-    protected function _insert_or_update_message_template($new = false)
2722
-    {
2723
-        $form_data    = $this->getMessageTemplateFormData();
2724
-        $GRP_ID       = $form_data['GRP_ID'];
2725
-        $messenger    = $form_data['MTP_messenger'];
2726
-        $message_type = $form_data['MTP_message_type'];
2727
-        $context      = $form_data['MTP_context'];
2728
-
2729
-        // if this is "new" then we need to generate the default contexts
2730
-        // for the selected messenger/message_type for user to edit.
2731
-        [$success, $query_args] = $new
2732
-            ? $this->generateNewTemplates($GRP_ID, $messenger, $message_type)
2733
-            : $this->updateExistingTemplates($GRP_ID, $messenger, $message_type, $context, $form_data);
2734
-
2735
-        $success     = $success ? 1 : 0;
2736
-        $action_desc = $new ? 'created' : 'updated';
2737
-        $item_desc   = $this->generateUpdateDescription($messenger, $message_type, $context);
2738
-        $override    = $this->performTestSendAfterUpdate($messenger, $message_type, $context);
2739
-
2740
-        $this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
2741
-    }
2742
-
2743
-
2744
-    /**
2745
-     * retrieve and sanitize form data
2746
-     *
2747
-     * @return array
2748
-     * @since 4.10.29.p
2749
-     */
2750
-    protected function getMessageTemplateFormData()
2751
-    {
2752
-        return [
2753
-            'GRP_ID'           => $this->request->getRequestParam('GRP_ID', 0, 'int'),
2754
-            'MTP_context'      => strtolower($this->request->getRequestParam('MTP_context', '')),
2755
-            'MTP_messenger'    => strtolower($this->request->getRequestParam('MTP_messenger', '')),
2756
-            'MTP_message_type' => strtolower($this->request->getRequestParam('MTP_message_type', '')),
2757
-            'MTP_user_id'      => $this->request->getRequestParam('MTP_user_id', 0, 'int'),
2758
-            'MTP_is_global'    => $this->request->getRequestParam('MTP_is_global', 0, 'int'),
2759
-            'MTP_is_override'  => $this->request->getRequestParam('MTP_is_override', 0, 'int'),
2760
-            'MTP_deleted'      => $this->request->getRequestParam('MTP_deleted', 0, 'int'),
2761
-            'MTP_is_active'    => $this->request->getRequestParam('MTP_is_active', 0, 'int'),
2762
-        ];
2763
-    }
2764
-
2765
-
2766
-    /**
2767
-     * @param int    $GRP_ID
2768
-     * @param string $messenger
2769
-     * @param string $message_type
2770
-     * @return array no return on AJAX requests
2771
-     * @throws EE_Error
2772
-     * @throws ReflectionException
2773
-     * @since 4.10.29.p
2774
-     */
2775
-    private function generateNewTemplates($GRP_ID, $messenger, $message_type)
2776
-    {
2777
-        $new_templates = $this->_generate_new_templates($messenger, [$message_type], $GRP_ID);
2778
-        $success       = ! empty($new_templates);
2779
-
2780
-        // we return things differently if doing ajax
2781
-        if ($this->request->isAjax()) {
2782
-            $this->_template_args['success'] = $success;
2783
-            $this->_template_args['error']   = ! $success;
2784
-            $this->_template_args['content'] = '';
2785
-            $this->_template_args['data']    = [
2786
-                'grpID'        => $new_templates['GRP_ID'],
2787
-                'templateName' => $new_templates['template_name'],
2788
-            ];
2789
-            if ($success) {
2790
-                EE_Error::overwrite_success();
2791
-                EE_Error::add_success(
2792
-                    esc_html__(
2793
-                        'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2794
-                        'event_espresso'
2795
-                    )
2796
-                );
2797
-            }
2798
-            $this->_return_json();
2799
-        }
2800
-        return [
2801
-            $success,
2802
-            // 'query_args'
2803
-            [
2804
-                'id'      => $new_templates['GRP_ID'],
2805
-                'context' => $new_templates['MTP_context'],
2806
-                'action'  => 'edit_message_template',
2807
-            ],
2808
-        ];
2809
-    }
2810
-
2811
-
2812
-    /**
2813
-     * @param int    $GRP_ID
2814
-     * @param string $messenger
2815
-     * @param string $message_type
2816
-     * @param string $context
2817
-     * @param array  $form_data
2818
-     * @return array
2819
-     * @throws EE_Error
2820
-     * @since 4.10.29.p
2821
-     */
2822
-    private function updateExistingTemplates(
2823
-        $GRP_ID,
2824
-        $messenger,
2825
-        $message_type,
2826
-        $context,
2827
-        array $form_data
2828
-    ) {
2829
-        $success         = false;
2830
-        $template_fields = $this->getTemplateFields();
2831
-        if ($template_fields) {
2832
-            // if field data is valid, then success will be true
2833
-            $success = $this->validateTemplateFields(
2834
-                $messenger,
2835
-                $message_type,
2836
-                $context,
2837
-                $template_fields
2838
-            );
2839
-            if ($success) {
2840
-                $field_data = [];
2841
-                foreach ($template_fields as $template_field => $content) {
2842
-                    // combine top-level form data with content for this field
2843
-                    $field_data = $this->getTemplateFieldFormData($content, $form_data);
2844
-                    $success    = $this->updateMessageTemplates($template_field, $field_data) ? $success : false;
2845
-                }
2846
-                // we can use the last set_column_values for the MTPG update
2847
-                // (because its the same for all of these specific MTPs)
2848
-                $success = $this->updateMessageTemplateGroup($field_data) ? $success : false;
2849
-            }
2850
-        }
2851
-
2852
-        return [
2853
-            $success,
2854
-            // 'query_args'
2855
-            [
2856
-                'id'      => $GRP_ID,
2857
-                'context' => $context,
2858
-                'action'  => 'edit_message_template',
2859
-            ],
2860
-        ];
2861
-    }
2862
-
2863
-
2864
-    /**
2865
-     * @return array
2866
-     * @since 4.10.29.p
2867
-     */
2868
-    private function getTemplateFields()
2869
-    {
2870
-        $template_fields = $this->request->getRequestParam('MTP_template_fields', null, DataType::EDITOR, true);
2871
-        if (empty($template_fields)) {
2872
-            EE_Error::add_error(
2873
-                esc_html__(
2874
-                    'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2875
-                    'event_espresso'
2876
-                ),
2877
-                __FILE__,
2878
-                __FUNCTION__,
2879
-                __LINE__
2880
-            );
2881
-            return null;
2882
-        }
2883
-        // messages content is expected to be escaped
2884
-        return EEH_Array::addSlashesRecursively($template_fields);
2885
-    }
2886
-
2887
-
2888
-    /**
2889
-     * @param string $messenger
2890
-     * @param string $message_type
2891
-     * @param string $context
2892
-     * @param array  $template_fields
2893
-     * @return bool
2894
-     * @throws EE_Error
2895
-     * @since   4.10.29.p
2896
-     */
2897
-    private function validateTemplateFields(
2898
-        $messenger,
2899
-        $message_type,
2900
-        $context,
2901
-        array $template_fields
2902
-    ) {
2903
-        // first validate all fields!
2904
-        // this filter allows client code to add its own validation to the template fields as well.
2905
-        // returning an empty array means everything passed validation.
2906
-        // errors in validation should be represented in an array with the following shape:
2907
-        // array(
2908
-        //   'fieldname' => array(
2909
-        //          'msg' => 'error message'
2910
-        //          'value' => 'value for field producing error'
2911
-        // )
2912
-        $custom_validation = (array) apply_filters(
2913
-            'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2914
-            [],
2915
-            $template_fields,
2916
-            $context,
2917
-            $messenger,
2918
-            $message_type
2919
-        );
2920
-
2921
-        $system_validation = $this->getMtgModel()->validate(
2922
-            $template_fields,
2923
-            $context,
2924
-            $messenger,
2925
-            $message_type
2926
-        );
2927
-
2928
-        $system_validation = ! is_array($system_validation) && $system_validation ? [] : $system_validation;
2929
-        $validates         = array_merge($custom_validation, $system_validation);
2930
-
2931
-        // if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2932
-        // appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2933
-        //  WE need to make sure there is no actual error messages in validates.
2934
-        if (empty($validates)) {
2935
-            return true;
2936
-        }
2937
-
2938
-        // add the transient so when the form loads we know which fields to highlight
2939
-        $this->_add_transient('edit_message_template', $validates);
2940
-        // setup notices
2941
-        foreach ($validates as $error) {
2942
-            if (isset($error['msg'])) {
2943
-                EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2944
-            }
2945
-        }
2946
-        return false;
2947
-    }
2948
-
2949
-
2950
-    /**
2951
-     * @param array $field_data
2952
-     * @param array $form_data
2953
-     * @return array
2954
-     * @since   4.10.29.p
2955
-     */
2956
-    private function getTemplateFieldFormData(array $field_data, array $form_data)
2957
-    {
2958
-        return $form_data + [
2959
-                'MTP_ID'             => $field_data['MTP_ID'],
2960
-                'MTP_template_field' => $field_data['name'],
2961
-                // if they aren't allowed to use all JS, restrict them to standard allowed post tags
2962
-                'MTP_content'        => ! current_user_can('unfiltered_html')
2963
-                    ? $this->sanitizeMessageTemplateContent($field_data['content'])
2964
-                    : $field_data['content'],
2965
-            ];
2966
-    }
2967
-
2968
-
2969
-    /**
2970
-     * @param string $template_field
2971
-     * @param array  $form_data
2972
-     * @return bool
2973
-     * @throws EE_Error
2974
-     * @since 4.10.29.p
2975
-     */
2976
-    private function updateMessageTemplates($template_field, array $form_data)
2977
-    {
2978
-        $MTP_ID                  = $form_data['MTP_ID'];
2979
-        $message_template_fields = [
2980
-            'GRP_ID'             => $form_data['GRP_ID'],
2981
-            'MTP_template_field' => $form_data['MTP_template_field'],
2982
-            'MTP_context'        => $form_data['MTP_context'],
2983
-            'MTP_content'        => $form_data['MTP_content'],
2984
-        ];
2985
-
2986
-        $hasMtpID = ! empty($MTP_ID);
2987
-        // if we have a MTP_ID for this field then update it, otherwise insert.
2988
-        // this has already been through the template field validator and sanitized, so it will be
2989
-        // safe to insert this field.  Why insert?  This typically happens when we introduce a new
2990
-        // message template field in a messenger/message type and existing users don't have the
2991
-        // default setup for it.
2992
-        // @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2993
-        $updated = $hasMtpID
2994
-            ? $this->getMtpModel()->update($message_template_fields, [['MTP_ID' => $MTP_ID]])
2995
-            : $this->getMtpModel()->insert($message_template_fields);
2996
-
2997
-        $insert_failed = ! $hasMtpID && ! $updated;
2998
-        // updates will return 0 if the field was not changed (ie: no changes = nothing actually updated)
2999
-        // but we won't consider that a problem, but if it returns false, then something went BOOM!
3000
-        $update_failed = $hasMtpID && $updated === false;
3001
-
3002
-        if ($insert_failed || $update_failed) {
3003
-            EE_Error::add_error(
3004
-                sprintf(
3005
-                    esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
3006
-                    $template_field
3007
-                ),
3008
-                __FILE__,
3009
-                __FUNCTION__,
3010
-                __LINE__
3011
-            );
3012
-            return false;
3013
-        }
3014
-        return true;
3015
-    }
3016
-
3017
-
3018
-    /**
3019
-     * @param array $form_data
3020
-     * @return bool
3021
-     * @throws EE_Error
3022
-     * @since 4.10.29.p
3023
-     */
3024
-    private function updateMessageTemplateGroup(array $form_data)
3025
-    {
3026
-        $GRP_ID  = $form_data['GRP_ID'];
3027
-        $updated = $this->getMtgModel()->update(
3028
-        // fields and values
3029
-            [
3030
-                'MTP_user_id'      => $form_data['MTP_user_id'],
3031
-                'MTP_messenger'    => $form_data['MTP_messenger'],
3032
-                'MTP_message_type' => $form_data['MTP_message_type'],
3033
-                'MTP_is_global'    => $form_data['MTP_is_global'],
3034
-                'MTP_is_override'  => $form_data['MTP_is_override'],
3035
-                'MTP_deleted'      => $form_data['MTP_deleted'],
3036
-                'MTP_is_active'    => $form_data['MTP_is_active'],
3037
-                'MTP_name'         => $this->request->getRequestParam('ee_msg_non_global_fields[MTP_name]', ''),
3038
-                'MTP_description'  => $this->request->getRequestParam(
3039
-                    'ee_msg_non_global_fields[MTP_description]',
3040
-                    ''
3041
-                ),
3042
-            ],
3043
-            // where
3044
-            [['GRP_ID' => $GRP_ID]]
3045
-        );
3046
-
3047
-        if ($updated === false) {
3048
-            EE_Error::add_error(
3049
-                sprintf(
3050
-                    esc_html__(
3051
-                        'The Message Template Group (%d) was NOT updated for some reason',
3052
-                        'event_espresso'
3053
-                    ),
3054
-                    $form_data['GRP_ID']
3055
-                ),
3056
-                __FILE__,
3057
-                __FUNCTION__,
3058
-                __LINE__
3059
-            );
3060
-            return false;
3061
-        }
3062
-        // k now we need to ensure the template_pack and template_variation fields are set.
3063
-        $template_pack      = $this->request->getRequestParam('MTP_template_pack', 'default');
3064
-        $template_variation = $this->request->getRequestParam('MTP_template_variation', 'default');
3065
-
3066
-        $message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3067
-        if ($message_template_group instanceof EE_Message_Template_Group) {
3068
-            $message_template_group->set_template_pack_name($template_pack);
3069
-            $message_template_group->set_template_pack_variation($template_variation);
3070
-        }
3071
-        return true;
3072
-    }
3073
-
3074
-
3075
-    /**
3076
-     * recursively runs wp_kses() on message template content in a model safe manner
3077
-     *
3078
-     * @param array|string $content
3079
-     * @return array|string
3080
-     * @since   4.10.29.p
3081
-     */
3082
-    private function sanitizeMessageTemplateContent($content)
3083
-    {
3084
-        if (is_array($content)) {
3085
-            foreach ($content as $key => $value) {
3086
-                $content[ $key ] = $this->sanitizeMessageTemplateContent($value);
3087
-            }
3088
-            return $content;
3089
-        }
3090
-        // remove slashes so wp_kses() works properly
3091
-        // wp_kses_stripslashes() only removes slashes from double-quotes,
3092
-        // so attributes using single quotes always appear invalid.
3093
-        $content = stripslashes($content);
3094
-        $content = wp_kses($content, wp_kses_allowed_html('post'));
3095
-        // But currently the models expect slashed data, so after wp_kses()
3096
-        // runs we need to re-slash the data. Sheesh.
3097
-        // See https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
3098
-        return addslashes($content);
3099
-    }
3100
-
3101
-
3102
-    /**
3103
-     * @param string $messenger
3104
-     * @param string $message_type
3105
-     * @param string $context
3106
-     * @return string
3107
-     * @since 4.10.29.p
3108
-     */
3109
-    private function generateUpdateDescription($messenger, $message_type, $context)
3110
-    {
3111
-        // need the message type and messenger objects to be able to use the labels for the notices
3112
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger);
3113
-        $messenger_label  = $messenger_object instanceof EE_messenger
3114
-            ? ucwords($messenger_object->label['singular'])
3115
-            : '';
3116
-
3117
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type);
3118
-        $message_type_label  = $message_type_object instanceof EE_message_type
3119
-            ? ucwords($message_type_object->label['singular'])
3120
-            : '';
3121
-
3122
-        $context   = ucwords(str_replace('_', ' ', $context));
3123
-        $item_desc = $messenger_label && $message_type_label
3124
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
3125
-            : '';
3126
-        $item_desc .= 'Message Template';
3127
-        return $item_desc;
3128
-    }
3129
-
3130
-
3131
-    /**
3132
-     * @param string $messenger
3133
-     * @param string $message_type
3134
-     * @param string $context
3135
-     * @return bool
3136
-     * @throws EE_Error
3137
-     * @throws ReflectionException
3138
-     * @since 4.10.29.p
3139
-     */
3140
-    private function performTestSendAfterUpdate($messenger, $message_type, $context)
3141
-    {
3142
-        // was a test send triggered?
3143
-        if ($this->request->requestParamIsSet('test_button')) {
3144
-            EE_Error::overwrite_success();
3145
-            $this->_do_test_send($context, $messenger, $message_type);
3146
-            return true;
3147
-        }
3148
-        return false;
3149
-    }
3150
-
3151
-
3152
-    /**
3153
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
3154
-     *
3155
-     * @param string $context      what context being tested
3156
-     * @param string $messenger    messenger being tested
3157
-     * @param string $message_type message type being tested
3158
-     * @throws EE_Error
3159
-     * @throws InvalidArgumentException
3160
-     * @throws InvalidDataTypeException
3161
-     * @throws InvalidInterfaceException
3162
-     * @throws ReflectionException
3163
-     */
3164
-    protected function _do_test_send($context, $messenger, $message_type)
3165
-    {
3166
-        // set things up for preview
3167
-        $this->request->setRequestParam('messenger', $messenger);
3168
-        $this->request->setRequestParam('message_type', $message_type);
3169
-        $this->request->setRequestParam('context', $context);
3170
-        $GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
3171
-        $this->request->setRequestParam('GRP_ID', $GRP_ID);
3172
-
3173
-        $active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
3174
-        $test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
3175
-
3176
-        // let's save any existing fields that might be required by the messenger
3177
-        if (
3178
-            ! empty($test_settings_fld)
3179
-            && $active_messenger instanceof EE_messenger
3180
-            && apply_filters(
3181
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3182
-                true,
3183
-                $test_settings_fld,
3184
-                $active_messenger
3185
-            )
3186
-        ) {
3187
-            $active_messenger->set_existing_test_settings($test_settings_fld);
3188
-        }
3189
-
3190
-        /**
3191
-         * Use filter to add additional controls on whether message can send or not
3192
-         */
3193
-        if (
3194
-            apply_filters(
3195
-                'FHEE__Messages_Admin_Page__do_test_send__can_send',
3196
-                true,
3197
-                $context,
3198
-                $this->request->requestParams(),
3199
-                $messenger,
3200
-                $message_type
3201
-            )
3202
-        ) {
3203
-            if (EEM_Event::instance()->count() > 0) {
3204
-                $success = $this->_preview_message(true);
3205
-                if ($success) {
3206
-                    EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
3207
-                } else {
3208
-                    EE_Error::add_error(
3209
-                        esc_html__('The test message was not sent', 'event_espresso'),
3210
-                        __FILE__,
3211
-                        __FUNCTION__,
3212
-                        __LINE__
3213
-                    );
3214
-                }
3215
-            } else {
3216
-                $this->noEventsErrorMessage(true);
3217
-            }
3218
-        }
3219
-    }
3220
-
3221
-
3222
-    /**
3223
-     * _generate_new_templates
3224
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3225
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3226
-     * for the event.
3227
-     *
3228
-     *
3229
-     * @param string $messenger      the messenger we are generating templates for
3230
-     * @param array  $message_types  array of message types that the templates are generated for.
3231
-     * @param int    $GRP_ID         If this is a custom template being generated then a GRP_ID needs to be included to
3232
-     *                               indicate the message_template_group being used as the base.
3233
-     *
3234
-     * @param bool   $global
3235
-     *
3236
-     * @return array|bool array of data required for the redirect to the correct edit page or bool if
3237
-     *                               encountering problems.
3238
-     * @throws EE_Error
3239
-     * @throws ReflectionException
3240
-     */
3241
-    protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3242
-    {
3243
-        // if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3244
-        // just don't generate any templates.
3245
-        if (empty($message_types)) {
3246
-            return [];
3247
-        }
3248
-
3249
-        $templates = EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3250
-        return $templates[0];
3251
-    }
3252
-
3253
-
3254
-    /**
3255
-     * [_trash_or_restore_message_template]
3256
-     *
3257
-     * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3258
-     * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3259
-     *                        an individual context (FALSE).
3260
-     * @return void
3261
-     * @throws EE_Error
3262
-     * @throws InvalidArgumentException
3263
-     * @throws InvalidDataTypeException
3264
-     * @throws InvalidInterfaceException
3265
-     */
3266
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
3267
-    {
3268
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3269
-
3270
-        $success = 1;
3271
-
3272
-        // incoming GRP_IDs
3273
-        if ($all) {
3274
-            // Checkboxes
3275
-            $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3276
-            if (! empty($checkboxes)) {
3277
-                // if array has more than one element then success message should be plural.
3278
-                // todo: what about nonce?
3279
-                $success = count($checkboxes) > 1 ? 2 : 1;
3280
-
3281
-                // cycle through checkboxes
3282
-                foreach (array_keys($checkboxes) as $GRP_ID) {
3283
-                    $trashed_or_restored = $trash
3284
-                        ? $this->getMtgModel()->delete_by_ID($GRP_ID)
3285
-                        : $this->getMtgModel()->restore_by_ID($GRP_ID);
3286
-                    if (! $trashed_or_restored) {
3287
-                        $success = 0;
3288
-                    }
3289
-                }
3290
-            } else {
3291
-                // grab single GRP_ID and handle
3292
-                $GRP_ID = $this->request->getRequestParam('id', 0, 'int');
3293
-                if (! empty($GRP_ID)) {
3294
-                    $trashed_or_restored = $trash
3295
-                        ? $this->getMtgModel()->delete_by_ID($GRP_ID)
3296
-                        : $this->getMtgModel()->restore_by_ID($GRP_ID);
3297
-                    if (! $trashed_or_restored) {
3298
-                        $success = 0;
3299
-                    }
3300
-                } else {
3301
-                    $success = 0;
3302
-                }
3303
-            }
3304
-        }
3305
-
3306
-        $action_desc = $trash
3307
-            ? esc_html__('moved to the trash', 'event_espresso')
3308
-            : esc_html__('restored', 'event_espresso');
3309
-
3310
-        $template_switch = $this->request->getRequestParam('template_switch', false, 'bool');
3311
-        $action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
3312
-
3313
-        $item_desc = $all ? _n(
3314
-            'Message Template Group',
3315
-            'Message Template Groups',
3316
-            $success,
3317
-            'event_espresso'
3318
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3319
-
3320
-        $item_desc = $template_switch
3321
-            ? _n('template', 'templates', $success, 'event_espresso')
3322
-            : $item_desc;
3323
-
3324
-        $this->_redirect_after_action($success, $item_desc, $action_desc, [
3325
-            'action' => $this->request->getRequestParam('return')
3326
-        ]);
3327
-    }
3328
-
3329
-
3330
-    /**
3331
-     * [_delete_message_template]
3332
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3333
-     *
3334
-     * @return void
3335
-     * @throws EE_Error
3336
-     * @throws InvalidArgumentException
3337
-     * @throws InvalidDataTypeException
3338
-     * @throws InvalidInterfaceException
3339
-     * @throws ReflectionException
3340
-     */
3341
-    protected function _delete_message_template()
3342
-    {
3343
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3344
-
3345
-        // checkboxes
3346
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3347
-        if (! empty($checkboxes)) {
3348
-            // if array has more than one element then success message should be plural
3349
-            $success = count($checkboxes) > 1 ? 2 : 1;
3350
-
3351
-            // cycle through bulk action checkboxes
3352
-            foreach (array_keys($checkboxes) as $GRP_ID) {
3353
-                $success = $this->_delete_mtp_permanently($GRP_ID) ? $success : false;
3354
-            }
3355
-        } else {
3356
-            // grab single grp_id and delete
3357
-            $GRP_ID  = $this->request->getRequestParam('id', 0, 'int');
3358
-            $success = $this->_delete_mtp_permanently($GRP_ID);
3359
-        }
3360
-
3361
-        $this->_redirect_after_action($success, 'Message Templates', 'deleted', [
3362
-            'action' => $this->request->getRequestParam('return')
3363
-        ]);
3364
-    }
3365
-
3366
-
3367
-    /**
3368
-     * helper for permanently deleting a mtP group and all related message_templates
3369
-     *
3370
-     * @param int  $GRP_ID        The group being deleted
3371
-     * @param bool $include_group whether to delete the Message Template Group as well.
3372
-     * @return bool boolean to indicate the success of the deletes or not.
3373
-     * @throws EE_Error
3374
-     * @throws InvalidArgumentException
3375
-     * @throws InvalidDataTypeException
3376
-     * @throws InvalidInterfaceException
3377
-     * @throws ReflectionException
3378
-     * @throws ReflectionException
3379
-     */
3380
-    private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3381
-    {
3382
-        $success = true;
3383
-        // first let's GET this group
3384
-        $MTG = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3385
-        // then delete permanently all the related Message Templates
3386
-        $deleted = $MTG->delete_related_permanently('Message_Template');
3387
-
3388
-        if ($deleted === 0) {
3389
-            $success = false;
3390
-        }
3391
-
3392
-        // now delete permanently this particular group
3393
-
3394
-        if ($include_group && ! $MTG->delete_permanently()) {
3395
-            $success = false;
3396
-        }
3397
-
3398
-        return $success;
3399
-    }
3400
-
3401
-
3402
-    /**
3403
-     *    _learn_more_about_message_templates_link
3404
-     *
3405
-     * @access protected
3406
-     * @return string
3407
-     */
3408
-    protected function _learn_more_about_message_templates_link()
3409
-    {
3410
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3411
-               . esc_html__('learn more about how message templates works', 'event_espresso')
3412
-               . '</a>';
3413
-    }
3414
-
3415
-
3416
-    /**
3417
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3418
-     * ajax and other routes.
3419
-     *
3420
-     * @return void
3421
-     * @throws DomainException
3422
-     * @throws EE_Error
3423
-     */
3424
-    protected function _settings()
3425
-    {
3426
-        $this->_set_m_mt_settings();
3427
-
3428
-        // let's setup the messenger tabs
3429
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3430
-            $this->_m_mt_settings['messenger_tabs'],
3431
-            'messenger_links',
3432
-            '|',
3433
-            $this->request->getRequestParam('selected_messenger', 'email')
3434
-        );
3435
-
3436
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3437
-        $this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
3438
-
3439
-        $this->display_admin_page_with_sidebar();
3440
-    }
3441
-
3442
-
3443
-    /**
3444
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3445
-     *
3446
-     * @access protected
3447
-     * @return void
3448
-     * @throws DomainException
3449
-     */
3450
-    protected function _set_m_mt_settings()
3451
-    {
3452
-        // first if this is already set then lets get out no need to regenerate data.
3453
-        if (! empty($this->_m_mt_settings)) {
3454
-            return;
3455
-        }
3456
-
3457
-        // get all installed messengers and message_types
3458
-        $messengers    = $this->_message_resource_manager->installed_messengers();
3459
-        $message_types = $this->_message_resource_manager->installed_message_types();
3460
-
3461
-
3462
-        // assemble the array for the _tab_text_links helper
3463
-
3464
-        foreach ($messengers as $messenger) {
3465
-            $active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3466
-            $class = 'ee-messenger-' .  sanitize_key($messenger->label['singular']);
3467
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
3468
-                'label' => ucwords($messenger->label['singular']),
3469
-                'class' => $active ? "{$class} messenger-active" : $class,
3470
-                'href'  => $messenger->name,
3471
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3472
-                'slug'  => $messenger->name,
3473
-                'obj'   => $messenger,
3474
-                'icon' => $active
3475
-                    ? '<span class="dashicons dashicons-yes-alt"></span>'
3476
-                    : '<span class="dashicons dashicons-remove"></span>',
3477
-            ];
3478
-
3479
-
3480
-            $message_types_for_messenger = $messenger->get_valid_message_types();
3481
-
3482
-            foreach ($message_types as $message_type) {
3483
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3484
-                // it shouldn't show in either the inactive OR active metabox.
3485
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3486
-                    continue;
3487
-                }
3488
-
3489
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3490
-                    $messenger->name,
3491
-                    $message_type->name
3492
-                )
3493
-                    ? 'active'
3494
-                    : 'inactive';
3495
-
3496
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
3497
-                    'label'    => ucwords($message_type->label['singular']),
3498
-                    'class'    => 'message-type-' . $a_or_i,
3499
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3500
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3501
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3502
-                    'title'    => $a_or_i === 'active'
3503
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3504
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3505
-                    'content'  => $a_or_i === 'active'
3506
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
3507
-                        : $this->_message_type_settings_content($message_type, $messenger),
3508
-                    'slug'     => $message_type->name,
3509
-                    'active'   => $a_or_i === 'active',
3510
-                    'obj'      => $message_type,
3511
-                ];
3512
-            }
3513
-        }
3514
-    }
3515
-
3516
-
3517
-    /**
3518
-     * This just prepares the content for the message type settings
3519
-     *
3520
-     * @param EE_message_type $message_type The message type object
3521
-     * @param EE_messenger    $messenger    The messenger object
3522
-     * @param boolean         $active       Whether the message type is active or not
3523
-     * @return string html output for the content
3524
-     * @throws DomainException
3525
-     */
3526
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
3527
-    {
3528
-        // get message type fields
3529
-        $fields                                         = $message_type->get_admin_settings_fields();
3530
-        $settings_template_args['template_form_fields'] = '';
3531
-
3532
-        if (! empty($fields) && $active) {
3533
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3534
-            foreach ($fields as $fldname => $fldprops) {
3535
-                $field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3536
-                $template_form_field[ $field_id ] = [
3537
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3538
-                    'label'      => $fldprops['label'],
3539
-                    'input'      => $fldprops['field_type'],
3540
-                    'type'       => $fldprops['value_type'],
3541
-                    'required'   => $fldprops['required'],
3542
-                    'validation' => $fldprops['validation'],
3543
-                    'value'      => isset($existing_settings[ $fldname ])
3544
-                        ? $existing_settings[ $fldname ]
3545
-                        : $fldprops['default'],
3546
-                    'options'    => isset($fldprops['options'])
3547
-                        ? $fldprops['options']
3548
-                        : [],
3549
-                    'default'    => isset($existing_settings[ $fldname ])
3550
-                        ? $existing_settings[ $fldname ]
3551
-                        : $fldprops['default'],
3552
-                    'css_class'  => 'no-drag',
3553
-                    'format'     => $fldprops['format'],
3554
-                ];
3555
-            }
3556
-
3557
-
3558
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3559
-                ? $this->_generate_admin_form_fields(
3560
-                    $template_form_field,
3561
-                    'string',
3562
-                    'ee_mt_activate_form'
3563
-                )
3564
-                : '';
3565
-        }
3566
-
3567
-        $settings_template_args['description'] = $message_type->description;
3568
-        // we also need some hidden fields
3569
-        $hidden_fields = [
3570
-            'message_type_settings[messenger]' . $message_type->name    => [
3571
-                'type'  => 'hidden',
3572
-                'value' => $messenger->name,
3573
-            ],
3574
-            'message_type_settings[message_type]' . $message_type->name => [
3575
-                'type'  => 'hidden',
3576
-                'value' => $message_type->name,
3577
-            ],
3578
-            'type' . $message_type->name                                => [
3579
-                'type'  => 'hidden',
3580
-                'value' => 'message_type',
3581
-            ],
3582
-        ];
3583
-
3584
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3585
-            $hidden_fields,
3586
-            'array'
3587
-        );
3588
-        $settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3589
-            ? ' hidden'
3590
-            : '';
3591
-
3592
-
3593
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3594
-        return EEH_Template::display_template($template, $settings_template_args, true);
3595
-    }
3596
-
3597
-
3598
-    /**
3599
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3600
-     *
3601
-     * @access protected
3602
-     * @return void
3603
-     * @throws DomainException
3604
-     */
3605
-    protected function _messages_settings_metaboxes()
3606
-    {
3607
-        $this->_set_m_mt_settings();
3608
-        $m_boxes         = $mt_boxes = [];
3609
-        $m_template_args = $mt_template_args = [];
3610
-
3611
-        $selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3612
-
3613
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3614
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3615
-                $is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3616
-                $hide_on_message     = $is_messenger_active ? '' : 'hidden';
3617
-                $hide_off_message    = $is_messenger_active ? 'hidden' : '';
3618
-
3619
-                // messenger meta boxes
3620
-                $active         = $selected_messenger === $messenger;
3621
-                $active_mt_tabs = isset($this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'])
3622
-                    ? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3623
-                    : '';
3624
-
3625
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3626
-                    esc_html__('%s Settings', 'event_espresso'),
3627
-                    $tab_array['label']
3628
-                );
3629
-
3630
-                $m_template_args[ $messenger . '_a_box' ] = [
3631
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3632
-                    'inactive_message_types' => isset(
3633
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3634
-                    )
3635
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3636
-                        : '',
3637
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3638
-                    'hidden'                 => $active ? '' : ' hidden',
3639
-                    'hide_on_message'        => $hide_on_message,
3640
-                    'messenger'              => $messenger,
3641
-                    'active'                 => $active,
3642
-                ];
3643
-
3644
-                // message type meta boxes
3645
-                // (which is really just the inactive container for each messenger
3646
-                // showing inactive message types for that messenger)
3647
-                $mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3648
-                $mt_template_args[ $messenger . '_i_box' ] = [
3649
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3650
-                    'inactive_message_types' => isset(
3651
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3652
-                    )
3653
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3654
-                        : '',
3655
-                    'hidden'                 => $active ? '' : ' hidden',
3656
-                    'hide_on_message'        => $hide_on_message,
3657
-                    'hide_off_message'       => $hide_off_message,
3658
-                    'messenger'              => $messenger,
3659
-                    'active'                 => $active,
3660
-                ];
3661
-            }
3662
-        }
3663
-
3664
-
3665
-        // register messenger metaboxes
3666
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3667
-        foreach ($m_boxes as $box => $label) {
3668
-            $callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3669
-            $msgr          = str_replace('_a_box', '', $box);
3670
-            $this->addMetaBox(
3671
-                'espresso_' . $msgr . '_settings',
3672
-                $label,
3673
-                function ($post, $metabox) {
3674
-                    EEH_Template::display_template(
3675
-                        $metabox['args']['template_path'],
3676
-                        $metabox['args']['template_args']
3677
-                    );
3678
-                },
3679
-                $this->_current_screen->id,
3680
-                'normal',
3681
-                'high',
3682
-                $callback_args
3683
-            );
3684
-        }
3685
-
3686
-        // register message type metaboxes
3687
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3688
-        foreach ($mt_boxes as $box => $label) {
3689
-            $callback_args = [
3690
-                'template_path' => $mt_template_path,
3691
-                'template_args' => $mt_template_args[ $box ],
3692
-            ];
3693
-            $mt            = str_replace('_i_box', '', $box);
3694
-            $this->addMetaBox(
3695
-                'espresso_' . $mt . '_inactive_mts',
3696
-                $label,
3697
-                function ($post, $metabox) {
3698
-                    EEH_Template::display_template(
3699
-                        $metabox['args']['template_path'],
3700
-                        $metabox['args']['template_args']
3701
-                    );
3702
-                },
3703
-                $this->_current_screen->id,
3704
-                'side',
3705
-                'high',
3706
-                $callback_args
3707
-            );
3708
-        }
3709
-
3710
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3711
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3712
-        if (is_main_site()) {
3713
-            $this->addMetaBox(
3714
-                'espresso_global_message_settings',
3715
-                esc_html__('Global Message Settings', 'event_espresso'),
3716
-                [$this, 'global_messages_settings_metabox_content'],
3717
-                $this->_current_screen->id,
3718
-                'normal',
3719
-                'low',
3720
-                []
3721
-            );
3722
-        }
3723
-    }
3724
-
3725
-
3726
-    /**
3727
-     *  This generates the content for the global messages settings metabox.
3728
-     *
3729
-     * @return void
3730
-     * @throws EE_Error
3731
-     * @throws InvalidArgumentException
3732
-     * @throws ReflectionException
3733
-     * @throws InvalidDataTypeException
3734
-     * @throws InvalidInterfaceException
3735
-     */
3736
-    public function global_messages_settings_metabox_content()
3737
-    {
3738
-        $form = $this->_generate_global_settings_form();
3739
-        echo wp_kses(
3740
-            $form->form_open(
3741
-                $this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3742
-                'POST'
3743
-            ),
3744
-            AllowedTags::getWithFormTags()
3745
-        );
3746
-        echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3747
-        echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3748
-    }
3749
-
3750
-
3751
-    /**
3752
-     * This generates and returns the form object for the global messages settings.
3753
-     *
3754
-     * @return EE_Form_Section_Proper
3755
-     * @throws EE_Error
3756
-     * @throws InvalidArgumentException
3757
-     * @throws ReflectionException
3758
-     * @throws InvalidDataTypeException
3759
-     * @throws InvalidInterfaceException
3760
-     */
3761
-    protected function _generate_global_settings_form()
3762
-    {
3763
-        /** @var EE_Network_Core_Config $network_config */
3764
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3765
-
3766
-        return new EE_Form_Section_Proper(
3767
-            [
3768
-                'name'            => 'global_messages_settings',
3769
-                'html_id'         => 'global_messages_settings',
3770
-                'html_class'      => 'form-table',
3771
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3772
-                'subsections'     => apply_filters(
3773
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3774
-                    [
3775
-                        'do_messages_on_same_request' => new EE_Select_Input(
3776
-                            [
3777
-                                true  => esc_html__('On the same request', 'event_espresso'),
3778
-                                false => esc_html__('On a separate request', 'event_espresso'),
3779
-                            ],
3780
-                            [
3781
-                                'default'         => $network_config->do_messages_on_same_request,
3782
-                                'html_label_text' => esc_html__(
3783
-                                    'Generate and send all messages:',
3784
-                                    'event_espresso'
3785
-                                ),
3786
-                                'html_help_text'  => esc_html__(
3787
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3788
-                                    'event_espresso'
3789
-                                ),
3790
-                            ]
3791
-                        ),
3792
-                        'delete_threshold'            => new EE_Select_Input(
3793
-                            [
3794
-                                0  => esc_html__('Forever', 'event_espresso'),
3795
-                                3  => esc_html__('3 Months', 'event_espresso'),
3796
-                                6  => esc_html__('6 Months', 'event_espresso'),
3797
-                                9  => esc_html__('9 Months', 'event_espresso'),
3798
-                                12 => esc_html__('12 Months', 'event_espresso'),
3799
-                                24 => esc_html__('24 Months', 'event_espresso'),
3800
-                                36 => esc_html__('36 Months', 'event_espresso'),
3801
-                            ],
3802
-                            [
3803
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3804
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3805
-                                'html_help_text'  => esc_html__(
3806
-                                    'You can control how long a record of processed messages is kept via this option.',
3807
-                                    'event_espresso'
3808
-                                ),
3809
-                            ]
3810
-                        ),
3811
-                        'update_settings'             => new EE_Submit_Input(
3812
-                            [
3813
-                                'default'         => esc_html__('Update', 'event_espresso'),
3814
-                                'html_label_text' => '',
3815
-                            ]
3816
-                        ),
3817
-                    ]
3818
-                ),
3819
-            ]
3820
-        );
3821
-    }
3822
-
3823
-
3824
-    /**
3825
-     * This handles updating the global settings set on the admin page.
3826
-     *
3827
-     * @throws EE_Error
3828
-     * @throws InvalidDataTypeException
3829
-     * @throws InvalidInterfaceException
3830
-     * @throws InvalidArgumentException
3831
-     * @throws ReflectionException
3832
-     */
3833
-    protected function _update_global_settings()
3834
-    {
3835
-        /** @var EE_Network_Core_Config $network_config */
3836
-        $network_config  = EE_Registry::instance()->NET_CFG->core;
3837
-        $messages_config = EE_Registry::instance()->CFG->messages;
3838
-        $form            = $this->_generate_global_settings_form();
3839
-        if ($form->was_submitted()) {
3840
-            $form->receive_form_submission();
3841
-            if ($form->is_valid()) {
3842
-                $valid_data = $form->valid_data();
3843
-                foreach ($valid_data as $property => $value) {
3844
-                    $setter = 'set_' . $property;
3845
-                    if (method_exists($network_config, $setter)) {
3846
-                        $network_config->{$setter}($value);
3847
-                    } elseif (
3848
-                        property_exists($network_config, $property)
3849
-                        && $network_config->{$property} !== $value
3850
-                    ) {
3851
-                        $network_config->{$property} = $value;
3852
-                    } elseif (
3853
-                        property_exists($messages_config, $property)
3854
-                        && $messages_config->{$property} !== $value
3855
-                    ) {
3856
-                        $messages_config->{$property} = $value;
3857
-                    }
3858
-                }
3859
-                // only update if the form submission was valid!
3860
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3861
-                EE_Registry::instance()->CFG->update_espresso_config();
3862
-                EE_Error::overwrite_success();
3863
-                EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3864
-            }
3865
-        }
3866
-        $this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3867
-    }
3868
-
3869
-
3870
-    /**
3871
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3872
-     *
3873
-     * @param array $tab_array This is an array of message type tab details used to generate the tabs
3874
-     * @return string html formatted tabs
3875
-     * @throws DomainException
3876
-     */
3877
-    protected function _get_mt_tabs($tab_array)
3878
-    {
3879
-        $tab_array = (array) $tab_array;
3880
-        $template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3881
-        $tabs      = '';
3882
-
3883
-        foreach ($tab_array as $tab) {
3884
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3885
-        }
3886
-
3887
-        return $tabs;
3888
-    }
3889
-
3890
-
3891
-    /**
3892
-     * This prepares the content of the messenger meta box admin settings
3893
-     *
3894
-     * @param EE_messenger $messenger The messenger we're setting up content for
3895
-     * @return string html formatted content
3896
-     * @throws DomainException
3897
-     */
3898
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3899
-    {
3900
-
3901
-        $fields = $messenger->get_admin_settings_fields();
3902
-
3903
-        $settings_template_args['template_form_fields'] = '';
3904
-        // is $messenger active?
3905
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3906
-
3907
-
3908
-        if (! empty($fields)) {
3909
-            $existing_settings = $messenger->get_existing_admin_settings();
3910
-
3911
-            foreach ($fields as $field_name => $field_props) {
3912
-                $field_id                         = $messenger->name . '-' . $field_name;
3913
-                $template_form_field[ $field_id ] = [
3914
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3915
-                    'label'      => $field_props['label'],
3916
-                    'input'      => $field_props['field_type'],
3917
-                    'type'       => $field_props['value_type'],
3918
-                    'required'   => $field_props['required'],
3919
-                    'validation' => $field_props['validation'],
3920
-                    'value'      => $existing_settings[ $field_id ] ?? $field_props['default'],
3921
-                    'css_class'  => '',
3922
-                    'format'     => $field_props['format'],
3923
-                ];
3924
-            }
3925
-
3926
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3927
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3928
-                : '';
3929
-        }
3930
-
3931
-        // we also need some hidden fields
3932
-        $settings_template_args['hidden_fields'] = [
3933
-            'messenger_settings[messenger]' . $messenger->name => [
3934
-                'type'  => 'hidden',
3935
-                'value' => $messenger->name,
3936
-            ],
3937
-            'type' . $messenger->name                          => [
3938
-                'type'  => 'hidden',
3939
-                'value' => 'messenger',
3940
-            ],
3941
-        ];
3942
-
3943
-        // make sure any active message types that are existing are included in the hidden fields
3944
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3945
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3946
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3947
-                    'type'  => 'hidden',
3948
-                    'value' => $mt,
3949
-                ];
3950
-            }
3951
-        }
3952
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3953
-            $settings_template_args['hidden_fields'],
3954
-            'array'
3955
-        );
3956
-        $active                                  =
3957
-            $this->_message_resource_manager->is_messenger_active($messenger->name);
3958
-
3959
-        $settings_template_args['messenger']           = $messenger->name;
3960
-        $settings_template_args['description']         = $messenger->description;
3961
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3962
-
3963
-
3964
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3965
-            $messenger->name
3966
-        )
3967
-            ? $settings_template_args['show_hide_edit_form']
3968
-            : ' hidden';
3969
-
3970
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3971
-            ? ' hidden'
3972
-            : $settings_template_args['show_hide_edit_form'];
3973
-
3974
-
3975
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3976
-        $settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3977
-        $settings_template_args['on_off_status'] = $active;
3978
-        $template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3979
-        return EEH_Template::display_template(
3980
-            $template,
3981
-            $settings_template_args,
3982
-            true
3983
-        );
3984
-    }
3985
-
3986
-
3987
-    /**
3988
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3989
-     *
3990
-     * @throws DomainException
3991
-     * @throws EE_Error
3992
-     * @throws InvalidDataTypeException
3993
-     * @throws InvalidInterfaceException
3994
-     * @throws InvalidArgumentException
3995
-     * @throws ReflectionException
3996
-     */
3997
-    public function activate_messenger_toggle()
3998
-    {
3999
-        $success = true;
4000
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
4001
-        // let's check that we have required data
4002
-
4003
-        if (! $this->_active_messenger_name) {
4004
-            EE_Error::add_error(
4005
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4006
-                __FILE__,
4007
-                __FUNCTION__,
4008
-                __LINE__
4009
-            );
4010
-            $success = false;
4011
-        }
4012
-
4013
-        // do a nonce check here since we're not arriving via a normal route
4014
-        $nonce     = $this->request->getRequestParam('activate_nonce', '');
4015
-        $nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
4016
-
4017
-        $this->_verify_nonce($nonce, $nonce_ref);
4018
-
4019
-
4020
-        $status = $this->request->getRequestParam('status');
4021
-        if (! $status) {
4022
-            EE_Error::add_error(
4023
-                esc_html__(
4024
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4025
-                    'event_espresso'
4026
-                ),
4027
-                __FILE__,
4028
-                __FUNCTION__,
4029
-                __LINE__
4030
-            );
4031
-            $success = false;
4032
-        }
4033
-
4034
-        // do check to verify we have a valid status.
4035
-        if ($status !== 'off' && $status !== 'on') {
4036
-            EE_Error::add_error(
4037
-                sprintf(
4038
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
4039
-                    $status
4040
-                ),
4041
-                __FILE__,
4042
-                __FUNCTION__,
4043
-                __LINE__
4044
-            );
4045
-            $success = false;
4046
-        }
4047
-
4048
-        if ($success) {
4049
-            // made it here?  Stop dawdling then!!
4050
-            $success = $status === 'off'
4051
-                ? $this->_deactivate_messenger($this->_active_messenger_name)
4052
-                : $this->_activate_messenger($this->_active_messenger_name);
4053
-        }
4054
-
4055
-        $this->_template_args['success'] = $success;
4056
-
4057
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
4058
-        $this->_return_json();
4059
-    }
4060
-
4061
-
4062
-    /**
4063
-     * used by ajax from the messages settings page to activate|deactivate a message type
4064
-     *
4065
-     * @throws DomainException
4066
-     * @throws EE_Error
4067
-     * @throws ReflectionException
4068
-     * @throws InvalidDataTypeException
4069
-     * @throws InvalidInterfaceException
4070
-     * @throws InvalidArgumentException
4071
-     */
4072
-    public function activate_mt_toggle()
4073
-    {
4074
-        $success = true;
4075
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
4076
-
4077
-        // let's make sure we have the necessary data
4078
-        if (! $this->_active_message_type_name) {
4079
-            EE_Error::add_error(
4080
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
4081
-                __FILE__,
4082
-                __FUNCTION__,
4083
-                __LINE__
4084
-            );
4085
-            $success = false;
4086
-        }
4087
-
4088
-        if (! $this->_active_messenger_name) {
4089
-            EE_Error::add_error(
4090
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4091
-                __FILE__,
4092
-                __FUNCTION__,
4093
-                __LINE__
4094
-            );
4095
-            $success = false;
4096
-        }
4097
-
4098
-        $status = $this->request->getRequestParam('status');
4099
-        if (! $status) {
4100
-            EE_Error::add_error(
4101
-                esc_html__(
4102
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4103
-                    'event_espresso'
4104
-                ),
4105
-                __FILE__,
4106
-                __FUNCTION__,
4107
-                __LINE__
4108
-            );
4109
-            $success = false;
4110
-        }
4111
-
4112
-
4113
-        // do check to verify we have a valid status.
4114
-        if ($status !== 'activate' && $status !== 'deactivate') {
4115
-            EE_Error::add_error(
4116
-                sprintf(
4117
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
4118
-                    $status
4119
-                ),
4120
-                __FILE__,
4121
-                __FUNCTION__,
4122
-                __LINE__
4123
-            );
4124
-            $success = false;
4125
-        }
4126
-
4127
-
4128
-        // do a nonce check here since we're not arriving via a normal route
4129
-        $nonce = $this->request->getRequestParam('mt_nonce', '');
4130
-        $this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
4131
-
4132
-        if ($success) {
4133
-            // made it here? um, what are you waiting for then?
4134
-            $success = $status === 'deactivate'
4135
-                ? $this->_deactivate_message_type_for_messenger(
4136
-                    $this->_active_messenger_name,
4137
-                    $this->_active_message_type_name
4138
-                )
4139
-                : $this->_activate_message_type_for_messenger(
4140
-                    $this->_active_messenger_name,
4141
-                    $this->_active_message_type_name
4142
-                );
4143
-        }
4144
-
4145
-        $this->_template_args['success'] = $success;
4146
-        $this->_return_json();
4147
-    }
4148
-
4149
-
4150
-    /**
4151
-     * Takes care of processing activating a messenger and preparing the appropriate response.
4152
-     *
4153
-     * @param string $messenger_name The name of the messenger being activated
4154
-     * @return bool
4155
-     * @throws DomainException
4156
-     * @throws EE_Error
4157
-     * @throws InvalidArgumentException
4158
-     * @throws ReflectionException
4159
-     * @throws InvalidDataTypeException
4160
-     * @throws InvalidInterfaceException
4161
-     */
4162
-    protected function _activate_messenger($messenger_name)
4163
-    {
4164
-        $active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
4165
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
4166
-            ? $active_messenger->get_default_message_types()
4167
-            : [];
4168
-
4169
-        // ensure is active
4170
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
4171
-
4172
-        // set response_data for reload
4173
-        foreach ($message_types_to_activate as $message_type_name) {
4174
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4175
-            if (
4176
-                $this->_message_resource_manager->is_message_type_active_for_messenger(
4177
-                    $messenger_name,
4178
-                    $message_type_name
4179
-                )
4180
-                && $message_type instanceof EE_message_type
4181
-            ) {
4182
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
4183
-                if ($message_type->get_admin_settings_fields()) {
4184
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
4185
-                }
4186
-            }
4187
-        }
4188
-
4189
-        // add success message for activating messenger
4190
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4191
-    }
4192
-
4193
-
4194
-    /**
4195
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
4196
-     *
4197
-     * @param string $messenger_name The name of the messenger being activated
4198
-     * @return bool
4199
-     * @throws DomainException
4200
-     * @throws EE_Error
4201
-     * @throws InvalidArgumentException
4202
-     * @throws ReflectionException
4203
-     * @throws InvalidDataTypeException
4204
-     * @throws InvalidInterfaceException
4205
-     */
4206
-    protected function _deactivate_messenger($messenger_name)
4207
-    {
4208
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4209
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
4210
-
4211
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4212
-    }
4213
-
4214
-
4215
-    /**
4216
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4217
-     *
4218
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
4219
-     * @param string $message_type_name The name of the message type being activated for the messenger
4220
-     * @return bool
4221
-     * @throws DomainException
4222
-     * @throws EE_Error
4223
-     * @throws InvalidArgumentException
4224
-     * @throws ReflectionException
4225
-     * @throws InvalidDataTypeException
4226
-     * @throws InvalidInterfaceException
4227
-     */
4228
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4229
-    {
4230
-        $active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
4231
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4232
-
4233
-        // ensure is active
4234
-        $this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
4235
-
4236
-        // set response for load
4237
-        if (
4238
-            $this->_message_resource_manager->is_message_type_active_for_messenger(
4239
-                $messenger_name,
4240
-                $message_type_name
4241
-            )
4242
-        ) {
4243
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
4244
-            if ($message_type_to_activate->get_admin_settings_fields()) {
4245
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
4246
-            }
4247
-        }
4248
-
4249
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
4250
-            $active_messenger,
4251
-            $message_type_to_activate
4252
-        );
4253
-    }
4254
-
4255
-
4256
-    /**
4257
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4258
-     *
4259
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4260
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
4261
-     * @return bool
4262
-     * @throws DomainException
4263
-     * @throws EE_Error
4264
-     * @throws InvalidArgumentException
4265
-     * @throws ReflectionException
4266
-     * @throws InvalidDataTypeException
4267
-     * @throws InvalidInterfaceException
4268
-     */
4269
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4270
-    {
4271
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4272
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4273
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4274
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4275
-
4276
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4277
-            $active_messenger,
4278
-            $message_type_to_deactivate
4279
-        );
4280
-    }
4281
-
4282
-
4283
-    /**
4284
-     * This just initializes the defaults for activating messenger and message type responses.
4285
-     */
4286
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
4287
-    {
4288
-        $this->_template_args['data']['active_mts'] = [];
4289
-        $this->_template_args['data']['mt_reload']  = [];
4290
-    }
4291
-
4292
-
4293
-    /**
4294
-     * Setup appropriate response for activating a messenger and/or message types
4295
-     *
4296
-     * @param EE_messenger         $messenger
4297
-     * @param EE_message_type|null $message_type
4298
-     * @return bool
4299
-     * @throws DomainException
4300
-     * @throws EE_Error
4301
-     * @throws InvalidArgumentException
4302
-     * @throws ReflectionException
4303
-     * @throws InvalidDataTypeException
4304
-     * @throws InvalidInterfaceException
4305
-     */
4306
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
4307
-        $messenger,
4308
-        EE_Message_Type $message_type = null
4309
-    ) {
4310
-        // if $messenger isn't a valid messenger object then get out.
4311
-        if (! $messenger instanceof EE_Messenger) {
4312
-            EE_Error::add_error(
4313
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4314
-                __FILE__,
4315
-                __FUNCTION__,
4316
-                __LINE__
4317
-            );
4318
-            return false;
4319
-        }
4320
-        // activated
4321
-        if ($this->_template_args['data']['active_mts']) {
4322
-            EE_Error::overwrite_success();
4323
-            // activated a message type with the messenger
4324
-            if ($message_type instanceof EE_message_type) {
4325
-                EE_Error::add_success(
4326
-                    sprintf(
4327
-                        esc_html__(
4328
-                            '%s message type has been successfully activated with the %s messenger',
4329
-                            'event_espresso'
4330
-                        ),
4331
-                        ucwords($message_type->label['singular']),
4332
-                        ucwords($messenger->label['singular'])
4333
-                    )
4334
-                );
4335
-
4336
-                // if message type was invoice then let's make sure we activate the invoice payment method.
4337
-                if ($message_type->name === 'invoice') {
4338
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
4339
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4340
-                    if ($pm instanceof EE_Payment_Method) {
4341
-                        EE_Error::add_attention(
4342
-                            esc_html__(
4343
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4344
-                                'event_espresso'
4345
-                            )
4346
-                        );
4347
-                    }
4348
-                }
4349
-                // just toggles the entire messenger
4350
-            } else {
4351
-                EE_Error::add_success(
4352
-                    sprintf(
4353
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4354
-                        ucwords($messenger->label['singular'])
4355
-                    )
4356
-                );
4357
-            }
4358
-
4359
-            return true;
4360
-
4361
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4362
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4363
-            // in which case we just give a success message for the messenger being successfully activated.
4364
-        } else {
4365
-            if (! $messenger->get_default_message_types()) {
4366
-                // messenger doesn't have any default message types so still a success.
4367
-                EE_Error::add_success(
4368
-                    sprintf(
4369
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4370
-                        ucwords($messenger->label['singular'])
4371
-                    )
4372
-                );
4373
-
4374
-                return true;
4375
-            } else {
4376
-                EE_Error::add_error(
4377
-                    $message_type instanceof EE_message_type
4378
-                    ? sprintf(
4379
-                        esc_html__(
4380
-                            '%s message type was not successfully activated with the %s messenger',
4381
-                            'event_espresso'
4382
-                        ),
4383
-                        ucwords($message_type->label['singular']),
4384
-                        ucwords($messenger->label['singular'])
4385
-                    )
4386
-                    : sprintf(
4387
-                        esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4388
-                        ucwords($messenger->label['singular'])
4389
-                    ),
4390
-                    __FILE__,
4391
-                    __FUNCTION__,
4392
-                    __LINE__
4393
-                );
4394
-
4395
-                return false;
4396
-            }
4397
-        }
4398
-    }
4399
-
4400
-
4401
-    /**
4402
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
4403
-     *
4404
-     * @param EE_messenger         $messenger
4405
-     * @param EE_message_type|null $message_type
4406
-     * @return bool
4407
-     * @throws DomainException
4408
-     * @throws EE_Error
4409
-     * @throws InvalidArgumentException
4410
-     * @throws ReflectionException
4411
-     * @throws InvalidDataTypeException
4412
-     * @throws InvalidInterfaceException
4413
-     */
4414
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4415
-        $messenger,
4416
-        EE_message_type $message_type = null
4417
-    ) {
4418
-        EE_Error::overwrite_success();
4419
-
4420
-        // if $messenger isn't a valid messenger object then get out.
4421
-        if (! $messenger instanceof EE_Messenger) {
4422
-            EE_Error::add_error(
4423
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4424
-                __FILE__,
4425
-                __FUNCTION__,
4426
-                __LINE__
4427
-            );
4428
-
4429
-            return false;
4430
-        }
4431
-
4432
-        if ($message_type instanceof EE_message_type) {
4433
-            $message_type_name = $message_type->name;
4434
-            EE_Error::add_success(
4435
-                sprintf(
4436
-                    esc_html__(
4437
-                        '%s message type has been successfully deactivated for the %s messenger.',
4438
-                        'event_espresso'
4439
-                    ),
4440
-                    ucwords($message_type->label['singular']),
4441
-                    ucwords($messenger->label['singular'])
4442
-                )
4443
-            );
4444
-        } else {
4445
-            $message_type_name = '';
4446
-            EE_Error::add_success(
4447
-                sprintf(
4448
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4449
-                    ucwords($messenger->label['singular'])
4450
-                )
4451
-            );
4452
-        }
4453
-
4454
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4455
-        if (
4456
-            $messenger->name === 'html'
4457
-            && (
4458
-                is_null($message_type)
4459
-                || $message_type_name === 'invoice'
4460
-            )
4461
-        ) {
4462
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
4463
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4464
-            if ($count_updated > 0) {
4465
-                $msg = $message_type_name === 'invoice'
4466
-                    ? esc_html__(
4467
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4468
-                        'event_espresso'
4469
-                    )
4470
-                    : esc_html__(
4471
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4472
-                        'event_espresso'
4473
-                    );
4474
-                EE_Error::add_attention($msg);
4475
-            }
4476
-        }
4477
-
4478
-        return true;
4479
-    }
4480
-
4481
-
4482
-    /**
4483
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4484
-     *
4485
-     * @throws DomainException
4486
-     * @throws EE_Error
4487
-     * @throws EE_Error
4488
-     */
4489
-    public function update_mt_form()
4490
-    {
4491
-        if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
4492
-            EE_Error::add_error(
4493
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4494
-                __FILE__,
4495
-                __FUNCTION__,
4496
-                __LINE__
4497
-            );
4498
-            $this->_return_json();
4499
-        }
4500
-
4501
-        $message_types = $this->get_installed_message_types();
4502
-        $message_type  = $message_types[ $this->_active_message_type_name ];
4503
-        $messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
4504
-        $content       = $this->_message_type_settings_content($message_type, $messenger, true);
4505
-
4506
-        $this->_template_args['success'] = true;
4507
-        $this->_template_args['content'] = $content;
4508
-        $this->_return_json();
4509
-    }
4510
-
4511
-
4512
-    /**
4513
-     * this handles saving the settings for a messenger or message type
4514
-     *
4515
-     * @throws EE_Error
4516
-     * @throws EE_Error
4517
-     */
4518
-    public function save_settings()
4519
-    {
4520
-        $type = $this->request->getRequestParam('type');
4521
-        if (! $type) {
4522
-            EE_Error::add_error(
4523
-                esc_html__(
4524
-                    'Cannot save settings because type is unknown (messenger settings or message type settings?)',
4525
-                    'event_espresso'
4526
-                ),
4527
-                __FILE__,
4528
-                __FUNCTION__,
4529
-                __LINE__
4530
-            );
4531
-            $this->_template_args['error'] = true;
4532
-            $this->_return_json();
4533
-        }
4534
-
4535
-
4536
-        if ($type === 'messenger') {
4537
-            // this should be an array.
4538
-            $settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4539
-            $messenger = $settings['messenger'];
4540
-            // remove messenger and message_types from settings array
4541
-            unset($settings['messenger'], $settings['message_types']);
4542
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4543
-        } elseif ($type === 'message_type') {
4544
-            $settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4545
-            $messenger    = $settings['messenger'];
4546
-            $message_type = $settings['message_type'];
4547
-            // remove messenger and message_types from settings array
4548
-            unset($settings['messenger'], $settings['message_types']);
4549
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4550
-        }
4551
-
4552
-        // okay we should have the data all setup.  Now we just update!
4553
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4554
-
4555
-        if ($success) {
4556
-            EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4557
-        } else {
4558
-            EE_Error::add_error(
4559
-                esc_html__('Settings did not get updated', 'event_espresso'),
4560
-                __FILE__,
4561
-                __FUNCTION__,
4562
-                __LINE__
4563
-            );
4564
-        }
4565
-
4566
-        $this->_template_args['success'] = $success;
4567
-        $this->_return_json();
4568
-    }
4569
-
4570
-
4571
-
4572
-
4573
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4574
-
4575
-
4576
-    /**
4577
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4578
-     * However, this does not send immediately, it just queues for sending.
4579
-     *
4580
-     * @throws EE_Error
4581
-     * @throws InvalidDataTypeException
4582
-     * @throws InvalidInterfaceException
4583
-     * @throws InvalidArgumentException
4584
-     * @throws ReflectionException
4585
-     * @since 4.9.0
4586
-     */
4587
-    protected function _generate_now()
4588
-    {
4589
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4590
-        $this->_redirect_after_action(false, '', '', [], true);
4591
-    }
4592
-
4593
-
4594
-    /**
4595
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4596
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4597
-     *
4598
-     * @throws EE_Error
4599
-     * @throws InvalidDataTypeException
4600
-     * @throws InvalidInterfaceException
4601
-     * @throws InvalidArgumentException
4602
-     * @throws ReflectionException
4603
-     * @since 4.9.0
4604
-     */
4605
-    protected function _generate_and_send_now()
4606
-    {
4607
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4608
-        $this->_redirect_after_action(false, '', '', [], true);
4609
-    }
4610
-
4611
-
4612
-    /**
4613
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4614
-     *
4615
-     * @throws EE_Error
4616
-     * @throws InvalidDataTypeException
4617
-     * @throws InvalidInterfaceException
4618
-     * @throws InvalidArgumentException
4619
-     * @throws ReflectionException
4620
-     * @since 4.9.0
4621
-     */
4622
-    protected function _queue_for_resending()
4623
-    {
4624
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4625
-        $this->_redirect_after_action(false, '', '', [], true);
4626
-    }
4627
-
4628
-
4629
-    /**
4630
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4631
-     *
4632
-     * @throws EE_Error
4633
-     * @throws InvalidDataTypeException
4634
-     * @throws InvalidInterfaceException
4635
-     * @throws InvalidArgumentException
4636
-     * @throws ReflectionException
4637
-     * @since 4.9.0
4638
-     */
4639
-    protected function _send_now()
4640
-    {
4641
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4642
-        $this->_redirect_after_action(false, '', '', [], true);
4643
-    }
4644
-
4645
-
4646
-    /**
4647
-     * Deletes EE_messages for IDs in the request.
4648
-     *
4649
-     * @throws EE_Error
4650
-     * @throws InvalidDataTypeException
4651
-     * @throws InvalidInterfaceException
4652
-     * @throws InvalidArgumentException
4653
-     * @since 4.9.0
4654
-     */
4655
-    protected function _delete_ee_messages()
4656
-    {
4657
-        $MSG_IDs       = $this->_get_msg_ids_from_request();
4658
-        $deleted_count = 0;
4659
-        foreach ($MSG_IDs as $MSG_ID) {
4660
-            if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4661
-                $deleted_count++;
4662
-            }
4663
-        }
4664
-        if ($deleted_count) {
4665
-            EE_Error::add_success(
4666
-                esc_html(
4667
-                    _n(
4668
-                        'Message successfully deleted',
4669
-                        'Messages successfully deleted',
4670
-                        $deleted_count,
4671
-                        'event_espresso'
4672
-                    )
4673
-                )
4674
-            );
4675
-        } else {
4676
-            EE_Error::add_error(
4677
-                _n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4678
-                __FILE__,
4679
-                __FUNCTION__,
4680
-                __LINE__
4681
-            );
4682
-        }
4683
-        $this->_redirect_after_action(false, '', '', [], true);
4684
-    }
4685
-
4686
-
4687
-    /**
4688
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4689
-     *
4690
-     * @return array
4691
-     * @since 4.9.0
4692
-     */
4693
-    protected function _get_msg_ids_from_request()
4694
-    {
4695
-        $MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4696
-        if (empty($MSG_IDs)) {
4697
-            return [];
4698
-        }
4699
-        // if 'MSG_ID' was just a single ID (not an array)
4700
-        // then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4701
-        // otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4702
-        return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4703
-            ? $MSG_IDs
4704
-            : array_keys($MSG_IDs);
4705
-    }
2713
+	}
2714
+
2715
+
2716
+	/**
2717
+	 * @param bool $new
2718
+	 * @throws EE_Error
2719
+	 * @throws ReflectionException
2720
+	 */
2721
+	protected function _insert_or_update_message_template($new = false)
2722
+	{
2723
+		$form_data    = $this->getMessageTemplateFormData();
2724
+		$GRP_ID       = $form_data['GRP_ID'];
2725
+		$messenger    = $form_data['MTP_messenger'];
2726
+		$message_type = $form_data['MTP_message_type'];
2727
+		$context      = $form_data['MTP_context'];
2728
+
2729
+		// if this is "new" then we need to generate the default contexts
2730
+		// for the selected messenger/message_type for user to edit.
2731
+		[$success, $query_args] = $new
2732
+			? $this->generateNewTemplates($GRP_ID, $messenger, $message_type)
2733
+			: $this->updateExistingTemplates($GRP_ID, $messenger, $message_type, $context, $form_data);
2734
+
2735
+		$success     = $success ? 1 : 0;
2736
+		$action_desc = $new ? 'created' : 'updated';
2737
+		$item_desc   = $this->generateUpdateDescription($messenger, $message_type, $context);
2738
+		$override    = $this->performTestSendAfterUpdate($messenger, $message_type, $context);
2739
+
2740
+		$this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
2741
+	}
2742
+
2743
+
2744
+	/**
2745
+	 * retrieve and sanitize form data
2746
+	 *
2747
+	 * @return array
2748
+	 * @since 4.10.29.p
2749
+	 */
2750
+	protected function getMessageTemplateFormData()
2751
+	{
2752
+		return [
2753
+			'GRP_ID'           => $this->request->getRequestParam('GRP_ID', 0, 'int'),
2754
+			'MTP_context'      => strtolower($this->request->getRequestParam('MTP_context', '')),
2755
+			'MTP_messenger'    => strtolower($this->request->getRequestParam('MTP_messenger', '')),
2756
+			'MTP_message_type' => strtolower($this->request->getRequestParam('MTP_message_type', '')),
2757
+			'MTP_user_id'      => $this->request->getRequestParam('MTP_user_id', 0, 'int'),
2758
+			'MTP_is_global'    => $this->request->getRequestParam('MTP_is_global', 0, 'int'),
2759
+			'MTP_is_override'  => $this->request->getRequestParam('MTP_is_override', 0, 'int'),
2760
+			'MTP_deleted'      => $this->request->getRequestParam('MTP_deleted', 0, 'int'),
2761
+			'MTP_is_active'    => $this->request->getRequestParam('MTP_is_active', 0, 'int'),
2762
+		];
2763
+	}
2764
+
2765
+
2766
+	/**
2767
+	 * @param int    $GRP_ID
2768
+	 * @param string $messenger
2769
+	 * @param string $message_type
2770
+	 * @return array no return on AJAX requests
2771
+	 * @throws EE_Error
2772
+	 * @throws ReflectionException
2773
+	 * @since 4.10.29.p
2774
+	 */
2775
+	private function generateNewTemplates($GRP_ID, $messenger, $message_type)
2776
+	{
2777
+		$new_templates = $this->_generate_new_templates($messenger, [$message_type], $GRP_ID);
2778
+		$success       = ! empty($new_templates);
2779
+
2780
+		// we return things differently if doing ajax
2781
+		if ($this->request->isAjax()) {
2782
+			$this->_template_args['success'] = $success;
2783
+			$this->_template_args['error']   = ! $success;
2784
+			$this->_template_args['content'] = '';
2785
+			$this->_template_args['data']    = [
2786
+				'grpID'        => $new_templates['GRP_ID'],
2787
+				'templateName' => $new_templates['template_name'],
2788
+			];
2789
+			if ($success) {
2790
+				EE_Error::overwrite_success();
2791
+				EE_Error::add_success(
2792
+					esc_html__(
2793
+						'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2794
+						'event_espresso'
2795
+					)
2796
+				);
2797
+			}
2798
+			$this->_return_json();
2799
+		}
2800
+		return [
2801
+			$success,
2802
+			// 'query_args'
2803
+			[
2804
+				'id'      => $new_templates['GRP_ID'],
2805
+				'context' => $new_templates['MTP_context'],
2806
+				'action'  => 'edit_message_template',
2807
+			],
2808
+		];
2809
+	}
2810
+
2811
+
2812
+	/**
2813
+	 * @param int    $GRP_ID
2814
+	 * @param string $messenger
2815
+	 * @param string $message_type
2816
+	 * @param string $context
2817
+	 * @param array  $form_data
2818
+	 * @return array
2819
+	 * @throws EE_Error
2820
+	 * @since 4.10.29.p
2821
+	 */
2822
+	private function updateExistingTemplates(
2823
+		$GRP_ID,
2824
+		$messenger,
2825
+		$message_type,
2826
+		$context,
2827
+		array $form_data
2828
+	) {
2829
+		$success         = false;
2830
+		$template_fields = $this->getTemplateFields();
2831
+		if ($template_fields) {
2832
+			// if field data is valid, then success will be true
2833
+			$success = $this->validateTemplateFields(
2834
+				$messenger,
2835
+				$message_type,
2836
+				$context,
2837
+				$template_fields
2838
+			);
2839
+			if ($success) {
2840
+				$field_data = [];
2841
+				foreach ($template_fields as $template_field => $content) {
2842
+					// combine top-level form data with content for this field
2843
+					$field_data = $this->getTemplateFieldFormData($content, $form_data);
2844
+					$success    = $this->updateMessageTemplates($template_field, $field_data) ? $success : false;
2845
+				}
2846
+				// we can use the last set_column_values for the MTPG update
2847
+				// (because its the same for all of these specific MTPs)
2848
+				$success = $this->updateMessageTemplateGroup($field_data) ? $success : false;
2849
+			}
2850
+		}
2851
+
2852
+		return [
2853
+			$success,
2854
+			// 'query_args'
2855
+			[
2856
+				'id'      => $GRP_ID,
2857
+				'context' => $context,
2858
+				'action'  => 'edit_message_template',
2859
+			],
2860
+		];
2861
+	}
2862
+
2863
+
2864
+	/**
2865
+	 * @return array
2866
+	 * @since 4.10.29.p
2867
+	 */
2868
+	private function getTemplateFields()
2869
+	{
2870
+		$template_fields = $this->request->getRequestParam('MTP_template_fields', null, DataType::EDITOR, true);
2871
+		if (empty($template_fields)) {
2872
+			EE_Error::add_error(
2873
+				esc_html__(
2874
+					'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2875
+					'event_espresso'
2876
+				),
2877
+				__FILE__,
2878
+				__FUNCTION__,
2879
+				__LINE__
2880
+			);
2881
+			return null;
2882
+		}
2883
+		// messages content is expected to be escaped
2884
+		return EEH_Array::addSlashesRecursively($template_fields);
2885
+	}
2886
+
2887
+
2888
+	/**
2889
+	 * @param string $messenger
2890
+	 * @param string $message_type
2891
+	 * @param string $context
2892
+	 * @param array  $template_fields
2893
+	 * @return bool
2894
+	 * @throws EE_Error
2895
+	 * @since   4.10.29.p
2896
+	 */
2897
+	private function validateTemplateFields(
2898
+		$messenger,
2899
+		$message_type,
2900
+		$context,
2901
+		array $template_fields
2902
+	) {
2903
+		// first validate all fields!
2904
+		// this filter allows client code to add its own validation to the template fields as well.
2905
+		// returning an empty array means everything passed validation.
2906
+		// errors in validation should be represented in an array with the following shape:
2907
+		// array(
2908
+		//   'fieldname' => array(
2909
+		//          'msg' => 'error message'
2910
+		//          'value' => 'value for field producing error'
2911
+		// )
2912
+		$custom_validation = (array) apply_filters(
2913
+			'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2914
+			[],
2915
+			$template_fields,
2916
+			$context,
2917
+			$messenger,
2918
+			$message_type
2919
+		);
2920
+
2921
+		$system_validation = $this->getMtgModel()->validate(
2922
+			$template_fields,
2923
+			$context,
2924
+			$messenger,
2925
+			$message_type
2926
+		);
2927
+
2928
+		$system_validation = ! is_array($system_validation) && $system_validation ? [] : $system_validation;
2929
+		$validates         = array_merge($custom_validation, $system_validation);
2930
+
2931
+		// if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2932
+		// appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2933
+		//  WE need to make sure there is no actual error messages in validates.
2934
+		if (empty($validates)) {
2935
+			return true;
2936
+		}
2937
+
2938
+		// add the transient so when the form loads we know which fields to highlight
2939
+		$this->_add_transient('edit_message_template', $validates);
2940
+		// setup notices
2941
+		foreach ($validates as $error) {
2942
+			if (isset($error['msg'])) {
2943
+				EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2944
+			}
2945
+		}
2946
+		return false;
2947
+	}
2948
+
2949
+
2950
+	/**
2951
+	 * @param array $field_data
2952
+	 * @param array $form_data
2953
+	 * @return array
2954
+	 * @since   4.10.29.p
2955
+	 */
2956
+	private function getTemplateFieldFormData(array $field_data, array $form_data)
2957
+	{
2958
+		return $form_data + [
2959
+				'MTP_ID'             => $field_data['MTP_ID'],
2960
+				'MTP_template_field' => $field_data['name'],
2961
+				// if they aren't allowed to use all JS, restrict them to standard allowed post tags
2962
+				'MTP_content'        => ! current_user_can('unfiltered_html')
2963
+					? $this->sanitizeMessageTemplateContent($field_data['content'])
2964
+					: $field_data['content'],
2965
+			];
2966
+	}
2967
+
2968
+
2969
+	/**
2970
+	 * @param string $template_field
2971
+	 * @param array  $form_data
2972
+	 * @return bool
2973
+	 * @throws EE_Error
2974
+	 * @since 4.10.29.p
2975
+	 */
2976
+	private function updateMessageTemplates($template_field, array $form_data)
2977
+	{
2978
+		$MTP_ID                  = $form_data['MTP_ID'];
2979
+		$message_template_fields = [
2980
+			'GRP_ID'             => $form_data['GRP_ID'],
2981
+			'MTP_template_field' => $form_data['MTP_template_field'],
2982
+			'MTP_context'        => $form_data['MTP_context'],
2983
+			'MTP_content'        => $form_data['MTP_content'],
2984
+		];
2985
+
2986
+		$hasMtpID = ! empty($MTP_ID);
2987
+		// if we have a MTP_ID for this field then update it, otherwise insert.
2988
+		// this has already been through the template field validator and sanitized, so it will be
2989
+		// safe to insert this field.  Why insert?  This typically happens when we introduce a new
2990
+		// message template field in a messenger/message type and existing users don't have the
2991
+		// default setup for it.
2992
+		// @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2993
+		$updated = $hasMtpID
2994
+			? $this->getMtpModel()->update($message_template_fields, [['MTP_ID' => $MTP_ID]])
2995
+			: $this->getMtpModel()->insert($message_template_fields);
2996
+
2997
+		$insert_failed = ! $hasMtpID && ! $updated;
2998
+		// updates will return 0 if the field was not changed (ie: no changes = nothing actually updated)
2999
+		// but we won't consider that a problem, but if it returns false, then something went BOOM!
3000
+		$update_failed = $hasMtpID && $updated === false;
3001
+
3002
+		if ($insert_failed || $update_failed) {
3003
+			EE_Error::add_error(
3004
+				sprintf(
3005
+					esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
3006
+					$template_field
3007
+				),
3008
+				__FILE__,
3009
+				__FUNCTION__,
3010
+				__LINE__
3011
+			);
3012
+			return false;
3013
+		}
3014
+		return true;
3015
+	}
3016
+
3017
+
3018
+	/**
3019
+	 * @param array $form_data
3020
+	 * @return bool
3021
+	 * @throws EE_Error
3022
+	 * @since 4.10.29.p
3023
+	 */
3024
+	private function updateMessageTemplateGroup(array $form_data)
3025
+	{
3026
+		$GRP_ID  = $form_data['GRP_ID'];
3027
+		$updated = $this->getMtgModel()->update(
3028
+		// fields and values
3029
+			[
3030
+				'MTP_user_id'      => $form_data['MTP_user_id'],
3031
+				'MTP_messenger'    => $form_data['MTP_messenger'],
3032
+				'MTP_message_type' => $form_data['MTP_message_type'],
3033
+				'MTP_is_global'    => $form_data['MTP_is_global'],
3034
+				'MTP_is_override'  => $form_data['MTP_is_override'],
3035
+				'MTP_deleted'      => $form_data['MTP_deleted'],
3036
+				'MTP_is_active'    => $form_data['MTP_is_active'],
3037
+				'MTP_name'         => $this->request->getRequestParam('ee_msg_non_global_fields[MTP_name]', ''),
3038
+				'MTP_description'  => $this->request->getRequestParam(
3039
+					'ee_msg_non_global_fields[MTP_description]',
3040
+					''
3041
+				),
3042
+			],
3043
+			// where
3044
+			[['GRP_ID' => $GRP_ID]]
3045
+		);
3046
+
3047
+		if ($updated === false) {
3048
+			EE_Error::add_error(
3049
+				sprintf(
3050
+					esc_html__(
3051
+						'The Message Template Group (%d) was NOT updated for some reason',
3052
+						'event_espresso'
3053
+					),
3054
+					$form_data['GRP_ID']
3055
+				),
3056
+				__FILE__,
3057
+				__FUNCTION__,
3058
+				__LINE__
3059
+			);
3060
+			return false;
3061
+		}
3062
+		// k now we need to ensure the template_pack and template_variation fields are set.
3063
+		$template_pack      = $this->request->getRequestParam('MTP_template_pack', 'default');
3064
+		$template_variation = $this->request->getRequestParam('MTP_template_variation', 'default');
3065
+
3066
+		$message_template_group = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3067
+		if ($message_template_group instanceof EE_Message_Template_Group) {
3068
+			$message_template_group->set_template_pack_name($template_pack);
3069
+			$message_template_group->set_template_pack_variation($template_variation);
3070
+		}
3071
+		return true;
3072
+	}
3073
+
3074
+
3075
+	/**
3076
+	 * recursively runs wp_kses() on message template content in a model safe manner
3077
+	 *
3078
+	 * @param array|string $content
3079
+	 * @return array|string
3080
+	 * @since   4.10.29.p
3081
+	 */
3082
+	private function sanitizeMessageTemplateContent($content)
3083
+	{
3084
+		if (is_array($content)) {
3085
+			foreach ($content as $key => $value) {
3086
+				$content[ $key ] = $this->sanitizeMessageTemplateContent($value);
3087
+			}
3088
+			return $content;
3089
+		}
3090
+		// remove slashes so wp_kses() works properly
3091
+		// wp_kses_stripslashes() only removes slashes from double-quotes,
3092
+		// so attributes using single quotes always appear invalid.
3093
+		$content = stripslashes($content);
3094
+		$content = wp_kses($content, wp_kses_allowed_html('post'));
3095
+		// But currently the models expect slashed data, so after wp_kses()
3096
+		// runs we need to re-slash the data. Sheesh.
3097
+		// See https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
3098
+		return addslashes($content);
3099
+	}
3100
+
3101
+
3102
+	/**
3103
+	 * @param string $messenger
3104
+	 * @param string $message_type
3105
+	 * @param string $context
3106
+	 * @return string
3107
+	 * @since 4.10.29.p
3108
+	 */
3109
+	private function generateUpdateDescription($messenger, $message_type, $context)
3110
+	{
3111
+		// need the message type and messenger objects to be able to use the labels for the notices
3112
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger);
3113
+		$messenger_label  = $messenger_object instanceof EE_messenger
3114
+			? ucwords($messenger_object->label['singular'])
3115
+			: '';
3116
+
3117
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type);
3118
+		$message_type_label  = $message_type_object instanceof EE_message_type
3119
+			? ucwords($message_type_object->label['singular'])
3120
+			: '';
3121
+
3122
+		$context   = ucwords(str_replace('_', ' ', $context));
3123
+		$item_desc = $messenger_label && $message_type_label
3124
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
3125
+			: '';
3126
+		$item_desc .= 'Message Template';
3127
+		return $item_desc;
3128
+	}
3129
+
3130
+
3131
+	/**
3132
+	 * @param string $messenger
3133
+	 * @param string $message_type
3134
+	 * @param string $context
3135
+	 * @return bool
3136
+	 * @throws EE_Error
3137
+	 * @throws ReflectionException
3138
+	 * @since 4.10.29.p
3139
+	 */
3140
+	private function performTestSendAfterUpdate($messenger, $message_type, $context)
3141
+	{
3142
+		// was a test send triggered?
3143
+		if ($this->request->requestParamIsSet('test_button')) {
3144
+			EE_Error::overwrite_success();
3145
+			$this->_do_test_send($context, $messenger, $message_type);
3146
+			return true;
3147
+		}
3148
+		return false;
3149
+	}
3150
+
3151
+
3152
+	/**
3153
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
3154
+	 *
3155
+	 * @param string $context      what context being tested
3156
+	 * @param string $messenger    messenger being tested
3157
+	 * @param string $message_type message type being tested
3158
+	 * @throws EE_Error
3159
+	 * @throws InvalidArgumentException
3160
+	 * @throws InvalidDataTypeException
3161
+	 * @throws InvalidInterfaceException
3162
+	 * @throws ReflectionException
3163
+	 */
3164
+	protected function _do_test_send($context, $messenger, $message_type)
3165
+	{
3166
+		// set things up for preview
3167
+		$this->request->setRequestParam('messenger', $messenger);
3168
+		$this->request->setRequestParam('message_type', $message_type);
3169
+		$this->request->setRequestParam('context', $context);
3170
+		$GRP_ID = $this->request->getRequestParam('GRP_ID', 0, 'int');
3171
+		$this->request->setRequestParam('GRP_ID', $GRP_ID);
3172
+
3173
+		$active_messenger  = $this->_message_resource_manager->get_active_messenger($messenger);
3174
+		$test_settings_fld = $this->request->getRequestParam('test_settings_fld', [], 'string', true);
3175
+
3176
+		// let's save any existing fields that might be required by the messenger
3177
+		if (
3178
+			! empty($test_settings_fld)
3179
+			&& $active_messenger instanceof EE_messenger
3180
+			&& apply_filters(
3181
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3182
+				true,
3183
+				$test_settings_fld,
3184
+				$active_messenger
3185
+			)
3186
+		) {
3187
+			$active_messenger->set_existing_test_settings($test_settings_fld);
3188
+		}
3189
+
3190
+		/**
3191
+		 * Use filter to add additional controls on whether message can send or not
3192
+		 */
3193
+		if (
3194
+			apply_filters(
3195
+				'FHEE__Messages_Admin_Page__do_test_send__can_send',
3196
+				true,
3197
+				$context,
3198
+				$this->request->requestParams(),
3199
+				$messenger,
3200
+				$message_type
3201
+			)
3202
+		) {
3203
+			if (EEM_Event::instance()->count() > 0) {
3204
+				$success = $this->_preview_message(true);
3205
+				if ($success) {
3206
+					EE_Error::add_success(esc_html__('Test message sent', 'event_espresso'));
3207
+				} else {
3208
+					EE_Error::add_error(
3209
+						esc_html__('The test message was not sent', 'event_espresso'),
3210
+						__FILE__,
3211
+						__FUNCTION__,
3212
+						__LINE__
3213
+					);
3214
+				}
3215
+			} else {
3216
+				$this->noEventsErrorMessage(true);
3217
+			}
3218
+		}
3219
+	}
3220
+
3221
+
3222
+	/**
3223
+	 * _generate_new_templates
3224
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3225
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3226
+	 * for the event.
3227
+	 *
3228
+	 *
3229
+	 * @param string $messenger      the messenger we are generating templates for
3230
+	 * @param array  $message_types  array of message types that the templates are generated for.
3231
+	 * @param int    $GRP_ID         If this is a custom template being generated then a GRP_ID needs to be included to
3232
+	 *                               indicate the message_template_group being used as the base.
3233
+	 *
3234
+	 * @param bool   $global
3235
+	 *
3236
+	 * @return array|bool array of data required for the redirect to the correct edit page or bool if
3237
+	 *                               encountering problems.
3238
+	 * @throws EE_Error
3239
+	 * @throws ReflectionException
3240
+	 */
3241
+	protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3242
+	{
3243
+		// if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3244
+		// just don't generate any templates.
3245
+		if (empty($message_types)) {
3246
+			return [];
3247
+		}
3248
+
3249
+		$templates = EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3250
+		return $templates[0];
3251
+	}
3252
+
3253
+
3254
+	/**
3255
+	 * [_trash_or_restore_message_template]
3256
+	 *
3257
+	 * @param boolean $trash  whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3258
+	 * @param boolean $all    whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3259
+	 *                        an individual context (FALSE).
3260
+	 * @return void
3261
+	 * @throws EE_Error
3262
+	 * @throws InvalidArgumentException
3263
+	 * @throws InvalidDataTypeException
3264
+	 * @throws InvalidInterfaceException
3265
+	 */
3266
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
3267
+	{
3268
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3269
+
3270
+		$success = 1;
3271
+
3272
+		// incoming GRP_IDs
3273
+		if ($all) {
3274
+			// Checkboxes
3275
+			$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3276
+			if (! empty($checkboxes)) {
3277
+				// if array has more than one element then success message should be plural.
3278
+				// todo: what about nonce?
3279
+				$success = count($checkboxes) > 1 ? 2 : 1;
3280
+
3281
+				// cycle through checkboxes
3282
+				foreach (array_keys($checkboxes) as $GRP_ID) {
3283
+					$trashed_or_restored = $trash
3284
+						? $this->getMtgModel()->delete_by_ID($GRP_ID)
3285
+						: $this->getMtgModel()->restore_by_ID($GRP_ID);
3286
+					if (! $trashed_or_restored) {
3287
+						$success = 0;
3288
+					}
3289
+				}
3290
+			} else {
3291
+				// grab single GRP_ID and handle
3292
+				$GRP_ID = $this->request->getRequestParam('id', 0, 'int');
3293
+				if (! empty($GRP_ID)) {
3294
+					$trashed_or_restored = $trash
3295
+						? $this->getMtgModel()->delete_by_ID($GRP_ID)
3296
+						: $this->getMtgModel()->restore_by_ID($GRP_ID);
3297
+					if (! $trashed_or_restored) {
3298
+						$success = 0;
3299
+					}
3300
+				} else {
3301
+					$success = 0;
3302
+				}
3303
+			}
3304
+		}
3305
+
3306
+		$action_desc = $trash
3307
+			? esc_html__('moved to the trash', 'event_espresso')
3308
+			: esc_html__('restored', 'event_espresso');
3309
+
3310
+		$template_switch = $this->request->getRequestParam('template_switch', false, 'bool');
3311
+		$action_desc     = $template_switch ? esc_html__('switched', 'event_espresso') : $action_desc;
3312
+
3313
+		$item_desc = $all ? _n(
3314
+			'Message Template Group',
3315
+			'Message Template Groups',
3316
+			$success,
3317
+			'event_espresso'
3318
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3319
+
3320
+		$item_desc = $template_switch
3321
+			? _n('template', 'templates', $success, 'event_espresso')
3322
+			: $item_desc;
3323
+
3324
+		$this->_redirect_after_action($success, $item_desc, $action_desc, [
3325
+			'action' => $this->request->getRequestParam('return')
3326
+		]);
3327
+	}
3328
+
3329
+
3330
+	/**
3331
+	 * [_delete_message_template]
3332
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3333
+	 *
3334
+	 * @return void
3335
+	 * @throws EE_Error
3336
+	 * @throws InvalidArgumentException
3337
+	 * @throws InvalidDataTypeException
3338
+	 * @throws InvalidInterfaceException
3339
+	 * @throws ReflectionException
3340
+	 */
3341
+	protected function _delete_message_template()
3342
+	{
3343
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3344
+
3345
+		// checkboxes
3346
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
3347
+		if (! empty($checkboxes)) {
3348
+			// if array has more than one element then success message should be plural
3349
+			$success = count($checkboxes) > 1 ? 2 : 1;
3350
+
3351
+			// cycle through bulk action checkboxes
3352
+			foreach (array_keys($checkboxes) as $GRP_ID) {
3353
+				$success = $this->_delete_mtp_permanently($GRP_ID) ? $success : false;
3354
+			}
3355
+		} else {
3356
+			// grab single grp_id and delete
3357
+			$GRP_ID  = $this->request->getRequestParam('id', 0, 'int');
3358
+			$success = $this->_delete_mtp_permanently($GRP_ID);
3359
+		}
3360
+
3361
+		$this->_redirect_after_action($success, 'Message Templates', 'deleted', [
3362
+			'action' => $this->request->getRequestParam('return')
3363
+		]);
3364
+	}
3365
+
3366
+
3367
+	/**
3368
+	 * helper for permanently deleting a mtP group and all related message_templates
3369
+	 *
3370
+	 * @param int  $GRP_ID        The group being deleted
3371
+	 * @param bool $include_group whether to delete the Message Template Group as well.
3372
+	 * @return bool boolean to indicate the success of the deletes or not.
3373
+	 * @throws EE_Error
3374
+	 * @throws InvalidArgumentException
3375
+	 * @throws InvalidDataTypeException
3376
+	 * @throws InvalidInterfaceException
3377
+	 * @throws ReflectionException
3378
+	 * @throws ReflectionException
3379
+	 */
3380
+	private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3381
+	{
3382
+		$success = true;
3383
+		// first let's GET this group
3384
+		$MTG = $this->getMtgModel()->get_one_by_ID($GRP_ID);
3385
+		// then delete permanently all the related Message Templates
3386
+		$deleted = $MTG->delete_related_permanently('Message_Template');
3387
+
3388
+		if ($deleted === 0) {
3389
+			$success = false;
3390
+		}
3391
+
3392
+		// now delete permanently this particular group
3393
+
3394
+		if ($include_group && ! $MTG->delete_permanently()) {
3395
+			$success = false;
3396
+		}
3397
+
3398
+		return $success;
3399
+	}
3400
+
3401
+
3402
+	/**
3403
+	 *    _learn_more_about_message_templates_link
3404
+	 *
3405
+	 * @access protected
3406
+	 * @return string
3407
+	 */
3408
+	protected function _learn_more_about_message_templates_link()
3409
+	{
3410
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3411
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
3412
+			   . '</a>';
3413
+	}
3414
+
3415
+
3416
+	/**
3417
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3418
+	 * ajax and other routes.
3419
+	 *
3420
+	 * @return void
3421
+	 * @throws DomainException
3422
+	 * @throws EE_Error
3423
+	 */
3424
+	protected function _settings()
3425
+	{
3426
+		$this->_set_m_mt_settings();
3427
+
3428
+		// let's setup the messenger tabs
3429
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3430
+			$this->_m_mt_settings['messenger_tabs'],
3431
+			'messenger_links',
3432
+			'|',
3433
+			$this->request->getRequestParam('selected_messenger', 'email')
3434
+		);
3435
+
3436
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3437
+		$this->_template_args['after_admin_page_content']  = '</div><!-- end .ui-widget -->';
3438
+
3439
+		$this->display_admin_page_with_sidebar();
3440
+	}
3441
+
3442
+
3443
+	/**
3444
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3445
+	 *
3446
+	 * @access protected
3447
+	 * @return void
3448
+	 * @throws DomainException
3449
+	 */
3450
+	protected function _set_m_mt_settings()
3451
+	{
3452
+		// first if this is already set then lets get out no need to regenerate data.
3453
+		if (! empty($this->_m_mt_settings)) {
3454
+			return;
3455
+		}
3456
+
3457
+		// get all installed messengers and message_types
3458
+		$messengers    = $this->_message_resource_manager->installed_messengers();
3459
+		$message_types = $this->_message_resource_manager->installed_message_types();
3460
+
3461
+
3462
+		// assemble the array for the _tab_text_links helper
3463
+
3464
+		foreach ($messengers as $messenger) {
3465
+			$active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3466
+			$class = 'ee-messenger-' .  sanitize_key($messenger->label['singular']);
3467
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = [
3468
+				'label' => ucwords($messenger->label['singular']),
3469
+				'class' => $active ? "{$class} messenger-active" : $class,
3470
+				'href'  => $messenger->name,
3471
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3472
+				'slug'  => $messenger->name,
3473
+				'obj'   => $messenger,
3474
+				'icon' => $active
3475
+					? '<span class="dashicons dashicons-yes-alt"></span>'
3476
+					: '<span class="dashicons dashicons-remove"></span>',
3477
+			];
3478
+
3479
+
3480
+			$message_types_for_messenger = $messenger->get_valid_message_types();
3481
+
3482
+			foreach ($message_types as $message_type) {
3483
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3484
+				// it shouldn't show in either the inactive OR active metabox.
3485
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3486
+					continue;
3487
+				}
3488
+
3489
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3490
+					$messenger->name,
3491
+					$message_type->name
3492
+				)
3493
+					? 'active'
3494
+					: 'inactive';
3495
+
3496
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = [
3497
+					'label'    => ucwords($message_type->label['singular']),
3498
+					'class'    => 'message-type-' . $a_or_i,
3499
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3500
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3501
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3502
+					'title'    => $a_or_i === 'active'
3503
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3504
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3505
+					'content'  => $a_or_i === 'active'
3506
+						? $this->_message_type_settings_content($message_type, $messenger, true)
3507
+						: $this->_message_type_settings_content($message_type, $messenger),
3508
+					'slug'     => $message_type->name,
3509
+					'active'   => $a_or_i === 'active',
3510
+					'obj'      => $message_type,
3511
+				];
3512
+			}
3513
+		}
3514
+	}
3515
+
3516
+
3517
+	/**
3518
+	 * This just prepares the content for the message type settings
3519
+	 *
3520
+	 * @param EE_message_type $message_type The message type object
3521
+	 * @param EE_messenger    $messenger    The messenger object
3522
+	 * @param boolean         $active       Whether the message type is active or not
3523
+	 * @return string html output for the content
3524
+	 * @throws DomainException
3525
+	 */
3526
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
3527
+	{
3528
+		// get message type fields
3529
+		$fields                                         = $message_type->get_admin_settings_fields();
3530
+		$settings_template_args['template_form_fields'] = '';
3531
+
3532
+		if (! empty($fields) && $active) {
3533
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3534
+			foreach ($fields as $fldname => $fldprops) {
3535
+				$field_id                         = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3536
+				$template_form_field[ $field_id ] = [
3537
+					'name'       => 'message_type_settings[' . $fldname . ']',
3538
+					'label'      => $fldprops['label'],
3539
+					'input'      => $fldprops['field_type'],
3540
+					'type'       => $fldprops['value_type'],
3541
+					'required'   => $fldprops['required'],
3542
+					'validation' => $fldprops['validation'],
3543
+					'value'      => isset($existing_settings[ $fldname ])
3544
+						? $existing_settings[ $fldname ]
3545
+						: $fldprops['default'],
3546
+					'options'    => isset($fldprops['options'])
3547
+						? $fldprops['options']
3548
+						: [],
3549
+					'default'    => isset($existing_settings[ $fldname ])
3550
+						? $existing_settings[ $fldname ]
3551
+						: $fldprops['default'],
3552
+					'css_class'  => 'no-drag',
3553
+					'format'     => $fldprops['format'],
3554
+				];
3555
+			}
3556
+
3557
+
3558
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3559
+				? $this->_generate_admin_form_fields(
3560
+					$template_form_field,
3561
+					'string',
3562
+					'ee_mt_activate_form'
3563
+				)
3564
+				: '';
3565
+		}
3566
+
3567
+		$settings_template_args['description'] = $message_type->description;
3568
+		// we also need some hidden fields
3569
+		$hidden_fields = [
3570
+			'message_type_settings[messenger]' . $message_type->name    => [
3571
+				'type'  => 'hidden',
3572
+				'value' => $messenger->name,
3573
+			],
3574
+			'message_type_settings[message_type]' . $message_type->name => [
3575
+				'type'  => 'hidden',
3576
+				'value' => $message_type->name,
3577
+			],
3578
+			'type' . $message_type->name                                => [
3579
+				'type'  => 'hidden',
3580
+				'value' => 'message_type',
3581
+			],
3582
+		];
3583
+
3584
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3585
+			$hidden_fields,
3586
+			'array'
3587
+		);
3588
+		$settings_template_args['show_form']     = empty($settings_template_args['template_form_fields'])
3589
+			? ' hidden'
3590
+			: '';
3591
+
3592
+
3593
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3594
+		return EEH_Template::display_template($template, $settings_template_args, true);
3595
+	}
3596
+
3597
+
3598
+	/**
3599
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3600
+	 *
3601
+	 * @access protected
3602
+	 * @return void
3603
+	 * @throws DomainException
3604
+	 */
3605
+	protected function _messages_settings_metaboxes()
3606
+	{
3607
+		$this->_set_m_mt_settings();
3608
+		$m_boxes         = $mt_boxes = [];
3609
+		$m_template_args = $mt_template_args = [];
3610
+
3611
+		$selected_messenger = $this->request->getRequestParam('selected_messenger', 'email');
3612
+
3613
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3614
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3615
+				$is_messenger_active = $this->_message_resource_manager->is_messenger_active($messenger);
3616
+				$hide_on_message     = $is_messenger_active ? '' : 'hidden';
3617
+				$hide_off_message    = $is_messenger_active ? 'hidden' : '';
3618
+
3619
+				// messenger meta boxes
3620
+				$active         = $selected_messenger === $messenger;
3621
+				$active_mt_tabs = isset($this->_m_mt_settings['message_type_tabs'][ $messenger ]['active'])
3622
+					? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3623
+					: '';
3624
+
3625
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3626
+					esc_html__('%s Settings', 'event_espresso'),
3627
+					$tab_array['label']
3628
+				);
3629
+
3630
+				$m_template_args[ $messenger . '_a_box' ] = [
3631
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3632
+					'inactive_message_types' => isset(
3633
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3634
+					)
3635
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3636
+						: '',
3637
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3638
+					'hidden'                 => $active ? '' : ' hidden',
3639
+					'hide_on_message'        => $hide_on_message,
3640
+					'messenger'              => $messenger,
3641
+					'active'                 => $active,
3642
+				];
3643
+
3644
+				// message type meta boxes
3645
+				// (which is really just the inactive container for each messenger
3646
+				// showing inactive message types for that messenger)
3647
+				$mt_boxes[ $messenger . '_i_box' ]         = esc_html__('Inactive Message Types', 'event_espresso');
3648
+				$mt_template_args[ $messenger . '_i_box' ] = [
3649
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3650
+					'inactive_message_types' => isset(
3651
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3652
+					)
3653
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3654
+						: '',
3655
+					'hidden'                 => $active ? '' : ' hidden',
3656
+					'hide_on_message'        => $hide_on_message,
3657
+					'hide_off_message'       => $hide_off_message,
3658
+					'messenger'              => $messenger,
3659
+					'active'                 => $active,
3660
+				];
3661
+			}
3662
+		}
3663
+
3664
+
3665
+		// register messenger metaboxes
3666
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3667
+		foreach ($m_boxes as $box => $label) {
3668
+			$callback_args = ['template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]];
3669
+			$msgr          = str_replace('_a_box', '', $box);
3670
+			$this->addMetaBox(
3671
+				'espresso_' . $msgr . '_settings',
3672
+				$label,
3673
+				function ($post, $metabox) {
3674
+					EEH_Template::display_template(
3675
+						$metabox['args']['template_path'],
3676
+						$metabox['args']['template_args']
3677
+					);
3678
+				},
3679
+				$this->_current_screen->id,
3680
+				'normal',
3681
+				'high',
3682
+				$callback_args
3683
+			);
3684
+		}
3685
+
3686
+		// register message type metaboxes
3687
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3688
+		foreach ($mt_boxes as $box => $label) {
3689
+			$callback_args = [
3690
+				'template_path' => $mt_template_path,
3691
+				'template_args' => $mt_template_args[ $box ],
3692
+			];
3693
+			$mt            = str_replace('_i_box', '', $box);
3694
+			$this->addMetaBox(
3695
+				'espresso_' . $mt . '_inactive_mts',
3696
+				$label,
3697
+				function ($post, $metabox) {
3698
+					EEH_Template::display_template(
3699
+						$metabox['args']['template_path'],
3700
+						$metabox['args']['template_args']
3701
+					);
3702
+				},
3703
+				$this->_current_screen->id,
3704
+				'side',
3705
+				'high',
3706
+				$callback_args
3707
+			);
3708
+		}
3709
+
3710
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3711
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3712
+		if (is_main_site()) {
3713
+			$this->addMetaBox(
3714
+				'espresso_global_message_settings',
3715
+				esc_html__('Global Message Settings', 'event_espresso'),
3716
+				[$this, 'global_messages_settings_metabox_content'],
3717
+				$this->_current_screen->id,
3718
+				'normal',
3719
+				'low',
3720
+				[]
3721
+			);
3722
+		}
3723
+	}
3724
+
3725
+
3726
+	/**
3727
+	 *  This generates the content for the global messages settings metabox.
3728
+	 *
3729
+	 * @return void
3730
+	 * @throws EE_Error
3731
+	 * @throws InvalidArgumentException
3732
+	 * @throws ReflectionException
3733
+	 * @throws InvalidDataTypeException
3734
+	 * @throws InvalidInterfaceException
3735
+	 */
3736
+	public function global_messages_settings_metabox_content()
3737
+	{
3738
+		$form = $this->_generate_global_settings_form();
3739
+		echo wp_kses(
3740
+			$form->form_open(
3741
+				$this->add_query_args_and_nonce(['action' => 'update_global_settings'], EE_MSG_ADMIN_URL),
3742
+				'POST'
3743
+			),
3744
+			AllowedTags::getWithFormTags()
3745
+		);
3746
+		echo wp_kses($form->get_html(), AllowedTags::getWithFormTags());
3747
+		echo wp_kses($form->form_close(), AllowedTags::getWithFormTags());
3748
+	}
3749
+
3750
+
3751
+	/**
3752
+	 * This generates and returns the form object for the global messages settings.
3753
+	 *
3754
+	 * @return EE_Form_Section_Proper
3755
+	 * @throws EE_Error
3756
+	 * @throws InvalidArgumentException
3757
+	 * @throws ReflectionException
3758
+	 * @throws InvalidDataTypeException
3759
+	 * @throws InvalidInterfaceException
3760
+	 */
3761
+	protected function _generate_global_settings_form()
3762
+	{
3763
+		/** @var EE_Network_Core_Config $network_config */
3764
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3765
+
3766
+		return new EE_Form_Section_Proper(
3767
+			[
3768
+				'name'            => 'global_messages_settings',
3769
+				'html_id'         => 'global_messages_settings',
3770
+				'html_class'      => 'form-table',
3771
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3772
+				'subsections'     => apply_filters(
3773
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3774
+					[
3775
+						'do_messages_on_same_request' => new EE_Select_Input(
3776
+							[
3777
+								true  => esc_html__('On the same request', 'event_espresso'),
3778
+								false => esc_html__('On a separate request', 'event_espresso'),
3779
+							],
3780
+							[
3781
+								'default'         => $network_config->do_messages_on_same_request,
3782
+								'html_label_text' => esc_html__(
3783
+									'Generate and send all messages:',
3784
+									'event_espresso'
3785
+								),
3786
+								'html_help_text'  => esc_html__(
3787
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3788
+									'event_espresso'
3789
+								),
3790
+							]
3791
+						),
3792
+						'delete_threshold'            => new EE_Select_Input(
3793
+							[
3794
+								0  => esc_html__('Forever', 'event_espresso'),
3795
+								3  => esc_html__('3 Months', 'event_espresso'),
3796
+								6  => esc_html__('6 Months', 'event_espresso'),
3797
+								9  => esc_html__('9 Months', 'event_espresso'),
3798
+								12 => esc_html__('12 Months', 'event_espresso'),
3799
+								24 => esc_html__('24 Months', 'event_espresso'),
3800
+								36 => esc_html__('36 Months', 'event_espresso'),
3801
+							],
3802
+							[
3803
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3804
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3805
+								'html_help_text'  => esc_html__(
3806
+									'You can control how long a record of processed messages is kept via this option.',
3807
+									'event_espresso'
3808
+								),
3809
+							]
3810
+						),
3811
+						'update_settings'             => new EE_Submit_Input(
3812
+							[
3813
+								'default'         => esc_html__('Update', 'event_espresso'),
3814
+								'html_label_text' => '',
3815
+							]
3816
+						),
3817
+					]
3818
+				),
3819
+			]
3820
+		);
3821
+	}
3822
+
3823
+
3824
+	/**
3825
+	 * This handles updating the global settings set on the admin page.
3826
+	 *
3827
+	 * @throws EE_Error
3828
+	 * @throws InvalidDataTypeException
3829
+	 * @throws InvalidInterfaceException
3830
+	 * @throws InvalidArgumentException
3831
+	 * @throws ReflectionException
3832
+	 */
3833
+	protected function _update_global_settings()
3834
+	{
3835
+		/** @var EE_Network_Core_Config $network_config */
3836
+		$network_config  = EE_Registry::instance()->NET_CFG->core;
3837
+		$messages_config = EE_Registry::instance()->CFG->messages;
3838
+		$form            = $this->_generate_global_settings_form();
3839
+		if ($form->was_submitted()) {
3840
+			$form->receive_form_submission();
3841
+			if ($form->is_valid()) {
3842
+				$valid_data = $form->valid_data();
3843
+				foreach ($valid_data as $property => $value) {
3844
+					$setter = 'set_' . $property;
3845
+					if (method_exists($network_config, $setter)) {
3846
+						$network_config->{$setter}($value);
3847
+					} elseif (
3848
+						property_exists($network_config, $property)
3849
+						&& $network_config->{$property} !== $value
3850
+					) {
3851
+						$network_config->{$property} = $value;
3852
+					} elseif (
3853
+						property_exists($messages_config, $property)
3854
+						&& $messages_config->{$property} !== $value
3855
+					) {
3856
+						$messages_config->{$property} = $value;
3857
+					}
3858
+				}
3859
+				// only update if the form submission was valid!
3860
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3861
+				EE_Registry::instance()->CFG->update_espresso_config();
3862
+				EE_Error::overwrite_success();
3863
+				EE_Error::add_success(esc_html__('Global message settings were updated', 'event_espresso'));
3864
+			}
3865
+		}
3866
+		$this->_redirect_after_action(0, '', '', ['action' => 'settings'], true);
3867
+	}
3868
+
3869
+
3870
+	/**
3871
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3872
+	 *
3873
+	 * @param array $tab_array This is an array of message type tab details used to generate the tabs
3874
+	 * @return string html formatted tabs
3875
+	 * @throws DomainException
3876
+	 */
3877
+	protected function _get_mt_tabs($tab_array)
3878
+	{
3879
+		$tab_array = (array) $tab_array;
3880
+		$template  = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3881
+		$tabs      = '';
3882
+
3883
+		foreach ($tab_array as $tab) {
3884
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3885
+		}
3886
+
3887
+		return $tabs;
3888
+	}
3889
+
3890
+
3891
+	/**
3892
+	 * This prepares the content of the messenger meta box admin settings
3893
+	 *
3894
+	 * @param EE_messenger $messenger The messenger we're setting up content for
3895
+	 * @return string html formatted content
3896
+	 * @throws DomainException
3897
+	 */
3898
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3899
+	{
3900
+
3901
+		$fields = $messenger->get_admin_settings_fields();
3902
+
3903
+		$settings_template_args['template_form_fields'] = '';
3904
+		// is $messenger active?
3905
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3906
+
3907
+
3908
+		if (! empty($fields)) {
3909
+			$existing_settings = $messenger->get_existing_admin_settings();
3910
+
3911
+			foreach ($fields as $field_name => $field_props) {
3912
+				$field_id                         = $messenger->name . '-' . $field_name;
3913
+				$template_form_field[ $field_id ] = [
3914
+					'name'       => 'messenger_settings[' . $field_id . ']',
3915
+					'label'      => $field_props['label'],
3916
+					'input'      => $field_props['field_type'],
3917
+					'type'       => $field_props['value_type'],
3918
+					'required'   => $field_props['required'],
3919
+					'validation' => $field_props['validation'],
3920
+					'value'      => $existing_settings[ $field_id ] ?? $field_props['default'],
3921
+					'css_class'  => '',
3922
+					'format'     => $field_props['format'],
3923
+				];
3924
+			}
3925
+
3926
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3927
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3928
+				: '';
3929
+		}
3930
+
3931
+		// we also need some hidden fields
3932
+		$settings_template_args['hidden_fields'] = [
3933
+			'messenger_settings[messenger]' . $messenger->name => [
3934
+				'type'  => 'hidden',
3935
+				'value' => $messenger->name,
3936
+			],
3937
+			'type' . $messenger->name                          => [
3938
+				'type'  => 'hidden',
3939
+				'value' => 'messenger',
3940
+			],
3941
+		];
3942
+
3943
+		// make sure any active message types that are existing are included in the hidden fields
3944
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3945
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3946
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = [
3947
+					'type'  => 'hidden',
3948
+					'value' => $mt,
3949
+				];
3950
+			}
3951
+		}
3952
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3953
+			$settings_template_args['hidden_fields'],
3954
+			'array'
3955
+		);
3956
+		$active                                  =
3957
+			$this->_message_resource_manager->is_messenger_active($messenger->name);
3958
+
3959
+		$settings_template_args['messenger']           = $messenger->name;
3960
+		$settings_template_args['description']         = $messenger->description;
3961
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3962
+
3963
+
3964
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3965
+			$messenger->name
3966
+		)
3967
+			? $settings_template_args['show_hide_edit_form']
3968
+			: ' hidden';
3969
+
3970
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3971
+			? ' hidden'
3972
+			: $settings_template_args['show_hide_edit_form'];
3973
+
3974
+
3975
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3976
+		$settings_template_args['nonce']         = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3977
+		$settings_template_args['on_off_status'] = $active;
3978
+		$template                                = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3979
+		return EEH_Template::display_template(
3980
+			$template,
3981
+			$settings_template_args,
3982
+			true
3983
+		);
3984
+	}
3985
+
3986
+
3987
+	/**
3988
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3989
+	 *
3990
+	 * @throws DomainException
3991
+	 * @throws EE_Error
3992
+	 * @throws InvalidDataTypeException
3993
+	 * @throws InvalidInterfaceException
3994
+	 * @throws InvalidArgumentException
3995
+	 * @throws ReflectionException
3996
+	 */
3997
+	public function activate_messenger_toggle()
3998
+	{
3999
+		$success = true;
4000
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
4001
+		// let's check that we have required data
4002
+
4003
+		if (! $this->_active_messenger_name) {
4004
+			EE_Error::add_error(
4005
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4006
+				__FILE__,
4007
+				__FUNCTION__,
4008
+				__LINE__
4009
+			);
4010
+			$success = false;
4011
+		}
4012
+
4013
+		// do a nonce check here since we're not arriving via a normal route
4014
+		$nonce     = $this->request->getRequestParam('activate_nonce', '');
4015
+		$nonce_ref = "activate_{$this->_active_messenger_name}_toggle_nonce";
4016
+
4017
+		$this->_verify_nonce($nonce, $nonce_ref);
4018
+
4019
+
4020
+		$status = $this->request->getRequestParam('status');
4021
+		if (! $status) {
4022
+			EE_Error::add_error(
4023
+				esc_html__(
4024
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4025
+					'event_espresso'
4026
+				),
4027
+				__FILE__,
4028
+				__FUNCTION__,
4029
+				__LINE__
4030
+			);
4031
+			$success = false;
4032
+		}
4033
+
4034
+		// do check to verify we have a valid status.
4035
+		if ($status !== 'off' && $status !== 'on') {
4036
+			EE_Error::add_error(
4037
+				sprintf(
4038
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
4039
+					$status
4040
+				),
4041
+				__FILE__,
4042
+				__FUNCTION__,
4043
+				__LINE__
4044
+			);
4045
+			$success = false;
4046
+		}
4047
+
4048
+		if ($success) {
4049
+			// made it here?  Stop dawdling then!!
4050
+			$success = $status === 'off'
4051
+				? $this->_deactivate_messenger($this->_active_messenger_name)
4052
+				: $this->_activate_messenger($this->_active_messenger_name);
4053
+		}
4054
+
4055
+		$this->_template_args['success'] = $success;
4056
+
4057
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
4058
+		$this->_return_json();
4059
+	}
4060
+
4061
+
4062
+	/**
4063
+	 * used by ajax from the messages settings page to activate|deactivate a message type
4064
+	 *
4065
+	 * @throws DomainException
4066
+	 * @throws EE_Error
4067
+	 * @throws ReflectionException
4068
+	 * @throws InvalidDataTypeException
4069
+	 * @throws InvalidInterfaceException
4070
+	 * @throws InvalidArgumentException
4071
+	 */
4072
+	public function activate_mt_toggle()
4073
+	{
4074
+		$success = true;
4075
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
4076
+
4077
+		// let's make sure we have the necessary data
4078
+		if (! $this->_active_message_type_name) {
4079
+			EE_Error::add_error(
4080
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
4081
+				__FILE__,
4082
+				__FUNCTION__,
4083
+				__LINE__
4084
+			);
4085
+			$success = false;
4086
+		}
4087
+
4088
+		if (! $this->_active_messenger_name) {
4089
+			EE_Error::add_error(
4090
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
4091
+				__FILE__,
4092
+				__FUNCTION__,
4093
+				__LINE__
4094
+			);
4095
+			$success = false;
4096
+		}
4097
+
4098
+		$status = $this->request->getRequestParam('status');
4099
+		if (! $status) {
4100
+			EE_Error::add_error(
4101
+				esc_html__(
4102
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
4103
+					'event_espresso'
4104
+				),
4105
+				__FILE__,
4106
+				__FUNCTION__,
4107
+				__LINE__
4108
+			);
4109
+			$success = false;
4110
+		}
4111
+
4112
+
4113
+		// do check to verify we have a valid status.
4114
+		if ($status !== 'activate' && $status !== 'deactivate') {
4115
+			EE_Error::add_error(
4116
+				sprintf(
4117
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
4118
+					$status
4119
+				),
4120
+				__FILE__,
4121
+				__FUNCTION__,
4122
+				__LINE__
4123
+			);
4124
+			$success = false;
4125
+		}
4126
+
4127
+
4128
+		// do a nonce check here since we're not arriving via a normal route
4129
+		$nonce = $this->request->getRequestParam('mt_nonce', '');
4130
+		$this->_verify_nonce($nonce, "{$this->_active_message_type_name}_nonce");
4131
+
4132
+		if ($success) {
4133
+			// made it here? um, what are you waiting for then?
4134
+			$success = $status === 'deactivate'
4135
+				? $this->_deactivate_message_type_for_messenger(
4136
+					$this->_active_messenger_name,
4137
+					$this->_active_message_type_name
4138
+				)
4139
+				: $this->_activate_message_type_for_messenger(
4140
+					$this->_active_messenger_name,
4141
+					$this->_active_message_type_name
4142
+				);
4143
+		}
4144
+
4145
+		$this->_template_args['success'] = $success;
4146
+		$this->_return_json();
4147
+	}
4148
+
4149
+
4150
+	/**
4151
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
4152
+	 *
4153
+	 * @param string $messenger_name The name of the messenger being activated
4154
+	 * @return bool
4155
+	 * @throws DomainException
4156
+	 * @throws EE_Error
4157
+	 * @throws InvalidArgumentException
4158
+	 * @throws ReflectionException
4159
+	 * @throws InvalidDataTypeException
4160
+	 * @throws InvalidInterfaceException
4161
+	 */
4162
+	protected function _activate_messenger($messenger_name)
4163
+	{
4164
+		$active_messenger          = $this->_message_resource_manager->get_messenger($messenger_name);
4165
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
4166
+			? $active_messenger->get_default_message_types()
4167
+			: [];
4168
+
4169
+		// ensure is active
4170
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_types_to_activate);
4171
+
4172
+		// set response_data for reload
4173
+		foreach ($message_types_to_activate as $message_type_name) {
4174
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4175
+			if (
4176
+				$this->_message_resource_manager->is_message_type_active_for_messenger(
4177
+					$messenger_name,
4178
+					$message_type_name
4179
+				)
4180
+				&& $message_type instanceof EE_message_type
4181
+			) {
4182
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
4183
+				if ($message_type->get_admin_settings_fields()) {
4184
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
4185
+				}
4186
+			}
4187
+		}
4188
+
4189
+		// add success message for activating messenger
4190
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4191
+	}
4192
+
4193
+
4194
+	/**
4195
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
4196
+	 *
4197
+	 * @param string $messenger_name The name of the messenger being activated
4198
+	 * @return bool
4199
+	 * @throws DomainException
4200
+	 * @throws EE_Error
4201
+	 * @throws InvalidArgumentException
4202
+	 * @throws ReflectionException
4203
+	 * @throws InvalidDataTypeException
4204
+	 * @throws InvalidInterfaceException
4205
+	 */
4206
+	protected function _deactivate_messenger($messenger_name)
4207
+	{
4208
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4209
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
4210
+
4211
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4212
+	}
4213
+
4214
+
4215
+	/**
4216
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4217
+	 *
4218
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
4219
+	 * @param string $message_type_name The name of the message type being activated for the messenger
4220
+	 * @return bool
4221
+	 * @throws DomainException
4222
+	 * @throws EE_Error
4223
+	 * @throws InvalidArgumentException
4224
+	 * @throws ReflectionException
4225
+	 * @throws InvalidDataTypeException
4226
+	 * @throws InvalidInterfaceException
4227
+	 */
4228
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4229
+	{
4230
+		$active_messenger         = $this->_message_resource_manager->get_messenger($messenger_name);
4231
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4232
+
4233
+		// ensure is active
4234
+		$this->_message_resource_manager->activate_messenger($active_messenger, $message_type_name);
4235
+
4236
+		// set response for load
4237
+		if (
4238
+			$this->_message_resource_manager->is_message_type_active_for_messenger(
4239
+				$messenger_name,
4240
+				$message_type_name
4241
+			)
4242
+		) {
4243
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
4244
+			if ($message_type_to_activate->get_admin_settings_fields()) {
4245
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
4246
+			}
4247
+		}
4248
+
4249
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
4250
+			$active_messenger,
4251
+			$message_type_to_activate
4252
+		);
4253
+	}
4254
+
4255
+
4256
+	/**
4257
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4258
+	 *
4259
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4260
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
4261
+	 * @return bool
4262
+	 * @throws DomainException
4263
+	 * @throws EE_Error
4264
+	 * @throws InvalidArgumentException
4265
+	 * @throws ReflectionException
4266
+	 * @throws InvalidDataTypeException
4267
+	 * @throws InvalidInterfaceException
4268
+	 */
4269
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4270
+	{
4271
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4272
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4273
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4274
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4275
+
4276
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4277
+			$active_messenger,
4278
+			$message_type_to_deactivate
4279
+		);
4280
+	}
4281
+
4282
+
4283
+	/**
4284
+	 * This just initializes the defaults for activating messenger and message type responses.
4285
+	 */
4286
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
4287
+	{
4288
+		$this->_template_args['data']['active_mts'] = [];
4289
+		$this->_template_args['data']['mt_reload']  = [];
4290
+	}
4291
+
4292
+
4293
+	/**
4294
+	 * Setup appropriate response for activating a messenger and/or message types
4295
+	 *
4296
+	 * @param EE_messenger         $messenger
4297
+	 * @param EE_message_type|null $message_type
4298
+	 * @return bool
4299
+	 * @throws DomainException
4300
+	 * @throws EE_Error
4301
+	 * @throws InvalidArgumentException
4302
+	 * @throws ReflectionException
4303
+	 * @throws InvalidDataTypeException
4304
+	 * @throws InvalidInterfaceException
4305
+	 */
4306
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
4307
+		$messenger,
4308
+		EE_Message_Type $message_type = null
4309
+	) {
4310
+		// if $messenger isn't a valid messenger object then get out.
4311
+		if (! $messenger instanceof EE_Messenger) {
4312
+			EE_Error::add_error(
4313
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4314
+				__FILE__,
4315
+				__FUNCTION__,
4316
+				__LINE__
4317
+			);
4318
+			return false;
4319
+		}
4320
+		// activated
4321
+		if ($this->_template_args['data']['active_mts']) {
4322
+			EE_Error::overwrite_success();
4323
+			// activated a message type with the messenger
4324
+			if ($message_type instanceof EE_message_type) {
4325
+				EE_Error::add_success(
4326
+					sprintf(
4327
+						esc_html__(
4328
+							'%s message type has been successfully activated with the %s messenger',
4329
+							'event_espresso'
4330
+						),
4331
+						ucwords($message_type->label['singular']),
4332
+						ucwords($messenger->label['singular'])
4333
+					)
4334
+				);
4335
+
4336
+				// if message type was invoice then let's make sure we activate the invoice payment method.
4337
+				if ($message_type->name === 'invoice') {
4338
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
4339
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4340
+					if ($pm instanceof EE_Payment_Method) {
4341
+						EE_Error::add_attention(
4342
+							esc_html__(
4343
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4344
+								'event_espresso'
4345
+							)
4346
+						);
4347
+					}
4348
+				}
4349
+				// just toggles the entire messenger
4350
+			} else {
4351
+				EE_Error::add_success(
4352
+					sprintf(
4353
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4354
+						ucwords($messenger->label['singular'])
4355
+					)
4356
+				);
4357
+			}
4358
+
4359
+			return true;
4360
+
4361
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4362
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4363
+			// in which case we just give a success message for the messenger being successfully activated.
4364
+		} else {
4365
+			if (! $messenger->get_default_message_types()) {
4366
+				// messenger doesn't have any default message types so still a success.
4367
+				EE_Error::add_success(
4368
+					sprintf(
4369
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4370
+						ucwords($messenger->label['singular'])
4371
+					)
4372
+				);
4373
+
4374
+				return true;
4375
+			} else {
4376
+				EE_Error::add_error(
4377
+					$message_type instanceof EE_message_type
4378
+					? sprintf(
4379
+						esc_html__(
4380
+							'%s message type was not successfully activated with the %s messenger',
4381
+							'event_espresso'
4382
+						),
4383
+						ucwords($message_type->label['singular']),
4384
+						ucwords($messenger->label['singular'])
4385
+					)
4386
+					: sprintf(
4387
+						esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4388
+						ucwords($messenger->label['singular'])
4389
+					),
4390
+					__FILE__,
4391
+					__FUNCTION__,
4392
+					__LINE__
4393
+				);
4394
+
4395
+				return false;
4396
+			}
4397
+		}
4398
+	}
4399
+
4400
+
4401
+	/**
4402
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
4403
+	 *
4404
+	 * @param EE_messenger         $messenger
4405
+	 * @param EE_message_type|null $message_type
4406
+	 * @return bool
4407
+	 * @throws DomainException
4408
+	 * @throws EE_Error
4409
+	 * @throws InvalidArgumentException
4410
+	 * @throws ReflectionException
4411
+	 * @throws InvalidDataTypeException
4412
+	 * @throws InvalidInterfaceException
4413
+	 */
4414
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4415
+		$messenger,
4416
+		EE_message_type $message_type = null
4417
+	) {
4418
+		EE_Error::overwrite_success();
4419
+
4420
+		// if $messenger isn't a valid messenger object then get out.
4421
+		if (! $messenger instanceof EE_Messenger) {
4422
+			EE_Error::add_error(
4423
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4424
+				__FILE__,
4425
+				__FUNCTION__,
4426
+				__LINE__
4427
+			);
4428
+
4429
+			return false;
4430
+		}
4431
+
4432
+		if ($message_type instanceof EE_message_type) {
4433
+			$message_type_name = $message_type->name;
4434
+			EE_Error::add_success(
4435
+				sprintf(
4436
+					esc_html__(
4437
+						'%s message type has been successfully deactivated for the %s messenger.',
4438
+						'event_espresso'
4439
+					),
4440
+					ucwords($message_type->label['singular']),
4441
+					ucwords($messenger->label['singular'])
4442
+				)
4443
+			);
4444
+		} else {
4445
+			$message_type_name = '';
4446
+			EE_Error::add_success(
4447
+				sprintf(
4448
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4449
+					ucwords($messenger->label['singular'])
4450
+				)
4451
+			);
4452
+		}
4453
+
4454
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4455
+		if (
4456
+			$messenger->name === 'html'
4457
+			&& (
4458
+				is_null($message_type)
4459
+				|| $message_type_name === 'invoice'
4460
+			)
4461
+		) {
4462
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
4463
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4464
+			if ($count_updated > 0) {
4465
+				$msg = $message_type_name === 'invoice'
4466
+					? esc_html__(
4467
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4468
+						'event_espresso'
4469
+					)
4470
+					: esc_html__(
4471
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4472
+						'event_espresso'
4473
+					);
4474
+				EE_Error::add_attention($msg);
4475
+			}
4476
+		}
4477
+
4478
+		return true;
4479
+	}
4480
+
4481
+
4482
+	/**
4483
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4484
+	 *
4485
+	 * @throws DomainException
4486
+	 * @throws EE_Error
4487
+	 * @throws EE_Error
4488
+	 */
4489
+	public function update_mt_form()
4490
+	{
4491
+		if (! $this->_active_messenger_name || ! $this->_active_message_type_name) {
4492
+			EE_Error::add_error(
4493
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4494
+				__FILE__,
4495
+				__FUNCTION__,
4496
+				__LINE__
4497
+			);
4498
+			$this->_return_json();
4499
+		}
4500
+
4501
+		$message_types = $this->get_installed_message_types();
4502
+		$message_type  = $message_types[ $this->_active_message_type_name ];
4503
+		$messenger     = $this->_message_resource_manager->get_active_messenger($this->_active_messenger_name);
4504
+		$content       = $this->_message_type_settings_content($message_type, $messenger, true);
4505
+
4506
+		$this->_template_args['success'] = true;
4507
+		$this->_template_args['content'] = $content;
4508
+		$this->_return_json();
4509
+	}
4510
+
4511
+
4512
+	/**
4513
+	 * this handles saving the settings for a messenger or message type
4514
+	 *
4515
+	 * @throws EE_Error
4516
+	 * @throws EE_Error
4517
+	 */
4518
+	public function save_settings()
4519
+	{
4520
+		$type = $this->request->getRequestParam('type');
4521
+		if (! $type) {
4522
+			EE_Error::add_error(
4523
+				esc_html__(
4524
+					'Cannot save settings because type is unknown (messenger settings or message type settings?)',
4525
+					'event_espresso'
4526
+				),
4527
+				__FILE__,
4528
+				__FUNCTION__,
4529
+				__LINE__
4530
+			);
4531
+			$this->_template_args['error'] = true;
4532
+			$this->_return_json();
4533
+		}
4534
+
4535
+
4536
+		if ($type === 'messenger') {
4537
+			// this should be an array.
4538
+			$settings  = $this->request->getRequestParam('messenger_settings', [], 'string', true);
4539
+			$messenger = $settings['messenger'];
4540
+			// remove messenger and message_types from settings array
4541
+			unset($settings['messenger'], $settings['message_types']);
4542
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4543
+		} elseif ($type === 'message_type') {
4544
+			$settings     = $this->request->getRequestParam('message_type_settings', [], 'string', true);
4545
+			$messenger    = $settings['messenger'];
4546
+			$message_type = $settings['message_type'];
4547
+			// remove messenger and message_types from settings array
4548
+			unset($settings['messenger'], $settings['message_types']);
4549
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4550
+		}
4551
+
4552
+		// okay we should have the data all setup.  Now we just update!
4553
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4554
+
4555
+		if ($success) {
4556
+			EE_Error::add_success(esc_html__('Settings updated', 'event_espresso'));
4557
+		} else {
4558
+			EE_Error::add_error(
4559
+				esc_html__('Settings did not get updated', 'event_espresso'),
4560
+				__FILE__,
4561
+				__FUNCTION__,
4562
+				__LINE__
4563
+			);
4564
+		}
4565
+
4566
+		$this->_template_args['success'] = $success;
4567
+		$this->_return_json();
4568
+	}
4569
+
4570
+
4571
+
4572
+
4573
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4574
+
4575
+
4576
+	/**
4577
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4578
+	 * However, this does not send immediately, it just queues for sending.
4579
+	 *
4580
+	 * @throws EE_Error
4581
+	 * @throws InvalidDataTypeException
4582
+	 * @throws InvalidInterfaceException
4583
+	 * @throws InvalidArgumentException
4584
+	 * @throws ReflectionException
4585
+	 * @since 4.9.0
4586
+	 */
4587
+	protected function _generate_now()
4588
+	{
4589
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4590
+		$this->_redirect_after_action(false, '', '', [], true);
4591
+	}
4592
+
4593
+
4594
+	/**
4595
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4596
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4597
+	 *
4598
+	 * @throws EE_Error
4599
+	 * @throws InvalidDataTypeException
4600
+	 * @throws InvalidInterfaceException
4601
+	 * @throws InvalidArgumentException
4602
+	 * @throws ReflectionException
4603
+	 * @since 4.9.0
4604
+	 */
4605
+	protected function _generate_and_send_now()
4606
+	{
4607
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4608
+		$this->_redirect_after_action(false, '', '', [], true);
4609
+	}
4610
+
4611
+
4612
+	/**
4613
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4614
+	 *
4615
+	 * @throws EE_Error
4616
+	 * @throws InvalidDataTypeException
4617
+	 * @throws InvalidInterfaceException
4618
+	 * @throws InvalidArgumentException
4619
+	 * @throws ReflectionException
4620
+	 * @since 4.9.0
4621
+	 */
4622
+	protected function _queue_for_resending()
4623
+	{
4624
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4625
+		$this->_redirect_after_action(false, '', '', [], true);
4626
+	}
4627
+
4628
+
4629
+	/**
4630
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4631
+	 *
4632
+	 * @throws EE_Error
4633
+	 * @throws InvalidDataTypeException
4634
+	 * @throws InvalidInterfaceException
4635
+	 * @throws InvalidArgumentException
4636
+	 * @throws ReflectionException
4637
+	 * @since 4.9.0
4638
+	 */
4639
+	protected function _send_now()
4640
+	{
4641
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4642
+		$this->_redirect_after_action(false, '', '', [], true);
4643
+	}
4644
+
4645
+
4646
+	/**
4647
+	 * Deletes EE_messages for IDs in the request.
4648
+	 *
4649
+	 * @throws EE_Error
4650
+	 * @throws InvalidDataTypeException
4651
+	 * @throws InvalidInterfaceException
4652
+	 * @throws InvalidArgumentException
4653
+	 * @since 4.9.0
4654
+	 */
4655
+	protected function _delete_ee_messages()
4656
+	{
4657
+		$MSG_IDs       = $this->_get_msg_ids_from_request();
4658
+		$deleted_count = 0;
4659
+		foreach ($MSG_IDs as $MSG_ID) {
4660
+			if ($this->getMsgModel()->delete_by_ID($MSG_ID)) {
4661
+				$deleted_count++;
4662
+			}
4663
+		}
4664
+		if ($deleted_count) {
4665
+			EE_Error::add_success(
4666
+				esc_html(
4667
+					_n(
4668
+						'Message successfully deleted',
4669
+						'Messages successfully deleted',
4670
+						$deleted_count,
4671
+						'event_espresso'
4672
+					)
4673
+				)
4674
+			);
4675
+		} else {
4676
+			EE_Error::add_error(
4677
+				_n('The message was not deleted.', 'The messages were not deleted', count($MSG_IDs), 'event_espresso'),
4678
+				__FILE__,
4679
+				__FUNCTION__,
4680
+				__LINE__
4681
+			);
4682
+		}
4683
+		$this->_redirect_after_action(false, '', '', [], true);
4684
+	}
4685
+
4686
+
4687
+	/**
4688
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4689
+	 *
4690
+	 * @return array
4691
+	 * @since 4.9.0
4692
+	 */
4693
+	protected function _get_msg_ids_from_request()
4694
+	{
4695
+		$MSG_IDs = $this->request->getRequestParam('MSG_ID', [], 'string', true);
4696
+		if (empty($MSG_IDs)) {
4697
+			return [];
4698
+		}
4699
+		// if 'MSG_ID' was just a single ID (not an array)
4700
+		// then $MSG_IDs will be something like [123] so $MSG_IDs[0] should be 123
4701
+		// otherwise, $MSG_IDs was already an array where message IDs were used as the keys
4702
+		return count($MSG_IDs) === 1 && isset($MSG_IDs[0])
4703
+			? $MSG_IDs
4704
+			: array_keys($MSG_IDs);
4705
+	}
4706 4706
 }
Please login to merge, or discard this patch.
modules/ticket_selector/EED_Ticket_Selector.module.php 1 patch
Indentation   +487 added lines, -487 removed lines patch added patch discarded remove patch
@@ -18,491 +18,491 @@
 block discarded – undo
18 18
  */
19 19
 class EED_Ticket_Selector extends EED_Module
20 20
 {
21
-    /**
22
-     * @var DisplayTicketSelector $ticket_selector
23
-     */
24
-    private static $ticket_selector;
25
-
26
-    /**
27
-     * @var TicketSelectorIframeEmbedButton $iframe_embed_button
28
-     */
29
-    private static $iframe_embed_button;
30
-
31
-
32
-    /**
33
-     * @return EED_Module|EED_Ticket_Selector
34
-     * @throws EE_Error
35
-     * @throws ReflectionException
36
-     */
37
-    public static function instance()
38
-    {
39
-        return parent::get_instance(__CLASS__);
40
-    }
41
-
42
-
43
-    /**
44
-     * @return EE_Ticket_Selector_Config
45
-     * @throws EE_Error
46
-     * @throws ReflectionException
47
-     */
48
-    public static function ticketConfig()
49
-    {
50
-        EED_Ticket_Selector::instance()->set_config();
51
-        return EED_Ticket_Selector::instance()->config();
52
-    }
53
-
54
-
55
-    /**
56
-     * @return void
57
-     */
58
-    protected function set_config()
59
-    {
60
-        if ($this->_config instanceof EE_Ticket_Selector_Config) {
61
-            return;
62
-        }
63
-        $this->set_config_section('template_settings');
64
-        $this->set_config_class('EE_Ticket_Selector_Config');
65
-        $this->set_config_name('EED_Ticket_Selector');
66
-    }
67
-
68
-
69
-    /**
70
-     *    set_hooks - for hooking into EE Core, other modules, etc
71
-     *
72
-     * @return void
73
-     */
74
-    public static function set_hooks()
75
-    {
76
-        // routing
77
-        EE_Config::register_route(
78
-            'iframe',
79
-            'EED_Ticket_Selector',
80
-            'ticket_selector_iframe',
81
-            'ticket_selector'
82
-        );
83
-        EE_Config::register_route(
84
-            'process_ticket_selections',
85
-            'EED_Ticket_Selector',
86
-            'process_ticket_selections'
87
-        );
88
-        EE_Config::register_route(
89
-            'cancel_ticket_selections',
90
-            'EED_Ticket_Selector',
91
-            'cancel_ticket_selections'
92
-        );
93
-        add_action('wp_loaded', ['EED_Ticket_Selector', 'set_definitions'], 2);
94
-        add_action('AHEE_event_details_header_bottom', ['EED_Ticket_Selector', 'display_ticket_selector'], 10, 1);
95
-        add_action('wp_enqueue_scripts', ['EED_Ticket_Selector', 'translate_js_strings'], 0);
96
-        add_action('wp_enqueue_scripts', ['EED_Ticket_Selector', 'load_tckt_slctr_assets'], 10);
97
-        EED_Ticket_Selector::loadIframeAssets();
98
-    }
99
-
100
-
101
-    /**
102
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
103
-     *
104
-     * @return void
105
-     */
106
-    public static function set_hooks_admin()
107
-    {
108
-        // hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
-        // to load assets for "espresso_events" page on the "edit" route (action)
110
-        add_action(
111
-            'admin_init',
112
-            ['EED_Ticket_Selector', 'ticket_selector_iframe_embed_button'],
113
-            10
114
-        );
115
-        /**
116
-         * Make sure assets for the ticket selector are loaded on the espresso registrations route so  admin side
117
-         * registrations work.
118
-         */
119
-        add_action(
120
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_registrations__new_registration',
121
-            ['EED_Ticket_Selector', 'set_definitions'],
122
-            10
123
-        );
124
-    }
125
-
126
-
127
-    /**
128
-     *    set_definitions
129
-     *
130
-     * @return void
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public static function set_definitions()
135
-    {
136
-        // don't do this twice
137
-        if (defined('TICKET_SELECTOR_ASSETS_URL')) {
138
-            return;
139
-        }
140
-        define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
141
-        define(
142
-            'TICKET_SELECTOR_TEMPLATES_PATH',
143
-            str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/'
144
-        );
145
-        // initialize config
146
-        EED_Ticket_Selector::instance()->set_config();
147
-        // if config is not set, initialize
148
-        if (
149
-            ! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
150
-        ) {
151
-            EED_Ticket_Selector::instance()->set_config();
152
-            EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector =
153
-                EED_Ticket_Selector::instance()->config();
154
-        }
155
-    }
156
-
157
-
158
-    /**
159
-     * @return DisplayTicketSelector
160
-     * @throws EE_Error
161
-     * @throws ReflectionException
162
-     */
163
-    public static function ticketSelector(): DisplayTicketSelector
164
-    {
165
-        if (! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
166
-            EED_Ticket_Selector::$ticket_selector = LoaderFactory::getLoader()->getShared(
167
-                DisplayTicketSelector::class,
168
-                [
169
-                    null,
170
-                    EED_Ticket_Selector::getRequest(),
171
-                    EED_Ticket_Selector::ticketConfig(),
172
-                    EED_Events_Archive::is_iframe(),
173
-                ]
174
-            );
175
-        }
176
-        return EED_Ticket_Selector::$ticket_selector;
177
-    }
178
-
179
-
180
-    /**
181
-     * gets the ball rolling
182
-     *
183
-     * @param WP $WP
184
-     * @return void
185
-     */
186
-    public function run($WP)
187
-    {
188
-    }
189
-
190
-
191
-    /**
192
-     * @return TicketSelectorIframeEmbedButton
193
-     */
194
-    public static function getIframeEmbedButton()
195
-    {
196
-        if (! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
197
-            self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
198
-        }
199
-        return self::$iframe_embed_button;
200
-    }
201
-
202
-
203
-    /**
204
-     * ticket_selector_iframe_embed_button
205
-     *
206
-     * @return void
207
-     */
208
-    public static function ticket_selector_iframe_embed_button()
209
-    {
210
-        $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
211
-        $iframe_embed_button->addEventEditorIframeEmbedButton();
212
-    }
213
-
214
-
215
-    /**
216
-     * ticket_selector_iframe
217
-     *
218
-     * @return void
219
-     * @throws DomainException
220
-     */
221
-    public function ticket_selector_iframe()
222
-    {
223
-        EE_Dependency_Map::register_dependencies(
224
-            TicketSelectorIframe::class,
225
-            [
226
-                'EEM_Event'                                            => EE_Dependency_Map::load_from_cache,
227
-                'EventEspresso\core\services\request\CurrentPage'      => EE_Dependency_Map::load_from_cache,
228
-                'EventEspresso\core\services\request\RequestInterface' => EE_Dependency_Map::load_from_cache,
229
-            ]
230
-        );
231
-        $ticket_selector_iframe = LoaderFactory::getLoader()->getNew(TicketSelectorIframe::class);
232
-        $ticket_selector_iframe->display();
233
-    }
234
-
235
-
236
-    /**
237
-     * creates buttons for selecting number of attendees for an event
238
-     *
239
-     * @param WP_Post|int $event
240
-     * @param bool        $view_details
241
-     * @return string
242
-     * @throws EE_Error
243
-     * @throws ReflectionException
244
-     */
245
-    public static function display_ticket_selector($event = null, $view_details = false)
246
-    {
247
-        return EED_Ticket_Selector::ticketSelector()->display($event, $view_details);
248
-    }
249
-
250
-
251
-    /**
252
-     * @return bool  or FALSE
253
-     * @throws EE_Error
254
-     * @throws InvalidArgumentException
255
-     * @throws InvalidInterfaceException
256
-     * @throws InvalidDataTypeException
257
-     * @throws ReflectionException
258
-     */
259
-    public function process_ticket_selections()
260
-    {
261
-        /** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
262
-        $form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
263
-        return $form->processTicketSelections();
264
-    }
265
-
266
-
267
-    /**
268
-     * @return bool
269
-     * @throws InvalidArgumentException
270
-     * @throws InvalidInterfaceException
271
-     * @throws InvalidDataTypeException
272
-     * @throws EE_Error
273
-     * @throws ReflectionException
274
-     */
275
-    public static function cancel_ticket_selections()
276
-    {
277
-        /** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
278
-        $form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
279
-        return $form->cancelTicketSelections();
280
-    }
281
-
282
-
283
-    /**
284
-     * @return void
285
-     */
286
-    public static function translate_js_strings()
287
-    {
288
-        EE_Registry::$i18n_js_strings['please_select_date_filter_notice'] = esc_html__(
289
-            'please select a datetime',
290
-            'event_espresso'
291
-        );
292
-    }
293
-
294
-
295
-    /**
296
-     * @return void
297
-     */
298
-    public static function load_tckt_slctr_assets()
299
-    {
300
-        if (apply_filters('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', false)) {
301
-            // add some style
302
-            wp_register_style(
303
-                'ticket_selector',
304
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css',
305
-                [],
306
-                EVENT_ESPRESSO_VERSION
307
-            );
308
-            wp_enqueue_style('ticket_selector');
309
-            // make it dance
310
-            wp_register_script(
311
-                'ticket_selector',
312
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js',
313
-                ['espresso_core'],
314
-                EVENT_ESPRESSO_VERSION,
315
-                true
316
-            );
317
-            wp_enqueue_script('ticket_selector');
318
-            require_once EE_LIBRARIES
319
-                         . 'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php';
320
-            EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
321
-        }
322
-    }
323
-
324
-
325
-    /**
326
-     * @return void
327
-     */
328
-    public static function loadIframeAssets()
329
-    {
330
-        // for event lists
331
-        add_filter(
332
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
333
-            ['EED_Ticket_Selector', 'iframeCss']
334
-        );
335
-        add_filter(
336
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
337
-            ['EED_Ticket_Selector', 'iframeJs']
338
-        );
339
-        // for ticket selectors
340
-        add_filter(
341
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
342
-            ['EED_Ticket_Selector', 'iframeCss']
343
-        );
344
-    }
345
-
346
-
347
-    /**
348
-     * Informs the rest of the forms system what CSS and JS is needed to display the input
349
-     *
350
-     * @param array $iframe_css
351
-     * @return array
352
-     */
353
-    public static function iframeCss(array $iframe_css)
354
-    {
355
-        $iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css';
356
-        return $iframe_css;
357
-    }
358
-
359
-
360
-    /**
361
-     * Informs the rest of the forms system what CSS and JS is needed to display the input
362
-     *
363
-     * @param array $iframe_js
364
-     * @return array
365
-     */
366
-    public static function iframeJs(array $iframe_js)
367
-    {
368
-        $iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js';
369
-        return $iframe_js;
370
-    }
371
-
372
-
373
-    /****************************** DEPRECATED ******************************/
374
-
375
-
376
-    /**
377
-     * @return string
378
-     * @throws EE_Error
379
-     * @throws ReflectionException
380
-     * @deprecated
381
-     */
382
-    public static function display_view_details_btn()
383
-    {
384
-        // todo add doing_it_wrong() notice during next major version
385
-        return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
386
-    }
387
-
388
-
389
-    /**
390
-     * @return string
391
-     * @throws EE_Error
392
-     * @throws ReflectionException
393
-     * @deprecated
394
-     */
395
-    public static function display_ticket_selector_submit()
396
-    {
397
-        // todo add doing_it_wrong() notice during next major version
398
-        return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
399
-    }
400
-
401
-
402
-    /**
403
-     * @param string $permalink_string
404
-     * @param int    $id
405
-     * @param string $new_title
406
-     * @param string $new_slug
407
-     * @return string
408
-     * @throws InvalidArgumentException
409
-     * @throws InvalidDataTypeException
410
-     * @throws InvalidInterfaceException
411
-     * @deprecated
412
-     */
413
-    public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
414
-    {
415
-        $request = self::getRequest();
416
-        // todo add doing_it_wrong() notice during next major version
417
-        if (
418
-            $request->getRequestParam('page') === 'espresso_events'
419
-            && $request->getRequestParam('action') === 'edit'
420
-        ) {
421
-            $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
422
-            $iframe_embed_button->addEventEditorIframeEmbedButton();
423
-        }
424
-        return '';
425
-    }
426
-
427
-
428
-    /**
429
-     * @param int    $ID
430
-     * @param string $external_url
431
-     * @return string
432
-     * @throws EE_Error
433
-     * @throws ReflectionException
434
-     * @deprecated
435
-     */
436
-    public static function ticket_selector_form_open($ID = 0, $external_url = '')
437
-    {
438
-        // todo add doing_it_wrong() notice during next major version
439
-        return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
440
-    }
441
-
442
-
443
-    /**
444
-     * @return string
445
-     * @throws EE_Error
446
-     * @throws ReflectionException
447
-     * @deprecated
448
-     */
449
-    public static function ticket_selector_form_close()
450
-    {
451
-        // todo add doing_it_wrong() notice during next major version
452
-        return EED_Ticket_Selector::ticketSelector()->formClose();
453
-    }
454
-
455
-
456
-    /**
457
-     * @return string
458
-     * @throws EE_Error
459
-     * @throws ReflectionException
460
-     * @deprecated
461
-     */
462
-    public static function no_tkt_slctr_end_dv()
463
-    {
464
-        // todo add doing_it_wrong() notice during next major version
465
-        return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
466
-    }
467
-
468
-
469
-    /**
470
-     * @return string
471
-     * @throws EE_Error
472
-     * @throws ReflectionException
473
-     * @deprecated 4.9.13
474
-     */
475
-    public static function tkt_slctr_end_dv()
476
-    {
477
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
478
-    }
479
-
480
-
481
-    /**
482
-     * @return string
483
-     * @throws EE_Error
484
-     * @throws ReflectionException
485
-     * @deprecated
486
-     */
487
-    public static function clear_tkt_slctr()
488
-    {
489
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
490
-    }
491
-
492
-
493
-    /**
494
-     * @deprecated
495
-     */
496
-    public static function load_tckt_slctr_assets_admin()
497
-    {
498
-        $request = self::getRequest();
499
-        // todo add doing_it_wrong() notice during next major version
500
-        if (
501
-            $request->getRequestParam('page') === 'espresso_events'
502
-            && $request->getRequestParam('action') === 'edit'
503
-        ) {
504
-            $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
505
-            $iframe_embed_button->embedButtonAssets();
506
-        }
507
-    }
21
+	/**
22
+	 * @var DisplayTicketSelector $ticket_selector
23
+	 */
24
+	private static $ticket_selector;
25
+
26
+	/**
27
+	 * @var TicketSelectorIframeEmbedButton $iframe_embed_button
28
+	 */
29
+	private static $iframe_embed_button;
30
+
31
+
32
+	/**
33
+	 * @return EED_Module|EED_Ticket_Selector
34
+	 * @throws EE_Error
35
+	 * @throws ReflectionException
36
+	 */
37
+	public static function instance()
38
+	{
39
+		return parent::get_instance(__CLASS__);
40
+	}
41
+
42
+
43
+	/**
44
+	 * @return EE_Ticket_Selector_Config
45
+	 * @throws EE_Error
46
+	 * @throws ReflectionException
47
+	 */
48
+	public static function ticketConfig()
49
+	{
50
+		EED_Ticket_Selector::instance()->set_config();
51
+		return EED_Ticket_Selector::instance()->config();
52
+	}
53
+
54
+
55
+	/**
56
+	 * @return void
57
+	 */
58
+	protected function set_config()
59
+	{
60
+		if ($this->_config instanceof EE_Ticket_Selector_Config) {
61
+			return;
62
+		}
63
+		$this->set_config_section('template_settings');
64
+		$this->set_config_class('EE_Ticket_Selector_Config');
65
+		$this->set_config_name('EED_Ticket_Selector');
66
+	}
67
+
68
+
69
+	/**
70
+	 *    set_hooks - for hooking into EE Core, other modules, etc
71
+	 *
72
+	 * @return void
73
+	 */
74
+	public static function set_hooks()
75
+	{
76
+		// routing
77
+		EE_Config::register_route(
78
+			'iframe',
79
+			'EED_Ticket_Selector',
80
+			'ticket_selector_iframe',
81
+			'ticket_selector'
82
+		);
83
+		EE_Config::register_route(
84
+			'process_ticket_selections',
85
+			'EED_Ticket_Selector',
86
+			'process_ticket_selections'
87
+		);
88
+		EE_Config::register_route(
89
+			'cancel_ticket_selections',
90
+			'EED_Ticket_Selector',
91
+			'cancel_ticket_selections'
92
+		);
93
+		add_action('wp_loaded', ['EED_Ticket_Selector', 'set_definitions'], 2);
94
+		add_action('AHEE_event_details_header_bottom', ['EED_Ticket_Selector', 'display_ticket_selector'], 10, 1);
95
+		add_action('wp_enqueue_scripts', ['EED_Ticket_Selector', 'translate_js_strings'], 0);
96
+		add_action('wp_enqueue_scripts', ['EED_Ticket_Selector', 'load_tckt_slctr_assets'], 10);
97
+		EED_Ticket_Selector::loadIframeAssets();
98
+	}
99
+
100
+
101
+	/**
102
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
103
+	 *
104
+	 * @return void
105
+	 */
106
+	public static function set_hooks_admin()
107
+	{
108
+		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
+		// to load assets for "espresso_events" page on the "edit" route (action)
110
+		add_action(
111
+			'admin_init',
112
+			['EED_Ticket_Selector', 'ticket_selector_iframe_embed_button'],
113
+			10
114
+		);
115
+		/**
116
+		 * Make sure assets for the ticket selector are loaded on the espresso registrations route so  admin side
117
+		 * registrations work.
118
+		 */
119
+		add_action(
120
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_registrations__new_registration',
121
+			['EED_Ticket_Selector', 'set_definitions'],
122
+			10
123
+		);
124
+	}
125
+
126
+
127
+	/**
128
+	 *    set_definitions
129
+	 *
130
+	 * @return void
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public static function set_definitions()
135
+	{
136
+		// don't do this twice
137
+		if (defined('TICKET_SELECTOR_ASSETS_URL')) {
138
+			return;
139
+		}
140
+		define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
141
+		define(
142
+			'TICKET_SELECTOR_TEMPLATES_PATH',
143
+			str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/'
144
+		);
145
+		// initialize config
146
+		EED_Ticket_Selector::instance()->set_config();
147
+		// if config is not set, initialize
148
+		if (
149
+			! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
150
+		) {
151
+			EED_Ticket_Selector::instance()->set_config();
152
+			EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector =
153
+				EED_Ticket_Selector::instance()->config();
154
+		}
155
+	}
156
+
157
+
158
+	/**
159
+	 * @return DisplayTicketSelector
160
+	 * @throws EE_Error
161
+	 * @throws ReflectionException
162
+	 */
163
+	public static function ticketSelector(): DisplayTicketSelector
164
+	{
165
+		if (! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
166
+			EED_Ticket_Selector::$ticket_selector = LoaderFactory::getLoader()->getShared(
167
+				DisplayTicketSelector::class,
168
+				[
169
+					null,
170
+					EED_Ticket_Selector::getRequest(),
171
+					EED_Ticket_Selector::ticketConfig(),
172
+					EED_Events_Archive::is_iframe(),
173
+				]
174
+			);
175
+		}
176
+		return EED_Ticket_Selector::$ticket_selector;
177
+	}
178
+
179
+
180
+	/**
181
+	 * gets the ball rolling
182
+	 *
183
+	 * @param WP $WP
184
+	 * @return void
185
+	 */
186
+	public function run($WP)
187
+	{
188
+	}
189
+
190
+
191
+	/**
192
+	 * @return TicketSelectorIframeEmbedButton
193
+	 */
194
+	public static function getIframeEmbedButton()
195
+	{
196
+		if (! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
197
+			self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
198
+		}
199
+		return self::$iframe_embed_button;
200
+	}
201
+
202
+
203
+	/**
204
+	 * ticket_selector_iframe_embed_button
205
+	 *
206
+	 * @return void
207
+	 */
208
+	public static function ticket_selector_iframe_embed_button()
209
+	{
210
+		$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
211
+		$iframe_embed_button->addEventEditorIframeEmbedButton();
212
+	}
213
+
214
+
215
+	/**
216
+	 * ticket_selector_iframe
217
+	 *
218
+	 * @return void
219
+	 * @throws DomainException
220
+	 */
221
+	public function ticket_selector_iframe()
222
+	{
223
+		EE_Dependency_Map::register_dependencies(
224
+			TicketSelectorIframe::class,
225
+			[
226
+				'EEM_Event'                                            => EE_Dependency_Map::load_from_cache,
227
+				'EventEspresso\core\services\request\CurrentPage'      => EE_Dependency_Map::load_from_cache,
228
+				'EventEspresso\core\services\request\RequestInterface' => EE_Dependency_Map::load_from_cache,
229
+			]
230
+		);
231
+		$ticket_selector_iframe = LoaderFactory::getLoader()->getNew(TicketSelectorIframe::class);
232
+		$ticket_selector_iframe->display();
233
+	}
234
+
235
+
236
+	/**
237
+	 * creates buttons for selecting number of attendees for an event
238
+	 *
239
+	 * @param WP_Post|int $event
240
+	 * @param bool        $view_details
241
+	 * @return string
242
+	 * @throws EE_Error
243
+	 * @throws ReflectionException
244
+	 */
245
+	public static function display_ticket_selector($event = null, $view_details = false)
246
+	{
247
+		return EED_Ticket_Selector::ticketSelector()->display($event, $view_details);
248
+	}
249
+
250
+
251
+	/**
252
+	 * @return bool  or FALSE
253
+	 * @throws EE_Error
254
+	 * @throws InvalidArgumentException
255
+	 * @throws InvalidInterfaceException
256
+	 * @throws InvalidDataTypeException
257
+	 * @throws ReflectionException
258
+	 */
259
+	public function process_ticket_selections()
260
+	{
261
+		/** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
262
+		$form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
263
+		return $form->processTicketSelections();
264
+	}
265
+
266
+
267
+	/**
268
+	 * @return bool
269
+	 * @throws InvalidArgumentException
270
+	 * @throws InvalidInterfaceException
271
+	 * @throws InvalidDataTypeException
272
+	 * @throws EE_Error
273
+	 * @throws ReflectionException
274
+	 */
275
+	public static function cancel_ticket_selections()
276
+	{
277
+		/** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
278
+		$form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
279
+		return $form->cancelTicketSelections();
280
+	}
281
+
282
+
283
+	/**
284
+	 * @return void
285
+	 */
286
+	public static function translate_js_strings()
287
+	{
288
+		EE_Registry::$i18n_js_strings['please_select_date_filter_notice'] = esc_html__(
289
+			'please select a datetime',
290
+			'event_espresso'
291
+		);
292
+	}
293
+
294
+
295
+	/**
296
+	 * @return void
297
+	 */
298
+	public static function load_tckt_slctr_assets()
299
+	{
300
+		if (apply_filters('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', false)) {
301
+			// add some style
302
+			wp_register_style(
303
+				'ticket_selector',
304
+				TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css',
305
+				[],
306
+				EVENT_ESPRESSO_VERSION
307
+			);
308
+			wp_enqueue_style('ticket_selector');
309
+			// make it dance
310
+			wp_register_script(
311
+				'ticket_selector',
312
+				TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js',
313
+				['espresso_core'],
314
+				EVENT_ESPRESSO_VERSION,
315
+				true
316
+			);
317
+			wp_enqueue_script('ticket_selector');
318
+			require_once EE_LIBRARIES
319
+						 . 'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php';
320
+			EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
321
+		}
322
+	}
323
+
324
+
325
+	/**
326
+	 * @return void
327
+	 */
328
+	public static function loadIframeAssets()
329
+	{
330
+		// for event lists
331
+		add_filter(
332
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
333
+			['EED_Ticket_Selector', 'iframeCss']
334
+		);
335
+		add_filter(
336
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
337
+			['EED_Ticket_Selector', 'iframeJs']
338
+		);
339
+		// for ticket selectors
340
+		add_filter(
341
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
342
+			['EED_Ticket_Selector', 'iframeCss']
343
+		);
344
+	}
345
+
346
+
347
+	/**
348
+	 * Informs the rest of the forms system what CSS and JS is needed to display the input
349
+	 *
350
+	 * @param array $iframe_css
351
+	 * @return array
352
+	 */
353
+	public static function iframeCss(array $iframe_css)
354
+	{
355
+		$iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css';
356
+		return $iframe_css;
357
+	}
358
+
359
+
360
+	/**
361
+	 * Informs the rest of the forms system what CSS and JS is needed to display the input
362
+	 *
363
+	 * @param array $iframe_js
364
+	 * @return array
365
+	 */
366
+	public static function iframeJs(array $iframe_js)
367
+	{
368
+		$iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js';
369
+		return $iframe_js;
370
+	}
371
+
372
+
373
+	/****************************** DEPRECATED ******************************/
374
+
375
+
376
+	/**
377
+	 * @return string
378
+	 * @throws EE_Error
379
+	 * @throws ReflectionException
380
+	 * @deprecated
381
+	 */
382
+	public static function display_view_details_btn()
383
+	{
384
+		// todo add doing_it_wrong() notice during next major version
385
+		return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
386
+	}
387
+
388
+
389
+	/**
390
+	 * @return string
391
+	 * @throws EE_Error
392
+	 * @throws ReflectionException
393
+	 * @deprecated
394
+	 */
395
+	public static function display_ticket_selector_submit()
396
+	{
397
+		// todo add doing_it_wrong() notice during next major version
398
+		return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
399
+	}
400
+
401
+
402
+	/**
403
+	 * @param string $permalink_string
404
+	 * @param int    $id
405
+	 * @param string $new_title
406
+	 * @param string $new_slug
407
+	 * @return string
408
+	 * @throws InvalidArgumentException
409
+	 * @throws InvalidDataTypeException
410
+	 * @throws InvalidInterfaceException
411
+	 * @deprecated
412
+	 */
413
+	public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
414
+	{
415
+		$request = self::getRequest();
416
+		// todo add doing_it_wrong() notice during next major version
417
+		if (
418
+			$request->getRequestParam('page') === 'espresso_events'
419
+			&& $request->getRequestParam('action') === 'edit'
420
+		) {
421
+			$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
422
+			$iframe_embed_button->addEventEditorIframeEmbedButton();
423
+		}
424
+		return '';
425
+	}
426
+
427
+
428
+	/**
429
+	 * @param int    $ID
430
+	 * @param string $external_url
431
+	 * @return string
432
+	 * @throws EE_Error
433
+	 * @throws ReflectionException
434
+	 * @deprecated
435
+	 */
436
+	public static function ticket_selector_form_open($ID = 0, $external_url = '')
437
+	{
438
+		// todo add doing_it_wrong() notice during next major version
439
+		return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
440
+	}
441
+
442
+
443
+	/**
444
+	 * @return string
445
+	 * @throws EE_Error
446
+	 * @throws ReflectionException
447
+	 * @deprecated
448
+	 */
449
+	public static function ticket_selector_form_close()
450
+	{
451
+		// todo add doing_it_wrong() notice during next major version
452
+		return EED_Ticket_Selector::ticketSelector()->formClose();
453
+	}
454
+
455
+
456
+	/**
457
+	 * @return string
458
+	 * @throws EE_Error
459
+	 * @throws ReflectionException
460
+	 * @deprecated
461
+	 */
462
+	public static function no_tkt_slctr_end_dv()
463
+	{
464
+		// todo add doing_it_wrong() notice during next major version
465
+		return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
466
+	}
467
+
468
+
469
+	/**
470
+	 * @return string
471
+	 * @throws EE_Error
472
+	 * @throws ReflectionException
473
+	 * @deprecated 4.9.13
474
+	 */
475
+	public static function tkt_slctr_end_dv()
476
+	{
477
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
478
+	}
479
+
480
+
481
+	/**
482
+	 * @return string
483
+	 * @throws EE_Error
484
+	 * @throws ReflectionException
485
+	 * @deprecated
486
+	 */
487
+	public static function clear_tkt_slctr()
488
+	{
489
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
490
+	}
491
+
492
+
493
+	/**
494
+	 * @deprecated
495
+	 */
496
+	public static function load_tckt_slctr_assets_admin()
497
+	{
498
+		$request = self::getRequest();
499
+		// todo add doing_it_wrong() notice during next major version
500
+		if (
501
+			$request->getRequestParam('page') === 'espresso_events'
502
+			&& $request->getRequestParam('action') === 'edit'
503
+		) {
504
+			$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
505
+			$iframe_embed_button->embedButtonAssets();
506
+		}
507
+	}
508 508
 }
Please login to merge, or discard this patch.
modules/ticket_selector/TicketSelectorIframe.php 1 patch
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -19,77 +19,77 @@
 block discarded – undo
19 19
  */
20 20
 class TicketSelectorIframe extends Iframe
21 21
 {
22
-    /**
23
-     * TicketSelectorIframe constructor.
24
-     *
25
-     * @param EEM_Event        $event_model
26
-     * @param CurrentPage      $current_page
27
-     * @param RequestInterface $request
28
-     * @throws EE_Error
29
-     */
30
-    public function __construct(EEM_Event $event_model, CurrentPage $current_page, RequestInterface $request)
31
-    {
32
-        $current_page->setEspressoPage(true);
33
-        $ticket_selector = LoaderFactory::getLoader()->getNew(DisplayTicketSelector::class);
34
-        $ticket_selector->setIframe();
35
-        $event = $event_model->get_one_by_ID($request->getRequestParam('event', 0, 'int'));
36
-        parent::__construct(
37
-            esc_html__('Ticket Selector', 'event_espresso'),
38
-            $ticket_selector->display($event)
39
-        );
40
-        $this->addStylesheets(
41
-            apply_filters(
42
-                'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
43
-                array(
44
-                    'ticket_selector_embed' => TICKET_SELECTOR_ASSETS_URL
45
-                                               . 'ticket_selector_embed.css?ver='
46
-                                               . EVENT_ESPRESSO_VERSION,
47
-                    'ticket_selector'       => TICKET_SELECTOR_ASSETS_URL
48
-                                               . 'ticket_selector.css?ver='
49
-                                               . EVENT_ESPRESSO_VERSION,
50
-                ),
51
-                $this
52
-            )
53
-        );
54
-        if (! apply_filters('FHEE__EED_Ticket_Selector__ticket_selector_iframe__load_theme_css', false, $this)) {
55
-            $this->addStylesheets(array('site_theme' => ''));
56
-        }
57
-        $this->addScripts(
58
-            apply_filters(
59
-                'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
60
-                array(
61
-                    'ticket_selector_iframe_embed' => TICKET_SELECTOR_ASSETS_URL
62
-                                                      . 'ticket_selector_iframe_embed.js?ver='
63
-                                                      . EVENT_ESPRESSO_VERSION,
64
-                ),
65
-                $this
66
-            )
67
-        );
68
-        $js_attributes = apply_filters(
69
-            'FHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__js_attributes',
70
-            array(),
71
-            $this
72
-        );
73
-        if (! empty($js_attributes)) {
74
-            $this->addScriptAttributes($js_attributes);
75
-        }
76
-        $this->addLocalizedVars(
77
-            apply_filters(
78
-                'FHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__localized_vars',
79
-                array(
80
-                    'ticket_selector_iframe' => true,
81
-                    'EEDTicketSelectorMsg'   => wp_strip_all_tags(
82
-                        __(
83
-                            'Please choose at least one ticket before continuing.',
84
-                            'event_espresso'
85
-                        )
86
-                    ),
87
-                )
88
-            )
89
-        );
90
-        do_action(
91
-            'AHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__complete',
92
-            $this
93
-        );
94
-    }
22
+	/**
23
+	 * TicketSelectorIframe constructor.
24
+	 *
25
+	 * @param EEM_Event        $event_model
26
+	 * @param CurrentPage      $current_page
27
+	 * @param RequestInterface $request
28
+	 * @throws EE_Error
29
+	 */
30
+	public function __construct(EEM_Event $event_model, CurrentPage $current_page, RequestInterface $request)
31
+	{
32
+		$current_page->setEspressoPage(true);
33
+		$ticket_selector = LoaderFactory::getLoader()->getNew(DisplayTicketSelector::class);
34
+		$ticket_selector->setIframe();
35
+		$event = $event_model->get_one_by_ID($request->getRequestParam('event', 0, 'int'));
36
+		parent::__construct(
37
+			esc_html__('Ticket Selector', 'event_espresso'),
38
+			$ticket_selector->display($event)
39
+		);
40
+		$this->addStylesheets(
41
+			apply_filters(
42
+				'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
43
+				array(
44
+					'ticket_selector_embed' => TICKET_SELECTOR_ASSETS_URL
45
+											   . 'ticket_selector_embed.css?ver='
46
+											   . EVENT_ESPRESSO_VERSION,
47
+					'ticket_selector'       => TICKET_SELECTOR_ASSETS_URL
48
+											   . 'ticket_selector.css?ver='
49
+											   . EVENT_ESPRESSO_VERSION,
50
+				),
51
+				$this
52
+			)
53
+		);
54
+		if (! apply_filters('FHEE__EED_Ticket_Selector__ticket_selector_iframe__load_theme_css', false, $this)) {
55
+			$this->addStylesheets(array('site_theme' => ''));
56
+		}
57
+		$this->addScripts(
58
+			apply_filters(
59
+				'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
60
+				array(
61
+					'ticket_selector_iframe_embed' => TICKET_SELECTOR_ASSETS_URL
62
+													  . 'ticket_selector_iframe_embed.js?ver='
63
+													  . EVENT_ESPRESSO_VERSION,
64
+				),
65
+				$this
66
+			)
67
+		);
68
+		$js_attributes = apply_filters(
69
+			'FHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__js_attributes',
70
+			array(),
71
+			$this
72
+		);
73
+		if (! empty($js_attributes)) {
74
+			$this->addScriptAttributes($js_attributes);
75
+		}
76
+		$this->addLocalizedVars(
77
+			apply_filters(
78
+				'FHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__localized_vars',
79
+				array(
80
+					'ticket_selector_iframe' => true,
81
+					'EEDTicketSelectorMsg'   => wp_strip_all_tags(
82
+						__(
83
+							'Please choose at least one ticket before continuing.',
84
+							'event_espresso'
85
+						)
86
+					),
87
+				)
88
+			)
89
+		);
90
+		do_action(
91
+			'AHEE__EventEspresso_modules_ticket_selector_TicketSelectorIframe__construct__complete',
92
+			$this
93
+		);
94
+	}
95 95
 }
Please login to merge, or discard this patch.
modules/core_rest_api/EED_Core_Rest_Api.module.php 1 patch
Indentation   +1378 added lines, -1378 removed lines patch added patch discarded remove patch
@@ -21,1382 +21,1382 @@
 block discarded – undo
21 21
  */
22 22
 class EED_Core_Rest_Api extends EED_Module
23 23
 {
24
-    const ee_api_namespace = Domain::API_NAMESPACE;
25
-
26
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
27
-
28
-    const saved_routes_option_names = 'ee_core_routes';
29
-
30
-    /**
31
-     * string used in _links response bodies to make them globally unique.
32
-     *
33
-     * @see http://v2.wp-api.org/extending/linking/
34
-     */
35
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
36
-
37
-    /**
38
-     * @var CalculatedModelFields
39
-     */
40
-    protected static $_field_calculator;
41
-
42
-
43
-    /**
44
-     * @return EED_Core_Rest_Api|EED_Module
45
-     */
46
-    public static function instance()
47
-    {
48
-        return parent::get_instance(EED_Core_Rest_Api::class);
49
-    }
50
-
51
-
52
-    /**
53
-     *    set_hooks - for hooking into EE Core, other modules, etc
54
-     *
55
-     * @access    public
56
-     * @return    void
57
-     */
58
-    public static function set_hooks()
59
-    {
60
-    }
61
-
62
-
63
-    /**
64
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
-     *
66
-     * @access    public
67
-     * @return    void
68
-     */
69
-    public static function set_hooks_admin()
70
-    {
71
-    }
72
-
73
-
74
-    public static function set_hooks_both()
75
-    {
76
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
77
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
78
-        add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
79
-        add_filter(
80
-            'rest_index',
81
-            ['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
82
-        );
83
-    }
84
-
85
-
86
-    /**
87
-     * @since   5.0.0.p
88
-     */
89
-    public static function loadCalculatedModelFields()
90
-    {
91
-        EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
-            'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
-        );
94
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
95
-    }
96
-
97
-
98
-    /**
99
-     * sets up hooks which only need to be included as part of REST API requests;
100
-     * other requests like to the frontend or admin etc don't need them
101
-     *
102
-     * @throws EE_Error
103
-     */
104
-    public static function set_hooks_rest_api()
105
-    {
106
-        // set hooks which account for changes made to the API
107
-        EED_Core_Rest_Api::_set_hooks_for_changes();
108
-    }
109
-
110
-
111
-    /**
112
-     * public wrapper of _set_hooks_for_changes.
113
-     * Loads all the hooks which make requests to old versions of the API
114
-     * appear the same as they always did
115
-     *
116
-     * @throws EE_Error
117
-     */
118
-    public static function set_hooks_for_changes()
119
-    {
120
-        EED_Core_Rest_Api::_set_hooks_for_changes();
121
-    }
122
-
123
-
124
-    /**
125
-     * Loads all the hooks which make requests to old versions of the API
126
-     * appear the same as they always did
127
-     *
128
-     * @throws EE_Error
129
-     */
130
-    protected static function _set_hooks_for_changes()
131
-    {
132
-        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
-            // ignore the base parent class
135
-            // and legacy named classes
136
-            if (
137
-                $classname_in_namespace === 'ChangesInBase'
138
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
139
-            ) {
140
-                continue;
141
-            }
142
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
-            if (class_exists($full_classname)) {
144
-                $instance_of_class = new $full_classname();
145
-                if ($instance_of_class instanceof ChangesInBase) {
146
-                    $instance_of_class->setHooks();
147
-                }
148
-            }
149
-        }
150
-    }
151
-
152
-
153
-    /**
154
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
155
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
156
-     *
157
-     * @throws EE_Error
158
-     * @throws ReflectionException
159
-     */
160
-    public static function register_routes()
161
-    {
162
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
163
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
164
-                /**
165
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
166
-                 *                                         but can also contain route options like {
167
-                 * @type array    $schema                      {
168
-                 * @type callable $schema_callback
169
-                 * @type array    $callback_args               arguments that will be passed to the callback, after the
170
-                 * WP_REST_Request of course
171
-                 * }
172
-                 * }
173
-                 */
174
-                // when registering routes, register all the endpoints' data at the same time
175
-                $multiple_endpoint_args = [];
176
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
177
-                    /**
178
-                     * @var array     $data_for_single_endpoint {
179
-                     * @type callable $callback
180
-                     * @type string methods
181
-                     * @type array args
182
-                     * @type array _links
183
-                     * @type array    $callback_args            arguments that will be passed to the callback, after the
184
-                     * WP_REST_Request of course
185
-                     * }
186
-                     */
187
-                    // skip route options
188
-                    if (! is_numeric($endpoint_key)) {
189
-                        continue;
190
-                    }
191
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
-                        throw new EE_Error(
193
-                            esc_html__(
194
-                            // @codingStandardsIgnoreStart
195
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
196
-                                // @codingStandardsIgnoreEnd
197
-                                'event_espresso'
198
-                            )
199
-                        );
200
-                    }
201
-                    $callback = $data_for_single_endpoint['callback'];
202
-                    $single_endpoint_args = [
203
-                        'methods' => $data_for_single_endpoint['methods'],
204
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
-                            : [],
206
-                    ];
207
-                    if (isset($data_for_single_endpoint['_links'])) {
208
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
-                    }
210
-                    if (isset($data_for_single_endpoint['callback_args'])) {
211
-                        $callback_args = $data_for_single_endpoint['callback_args'];
212
-                        $single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
213
-                            $callback,
214
-                            $callback_args
215
-                        ) {
216
-                            array_unshift($callback_args, $request);
217
-                            return call_user_func_array(
218
-                                $callback,
219
-                                $callback_args
220
-                            );
221
-                        };
222
-                    } else {
223
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
-                    }
225
-                    // As of WordPress 5.5, if a permission_callback is not provided,
226
-                    // the REST API will issue a _doing_it_wrong notice.
227
-                    // Since the EE REST API defers capabilities to the db model system,
228
-                    // we will just use the generic WP callback for public endpoints
229
-                    if (! isset($single_endpoint_args['permission_callback'])) {
230
-                        $single_endpoint_args['permission_callback'] = '__return_true';
231
-                    }
232
-                    $multiple_endpoint_args[] = $single_endpoint_args;
233
-                }
234
-                if (isset($data_for_multiple_endpoints['schema'])) {
235
-                    $schema_route_data = $data_for_multiple_endpoints['schema'];
236
-                    $schema_callback = $schema_route_data['schema_callback'];
237
-                    $callback_args = $schema_route_data['callback_args'];
238
-                    $multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
239
-                        return call_user_func_array(
240
-                            $schema_callback,
241
-                            $callback_args
242
-                        );
243
-                    };
244
-                }
245
-                register_rest_route(
246
-                    $namespace,
247
-                    $relative_route,
248
-                    $multiple_endpoint_args
249
-                );
250
-            }
251
-        }
252
-    }
253
-
254
-
255
-    /**
256
-     * Checks if there was a version change or something that merits invalidating the cached
257
-     * route data. If so, invalidates the cached route data so that it gets refreshed
258
-     * next time the WP API is used
259
-     */
260
-    public static function invalidate_cached_route_data_on_version_change()
261
-    {
262
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
263
-            EED_Core_Rest_Api::invalidate_cached_route_data();
264
-        }
265
-        foreach (EE_Registry::instance()->addons as $addon) {
266
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
267
-                EED_Core_Rest_Api::invalidate_cached_route_data();
268
-            }
269
-        }
270
-    }
271
-
272
-
273
-    /**
274
-     * Removes the cached route data so it will get refreshed next time the WP API is used
275
-     */
276
-    public static function invalidate_cached_route_data()
277
-    {
278
-        // delete the saved EE REST API routes
279
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
280
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
281
-        }
282
-    }
283
-
284
-
285
-    /**
286
-     * Gets the EE route data
287
-     *
288
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
289
-     * @throws EE_Error
290
-     * @throws ReflectionException
291
-     * @type string|array $callback
292
-     * @type string       $methods
293
-     * @type boolean      $hidden_endpoint
294
-     * }
295
-     */
296
-    public static function get_ee_route_data()
297
-    {
298
-        $ee_routes = [];
299
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
300
-            $ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
301
-                $version,
302
-                $hidden_endpoints
303
-            );
304
-        }
305
-        return $ee_routes;
306
-    }
307
-
308
-
309
-    /**
310
-     * Gets the EE route data from the wp options if it exists already,
311
-     * otherwise re-generates it and saves it to the option
312
-     *
313
-     * @param string  $version
314
-     * @param boolean $hidden_endpoints
315
-     * @return array
316
-     * @throws EE_Error
317
-     * @throws ReflectionException
318
-     */
319
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
320
-    {
321
-        $ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
322
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
323
-            $ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
324
-        }
325
-        return $ee_routes;
326
-    }
327
-
328
-
329
-    /**
330
-     * Saves the EE REST API route data to a wp option and returns it
331
-     *
332
-     * @param string  $version
333
-     * @param boolean $hidden_endpoints
334
-     * @return mixed|null
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
339
-    {
340
-        $instance = EED_Core_Rest_Api::instance();
341
-        $routes = apply_filters(
342
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
343
-            array_replace_recursive(
344
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
345
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
346
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
347
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
348
-            )
349
-        );
350
-        $option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
351
-        if (get_option($option_name)) {
352
-            update_option($option_name, $routes, true);
353
-        } else {
354
-            add_option($option_name, $routes, null, 'no');
355
-        }
356
-        return $routes;
357
-    }
358
-
359
-
360
-    /**
361
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
362
-     * need to calculate it on every request
363
-     *
364
-     * @return void
365
-     * @deprecated since version 4.9.1
366
-     */
367
-    public static function save_ee_routes()
368
-    {
369
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
370
-            $instance = EED_Core_Rest_Api::instance();
371
-            $routes = apply_filters(
372
-                'EED_Core_Rest_Api__save_ee_routes__routes',
373
-                array_replace_recursive(
374
-                    $instance->_register_config_routes(),
375
-                    $instance->_register_meta_routes(),
376
-                    $instance->_register_model_routes(),
377
-                    $instance->_register_rpc_routes()
378
-                )
379
-            );
380
-            update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
381
-        }
382
-    }
383
-
384
-
385
-    /**
386
-     * Gets all the route information relating to EE models
387
-     *
388
-     * @return array @see get_ee_route_data
389
-     * @deprecated since version 4.9.1
390
-     */
391
-    protected function _register_model_routes()
392
-    {
393
-        $model_routes = [];
394
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
395
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
396
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
397
-        }
398
-        return $model_routes;
399
-    }
400
-
401
-
402
-    /**
403
-     * Decides whether or not to add write endpoints for this model.
404
-     * Currently, this defaults to exclude all global tables and models
405
-     * which would allow inserting WP core data (we don't want to duplicate
406
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
407
-     *
408
-     * @param EEM_Base $model
409
-     * @return bool
410
-     */
411
-    public static function should_have_write_endpoints(EEM_Base $model)
412
-    {
413
-        if ($model->is_wp_core_model()) {
414
-            return false;
415
-        }
416
-        foreach ($model->get_tables() as $table) {
417
-            if ($table->is_global()) {
418
-                return false;
419
-            }
420
-        }
421
-        return true;
422
-    }
423
-
424
-
425
-    /**
426
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
427
-     * in this versioned namespace of EE4
428
-     *
429
-     * @param $version
430
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
431
-     */
432
-    public static function model_names_with_plural_routes($version)
433
-    {
434
-        $model_version_info = new ModelVersionInfo($version);
435
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
436
-        // let's not bother having endpoints for extra metas
437
-        unset(
438
-            $models_to_register['Extra_Meta'],
439
-            $models_to_register['Extra_Join'],
440
-            $models_to_register['Post_Meta']
441
-        );
442
-        return apply_filters(
443
-            'FHEE__EED_Core_REST_API___register_model_routes',
444
-            $models_to_register
445
-        );
446
-    }
447
-
448
-
449
-    /**
450
-     * Gets the route data for EE models in the specified version
451
-     *
452
-     * @param string  $version
453
-     * @param boolean $hidden_endpoint
454
-     * @return array
455
-     * @throws EE_Error
456
-     * @throws ReflectionException
457
-     */
458
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
459
-    {
460
-        $model_routes = [];
461
-        $model_version_info = new ModelVersionInfo($version);
462
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
463
-            $model = EE_Registry::instance()->load_model($model_name);
464
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
465
-            if (! $model instanceof EEM_Base) {
466
-                continue;
467
-            }
468
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
469
-            $plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
470
-            $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
471
-            $model_routes[ $plural_model_route ] = [
472
-                [
473
-                    'callback'        => [
474
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
475
-                        'handleRequestGetAll',
476
-                    ],
477
-                    'callback_args'   => [$version, $model_name],
478
-                    'methods'         => WP_REST_Server::READABLE,
479
-                    'hidden_endpoint' => $hidden_endpoint,
480
-                    'args'            => $this->_get_read_query_params($model, $version),
481
-                    '_links'          => [
482
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
483
-                    ],
484
-                ],
485
-                'schema' => [
486
-                    'schema_callback' => [
487
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
488
-                        'handleSchemaRequest',
489
-                    ],
490
-                    'callback_args'   => [$version, $model_name],
491
-                ],
492
-            ];
493
-            $model_routes[ $singular_model_route ] = [
494
-                [
495
-                    'callback'        => [
496
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Read',
497
-                        'handleRequestGetOne',
498
-                    ],
499
-                    'callback_args'   => [$version, $model_name],
500
-                    'methods'         => WP_REST_Server::READABLE,
501
-                    'hidden_endpoint' => $hidden_endpoint,
502
-                    'args'            => $this->_get_response_selection_query_params($model, $version, true),
503
-                ],
504
-            ];
505
-            if (
506
-                apply_filters(
507
-                    'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
508
-                    EED_Core_Rest_Api::should_have_write_endpoints($model),
509
-                    $model
510
-                )
511
-            ) {
512
-                $model_routes[ $plural_model_route ][] = [
513
-                    'callback'        => [
514
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Write',
515
-                        'handleRequestInsert',
516
-                    ],
517
-                    'callback_args'   => [$version, $model_name],
518
-                    'methods'         => WP_REST_Server::CREATABLE,
519
-                    'hidden_endpoint' => $hidden_endpoint,
520
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
521
-                ];
522
-                $model_routes[ $singular_model_route ] = array_merge(
523
-                    $model_routes[ $singular_model_route ],
524
-                    [
525
-                        [
526
-                            'callback'        => [
527
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
-                                'handleRequestUpdate',
529
-                            ],
530
-                            'callback_args'   => [$version, $model_name],
531
-                            'methods'         => WP_REST_Server::EDITABLE,
532
-                            'hidden_endpoint' => $hidden_endpoint,
533
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
534
-                        ],
535
-                        [
536
-                            'callback'        => [
537
-                                'EventEspresso\core\libraries\rest_api\controllers\model\Write',
538
-                                'handleRequestDelete',
539
-                            ],
540
-                            'callback_args'   => [$version, $model_name],
541
-                            'methods'         => WP_REST_Server::DELETABLE,
542
-                            'hidden_endpoint' => $hidden_endpoint,
543
-                            'args'            => $this->_get_delete_query_params($model, $version),
544
-                        ],
545
-                    ]
546
-                );
547
-            }
548
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
549
-                $related_route = EED_Core_Rest_Api::get_relation_route_via(
550
-                    $model,
551
-                    '(?P<id>[^\/]+)',
552
-                    $relation_obj
553
-                );
554
-                $model_routes[ $related_route ] = [
555
-                    [
556
-                        'callback'        => [
557
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Read',
558
-                            'handleRequestGetRelated',
559
-                        ],
560
-                        'callback_args'   => [$version, $model_name, $relation_name],
561
-                        'methods'         => WP_REST_Server::READABLE,
562
-                        'hidden_endpoint' => $hidden_endpoint,
563
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
564
-                    ],
565
-                ];
566
-
567
-                $related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
568
-                $model_routes[ $related_write_route ] = [
569
-                    [
570
-                        'callback'        => [
571
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
572
-                            'handleRequestAddRelation',
573
-                        ],
574
-                        'callback_args'   => [$version, $model_name, $relation_name],
575
-                        'methods'         => WP_REST_Server::EDITABLE,
576
-                        'hidden_endpoint' => $hidden_endpoint,
577
-                        'args'            => $this->_get_add_relation_query_params(
578
-                            $model,
579
-                            $relation_obj->get_other_model(),
580
-                            $version
581
-                        ),
582
-                    ],
583
-                    [
584
-                        'callback'        => [
585
-                            'EventEspresso\core\libraries\rest_api\controllers\model\Write',
586
-                            'handleRequestRemoveRelation',
587
-                        ],
588
-                        'callback_args'   => [$version, $model_name, $relation_name],
589
-                        'methods'         => WP_REST_Server::DELETABLE,
590
-                        'hidden_endpoint' => $hidden_endpoint,
591
-                        'args'            => [],
592
-                    ],
593
-                ];
594
-            }
595
-        }
596
-        return $model_routes;
597
-    }
598
-
599
-
600
-    /**
601
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
602
-     * excluding the preceding slash.
603
-     * Eg you pass get_plural_route_to('Event') = 'events'
604
-     *
605
-     * @param EEM_Base $model
606
-     * @return string
607
-     */
608
-    public static function get_collection_route(EEM_Base $model)
609
-    {
610
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
611
-    }
612
-
613
-
614
-    /**
615
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
616
-     * excluding the preceding slash.
617
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
618
-     *
619
-     * @param EEM_Base $model eg Event or Venue
620
-     * @param string   $id
621
-     * @return string
622
-     */
623
-    public static function get_entity_route($model, $id)
624
-    {
625
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
626
-    }
627
-
628
-
629
-    /**
630
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
631
-     * excluding the preceding slash.
632
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
633
-     *
634
-     * @param EEM_Base               $model eg Event or Venue
635
-     * @param string                 $id
636
-     * @param EE_Model_Relation_Base $relation_obj
637
-     * @return string
638
-     */
639
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
640
-    {
641
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
642
-            $relation_obj->get_other_model()->get_this_model_name(),
643
-            $relation_obj
644
-        );
645
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
646
-    }
647
-
648
-
649
-    /**
650
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
651
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
652
-     *
653
-     * @param string $relative_route
654
-     * @param string $version
655
-     * @return string
656
-     */
657
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
658
-    {
659
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
660
-    }
661
-
662
-
663
-    /**
664
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
665
-     * routes that don't conform to the traditional REST CRUD-style).
666
-     *
667
-     * @deprecated since 4.9.1
668
-     */
669
-    protected function _register_rpc_routes()
670
-    {
671
-        $routes = [];
672
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
673
-            $routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
674
-                $version,
675
-                $hidden_endpoint
676
-            );
677
-        }
678
-        return $routes;
679
-    }
680
-
681
-
682
-    /**
683
-     * @param string  $version
684
-     * @param boolean $hidden_endpoint
685
-     * @return array
686
-     */
687
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
688
-    {
689
-        $this_versions_routes = [];
690
-        // checkin endpoint
691
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
692
-            [
693
-                'callback'        => [
694
-                    'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
695
-                    'handleRequestToggleCheckin',
696
-                ],
697
-                'methods'         => WP_REST_Server::CREATABLE,
698
-                'hidden_endpoint' => $hidden_endpoint,
699
-                'args'            => [
700
-                    'force' => [
701
-                        'required'    => false,
702
-                        'default'     => false,
703
-                        'description' => esc_html__(
704
-                        // @codingStandardsIgnoreStart
705
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
706
-                            // @codingStandardsIgnoreEnd
707
-                            'event_espresso'
708
-                        ),
709
-                    ],
710
-                ],
711
-                'callback_args'   => [$version],
712
-            ],
713
-        ];
714
-        return apply_filters(
715
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
716
-            $this_versions_routes,
717
-            $version,
718
-            $hidden_endpoint
719
-        );
720
-    }
721
-
722
-
723
-    /**
724
-     * Gets the query params that can be used when request one or many
725
-     *
726
-     * @param EEM_Base $model
727
-     * @param string   $version
728
-     * @return array
729
-     */
730
-    protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
731
-    {
732
-        EED_Core_Rest_Api::loadCalculatedModelFields();
733
-        $query_params = [
734
-            'include'   => [
735
-                'required' => false,
736
-                'default'  => '*',
737
-                'type'     => 'string',
738
-            ],
739
-            'calculate' => [
740
-                'required'          => false,
741
-                'default'           => '',
742
-                'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
743
-                'type'              => 'string',
744
-                // because we accept a CSV list of the enumerated strings, WP core validation and sanitization
745
-                // freaks out. We'll just validate this argument while handling the request
746
-                'validate_callback' => null,
747
-                'sanitize_callback' => null,
748
-            ],
749
-            'password'  => [
750
-                'required' => false,
751
-                'default'  => '',
752
-                'type'     => 'string',
753
-            ],
754
-        ];
755
-        return apply_filters(
756
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
757
-            $query_params,
758
-            $model,
759
-            $version
760
-        );
761
-    }
762
-
763
-
764
-    /**
765
-     * Gets the parameters acceptable for delete requests
766
-     *
767
-     * @param EEM_Base $model
768
-     * @param string   $version
769
-     * @return array
770
-     */
771
-    protected function _get_delete_query_params(EEM_Base $model, $version)
772
-    {
773
-        $params_for_delete = [
774
-            'allow_blocking' => [
775
-                'required' => false,
776
-                'default'  => true,
777
-                'type'     => 'boolean',
778
-            ],
779
-        ];
780
-        $params_for_delete['force'] = [
781
-            'required' => false,
782
-            'default'  => false,
783
-            'type'     => 'boolean',
784
-        ];
785
-        return apply_filters(
786
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
787
-            $params_for_delete,
788
-            $model,
789
-            $version
790
-        );
791
-    }
792
-
793
-
794
-    /**
795
-     * @param EEM_Base $source_model
796
-     * @param EEM_Base $related_model
797
-     * @param          $version
798
-     * @return array
799
-     * @throws EE_Error
800
-     * @since 5.0.0.p
801
-     */
802
-    protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
803
-    {
804
-        // if they're related through a HABTM relation, check for any non-FKs
805
-        $all_relation_settings = $source_model->relation_settings();
806
-        $relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
807
-        $params = [];
808
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
809
-            foreach ($relation_settings->getNonKeyFields() as $field) {
810
-                /* @var $field EE_Model_Field_Base */
811
-                $params[ $field->get_name() ] = [
812
-                    'required'          => ! $field->is_nullable(),
813
-                    'default'           => ModelDataTranslator::prepareFieldValueForJson(
814
-                        $field,
815
-                        $field->get_default_value(),
816
-                        $version
817
-                    ),
818
-                    'type'              => $field->getSchemaType(),
819
-                    'validate_callback' => null,
820
-                    'sanitize_callback' => null,
821
-                ];
822
-            }
823
-        }
824
-        return $params;
825
-    }
826
-
827
-
828
-    /**
829
-     * Gets info about reading query params that are acceptable
830
-     *
831
-     * @param EEM_Base $model eg 'Event' or 'Venue'
832
-     * @param string   $version
833
-     * @return array    describing the args acceptable when querying this model
834
-     * @throws EE_Error
835
-     */
836
-    protected function _get_read_query_params(EEM_Base $model, $version)
837
-    {
838
-        $default_orderby = [];
839
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
840
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
841
-        }
842
-        return array_merge(
843
-            $this->_get_response_selection_query_params($model, $version),
844
-            [
845
-                'where'    => [
846
-                    'required'          => false,
847
-                    'default'           => [],
848
-                    'type'              => 'object',
849
-                    // because we accept an almost infinite list of possible where conditions, WP
850
-                    // core validation and sanitization freaks out. We'll just validate this argument
851
-                    // while handling the request
852
-                    'validate_callback' => null,
853
-                    'sanitize_callback' => null,
854
-                ],
855
-                'limit'    => [
856
-                    'required'          => false,
857
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
858
-                    'type'              => [
859
-                        'array',
860
-                        'string',
861
-                        'integer',
862
-                    ],
863
-                    // because we accept a variety of types, WP core validation and sanitization
864
-                    // freaks out. We'll just validate this argument while handling the request
865
-                    'validate_callback' => null,
866
-                    'sanitize_callback' => null,
867
-                ],
868
-                'order_by' => [
869
-                    'required'          => false,
870
-                    'default'           => $default_orderby,
871
-                    'type'              => [
872
-                        'object',
873
-                        'string',
874
-                    ],// because we accept a variety of types, WP core validation and sanitization
875
-                    // freaks out. We'll just validate this argument while handling the request
876
-                    'validate_callback' => null,
877
-                    'sanitize_callback' => null,
878
-                ],
879
-                'group_by' => [
880
-                    'required'          => false,
881
-                    'default'           => null,
882
-                    'type'              => [
883
-                        'object',
884
-                        'string',
885
-                    ],
886
-                    // because we accept  an almost infinite list of possible groupings,
887
-                    // WP core validation and sanitization
888
-                    // freaks out. We'll just validate this argument while handling the request
889
-                    'validate_callback' => null,
890
-                    'sanitize_callback' => null,
891
-                ],
892
-                'having'   => [
893
-                    'required'          => false,
894
-                    'default'           => null,
895
-                    'type'              => 'object',
896
-                    // because we accept an almost infinite list of possible where conditions, WP
897
-                    // core validation and sanitization freaks out. We'll just validate this argument
898
-                    // while handling the request
899
-                    'validate_callback' => null,
900
-                    'sanitize_callback' => null,
901
-                ],
902
-                'caps'     => [
903
-                    'required' => false,
904
-                    'default'  => EEM_Base::caps_read,
905
-                    'type'     => 'string',
906
-                    'enum'     => [
907
-                        EEM_Base::caps_read,
908
-                        EEM_Base::caps_read_admin,
909
-                        EEM_Base::caps_edit,
910
-                        EEM_Base::caps_delete,
911
-                    ],
912
-                ],
913
-            ]
914
-        );
915
-    }
916
-
917
-
918
-    /**
919
-     * Gets parameter information for a model regarding writing data
920
-     *
921
-     * @param string           $model_name
922
-     * @param ModelVersionInfo $model_version_info
923
-     * @param boolean          $create                                       whether this is for request to create (in
924
-     *                                                                       which case we need all required params) or
925
-     *                                                                       just to update (in which case we don't
926
-     *                                                                       need those on every request)
927
-     * @return array
928
-     * @throws EE_Error
929
-     * @throws ReflectionException
930
-     */
931
-    protected function _get_write_params(
932
-        $model_name,
933
-        ModelVersionInfo $model_version_info,
934
-        $create = false
935
-    ) {
936
-        $model = EE_Registry::instance()->load_model($model_name);
937
-        $fields = $model_version_info->fieldsOnModelInThisVersion($model);
938
-
939
-        // we do our own validation and sanitization within the controller
940
-        $sanitize_callback = function_exists('rest_validate_value_from_schema')
941
-            ? ['EED_Core_Rest_Api', 'default_sanitize_callback']
942
-            : null;
943
-        $args_info = [];
944
-        foreach ($fields as $field_name => $field_obj) {
945
-            if ($field_obj->is_auto_increment()) {
946
-                // totally ignore auto increment IDs
947
-                continue;
948
-            }
949
-            $arg_info = $field_obj->getSchema();
950
-            $required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
951
-            $arg_info['required'] = $required;
952
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
953
-            unset($arg_info['readonly']);
954
-            $schema_properties = $field_obj->getSchemaProperties();
955
-            if (
956
-                isset($schema_properties['raw'])
957
-                && $field_obj->getSchemaType() === 'object'
958
-            ) {
959
-                // if there's a "raw" form of this argument, use those properties instead
960
-                $arg_info = array_replace(
961
-                    $arg_info,
962
-                    $schema_properties['raw']
963
-                );
964
-            }
965
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
966
-                $field_obj,
967
-                $field_obj->get_default_value(),
968
-                $model_version_info->requestedVersion()
969
-            );
970
-            $arg_info['sanitize_callback'] = $sanitize_callback;
971
-            $args_info[ $field_name ] = $arg_info;
972
-            if ($field_obj instanceof EE_Datetime_Field) {
973
-                $gmt_arg_info = $arg_info;
974
-                $gmt_arg_info['description'] = sprintf(
975
-                    esc_html__(
976
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
977
-                        'event_espresso'
978
-                    ),
979
-                    $field_obj->get_nicename(),
980
-                    $field_name
981
-                );
982
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
983
-            }
984
-        }
985
-        return $args_info;
986
-    }
987
-
988
-
989
-    /**
990
-     * Replacement for WP API's 'rest_parse_request_arg'.
991
-     * If the value is blank but not required, don't bother validating it.
992
-     * Also, it uses our email validation instead of WP API's default.
993
-     *
994
-     * @param                 $value
995
-     * @param WP_REST_Request $request
996
-     * @param                 $param
997
-     * @return bool|true|WP_Error
998
-     * @throws InvalidArgumentException
999
-     * @throws InvalidInterfaceException
1000
-     * @throws InvalidDataTypeException
1001
-     */
1002
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
1003
-    {
1004
-        $attributes = $request->get_attributes();
1005
-        if (
1006
-            ! isset($attributes['args'][ $param ])
1007
-            || ! is_array($attributes['args'][ $param ])
1008
-        ) {
1009
-            $validation_result = true;
1010
-        } else {
1011
-            $args = $attributes['args'][ $param ];
1012
-            if (
1013
-                (
1014
-                    $value === ''
1015
-                    || $value === null
1016
-                )
1017
-                && (! isset($args['required'])
1018
-                    || $args['required'] === false
1019
-                )
1020
-            ) {
1021
-                // not required and not provided? that's cool
1022
-                $validation_result = true;
1023
-            } elseif (
1024
-                isset($args['format'])
1025
-                      && $args['format'] === 'email'
1026
-            ) {
1027
-                $validation_result = true;
1028
-                if (! EED_Core_Rest_Api::_validate_email($value)) {
1029
-                    $validation_result = new WP_Error(
1030
-                        'rest_invalid_param',
1031
-                        esc_html__(
1032
-                            'The email address is not valid or does not exist.',
1033
-                            'event_espresso'
1034
-                        )
1035
-                    );
1036
-                }
1037
-            } else {
1038
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
1039
-            }
1040
-        }
1041
-        if (is_wp_error($validation_result)) {
1042
-            return $validation_result;
1043
-        }
1044
-        return rest_sanitize_request_arg($value, $request, $param);
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1050
-     *
1051
-     * @param $email
1052
-     * @return bool
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidInterfaceException
1055
-     * @throws InvalidDataTypeException
1056
-     */
1057
-    protected static function _validate_email($email)
1058
-    {
1059
-        try {
1060
-            EmailAddressFactory::create($email);
1061
-            return true;
1062
-        } catch (EmailValidationException $e) {
1063
-            return false;
1064
-        }
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * Gets routes for the config
1070
-     *
1071
-     * @return array @see _register_model_routes
1072
-     * @deprecated since version 4.9.1
1073
-     */
1074
-    protected function _register_config_routes()
1075
-    {
1076
-        $config_routes = [];
1077
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1078
-            $config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1079
-                $version,
1080
-                $hidden_endpoint
1081
-            );
1082
-        }
1083
-        return $config_routes;
1084
-    }
1085
-
1086
-
1087
-    /**
1088
-     * Gets routes for the config for the specified version
1089
-     *
1090
-     * @param string  $version
1091
-     * @param boolean $hidden_endpoint
1092
-     * @return array
1093
-     */
1094
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1095
-    {
1096
-        return [
1097
-            'config'    => [
1098
-                [
1099
-                    'callback'        => [
1100
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1101
-                        'handleRequest',
1102
-                    ],
1103
-                    'methods'         => WP_REST_Server::READABLE,
1104
-                    'hidden_endpoint' => $hidden_endpoint,
1105
-                    'callback_args'   => [$version],
1106
-                ],
1107
-            ],
1108
-            'site_info' => [
1109
-                [
1110
-                    'callback'        => [
1111
-                        'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1112
-                        'handleRequestSiteInfo',
1113
-                    ],
1114
-                    'methods'         => WP_REST_Server::READABLE,
1115
-                    'hidden_endpoint' => $hidden_endpoint,
1116
-                    'callback_args'   => [$version],
1117
-                ],
1118
-            ],
1119
-        ];
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     * Gets the meta info routes
1125
-     *
1126
-     * @return array @see _register_model_routes
1127
-     * @deprecated since version 4.9.1
1128
-     */
1129
-    protected function _register_meta_routes()
1130
-    {
1131
-        $meta_routes = [];
1132
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1133
-            $meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1134
-                $version,
1135
-                $hidden_endpoint
1136
-            );
1137
-        }
1138
-        return $meta_routes;
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * @param string  $version
1144
-     * @param boolean $hidden_endpoint
1145
-     * @return array
1146
-     */
1147
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1148
-    {
1149
-        return [
1150
-            'resources' => [
1151
-                [
1152
-                    'callback'        => [
1153
-                        'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1154
-                        'handleRequestModelsMeta',
1155
-                    ],
1156
-                    'methods'         => WP_REST_Server::READABLE,
1157
-                    'hidden_endpoint' => $hidden_endpoint,
1158
-                    'callback_args'   => [$version],
1159
-                ],
1160
-            ],
1161
-        ];
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Tries to hide old 4.6 endpoints from the
1167
-     *
1168
-     * @param array $route_data
1169
-     * @return array
1170
-     * @throws EE_Error
1171
-     * @throws ReflectionException
1172
-     */
1173
-    public static function hide_old_endpoints($route_data)
1174
-    {
1175
-        // allow API clients to override which endpoints get hidden, in case
1176
-        // they want to discover particular endpoints
1177
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1178
-        $force_show_ee_namespace = ltrim(
1179
-            EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1180
-            '/'
1181
-        );
1182
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1183
-            foreach ($relative_urls as $resource_name => $endpoints) {
1184
-                foreach ($endpoints as $key => $endpoint) {
1185
-                    // skip schema and other route options
1186
-                    if (! is_numeric($key)) {
1187
-                        continue;
1188
-                    }
1189
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1190
-                    // to $force_show_ee_namespace, in which case only show that one
1191
-                    // namespace's endpoints (and hide all others)
1192
-                    if (
1193
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1194
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1195
-                    ) {
1196
-                        $full_route = '/' . ltrim($namespace, '/');
1197
-                        $full_route .= '/' . ltrim($resource_name, '/');
1198
-                        unset($route_data[ $full_route ]);
1199
-                    }
1200
-                }
1201
-            }
1202
-        }
1203
-        return $route_data;
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * Returns an array describing which versions of core support serving requests for.
1209
-     * Keys are core versions' major and minor version, and values are the
1210
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1211
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1212
-     * the answers table entirely, in which case it would be very difficult for
1213
-     * it to serve 4.6-style responses.
1214
-     * Versions of core that are missing from this array are unknowns.
1215
-     * previous ver
1216
-     *
1217
-     * @return array
1218
-     */
1219
-    public static function version_compatibilities()
1220
-    {
1221
-        return apply_filters(
1222
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1223
-            [
1224
-                '4.8.29' => '4.8.29',
1225
-                '4.8.33' => '4.8.29',
1226
-                '4.8.34' => '4.8.29',
1227
-                '4.8.36' => '4.8.29',
1228
-            ]
1229
-        );
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Gets the latest API version served. Eg if there
1235
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1236
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1237
-     *
1238
-     * @return string
1239
-     */
1240
-    public static function latest_rest_api_version()
1241
-    {
1242
-        $versions_served = EED_Core_Rest_Api::versions_served();
1243
-        $versions_served_keys = array_keys($versions_served);
1244
-        return end($versions_served_keys);
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1250
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1251
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1252
-     * We also indicate whether or not this version should be put in the index or not
1253
-     *
1254
-     * @return array keys are API version numbers (just major and minor numbers), and values
1255
-     * are whether or not they should be hidden
1256
-     */
1257
-    public static function versions_served()
1258
-    {
1259
-        $versions_served = [];
1260
-        $possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1261
-        $lowest_compatible_version = end($possibly_served_versions);
1262
-        reset($possibly_served_versions);
1263
-        $versions_served_historically = array_keys($possibly_served_versions);
1264
-        $latest_version = end($versions_served_historically);
1265
-        reset($versions_served_historically);
1266
-        // for each version of core we have ever served:
1267
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1268
-            // if it's not above the current core version, and it's compatible with the current version of core
1269
-
1270
-            if ($key_versioned_endpoint === $latest_version) {
1271
-                // don't hide the latest version in the index
1272
-                $versions_served[ $key_versioned_endpoint ] = false;
1273
-            } elseif (
1274
-                version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1275
-                && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1276
-            ) {
1277
-                // include, but hide, previous versions which are still supported
1278
-                $versions_served[ $key_versioned_endpoint ] = true;
1279
-            } elseif (
1280
-                apply_filters(
1281
-                    'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1282
-                    false,
1283
-                    $possibly_served_versions
1284
-                )
1285
-            ) {
1286
-                // if a version is no longer supported, don't include it in index or list of versions served
1287
-                $versions_served[ $key_versioned_endpoint ] = true;
1288
-            }
1289
-        }
1290
-        return $versions_served;
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * Gets the major and minor version of EE core's version string
1296
-     *
1297
-     * @return string
1298
-     */
1299
-    public static function core_version()
1300
-    {
1301
-        return apply_filters(
1302
-            'FHEE__EED_Core_REST_API__core_version',
1303
-            implode(
1304
-                '.',
1305
-                array_slice(
1306
-                    explode(
1307
-                        '.',
1308
-                        espresso_version()
1309
-                    ),
1310
-                    0,
1311
-                    3
1312
-                )
1313
-            )
1314
-        );
1315
-    }
1316
-
1317
-
1318
-    /**
1319
-     * Gets the default limit that should be used when querying for resources
1320
-     *
1321
-     * @return int
1322
-     */
1323
-    public static function get_default_query_limit()
1324
-    {
1325
-        // we actually don't use a const because we want folks to always use
1326
-        // this method, not the const directly
1327
-        return apply_filters(
1328
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1329
-            100
1330
-        );
1331
-    }
1332
-
1333
-
1334
-    /**
1335
-     * @param string $version api version string (i.e. '4.8.36')
1336
-     * @return array
1337
-     */
1338
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1339
-    {
1340
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1341
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1342
-        $collection_routes = [];
1343
-        foreach ($model_names as $model_name => $model_class_name) {
1344
-            $collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1345
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1346
-        }
1347
-        return $collection_routes;
1348
-    }
1349
-
1350
-
1351
-    /**
1352
-     * Returns an array of primary key names indexed by model names.
1353
-     *
1354
-     * @param string $version
1355
-     * @return array
1356
-     */
1357
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1358
-    {
1359
-        $version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1360
-        $model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1361
-        $primary_key_items = [];
1362
-        foreach ($model_names as $model_name => $model_class_name) {
1363
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1364
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1365
-                if (count($primary_keys) > 1) {
1366
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1367
-                } else {
1368
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1369
-                }
1370
-            }
1371
-        }
1372
-        return $primary_key_items;
1373
-    }
1374
-
1375
-
1376
-    /**
1377
-     * Determines the EE REST API debug mode is activated, or not.
1378
-     *
1379
-     * @return bool
1380
-     * @since 4.9.76.p
1381
-     */
1382
-    public static function debugMode()
1383
-    {
1384
-        static $debug_mode = null; // could be class prop
1385
-        if ($debug_mode === null) {
1386
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1387
-        }
1388
-        return $debug_mode;
1389
-    }
1390
-
1391
-
1392
-    /**
1393
-     *    run - initial module setup
1394
-     *
1395
-     * @access    public
1396
-     * @param WP $WP
1397
-     * @return    void
1398
-     */
1399
-    public function run($WP)
1400
-    {
1401
-    }
24
+	const ee_api_namespace = Domain::API_NAMESPACE;
25
+
26
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
27
+
28
+	const saved_routes_option_names = 'ee_core_routes';
29
+
30
+	/**
31
+	 * string used in _links response bodies to make them globally unique.
32
+	 *
33
+	 * @see http://v2.wp-api.org/extending/linking/
34
+	 */
35
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
36
+
37
+	/**
38
+	 * @var CalculatedModelFields
39
+	 */
40
+	protected static $_field_calculator;
41
+
42
+
43
+	/**
44
+	 * @return EED_Core_Rest_Api|EED_Module
45
+	 */
46
+	public static function instance()
47
+	{
48
+		return parent::get_instance(EED_Core_Rest_Api::class);
49
+	}
50
+
51
+
52
+	/**
53
+	 *    set_hooks - for hooking into EE Core, other modules, etc
54
+	 *
55
+	 * @access    public
56
+	 * @return    void
57
+	 */
58
+	public static function set_hooks()
59
+	{
60
+	}
61
+
62
+
63
+	/**
64
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
65
+	 *
66
+	 * @access    public
67
+	 * @return    void
68
+	 */
69
+	public static function set_hooks_admin()
70
+	{
71
+	}
72
+
73
+
74
+	public static function set_hooks_both()
75
+	{
76
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
77
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
78
+		add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
79
+		add_filter(
80
+			'rest_index',
81
+			['EventEspresso\core\libraries\rest_api\controllers\model\Meta', 'filterEeMetadataIntoIndex']
82
+		);
83
+	}
84
+
85
+
86
+	/**
87
+	 * @since   5.0.0.p
88
+	 */
89
+	public static function loadCalculatedModelFields()
90
+	{
91
+		EED_Core_Rest_Api::$_field_calculator = LoaderFactory::getLoader()->load(
92
+			'EventEspresso\core\libraries\rest_api\CalculatedModelFields'
93
+		);
94
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
95
+	}
96
+
97
+
98
+	/**
99
+	 * sets up hooks which only need to be included as part of REST API requests;
100
+	 * other requests like to the frontend or admin etc don't need them
101
+	 *
102
+	 * @throws EE_Error
103
+	 */
104
+	public static function set_hooks_rest_api()
105
+	{
106
+		// set hooks which account for changes made to the API
107
+		EED_Core_Rest_Api::_set_hooks_for_changes();
108
+	}
109
+
110
+
111
+	/**
112
+	 * public wrapper of _set_hooks_for_changes.
113
+	 * Loads all the hooks which make requests to old versions of the API
114
+	 * appear the same as they always did
115
+	 *
116
+	 * @throws EE_Error
117
+	 */
118
+	public static function set_hooks_for_changes()
119
+	{
120
+		EED_Core_Rest_Api::_set_hooks_for_changes();
121
+	}
122
+
123
+
124
+	/**
125
+	 * Loads all the hooks which make requests to old versions of the API
126
+	 * appear the same as they always did
127
+	 *
128
+	 * @throws EE_Error
129
+	 */
130
+	protected static function _set_hooks_for_changes()
131
+	{
132
+		$folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes'], false);
133
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
134
+			// ignore the base parent class
135
+			// and legacy named classes
136
+			if (
137
+				$classname_in_namespace === 'ChangesInBase'
138
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
139
+			) {
140
+				continue;
141
+			}
142
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
143
+			if (class_exists($full_classname)) {
144
+				$instance_of_class = new $full_classname();
145
+				if ($instance_of_class instanceof ChangesInBase) {
146
+					$instance_of_class->setHooks();
147
+				}
148
+			}
149
+		}
150
+	}
151
+
152
+
153
+	/**
154
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
155
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
156
+	 *
157
+	 * @throws EE_Error
158
+	 * @throws ReflectionException
159
+	 */
160
+	public static function register_routes()
161
+	{
162
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
163
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
164
+				/**
165
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
166
+				 *                                         but can also contain route options like {
167
+				 * @type array    $schema                      {
168
+				 * @type callable $schema_callback
169
+				 * @type array    $callback_args               arguments that will be passed to the callback, after the
170
+				 * WP_REST_Request of course
171
+				 * }
172
+				 * }
173
+				 */
174
+				// when registering routes, register all the endpoints' data at the same time
175
+				$multiple_endpoint_args = [];
176
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
177
+					/**
178
+					 * @var array     $data_for_single_endpoint {
179
+					 * @type callable $callback
180
+					 * @type string methods
181
+					 * @type array args
182
+					 * @type array _links
183
+					 * @type array    $callback_args            arguments that will be passed to the callback, after the
184
+					 * WP_REST_Request of course
185
+					 * }
186
+					 */
187
+					// skip route options
188
+					if (! is_numeric($endpoint_key)) {
189
+						continue;
190
+					}
191
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
192
+						throw new EE_Error(
193
+							esc_html__(
194
+							// @codingStandardsIgnoreStart
195
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
196
+								// @codingStandardsIgnoreEnd
197
+								'event_espresso'
198
+							)
199
+						);
200
+					}
201
+					$callback = $data_for_single_endpoint['callback'];
202
+					$single_endpoint_args = [
203
+						'methods' => $data_for_single_endpoint['methods'],
204
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
205
+							: [],
206
+					];
207
+					if (isset($data_for_single_endpoint['_links'])) {
208
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
209
+					}
210
+					if (isset($data_for_single_endpoint['callback_args'])) {
211
+						$callback_args = $data_for_single_endpoint['callback_args'];
212
+						$single_endpoint_args['callback'] = static function (WP_REST_Request $request) use (
213
+							$callback,
214
+							$callback_args
215
+						) {
216
+							array_unshift($callback_args, $request);
217
+							return call_user_func_array(
218
+								$callback,
219
+								$callback_args
220
+							);
221
+						};
222
+					} else {
223
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
224
+					}
225
+					// As of WordPress 5.5, if a permission_callback is not provided,
226
+					// the REST API will issue a _doing_it_wrong notice.
227
+					// Since the EE REST API defers capabilities to the db model system,
228
+					// we will just use the generic WP callback for public endpoints
229
+					if (! isset($single_endpoint_args['permission_callback'])) {
230
+						$single_endpoint_args['permission_callback'] = '__return_true';
231
+					}
232
+					$multiple_endpoint_args[] = $single_endpoint_args;
233
+				}
234
+				if (isset($data_for_multiple_endpoints['schema'])) {
235
+					$schema_route_data = $data_for_multiple_endpoints['schema'];
236
+					$schema_callback = $schema_route_data['schema_callback'];
237
+					$callback_args = $schema_route_data['callback_args'];
238
+					$multiple_endpoint_args['schema'] = static function () use ($schema_callback, $callback_args) {
239
+						return call_user_func_array(
240
+							$schema_callback,
241
+							$callback_args
242
+						);
243
+					};
244
+				}
245
+				register_rest_route(
246
+					$namespace,
247
+					$relative_route,
248
+					$multiple_endpoint_args
249
+				);
250
+			}
251
+		}
252
+	}
253
+
254
+
255
+	/**
256
+	 * Checks if there was a version change or something that merits invalidating the cached
257
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
258
+	 * next time the WP API is used
259
+	 */
260
+	public static function invalidate_cached_route_data_on_version_change()
261
+	{
262
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
263
+			EED_Core_Rest_Api::invalidate_cached_route_data();
264
+		}
265
+		foreach (EE_Registry::instance()->addons as $addon) {
266
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
267
+				EED_Core_Rest_Api::invalidate_cached_route_data();
268
+			}
269
+		}
270
+	}
271
+
272
+
273
+	/**
274
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
275
+	 */
276
+	public static function invalidate_cached_route_data()
277
+	{
278
+		// delete the saved EE REST API routes
279
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
280
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
281
+		}
282
+	}
283
+
284
+
285
+	/**
286
+	 * Gets the EE route data
287
+	 *
288
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
289
+	 * @throws EE_Error
290
+	 * @throws ReflectionException
291
+	 * @type string|array $callback
292
+	 * @type string       $methods
293
+	 * @type boolean      $hidden_endpoint
294
+	 * }
295
+	 */
296
+	public static function get_ee_route_data()
297
+	{
298
+		$ee_routes = [];
299
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoints) {
300
+			$ee_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = EED_Core_Rest_Api::_get_ee_route_data_for_version(
301
+				$version,
302
+				$hidden_endpoints
303
+			);
304
+		}
305
+		return $ee_routes;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Gets the EE route data from the wp options if it exists already,
311
+	 * otherwise re-generates it and saves it to the option
312
+	 *
313
+	 * @param string  $version
314
+	 * @param boolean $hidden_endpoints
315
+	 * @return array
316
+	 * @throws EE_Error
317
+	 * @throws ReflectionException
318
+	 */
319
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
320
+	{
321
+		$ee_routes = get_option(EED_Core_Rest_Api::saved_routes_option_names . $version, null);
322
+		if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
323
+			$ee_routes = EED_Core_Rest_Api::_save_ee_route_data_for_version($version, $hidden_endpoints);
324
+		}
325
+		return $ee_routes;
326
+	}
327
+
328
+
329
+	/**
330
+	 * Saves the EE REST API route data to a wp option and returns it
331
+	 *
332
+	 * @param string  $version
333
+	 * @param boolean $hidden_endpoints
334
+	 * @return mixed|null
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
339
+	{
340
+		$instance = EED_Core_Rest_Api::instance();
341
+		$routes = apply_filters(
342
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
343
+			array_replace_recursive(
344
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
345
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
346
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
347
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
348
+			)
349
+		);
350
+		$option_name = EED_Core_Rest_Api::saved_routes_option_names . $version;
351
+		if (get_option($option_name)) {
352
+			update_option($option_name, $routes, true);
353
+		} else {
354
+			add_option($option_name, $routes, null, 'no');
355
+		}
356
+		return $routes;
357
+	}
358
+
359
+
360
+	/**
361
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
362
+	 * need to calculate it on every request
363
+	 *
364
+	 * @return void
365
+	 * @deprecated since version 4.9.1
366
+	 */
367
+	public static function save_ee_routes()
368
+	{
369
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
370
+			$instance = EED_Core_Rest_Api::instance();
371
+			$routes = apply_filters(
372
+				'EED_Core_Rest_Api__save_ee_routes__routes',
373
+				array_replace_recursive(
374
+					$instance->_register_config_routes(),
375
+					$instance->_register_meta_routes(),
376
+					$instance->_register_model_routes(),
377
+					$instance->_register_rpc_routes()
378
+				)
379
+			);
380
+			update_option(EED_Core_Rest_Api::saved_routes_option_names, $routes, true);
381
+		}
382
+	}
383
+
384
+
385
+	/**
386
+	 * Gets all the route information relating to EE models
387
+	 *
388
+	 * @return array @see get_ee_route_data
389
+	 * @deprecated since version 4.9.1
390
+	 */
391
+	protected function _register_model_routes()
392
+	{
393
+		$model_routes = [];
394
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
395
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
396
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
397
+		}
398
+		return $model_routes;
399
+	}
400
+
401
+
402
+	/**
403
+	 * Decides whether or not to add write endpoints for this model.
404
+	 * Currently, this defaults to exclude all global tables and models
405
+	 * which would allow inserting WP core data (we don't want to duplicate
406
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
407
+	 *
408
+	 * @param EEM_Base $model
409
+	 * @return bool
410
+	 */
411
+	public static function should_have_write_endpoints(EEM_Base $model)
412
+	{
413
+		if ($model->is_wp_core_model()) {
414
+			return false;
415
+		}
416
+		foreach ($model->get_tables() as $table) {
417
+			if ($table->is_global()) {
418
+				return false;
419
+			}
420
+		}
421
+		return true;
422
+	}
423
+
424
+
425
+	/**
426
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
427
+	 * in this versioned namespace of EE4
428
+	 *
429
+	 * @param $version
430
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
431
+	 */
432
+	public static function model_names_with_plural_routes($version)
433
+	{
434
+		$model_version_info = new ModelVersionInfo($version);
435
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
436
+		// let's not bother having endpoints for extra metas
437
+		unset(
438
+			$models_to_register['Extra_Meta'],
439
+			$models_to_register['Extra_Join'],
440
+			$models_to_register['Post_Meta']
441
+		);
442
+		return apply_filters(
443
+			'FHEE__EED_Core_REST_API___register_model_routes',
444
+			$models_to_register
445
+		);
446
+	}
447
+
448
+
449
+	/**
450
+	 * Gets the route data for EE models in the specified version
451
+	 *
452
+	 * @param string  $version
453
+	 * @param boolean $hidden_endpoint
454
+	 * @return array
455
+	 * @throws EE_Error
456
+	 * @throws ReflectionException
457
+	 */
458
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
459
+	{
460
+		$model_routes = [];
461
+		$model_version_info = new ModelVersionInfo($version);
462
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
463
+			$model = EE_Registry::instance()->load_model($model_name);
464
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
465
+			if (! $model instanceof EEM_Base) {
466
+				continue;
467
+			}
468
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
469
+			$plural_model_route = EED_Core_Rest_Api::get_collection_route($model);
470
+			$singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
471
+			$model_routes[ $plural_model_route ] = [
472
+				[
473
+					'callback'        => [
474
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
475
+						'handleRequestGetAll',
476
+					],
477
+					'callback_args'   => [$version, $model_name],
478
+					'methods'         => WP_REST_Server::READABLE,
479
+					'hidden_endpoint' => $hidden_endpoint,
480
+					'args'            => $this->_get_read_query_params($model, $version),
481
+					'_links'          => [
482
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
483
+					],
484
+				],
485
+				'schema' => [
486
+					'schema_callback' => [
487
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
488
+						'handleSchemaRequest',
489
+					],
490
+					'callback_args'   => [$version, $model_name],
491
+				],
492
+			];
493
+			$model_routes[ $singular_model_route ] = [
494
+				[
495
+					'callback'        => [
496
+						'EventEspresso\core\libraries\rest_api\controllers\model\Read',
497
+						'handleRequestGetOne',
498
+					],
499
+					'callback_args'   => [$version, $model_name],
500
+					'methods'         => WP_REST_Server::READABLE,
501
+					'hidden_endpoint' => $hidden_endpoint,
502
+					'args'            => $this->_get_response_selection_query_params($model, $version, true),
503
+				],
504
+			];
505
+			if (
506
+				apply_filters(
507
+					'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
508
+					EED_Core_Rest_Api::should_have_write_endpoints($model),
509
+					$model
510
+				)
511
+			) {
512
+				$model_routes[ $plural_model_route ][] = [
513
+					'callback'        => [
514
+						'EventEspresso\core\libraries\rest_api\controllers\model\Write',
515
+						'handleRequestInsert',
516
+					],
517
+					'callback_args'   => [$version, $model_name],
518
+					'methods'         => WP_REST_Server::CREATABLE,
519
+					'hidden_endpoint' => $hidden_endpoint,
520
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
521
+				];
522
+				$model_routes[ $singular_model_route ] = array_merge(
523
+					$model_routes[ $singular_model_route ],
524
+					[
525
+						[
526
+							'callback'        => [
527
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
528
+								'handleRequestUpdate',
529
+							],
530
+							'callback_args'   => [$version, $model_name],
531
+							'methods'         => WP_REST_Server::EDITABLE,
532
+							'hidden_endpoint' => $hidden_endpoint,
533
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
534
+						],
535
+						[
536
+							'callback'        => [
537
+								'EventEspresso\core\libraries\rest_api\controllers\model\Write',
538
+								'handleRequestDelete',
539
+							],
540
+							'callback_args'   => [$version, $model_name],
541
+							'methods'         => WP_REST_Server::DELETABLE,
542
+							'hidden_endpoint' => $hidden_endpoint,
543
+							'args'            => $this->_get_delete_query_params($model, $version),
544
+						],
545
+					]
546
+				);
547
+			}
548
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
549
+				$related_route = EED_Core_Rest_Api::get_relation_route_via(
550
+					$model,
551
+					'(?P<id>[^\/]+)',
552
+					$relation_obj
553
+				);
554
+				$model_routes[ $related_route ] = [
555
+					[
556
+						'callback'        => [
557
+							'EventEspresso\core\libraries\rest_api\controllers\model\Read',
558
+							'handleRequestGetRelated',
559
+						],
560
+						'callback_args'   => [$version, $model_name, $relation_name],
561
+						'methods'         => WP_REST_Server::READABLE,
562
+						'hidden_endpoint' => $hidden_endpoint,
563
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
564
+					],
565
+				];
566
+
567
+				$related_write_route = $related_route . '/' . '(?P<related_id>[^\/]+)';
568
+				$model_routes[ $related_write_route ] = [
569
+					[
570
+						'callback'        => [
571
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
572
+							'handleRequestAddRelation',
573
+						],
574
+						'callback_args'   => [$version, $model_name, $relation_name],
575
+						'methods'         => WP_REST_Server::EDITABLE,
576
+						'hidden_endpoint' => $hidden_endpoint,
577
+						'args'            => $this->_get_add_relation_query_params(
578
+							$model,
579
+							$relation_obj->get_other_model(),
580
+							$version
581
+						),
582
+					],
583
+					[
584
+						'callback'        => [
585
+							'EventEspresso\core\libraries\rest_api\controllers\model\Write',
586
+							'handleRequestRemoveRelation',
587
+						],
588
+						'callback_args'   => [$version, $model_name, $relation_name],
589
+						'methods'         => WP_REST_Server::DELETABLE,
590
+						'hidden_endpoint' => $hidden_endpoint,
591
+						'args'            => [],
592
+					],
593
+				];
594
+			}
595
+		}
596
+		return $model_routes;
597
+	}
598
+
599
+
600
+	/**
601
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
602
+	 * excluding the preceding slash.
603
+	 * Eg you pass get_plural_route_to('Event') = 'events'
604
+	 *
605
+	 * @param EEM_Base $model
606
+	 * @return string
607
+	 */
608
+	public static function get_collection_route(EEM_Base $model)
609
+	{
610
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
611
+	}
612
+
613
+
614
+	/**
615
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
616
+	 * excluding the preceding slash.
617
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
618
+	 *
619
+	 * @param EEM_Base $model eg Event or Venue
620
+	 * @param string   $id
621
+	 * @return string
622
+	 */
623
+	public static function get_entity_route($model, $id)
624
+	{
625
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
626
+	}
627
+
628
+
629
+	/**
630
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
631
+	 * excluding the preceding slash.
632
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
633
+	 *
634
+	 * @param EEM_Base               $model eg Event or Venue
635
+	 * @param string                 $id
636
+	 * @param EE_Model_Relation_Base $relation_obj
637
+	 * @return string
638
+	 */
639
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
640
+	{
641
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
642
+			$relation_obj->get_other_model()->get_this_model_name(),
643
+			$relation_obj
644
+		);
645
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
646
+	}
647
+
648
+
649
+	/**
650
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
651
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
652
+	 *
653
+	 * @param string $relative_route
654
+	 * @param string $version
655
+	 * @return string
656
+	 */
657
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
658
+	{
659
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
660
+	}
661
+
662
+
663
+	/**
664
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
665
+	 * routes that don't conform to the traditional REST CRUD-style).
666
+	 *
667
+	 * @deprecated since 4.9.1
668
+	 */
669
+	protected function _register_rpc_routes()
670
+	{
671
+		$routes = [];
672
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
673
+			$routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
674
+				$version,
675
+				$hidden_endpoint
676
+			);
677
+		}
678
+		return $routes;
679
+	}
680
+
681
+
682
+	/**
683
+	 * @param string  $version
684
+	 * @param boolean $hidden_endpoint
685
+	 * @return array
686
+	 */
687
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
688
+	{
689
+		$this_versions_routes = [];
690
+		// checkin endpoint
691
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
692
+			[
693
+				'callback'        => [
694
+					'EventEspresso\core\libraries\rest_api\controllers\rpc\Checkin',
695
+					'handleRequestToggleCheckin',
696
+				],
697
+				'methods'         => WP_REST_Server::CREATABLE,
698
+				'hidden_endpoint' => $hidden_endpoint,
699
+				'args'            => [
700
+					'force' => [
701
+						'required'    => false,
702
+						'default'     => false,
703
+						'description' => esc_html__(
704
+						// @codingStandardsIgnoreStart
705
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
706
+							// @codingStandardsIgnoreEnd
707
+							'event_espresso'
708
+						),
709
+					],
710
+				],
711
+				'callback_args'   => [$version],
712
+			],
713
+		];
714
+		return apply_filters(
715
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
716
+			$this_versions_routes,
717
+			$version,
718
+			$hidden_endpoint
719
+		);
720
+	}
721
+
722
+
723
+	/**
724
+	 * Gets the query params that can be used when request one or many
725
+	 *
726
+	 * @param EEM_Base $model
727
+	 * @param string   $version
728
+	 * @return array
729
+	 */
730
+	protected function _get_response_selection_query_params(EEM_Base $model, $version, $single_only = false)
731
+	{
732
+		EED_Core_Rest_Api::loadCalculatedModelFields();
733
+		$query_params = [
734
+			'include'   => [
735
+				'required' => false,
736
+				'default'  => '*',
737
+				'type'     => 'string',
738
+			],
739
+			'calculate' => [
740
+				'required'          => false,
741
+				'default'           => '',
742
+				'enum'              => EED_Core_Rest_Api::$_field_calculator->retrieveCalculatedFieldsForModel($model),
743
+				'type'              => 'string',
744
+				// because we accept a CSV list of the enumerated strings, WP core validation and sanitization
745
+				// freaks out. We'll just validate this argument while handling the request
746
+				'validate_callback' => null,
747
+				'sanitize_callback' => null,
748
+			],
749
+			'password'  => [
750
+				'required' => false,
751
+				'default'  => '',
752
+				'type'     => 'string',
753
+			],
754
+		];
755
+		return apply_filters(
756
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
757
+			$query_params,
758
+			$model,
759
+			$version
760
+		);
761
+	}
762
+
763
+
764
+	/**
765
+	 * Gets the parameters acceptable for delete requests
766
+	 *
767
+	 * @param EEM_Base $model
768
+	 * @param string   $version
769
+	 * @return array
770
+	 */
771
+	protected function _get_delete_query_params(EEM_Base $model, $version)
772
+	{
773
+		$params_for_delete = [
774
+			'allow_blocking' => [
775
+				'required' => false,
776
+				'default'  => true,
777
+				'type'     => 'boolean',
778
+			],
779
+		];
780
+		$params_for_delete['force'] = [
781
+			'required' => false,
782
+			'default'  => false,
783
+			'type'     => 'boolean',
784
+		];
785
+		return apply_filters(
786
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
787
+			$params_for_delete,
788
+			$model,
789
+			$version
790
+		);
791
+	}
792
+
793
+
794
+	/**
795
+	 * @param EEM_Base $source_model
796
+	 * @param EEM_Base $related_model
797
+	 * @param          $version
798
+	 * @return array
799
+	 * @throws EE_Error
800
+	 * @since 5.0.0.p
801
+	 */
802
+	protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
803
+	{
804
+		// if they're related through a HABTM relation, check for any non-FKs
805
+		$all_relation_settings = $source_model->relation_settings();
806
+		$relation_settings = $all_relation_settings[ $related_model->get_this_model_name() ];
807
+		$params = [];
808
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
809
+			foreach ($relation_settings->getNonKeyFields() as $field) {
810
+				/* @var $field EE_Model_Field_Base */
811
+				$params[ $field->get_name() ] = [
812
+					'required'          => ! $field->is_nullable(),
813
+					'default'           => ModelDataTranslator::prepareFieldValueForJson(
814
+						$field,
815
+						$field->get_default_value(),
816
+						$version
817
+					),
818
+					'type'              => $field->getSchemaType(),
819
+					'validate_callback' => null,
820
+					'sanitize_callback' => null,
821
+				];
822
+			}
823
+		}
824
+		return $params;
825
+	}
826
+
827
+
828
+	/**
829
+	 * Gets info about reading query params that are acceptable
830
+	 *
831
+	 * @param EEM_Base $model eg 'Event' or 'Venue'
832
+	 * @param string   $version
833
+	 * @return array    describing the args acceptable when querying this model
834
+	 * @throws EE_Error
835
+	 */
836
+	protected function _get_read_query_params(EEM_Base $model, $version)
837
+	{
838
+		$default_orderby = [];
839
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
840
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
841
+		}
842
+		return array_merge(
843
+			$this->_get_response_selection_query_params($model, $version),
844
+			[
845
+				'where'    => [
846
+					'required'          => false,
847
+					'default'           => [],
848
+					'type'              => 'object',
849
+					// because we accept an almost infinite list of possible where conditions, WP
850
+					// core validation and sanitization freaks out. We'll just validate this argument
851
+					// while handling the request
852
+					'validate_callback' => null,
853
+					'sanitize_callback' => null,
854
+				],
855
+				'limit'    => [
856
+					'required'          => false,
857
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
858
+					'type'              => [
859
+						'array',
860
+						'string',
861
+						'integer',
862
+					],
863
+					// because we accept a variety of types, WP core validation and sanitization
864
+					// freaks out. We'll just validate this argument while handling the request
865
+					'validate_callback' => null,
866
+					'sanitize_callback' => null,
867
+				],
868
+				'order_by' => [
869
+					'required'          => false,
870
+					'default'           => $default_orderby,
871
+					'type'              => [
872
+						'object',
873
+						'string',
874
+					],// because we accept a variety of types, WP core validation and sanitization
875
+					// freaks out. We'll just validate this argument while handling the request
876
+					'validate_callback' => null,
877
+					'sanitize_callback' => null,
878
+				],
879
+				'group_by' => [
880
+					'required'          => false,
881
+					'default'           => null,
882
+					'type'              => [
883
+						'object',
884
+						'string',
885
+					],
886
+					// because we accept  an almost infinite list of possible groupings,
887
+					// WP core validation and sanitization
888
+					// freaks out. We'll just validate this argument while handling the request
889
+					'validate_callback' => null,
890
+					'sanitize_callback' => null,
891
+				],
892
+				'having'   => [
893
+					'required'          => false,
894
+					'default'           => null,
895
+					'type'              => 'object',
896
+					// because we accept an almost infinite list of possible where conditions, WP
897
+					// core validation and sanitization freaks out. We'll just validate this argument
898
+					// while handling the request
899
+					'validate_callback' => null,
900
+					'sanitize_callback' => null,
901
+				],
902
+				'caps'     => [
903
+					'required' => false,
904
+					'default'  => EEM_Base::caps_read,
905
+					'type'     => 'string',
906
+					'enum'     => [
907
+						EEM_Base::caps_read,
908
+						EEM_Base::caps_read_admin,
909
+						EEM_Base::caps_edit,
910
+						EEM_Base::caps_delete,
911
+					],
912
+				],
913
+			]
914
+		);
915
+	}
916
+
917
+
918
+	/**
919
+	 * Gets parameter information for a model regarding writing data
920
+	 *
921
+	 * @param string           $model_name
922
+	 * @param ModelVersionInfo $model_version_info
923
+	 * @param boolean          $create                                       whether this is for request to create (in
924
+	 *                                                                       which case we need all required params) or
925
+	 *                                                                       just to update (in which case we don't
926
+	 *                                                                       need those on every request)
927
+	 * @return array
928
+	 * @throws EE_Error
929
+	 * @throws ReflectionException
930
+	 */
931
+	protected function _get_write_params(
932
+		$model_name,
933
+		ModelVersionInfo $model_version_info,
934
+		$create = false
935
+	) {
936
+		$model = EE_Registry::instance()->load_model($model_name);
937
+		$fields = $model_version_info->fieldsOnModelInThisVersion($model);
938
+
939
+		// we do our own validation and sanitization within the controller
940
+		$sanitize_callback = function_exists('rest_validate_value_from_schema')
941
+			? ['EED_Core_Rest_Api', 'default_sanitize_callback']
942
+			: null;
943
+		$args_info = [];
944
+		foreach ($fields as $field_name => $field_obj) {
945
+			if ($field_obj->is_auto_increment()) {
946
+				// totally ignore auto increment IDs
947
+				continue;
948
+			}
949
+			$arg_info = $field_obj->getSchema();
950
+			$required = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
951
+			$arg_info['required'] = $required;
952
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
953
+			unset($arg_info['readonly']);
954
+			$schema_properties = $field_obj->getSchemaProperties();
955
+			if (
956
+				isset($schema_properties['raw'])
957
+				&& $field_obj->getSchemaType() === 'object'
958
+			) {
959
+				// if there's a "raw" form of this argument, use those properties instead
960
+				$arg_info = array_replace(
961
+					$arg_info,
962
+					$schema_properties['raw']
963
+				);
964
+			}
965
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
966
+				$field_obj,
967
+				$field_obj->get_default_value(),
968
+				$model_version_info->requestedVersion()
969
+			);
970
+			$arg_info['sanitize_callback'] = $sanitize_callback;
971
+			$args_info[ $field_name ] = $arg_info;
972
+			if ($field_obj instanceof EE_Datetime_Field) {
973
+				$gmt_arg_info = $arg_info;
974
+				$gmt_arg_info['description'] = sprintf(
975
+					esc_html__(
976
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
977
+						'event_espresso'
978
+					),
979
+					$field_obj->get_nicename(),
980
+					$field_name
981
+				);
982
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
983
+			}
984
+		}
985
+		return $args_info;
986
+	}
987
+
988
+
989
+	/**
990
+	 * Replacement for WP API's 'rest_parse_request_arg'.
991
+	 * If the value is blank but not required, don't bother validating it.
992
+	 * Also, it uses our email validation instead of WP API's default.
993
+	 *
994
+	 * @param                 $value
995
+	 * @param WP_REST_Request $request
996
+	 * @param                 $param
997
+	 * @return bool|true|WP_Error
998
+	 * @throws InvalidArgumentException
999
+	 * @throws InvalidInterfaceException
1000
+	 * @throws InvalidDataTypeException
1001
+	 */
1002
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
1003
+	{
1004
+		$attributes = $request->get_attributes();
1005
+		if (
1006
+			! isset($attributes['args'][ $param ])
1007
+			|| ! is_array($attributes['args'][ $param ])
1008
+		) {
1009
+			$validation_result = true;
1010
+		} else {
1011
+			$args = $attributes['args'][ $param ];
1012
+			if (
1013
+				(
1014
+					$value === ''
1015
+					|| $value === null
1016
+				)
1017
+				&& (! isset($args['required'])
1018
+					|| $args['required'] === false
1019
+				)
1020
+			) {
1021
+				// not required and not provided? that's cool
1022
+				$validation_result = true;
1023
+			} elseif (
1024
+				isset($args['format'])
1025
+					  && $args['format'] === 'email'
1026
+			) {
1027
+				$validation_result = true;
1028
+				if (! EED_Core_Rest_Api::_validate_email($value)) {
1029
+					$validation_result = new WP_Error(
1030
+						'rest_invalid_param',
1031
+						esc_html__(
1032
+							'The email address is not valid or does not exist.',
1033
+							'event_espresso'
1034
+						)
1035
+					);
1036
+				}
1037
+			} else {
1038
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
1039
+			}
1040
+		}
1041
+		if (is_wp_error($validation_result)) {
1042
+			return $validation_result;
1043
+		}
1044
+		return rest_sanitize_request_arg($value, $request, $param);
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
1050
+	 *
1051
+	 * @param $email
1052
+	 * @return bool
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidInterfaceException
1055
+	 * @throws InvalidDataTypeException
1056
+	 */
1057
+	protected static function _validate_email($email)
1058
+	{
1059
+		try {
1060
+			EmailAddressFactory::create($email);
1061
+			return true;
1062
+		} catch (EmailValidationException $e) {
1063
+			return false;
1064
+		}
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * Gets routes for the config
1070
+	 *
1071
+	 * @return array @see _register_model_routes
1072
+	 * @deprecated since version 4.9.1
1073
+	 */
1074
+	protected function _register_config_routes()
1075
+	{
1076
+		$config_routes = [];
1077
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1078
+			$config_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1079
+				$version,
1080
+				$hidden_endpoint
1081
+			);
1082
+		}
1083
+		return $config_routes;
1084
+	}
1085
+
1086
+
1087
+	/**
1088
+	 * Gets routes for the config for the specified version
1089
+	 *
1090
+	 * @param string  $version
1091
+	 * @param boolean $hidden_endpoint
1092
+	 * @return array
1093
+	 */
1094
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
1095
+	{
1096
+		return [
1097
+			'config'    => [
1098
+				[
1099
+					'callback'        => [
1100
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1101
+						'handleRequest',
1102
+					],
1103
+					'methods'         => WP_REST_Server::READABLE,
1104
+					'hidden_endpoint' => $hidden_endpoint,
1105
+					'callback_args'   => [$version],
1106
+				],
1107
+			],
1108
+			'site_info' => [
1109
+				[
1110
+					'callback'        => [
1111
+						'EventEspresso\core\libraries\rest_api\controllers\config\Read',
1112
+						'handleRequestSiteInfo',
1113
+					],
1114
+					'methods'         => WP_REST_Server::READABLE,
1115
+					'hidden_endpoint' => $hidden_endpoint,
1116
+					'callback_args'   => [$version],
1117
+				],
1118
+			],
1119
+		];
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 * Gets the meta info routes
1125
+	 *
1126
+	 * @return array @see _register_model_routes
1127
+	 * @deprecated since version 4.9.1
1128
+	 */
1129
+	protected function _register_meta_routes()
1130
+	{
1131
+		$meta_routes = [];
1132
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden_endpoint) {
1133
+			$meta_routes[ EED_Core_Rest_Api::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1134
+				$version,
1135
+				$hidden_endpoint
1136
+			);
1137
+		}
1138
+		return $meta_routes;
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * @param string  $version
1144
+	 * @param boolean $hidden_endpoint
1145
+	 * @return array
1146
+	 */
1147
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
1148
+	{
1149
+		return [
1150
+			'resources' => [
1151
+				[
1152
+					'callback'        => [
1153
+						'EventEspresso\core\libraries\rest_api\controllers\model\Meta',
1154
+						'handleRequestModelsMeta',
1155
+					],
1156
+					'methods'         => WP_REST_Server::READABLE,
1157
+					'hidden_endpoint' => $hidden_endpoint,
1158
+					'callback_args'   => [$version],
1159
+				],
1160
+			],
1161
+		];
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Tries to hide old 4.6 endpoints from the
1167
+	 *
1168
+	 * @param array $route_data
1169
+	 * @return array
1170
+	 * @throws EE_Error
1171
+	 * @throws ReflectionException
1172
+	 */
1173
+	public static function hide_old_endpoints($route_data)
1174
+	{
1175
+		// allow API clients to override which endpoints get hidden, in case
1176
+		// they want to discover particular endpoints
1177
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1178
+		$force_show_ee_namespace = ltrim(
1179
+			EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1180
+			'/'
1181
+		);
1182
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1183
+			foreach ($relative_urls as $resource_name => $endpoints) {
1184
+				foreach ($endpoints as $key => $endpoint) {
1185
+					// skip schema and other route options
1186
+					if (! is_numeric($key)) {
1187
+						continue;
1188
+					}
1189
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1190
+					// to $force_show_ee_namespace, in which case only show that one
1191
+					// namespace's endpoints (and hide all others)
1192
+					if (
1193
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1194
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1195
+					) {
1196
+						$full_route = '/' . ltrim($namespace, '/');
1197
+						$full_route .= '/' . ltrim($resource_name, '/');
1198
+						unset($route_data[ $full_route ]);
1199
+					}
1200
+				}
1201
+			}
1202
+		}
1203
+		return $route_data;
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * Returns an array describing which versions of core support serving requests for.
1209
+	 * Keys are core versions' major and minor version, and values are the
1210
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1211
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1212
+	 * the answers table entirely, in which case it would be very difficult for
1213
+	 * it to serve 4.6-style responses.
1214
+	 * Versions of core that are missing from this array are unknowns.
1215
+	 * previous ver
1216
+	 *
1217
+	 * @return array
1218
+	 */
1219
+	public static function version_compatibilities()
1220
+	{
1221
+		return apply_filters(
1222
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1223
+			[
1224
+				'4.8.29' => '4.8.29',
1225
+				'4.8.33' => '4.8.29',
1226
+				'4.8.34' => '4.8.29',
1227
+				'4.8.36' => '4.8.29',
1228
+			]
1229
+		);
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Gets the latest API version served. Eg if there
1235
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1236
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1237
+	 *
1238
+	 * @return string
1239
+	 */
1240
+	public static function latest_rest_api_version()
1241
+	{
1242
+		$versions_served = EED_Core_Rest_Api::versions_served();
1243
+		$versions_served_keys = array_keys($versions_served);
1244
+		return end($versions_served_keys);
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1250
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1251
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1252
+	 * We also indicate whether or not this version should be put in the index or not
1253
+	 *
1254
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1255
+	 * are whether or not they should be hidden
1256
+	 */
1257
+	public static function versions_served()
1258
+	{
1259
+		$versions_served = [];
1260
+		$possibly_served_versions = EED_Core_Rest_Api::version_compatibilities();
1261
+		$lowest_compatible_version = end($possibly_served_versions);
1262
+		reset($possibly_served_versions);
1263
+		$versions_served_historically = array_keys($possibly_served_versions);
1264
+		$latest_version = end($versions_served_historically);
1265
+		reset($versions_served_historically);
1266
+		// for each version of core we have ever served:
1267
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1268
+			// if it's not above the current core version, and it's compatible with the current version of core
1269
+
1270
+			if ($key_versioned_endpoint === $latest_version) {
1271
+				// don't hide the latest version in the index
1272
+				$versions_served[ $key_versioned_endpoint ] = false;
1273
+			} elseif (
1274
+				version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1275
+				&& version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1276
+			) {
1277
+				// include, but hide, previous versions which are still supported
1278
+				$versions_served[ $key_versioned_endpoint ] = true;
1279
+			} elseif (
1280
+				apply_filters(
1281
+					'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1282
+					false,
1283
+					$possibly_served_versions
1284
+				)
1285
+			) {
1286
+				// if a version is no longer supported, don't include it in index or list of versions served
1287
+				$versions_served[ $key_versioned_endpoint ] = true;
1288
+			}
1289
+		}
1290
+		return $versions_served;
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * Gets the major and minor version of EE core's version string
1296
+	 *
1297
+	 * @return string
1298
+	 */
1299
+	public static function core_version()
1300
+	{
1301
+		return apply_filters(
1302
+			'FHEE__EED_Core_REST_API__core_version',
1303
+			implode(
1304
+				'.',
1305
+				array_slice(
1306
+					explode(
1307
+						'.',
1308
+						espresso_version()
1309
+					),
1310
+					0,
1311
+					3
1312
+				)
1313
+			)
1314
+		);
1315
+	}
1316
+
1317
+
1318
+	/**
1319
+	 * Gets the default limit that should be used when querying for resources
1320
+	 *
1321
+	 * @return int
1322
+	 */
1323
+	public static function get_default_query_limit()
1324
+	{
1325
+		// we actually don't use a const because we want folks to always use
1326
+		// this method, not the const directly
1327
+		return apply_filters(
1328
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1329
+			100
1330
+		);
1331
+	}
1332
+
1333
+
1334
+	/**
1335
+	 * @param string $version api version string (i.e. '4.8.36')
1336
+	 * @return array
1337
+	 */
1338
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1339
+	{
1340
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1341
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1342
+		$collection_routes = [];
1343
+		foreach ($model_names as $model_name => $model_class_name) {
1344
+			$collection_routes[ strtolower($model_name) ] = '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/'
1345
+															. EEH_Inflector::pluralize_and_lower($model_name);
1346
+		}
1347
+		return $collection_routes;
1348
+	}
1349
+
1350
+
1351
+	/**
1352
+	 * Returns an array of primary key names indexed by model names.
1353
+	 *
1354
+	 * @param string $version
1355
+	 * @return array
1356
+	 */
1357
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1358
+	{
1359
+		$version = empty($version) ? EED_Core_Rest_Api::latest_rest_api_version() : $version;
1360
+		$model_names = EED_Core_Rest_Api::model_names_with_plural_routes($version);
1361
+		$primary_key_items = [];
1362
+		foreach ($model_names as $model_name => $model_class_name) {
1363
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1364
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1365
+				if (count($primary_keys) > 1) {
1366
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1367
+				} else {
1368
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1369
+				}
1370
+			}
1371
+		}
1372
+		return $primary_key_items;
1373
+	}
1374
+
1375
+
1376
+	/**
1377
+	 * Determines the EE REST API debug mode is activated, or not.
1378
+	 *
1379
+	 * @return bool
1380
+	 * @since 4.9.76.p
1381
+	 */
1382
+	public static function debugMode()
1383
+	{
1384
+		static $debug_mode = null; // could be class prop
1385
+		if ($debug_mode === null) {
1386
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1387
+		}
1388
+		return $debug_mode;
1389
+	}
1390
+
1391
+
1392
+	/**
1393
+	 *    run - initial module setup
1394
+	 *
1395
+	 * @access    public
1396
+	 * @param WP $WP
1397
+	 * @return    void
1398
+	 */
1399
+	public function run($WP)
1400
+	{
1401
+	}
1402 1402
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +97 added lines, -97 removed lines patch added patch discarded remove patch
@@ -37,124 +37,124 @@
 block discarded – undo
37 37
  * @since           4.0
38 38
  */
39 39
 if (function_exists('espresso_version')) {
40
-    if (! function_exists('espresso_duplicate_plugin_error')) {
41
-        /**
42
-         *    espresso_duplicate_plugin_error
43
-         *    displays if more than one version of EE is activated at the same time.
44
-         */
45
-        function espresso_duplicate_plugin_error()
46
-        {
47
-            ?>
40
+	if (! function_exists('espresso_duplicate_plugin_error')) {
41
+		/**
42
+		 *    espresso_duplicate_plugin_error
43
+		 *    displays if more than one version of EE is activated at the same time.
44
+		 */
45
+		function espresso_duplicate_plugin_error()
46
+		{
47
+			?>
48 48
             <div class="error">
49 49
                 <p>
50 50
                     <?php
51
-                    echo esc_html__(
52
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
-                        'event_espresso'
54
-                    ); ?>
51
+					echo esc_html__(
52
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
+						'event_espresso'
54
+					); ?>
55 55
                 </p>
56 56
             </div>
57 57
             <?php
58
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
59
-        }
60
-    }
61
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
58
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
59
+		}
60
+	}
61
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62 62
 } else {
63
-    define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
-        /**
66
-         * espresso_minimum_php_version_error
67
-         *
68
-         * @return void
69
-         */
70
-        function espresso_minimum_php_version_error()
71
-        {
72
-            ?>
63
+	define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
+		/**
66
+		 * espresso_minimum_php_version_error
67
+		 *
68
+		 * @return void
69
+		 */
70
+		function espresso_minimum_php_version_error()
71
+		{
72
+			?>
73 73
             <div class="error">
74 74
                 <p>
75 75
                     <?php
76
-                    printf(
77
-                        esc_html__(
78
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
-                            'event_espresso'
80
-                        ),
81
-                        EE_MIN_PHP_VER_REQUIRED,
82
-                        PHP_VERSION,
83
-                        '<br/>',
84
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
85
-                    );
86
-                    ?>
76
+					printf(
77
+						esc_html__(
78
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
+							'event_espresso'
80
+						),
81
+						EE_MIN_PHP_VER_REQUIRED,
82
+						PHP_VERSION,
83
+						'<br/>',
84
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
85
+					);
86
+					?>
87 87
                 </p>
88 88
             </div>
89 89
             <?php
90
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
91
-        }
90
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
91
+		}
92 92
 
93
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
-    } else {
95
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
93
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
+	} else {
95
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
96 96
 
97
-        require_once __DIR__ . '/vendor/autoload.php';
98
-        require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
97
+		require_once __DIR__ . '/vendor/autoload.php';
98
+		require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
99 99
 
100
-        /**
101
-         * espresso_version
102
-         * Returns the plugin version
103
-         *
104
-         * @return string
105
-         */
106
-        function espresso_version()
107
-        {
108
-            return apply_filters('FHEE__espresso__espresso_version', '5.0.2.rc.000');
109
-        }
100
+		/**
101
+		 * espresso_version
102
+		 * Returns the plugin version
103
+		 *
104
+		 * @return string
105
+		 */
106
+		function espresso_version()
107
+		{
108
+			return apply_filters('FHEE__espresso__espresso_version', '5.0.2.rc.000');
109
+		}
110 110
 
111
-        /**
112
-         * espresso_plugin_activation
113
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
114
-         */
115
-        function espresso_plugin_activation()
116
-        {
117
-            update_option('ee_espresso_activation', true);
118
-            update_option('event-espresso-core_allow_tracking', 'no');
119
-            update_option('event-espresso-core_tracking_notice', 'hide');
120
-            // Run WP GraphQL activation callback
121
-            graphql_activation_callback();
122
-        }
111
+		/**
112
+		 * espresso_plugin_activation
113
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
114
+		 */
115
+		function espresso_plugin_activation()
116
+		{
117
+			update_option('ee_espresso_activation', true);
118
+			update_option('event-espresso-core_allow_tracking', 'no');
119
+			update_option('event-espresso-core_tracking_notice', 'hide');
120
+			// Run WP GraphQL activation callback
121
+			graphql_activation_callback();
122
+		}
123 123
 
124
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
124
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
125 125
 
126
-        /**
127
-         * espresso_plugin_deactivation
128
-         */
129
-        function espresso_plugin_deactivation()
130
-        {
131
-            // Run WP GraphQL deactivation callback
132
-            graphql_deactivation_callback();
133
-            delete_option('event-espresso-core_allow_tracking');
134
-            delete_option('event-espresso-core_tracking_notice');
135
-        }
136
-        register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
126
+		/**
127
+		 * espresso_plugin_deactivation
128
+		 */
129
+		function espresso_plugin_deactivation()
130
+		{
131
+			// Run WP GraphQL deactivation callback
132
+			graphql_deactivation_callback();
133
+			delete_option('event-espresso-core_allow_tracking');
134
+			delete_option('event-espresso-core_tracking_notice');
135
+		}
136
+		register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
137 137
 
138
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
139
-        bootstrap_espresso();
140
-    }
138
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
139
+		bootstrap_espresso();
140
+	}
141 141
 }
142 142
 
143 143
 if (! function_exists('espresso_deactivate_plugin')) {
144
-    /**
145
-     *    deactivate_plugin
146
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
147
-     *
148
-     * @access public
149
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
150
-     * @return    void
151
-     */
152
-    function espresso_deactivate_plugin($plugin_basename = '')
153
-    {
154
-        if (! function_exists('deactivate_plugins')) {
155
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
156
-        }
157
-        unset($_GET['activate'], $_REQUEST['activate']);
158
-        deactivate_plugins($plugin_basename);
159
-    }
144
+	/**
145
+	 *    deactivate_plugin
146
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
147
+	 *
148
+	 * @access public
149
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
150
+	 * @return    void
151
+	 */
152
+	function espresso_deactivate_plugin($plugin_basename = '')
153
+	{
154
+		if (! function_exists('deactivate_plugins')) {
155
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
156
+		}
157
+		unset($_GET['activate'], $_REQUEST['activate']);
158
+		deactivate_plugins($plugin_basename);
159
+	}
160 160
 }
Please login to merge, or discard this patch.
languages/event_espresso-translations-js.php 1 patch
Spacing   +700 added lines, -700 removed lines patch added patch discarded remove patch
@@ -2,137 +2,137 @@  discard block
 block discarded – undo
2 2
 /* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */
3 3
 $generated_i18n_strings = array(
4 4
 	// Reference: packages/ui-components/src/Pagination/constants.ts:6
5
-	__( '2', 'event_espresso' ),
5
+	__('2', 'event_espresso'),
6 6
 
7 7
 	// Reference: packages/ui-components/src/Pagination/constants.ts:7
8
-	__( '6', 'event_espresso' ),
8
+	__('6', 'event_espresso'),
9 9
 
10 10
 	// Reference: packages/ui-components/src/Pagination/constants.ts:8
11
-	__( '12', 'event_espresso' ),
11
+	__('12', 'event_espresso'),
12 12
 
13 13
 	// Reference: packages/ui-components/src/Pagination/constants.ts:9
14
-	__( '24', 'event_espresso' ),
14
+	__('24', 'event_espresso'),
15 15
 
16 16
 	// Reference: packages/ui-components/src/Pagination/constants.ts:10
17
-	__( '48', 'event_espresso' ),
17
+	__('48', 'event_espresso'),
18 18
 
19 19
 	// Reference: domains/core/admin/blocks/src/components/AvatarImage.tsx:27
20
-	__( 'contact avatar', 'event_espresso' ),
20
+	__('contact avatar', 'event_espresso'),
21 21
 
22 22
 	// Reference: domains/core/admin/blocks/src/components/OrderByControl.tsx:12
23
-	__( 'Order by', 'event_espresso' ),
23
+	__('Order by', 'event_espresso'),
24 24
 
25 25
 	// Reference: domains/core/admin/blocks/src/components/RegStatusControl.tsx:17
26 26
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectStatus.tsx:13
27
-	__( 'Select Registration Status', 'event_espresso' ),
27
+	__('Select Registration Status', 'event_espresso'),
28 28
 
29 29
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:14
30
-	__( 'Ascending', 'event_espresso' ),
30
+	__('Ascending', 'event_espresso'),
31 31
 
32 32
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:18
33
-	__( 'Descending', 'event_espresso' ),
33
+	__('Descending', 'event_espresso'),
34 34
 
35 35
 	// Reference: domains/core/admin/blocks/src/components/SortOrderControl.tsx:24
36
-	__( 'Sort order:', 'event_espresso' ),
36
+	__('Sort order:', 'event_espresso'),
37 37
 
38 38
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:41
39
-	__( 'There was some error fetching attendees list', 'event_espresso' ),
39
+	__('There was some error fetching attendees list', 'event_espresso'),
40 40
 
41 41
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:47
42
-	__( 'To get started, select what event you want to show attendees from in the block settings.', 'event_espresso' ),
42
+	__('To get started, select what event you want to show attendees from in the block settings.', 'event_espresso'),
43 43
 
44 44
 	// Reference: domains/core/admin/blocks/src/event-attendees/AttendeesDisplay.tsx:53
45
-	__( 'There are no attendees for selected options.', 'event_espresso' ),
45
+	__('There are no attendees for selected options.', 'event_espresso'),
46 46
 
47 47
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:12
48
-	__( 'Display on Archives', 'event_espresso' ),
48
+	__('Display on Archives', 'event_espresso'),
49 49
 
50 50
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:17
51
-	__( 'Attendees are shown whenever this post is listed in an archive view.', 'event_espresso' ),
51
+	__('Attendees are shown whenever this post is listed in an archive view.', 'event_espresso'),
52 52
 
53 53
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/ArchiveSettings.tsx:18
54
-	__( 'Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso' ),
54
+	__('Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso'),
55 55
 
56 56
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/AttendeeLimit.tsx:29
57
-	__( 'Number of Attendees to Display:', 'event_espresso' ),
57
+	__('Number of Attendees to Display:', 'event_espresso'),
58 58
 
59 59
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/AttendeeLimit.tsx:34
60 60
 	/* translators: %d attendees count */
61
-	_n_noop( 'Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso' ),
61
+	_n_noop('Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso'),
62 62
 
63 63
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:27
64
-	__( 'Display Gravatar', 'event_espresso' ),
64
+	__('Display Gravatar', 'event_espresso'),
65 65
 
66 66
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:32
67
-	__( 'Gravatar images are shown for each attendee.', 'event_espresso' ),
67
+	__('Gravatar images are shown for each attendee.', 'event_espresso'),
68 68
 
69 69
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:33
70
-	__( 'No gravatar images are shown for each attendee.', 'event_espresso' ),
70
+	__('No gravatar images are shown for each attendee.', 'event_espresso'),
71 71
 
72 72
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/GravatarSettings.tsx:38
73
-	__( 'Size of Gravatar', 'event_espresso' ),
73
+	__('Size of Gravatar', 'event_espresso'),
74 74
 
75 75
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectDatetime.tsx:22
76
-	__( 'Select Datetime', 'event_espresso' ),
76
+	__('Select Datetime', 'event_espresso'),
77 77
 
78 78
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectEvent.tsx:22
79 79
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectEvent.tsx:22
80
-	__( 'Select Event', 'event_espresso' ),
80
+	__('Select Event', 'event_espresso'),
81 81
 
82 82
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:11
83
-	__( 'Attendee id', 'event_espresso' ),
83
+	__('Attendee id', 'event_espresso'),
84 84
 
85 85
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:15
86
-	__( 'Last name only', 'event_espresso' ),
86
+	__('Last name only', 'event_espresso'),
87 87
 
88 88
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:19
89
-	__( 'First name only', 'event_espresso' ),
89
+	__('First name only', 'event_espresso'),
90 90
 
91 91
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:23
92
-	__( 'First, then Last name', 'event_espresso' ),
92
+	__('First, then Last name', 'event_espresso'),
93 93
 
94 94
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:27
95
-	__( 'Last, then First name', 'event_espresso' ),
95
+	__('Last, then First name', 'event_espresso'),
96 96
 
97 97
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectOrderBy.tsx:41
98
-	__( 'Order Attendees by:', 'event_espresso' ),
98
+	__('Order Attendees by:', 'event_espresso'),
99 99
 
100 100
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/SelectTicket.tsx:22
101
-	__( 'Select Ticket', 'event_espresso' ),
101
+	__('Select Ticket', 'event_espresso'),
102 102
 
103 103
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:21
104
-	__( 'Filter By Settings', 'event_espresso' ),
104
+	__('Filter By Settings', 'event_espresso'),
105 105
 
106 106
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:36
107
-	__( 'Gravatar Setttings', 'event_espresso' ),
107
+	__('Gravatar Setttings', 'event_espresso'),
108 108
 
109 109
 	// Reference: domains/core/admin/blocks/src/event-attendees/controls/index.tsx:39
110
-	__( 'Archive Settings', 'event_espresso' ),
110
+	__('Archive Settings', 'event_espresso'),
111 111
 
112 112
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:10
113
-	__( 'Event Attendees', 'event_espresso' ),
113
+	__('Event Attendees', 'event_espresso'),
114 114
 
115 115
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:11
116
-	__( 'Displays a list of people that have registered for the specified event', 'event_espresso' ),
116
+	__('Displays a list of people that have registered for the specified event', 'event_espresso'),
117 117
 
118 118
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
119 119
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:12
120 120
 	// Reference: packages/edtr-services/src/constants.ts:25
121
-	__( 'event', 'event_espresso' ),
121
+	__('event', 'event_espresso'),
122 122
 
123 123
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
124
-	__( 'attendees', 'event_espresso' ),
124
+	__('attendees', 'event_espresso'),
125 125
 
126 126
 	// Reference: domains/core/admin/blocks/src/event-attendees/index.tsx:14
127
-	__( 'list', 'event_espresso' ),
127
+	__('list', 'event_espresso'),
128 128
 
129 129
 	// Reference: domains/core/admin/blocks/src/event/DisplayField.tsx:41
130
-	__( 'An unknown error occurred while fetching event details.', 'event_espresso' ),
130
+	__('An unknown error occurred while fetching event details.', 'event_espresso'),
131 131
 
132 132
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:10
133 133
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:24
134 134
 	// Reference: packages/utils/src/list/index.ts:14
135
-	__( 'Select…', 'event_espresso' ),
135
+	__('Select…', 'event_espresso'),
136 136
 
137 137
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:15
138 138
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:75
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:196
142 142
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:49
143 143
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:40
144
-	__( 'Name', 'event_espresso' ),
144
+	__('Name', 'event_espresso'),
145 145
 
146 146
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:19
147 147
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:80
@@ -149,404 +149,404 @@  discard block
 block discarded – undo
149 149
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:201
150 150
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:55
151 151
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:47
152
-	__( 'Description', 'event_espresso' ),
152
+	__('Description', 'event_espresso'),
153 153
 
154 154
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:23
155
-	__( 'Short description', 'event_espresso' ),
155
+	__('Short description', 'event_espresso'),
156 156
 
157 157
 	// Reference: domains/core/admin/blocks/src/event/controls/SelectField.tsx:35
158
-	__( 'Select Field', 'event_espresso' ),
158
+	__('Select Field', 'event_espresso'),
159 159
 
160 160
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:27
161
-	__( 'Text Color', 'event_espresso' ),
161
+	__('Text Color', 'event_espresso'),
162 162
 
163 163
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:32
164
-	__( 'Background Color', 'event_espresso' ),
164
+	__('Background Color', 'event_espresso'),
165 165
 
166 166
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:41
167 167
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:22
168 168
 	// Reference: packages/form-builder/src/FormSection/Tabs/FormSectionTabs.tsx:21
169
-	__( 'Settings', 'event_espresso' ),
169
+	__('Settings', 'event_espresso'),
170 170
 
171 171
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:45
172
-	__( 'Typography', 'event_espresso' ),
172
+	__('Typography', 'event_espresso'),
173 173
 
174 174
 	// Reference: domains/core/admin/blocks/src/event/controls/index.tsx:48
175
-	__( 'Color', 'event_espresso' ),
175
+	__('Color', 'event_espresso'),
176 176
 
177 177
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:12
178
-	__( 'field', 'event_espresso' ),
178
+	__('field', 'event_espresso'),
179 179
 
180 180
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:8
181
-	__( 'Event Field', 'event_espresso' ),
181
+	__('Event Field', 'event_espresso'),
182 182
 
183 183
 	// Reference: domains/core/admin/blocks/src/event/index.tsx:9
184
-	__( 'Displays the selected field of an event', 'event_espresso' ),
184
+	__('Displays the selected field of an event', 'event_espresso'),
185 185
 
186 186
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:17
187
-	__( 'Error', 'event_espresso' ),
187
+	__('Error', 'event_espresso'),
188 188
 
189 189
 	// Reference: domains/core/admin/blocks/src/services/utils.ts:9
190
-	__( 'Loading…', 'event_espresso' ),
190
+	__('Loading…', 'event_espresso'),
191 191
 
192 192
 	// Reference: domains/core/admin/eventEditor/src/ui/EventDescription.tsx:33
193
-	__( 'Event Description', 'event_espresso' ),
193
+	__('Event Description', 'event_espresso'),
194 194
 
195 195
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:29
196
-	__( 'Active status', 'event_espresso' ),
196
+	__('Active status', 'event_espresso'),
197 197
 
198 198
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/AltRegPage.tsx:12
199
-	__( 'Alternative Registration Page', 'event_espresso' ),
199
+	__('Alternative Registration Page', 'event_espresso'),
200 200
 
201 201
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/DefaultRegistrationStatus.tsx:26
202
-	__( 'Default Registration Status', 'event_espresso' ),
202
+	__('Default Registration Status', 'event_espresso'),
203 203
 
204 204
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:8
205
-	__( 'Donations Enabled', 'event_espresso' ),
205
+	__('Donations Enabled', 'event_espresso'),
206 206
 
207 207
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:8
208
-	__( 'Donations Disabled', 'event_espresso' ),
208
+	__('Donations Disabled', 'event_espresso'),
209 209
 
210 210
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/EventManager.tsx:16
211
-	__( 'Event Manager', 'event_espresso' ),
211
+	__('Event Manager', 'event_espresso'),
212 212
 
213 213
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/EventPhoneNumber.tsx:15
214
-	__( 'Event Phone Number', 'event_espresso' ),
214
+	__('Event Phone Number', 'event_espresso'),
215 215
 
216 216
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/MaxRegistrations.tsx:13
217
-	__( 'Max Registrations per Transaction', 'event_espresso' ),
217
+	__('Max Registrations per Transaction', 'event_espresso'),
218 218
 
219 219
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:8
220
-	__( 'Ticket Selector Enabled', 'event_espresso' ),
220
+	__('Ticket Selector Enabled', 'event_espresso'),
221 221
 
222 222
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:8
223
-	__( 'Ticket Selector Disabled', 'event_espresso' ),
223
+	__('Ticket Selector Disabled', 'event_espresso'),
224 224
 
225 225
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/index.tsx:41
226
-	__( 'Event Details', 'event_espresso' ),
226
+	__('Event Details', 'event_espresso'),
227 227
 
228 228
 	// Reference: domains/core/admin/eventEditor/src/ui/EventRegistrationOptions/index.tsx:47
229
-	__( 'Registration Options', 'event_espresso' ),
229
+	__('Registration Options', 'event_espresso'),
230 230
 
231 231
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:10
232
-	__( 'primary information about the date', 'event_espresso' ),
232
+	__('primary information about the date', 'event_espresso'),
233 233
 
234 234
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:10
235
-	__( 'Date Details', 'event_espresso' ),
235
+	__('Date Details', 'event_espresso'),
236 236
 
237 237
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
238 238
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:16
239 239
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:16
240
-	__( 'relations between tickets and dates', 'event_espresso' ),
240
+	__('relations between tickets and dates', 'event_espresso'),
241 241
 
242 242
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
243
-	__( 'Assign Tickets', 'event_espresso' ),
243
+	__('Assign Tickets', 'event_espresso'),
244 244
 
245 245
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/FooterButtons.tsx:22
246
-	__( 'Save and assign tickets', 'event_espresso' ),
246
+	__('Save and assign tickets', 'event_espresso'),
247 247
 
248 248
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/Modal.tsx:27
249 249
 	/* translators: %s datetime id */
250
-	__( 'Edit datetime %s', 'event_espresso' ),
250
+	__('Edit datetime %s', 'event_espresso'),
251 251
 
252 252
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/multiStep/Modal.tsx:30
253
-	__( 'New Datetime', 'event_espresso' ),
253
+	__('New Datetime', 'event_espresso'),
254 254
 
255 255
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:110
256 256
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:108
257 257
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:231
258 258
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:108
259
-	__( 'Details', 'event_espresso' ),
259
+	__('Details', 'event_espresso'),
260 260
 
261 261
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:114
262 262
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:112
263 263
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:81
264
-	__( 'Capacity', 'event_espresso' ),
264
+	__('Capacity', 'event_espresso'),
265 265
 
266 266
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:119
267
-	__( 'The maximum number of registrants that can attend the event at this particular date.', 'event_espresso' ),
267
+	__('The maximum number of registrants that can attend the event at this particular date.', 'event_espresso'),
268 268
 
269 269
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:123
270
-	__( 'Set to 0 to close registration or leave blank for no limit.', 'event_espresso' ),
270
+	__('Set to 0 to close registration or leave blank for no limit.', 'event_espresso'),
271 271
 
272 272
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:129
273 273
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:169
274
-	__( 'Trash', 'event_espresso' ),
274
+	__('Trash', 'event_espresso'),
275 275
 
276 276
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:71
277 277
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:45
278 278
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:192
279 279
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:45
280
-	__( 'Basics', 'event_espresso' ),
280
+	__('Basics', 'event_espresso'),
281 281
 
282 282
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:88
283 283
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:63
284 284
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:63
285
-	__( 'Dates', 'event_espresso' ),
285
+	__('Dates', 'event_espresso'),
286 286
 
287 287
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:92
288 288
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:51
289 289
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:213
290
-	__( 'Start Date', 'event_espresso' ),
290
+	__('Start Date', 'event_espresso'),
291 291
 
292 292
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:99
293 293
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:65
294 294
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:220
295
-	__( 'End Date', 'event_espresso' ),
295
+	__('End Date', 'event_espresso'),
296 296
 
297 297
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DateRegistrationsLink.tsx:13
298
-	__( 'view ALL registrations for this date.', 'event_espresso' ),
298
+	__('view ALL registrations for this date.', 'event_espresso'),
299 299
 
300 300
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DateSoldLink.tsx:13
301
-	__( 'view approved registrations for this date.', 'event_espresso' ),
301
+	__('view approved registrations for this date.', 'event_espresso'),
302 302
 
303 303
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:35
304 304
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/TableView.tsx:33
305
-	__( 'Event Dates', 'event_espresso' ),
305
+	__('Event Dates', 'event_espresso'),
306 306
 
307 307
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:38
308
-	__( 'loading event dates…', 'event_espresso' ),
308
+	__('loading event dates…', 'event_espresso'),
309 309
 
310 310
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesListButtons.tsx:22
311
-	__( 'Add a date or a ticket in order to use Ticket Assignment Manager', 'event_espresso' ),
311
+	__('Add a date or a ticket in order to use Ticket Assignment Manager', 'event_espresso'),
312 312
 
313 313
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/DatesListButtons.tsx:32
314
-	__( 'Ticket Assignments', 'event_espresso' ),
314
+	__('Ticket Assignments', 'event_espresso'),
315 315
 
316 316
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:25
317
-	__( 'Number of related tickets', 'event_espresso' ),
317
+	__('Number of related tickets', 'event_espresso'),
318 318
 
319 319
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:26
320
-	__( 'There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso' ),
320
+	__('There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso'),
321 321
 
322 322
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:34
323
-	__( 'assign tickets', 'event_espresso' ),
323
+	__('assign tickets', 'event_espresso'),
324 324
 
325 325
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:21
326
-	__( 'event date main menu', 'event_espresso' ),
326
+	__('event date main menu', 'event_espresso'),
327 327
 
328 328
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:33
329
-	__( 'edit datetime', 'event_espresso' ),
329
+	__('edit datetime', 'event_espresso'),
330 330
 
331 331
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:34
332
-	__( 'copy datetime', 'event_espresso' ),
332
+	__('copy datetime', 'event_espresso'),
333 333
 
334 334
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:15
335 335
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:48
336
-	__( 'delete permanently', 'event_espresso' ),
336
+	__('delete permanently', 'event_espresso'),
337 337
 
338 338
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:15
339
-	__( 'trash datetime', 'event_espresso' ),
339
+	__('trash datetime', 'event_espresso'),
340 340
 
341 341
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:18
342
-	__( 'Permanently Delete Datetime?', 'event_espresso' ),
342
+	__('Permanently Delete Datetime?', 'event_espresso'),
343 343
 
344 344
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:18
345
-	__( 'Move Datetime to Trash?', 'event_espresso' ),
345
+	__('Move Datetime to Trash?', 'event_espresso'),
346 346
 
347 347
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:20
348
-	__( 'Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso' ),
348
+	__('Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso'),
349 349
 
350 350
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:23
351
-	__( 'Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso' ),
351
+	__('Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso'),
352 352
 
353 353
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DeleteDatetime.tsx:33
354
-	__( 'delete', 'event_espresso' ),
354
+	__('delete', 'event_espresso'),
355 355
 
356 356
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:36
357 357
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:40
358 358
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:43
359
-	__( 'bulk actions', 'event_espresso' ),
359
+	__('bulk actions', 'event_espresso'),
360 360
 
361 361
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:40
362
-	__( 'edit datetime details', 'event_espresso' ),
362
+	__('edit datetime details', 'event_espresso'),
363 363
 
364 364
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:44
365
-	__( 'delete datetimes', 'event_espresso' ),
365
+	__('delete datetimes', 'event_espresso'),
366 366
 
367 367
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:44
368
-	__( 'trash datetimes', 'event_espresso' ),
368
+	__('trash datetimes', 'event_espresso'),
369 369
 
370 370
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:14
371
-	__( 'Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso' ),
371
+	__('Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso'),
372 372
 
373 373
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:15
374
-	__( 'Are you sure you want to trash these datetimes?', 'event_espresso' ),
374
+	__('Are you sure you want to trash these datetimes?', 'event_espresso'),
375 375
 
376 376
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:16
377
-	__( 'Delete datetimes permanently', 'event_espresso' ),
377
+	__('Delete datetimes permanently', 'event_espresso'),
378 378
 
379 379
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:16
380
-	__( 'Trash datetimes', 'event_espresso' ),
380
+	__('Trash datetimes', 'event_espresso'),
381 381
 
382 382
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:21
383
-	__( 'Bulk edit date details', 'event_espresso' ),
383
+	__('Bulk edit date details', 'event_espresso'),
384 384
 
385 385
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:22
386
-	__( 'any changes will be applied to ALL of the selected dates.', 'event_espresso' ),
386
+	__('any changes will be applied to ALL of the selected dates.', 'event_espresso'),
387 387
 
388 388
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/formValidation.ts:12
389 389
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/formValidation.ts:12
390
-	__( 'Name must be at least three characters', 'event_espresso' ),
390
+	__('Name must be at least three characters', 'event_espresso'),
391 391
 
392 392
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:67
393 393
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:67
394
-	__( 'Shift dates', 'event_espresso' ),
394
+	__('Shift dates', 'event_espresso'),
395 395
 
396 396
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:92
397 397
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:92
398
-	__( 'earlier', 'event_espresso' ),
398
+	__('earlier', 'event_espresso'),
399 399
 
400 400
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:96
401 401
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:96
402
-	__( 'later', 'event_espresso' ),
402
+	__('later', 'event_espresso'),
403 403
 
404 404
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCapacity.tsx:31
405 405
 	/* translators: click to edit capacity<linebreak>(registration limit)… */
406
-	__( 'click to edit capacity%s(registration limit)…', 'event_espresso' ),
406
+	__('click to edit capacity%s(registration limit)…', 'event_espresso'),
407 407
 
408 408
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:31
409 409
 	// Reference: packages/ee-components/src/SimpleTicketCard/SimpleTicketCard.tsx:27
410 410
 	// Reference: packages/ui-components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:34
411
-	__( 'starts', 'event_espresso' ),
411
+	__('starts', 'event_espresso'),
412 412
 
413 413
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
414 414
 	// Reference: packages/ee-components/src/SimpleTicketCard/SimpleTicketCard.tsx:34
415 415
 	// Reference: packages/ui-components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:47
416
-	__( 'ends', 'event_espresso' ),
416
+	__('ends', 'event_espresso'),
417 417
 
418 418
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
419
-	__( 'started', 'event_espresso' ),
419
+	__('started', 'event_espresso'),
420 420
 
421 421
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:32
422
-	__( 'ended', 'event_espresso' ),
422
+	__('ended', 'event_espresso'),
423 423
 
424 424
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:46
425
-	__( 'Edit Event Date', 'event_espresso' ),
425
+	__('Edit Event Date', 'event_espresso'),
426 426
 
427 427
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:50
428
-	__( 'edit start and end dates', 'event_espresso' ),
428
+	__('edit start and end dates', 'event_espresso'),
429 429
 
430 430
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:16
431 431
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:16
432
-	__( 'sold', 'event_espresso' ),
432
+	__('sold', 'event_espresso'),
433 433
 
434 434
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:21
435
-	__( 'capacity', 'event_espresso' ),
435
+	__('capacity', 'event_espresso'),
436 436
 
437 437
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:27
438 438
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:26
439
-	__( 'reg list', 'event_espresso' ),
439
+	__('reg list', 'event_espresso'),
440 440
 
441 441
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:43
442 442
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:35
443
-	__( 'add description…', 'event_espresso' ),
443
+	__('add description…', 'event_espresso'),
444 444
 
445 445
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:44
446 446
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:36
447
-	__( 'Edit description', 'event_espresso' ),
447
+	__('Edit description', 'event_espresso'),
448 448
 
449 449
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:45
450 450
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:37
451
-	__( 'click to edit description…', 'event_espresso' ),
451
+	__('click to edit description…', 'event_espresso'),
452 452
 
453 453
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:10
454
-	__( 'Move Date to Trash', 'event_espresso' ),
454
+	__('Move Date to Trash', 'event_espresso'),
455 455
 
456 456
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:13
457 457
 	// Reference: packages/constants/src/datetime.ts:6
458
-	__( 'Active', 'event_espresso' ),
458
+	__('Active', 'event_espresso'),
459 459
 
460 460
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:14
461 461
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:13
462
-	__( 'Trashed', 'event_espresso' ),
462
+	__('Trashed', 'event_espresso'),
463 463
 
464 464
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:15
465 465
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:14
466 466
 	// Reference: packages/constants/src/datetime.ts:8
467
-	__( 'Expired', 'event_espresso' ),
467
+	__('Expired', 'event_espresso'),
468 468
 
469 469
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:16
470 470
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:16
471
-	__( 'Sold Out', 'event_espresso' ),
471
+	__('Sold Out', 'event_espresso'),
472 472
 
473 473
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:17
474 474
 	// Reference: packages/constants/src/datetime.ts:12
475
-	__( 'Upcoming', 'event_espresso' ),
475
+	__('Upcoming', 'event_espresso'),
476 476
 
477 477
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:7
478
-	__( 'Edit Event Date Details', 'event_espresso' ),
478
+	__('Edit Event Date Details', 'event_espresso'),
479 479
 
480 480
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:8
481
-	__( 'View Registrations for this Date', 'event_espresso' ),
481
+	__('View Registrations for this Date', 'event_espresso'),
482 482
 
483 483
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/config.ts:9
484
-	__( 'Manage Ticket Assignments', 'event_espresso' ),
484
+	__('Manage Ticket Assignments', 'event_espresso'),
485 485
 
486 486
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/editable/EditableName.tsx:41
487 487
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditableName.tsx:41
488
-	__( 'click to edit title…', 'event_espresso' ),
488
+	__('click to edit title…', 'event_espresso'),
489 489
 
490 490
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/editable/EditableName.tsx:42
491 491
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditableName.tsx:42
492
-	__( 'add title…', 'event_espresso' ),
492
+	__('add title…', 'event_espresso'),
493 493
 
494 494
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/ActiveDatesFilters.tsx:17
495 495
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/ActiveTicketsFilters.tsx:17
496
-	__( 'ON', 'event_espresso' ),
496
+	__('ON', 'event_espresso'),
497 497
 
498 498
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:10
499
-	__( 'end dates only', 'event_espresso' ),
499
+	__('end dates only', 'event_espresso'),
500 500
 
501 501
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:11
502
-	__( 'start and end dates', 'event_espresso' ),
502
+	__('start and end dates', 'event_espresso'),
503 503
 
504 504
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:16
505
-	__( 'dates above 90% capacity', 'event_espresso' ),
505
+	__('dates above 90% capacity', 'event_espresso'),
506 506
 
507 507
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:17
508
-	__( 'dates above 75% capacity', 'event_espresso' ),
508
+	__('dates above 75% capacity', 'event_espresso'),
509 509
 
510 510
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:18
511
-	__( 'dates above 50% capacity', 'event_espresso' ),
511
+	__('dates above 50% capacity', 'event_espresso'),
512 512
 
513 513
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:19
514
-	__( 'dates below 50% capacity', 'event_espresso' ),
514
+	__('dates below 50% capacity', 'event_espresso'),
515 515
 
516 516
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:23
517
-	__( 'all dates', 'event_espresso' ),
517
+	__('all dates', 'event_espresso'),
518 518
 
519 519
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:24
520
-	__( 'all active and upcoming', 'event_espresso' ),
520
+	__('all active and upcoming', 'event_espresso'),
521 521
 
522 522
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:25
523
-	__( 'active dates only', 'event_espresso' ),
523
+	__('active dates only', 'event_espresso'),
524 524
 
525 525
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:26
526
-	__( 'upcoming dates only', 'event_espresso' ),
526
+	__('upcoming dates only', 'event_espresso'),
527 527
 
528 528
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:27
529
-	__( 'next active or upcoming only', 'event_espresso' ),
529
+	__('next active or upcoming only', 'event_espresso'),
530 530
 
531 531
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:28
532
-	__( 'sold out dates only', 'event_espresso' ),
532
+	__('sold out dates only', 'event_espresso'),
533 533
 
534 534
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:29
535
-	__( 'recently expired dates', 'event_espresso' ),
535
+	__('recently expired dates', 'event_espresso'),
536 536
 
537 537
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:30
538
-	__( 'all expired dates', 'event_espresso' ),
538
+	__('all expired dates', 'event_espresso'),
539 539
 
540 540
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:31
541
-	__( 'trashed dates only', 'event_espresso' ),
541
+	__('trashed dates only', 'event_espresso'),
542 542
 
543 543
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:35
544 544
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:9
545 545
 	// Reference: packages/dates/src/components/DateRangePicker/index.tsx:61
546
-	__( 'start date', 'event_espresso' ),
546
+	__('start date', 'event_espresso'),
547 547
 
548 548
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:36
549
-	__( 'name', 'event_espresso' ),
549
+	__('name', 'event_espresso'),
550 550
 
551 551
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:37
552 552
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:31
@@ -554,181 +554,181 @@  discard block
 block discarded – undo
554 554
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/HeaderCell.tsx:27
555 555
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:31
556 556
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:23
557
-	__( 'ID', 'event_espresso' ),
557
+	__('ID', 'event_espresso'),
558 558
 
559 559
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:38
560 560
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:47
561
-	__( 'custom order', 'event_espresso' ),
561
+	__('custom order', 'event_espresso'),
562 562
 
563 563
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:42
564 564
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:51
565
-	__( 'display', 'event_espresso' ),
565
+	__('display', 'event_espresso'),
566 566
 
567 567
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:43
568
-	__( 'recurrence', 'event_espresso' ),
568
+	__('recurrence', 'event_espresso'),
569 569
 
570 570
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:44
571 571
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:53
572
-	__( 'sales', 'event_espresso' ),
572
+	__('sales', 'event_espresso'),
573 573
 
574 574
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:45
575 575
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:55
576
-	__( 'sort by', 'event_espresso' ),
576
+	__('sort by', 'event_espresso'),
577 577
 
578 578
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:46
579 579
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:54
580 580
 	// Reference: packages/ee-components/src/EntityList/EntityListFilterBar.tsx:46
581
-	__( 'search', 'event_espresso' ),
581
+	__('search', 'event_espresso'),
582 582
 
583 583
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:47
584 584
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:56
585
-	__( 'status', 'event_espresso' ),
585
+	__('status', 'event_espresso'),
586 586
 
587 587
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:9
588
-	__( 'start dates only', 'event_espresso' ),
588
+	__('start dates only', 'event_espresso'),
589 589
 
590 590
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:26
591 591
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/NewDateModal.tsx:12
592 592
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/OptionsModalButton.tsx:18
593
-	__( 'Add New Date', 'event_espresso' ),
593
+	__('Add New Date', 'event_espresso'),
594 594
 
595 595
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:26
596
-	__( 'Add Single Date', 'event_espresso' ),
596
+	__('Add Single Date', 'event_espresso'),
597 597
 
598 598
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:44
599
-	__( 'Add a single date that only occurs once', 'event_espresso' ),
599
+	__('Add a single date that only occurs once', 'event_espresso'),
600 600
 
601 601
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:46
602
-	__( 'Single Date', 'event_espresso' ),
602
+	__('Single Date', 'event_espresso'),
603 603
 
604 604
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:106
605
-	__( 'Reg list', 'event_espresso' ),
605
+	__('Reg list', 'event_espresso'),
606 606
 
607 607
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:107
608 608
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:111
609
-	__( 'Regs', 'event_espresso' ),
609
+	__('Regs', 'event_espresso'),
610 610
 
611 611
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:122
612 612
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:126
613 613
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:59
614
-	__( 'Actions', 'event_espresso' ),
614
+	__('Actions', 'event_espresso'),
615 615
 
616 616
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:52
617
-	__( 'Start', 'event_espresso' ),
617
+	__('Start', 'event_espresso'),
618 618
 
619 619
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:66
620
-	__( 'End', 'event_espresso' ),
620
+	__('End', 'event_espresso'),
621 621
 
622 622
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:82
623
-	__( 'Cap', 'event_espresso' ),
623
+	__('Cap', 'event_espresso'),
624 624
 
625 625
 	// Reference: domains/core/admin/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:94
626 626
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:98
627
-	__( 'Sold', 'event_espresso' ),
627
+	__('Sold', 'event_espresso'),
628 628
 
629 629
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:33
630 630
 	// Reference: packages/form-builder/src/constants.ts:67
631
-	__( 'Text Input', 'event_espresso' ),
631
+	__('Text Input', 'event_espresso'),
632 632
 
633 633
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:34
634 634
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:32
635
-	__( 'Attendee First Name', 'event_espresso' ),
635
+	__('Attendee First Name', 'event_espresso'),
636 636
 
637 637
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:39
638 638
 	/* translators: field name */
639
-	__( 'Registration form must have a field of type "%1$s" which maps to "%2$s"', 'event_espresso' ),
639
+	__('Registration form must have a field of type "%1$s" which maps to "%2$s"', 'event_espresso'),
640 640
 
641 641
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:40
642 642
 	// Reference: packages/form-builder/src/constants.ts:82
643
-	__( 'Email Address', 'event_espresso' ),
643
+	__('Email Address', 'event_espresso'),
644 644
 
645 645
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:41
646 646
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:40
647
-	__( 'Attendee Email Address', 'event_espresso' ),
647
+	__('Attendee Email Address', 'event_espresso'),
648 648
 
649 649
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/ErrorMessage.tsx:49
650
-	__( 'Please add the required fields', 'event_espresso' ),
650
+	__('Please add the required fields', 'event_espresso'),
651 651
 
652 652
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/RegistrationForm.tsx:12
653
-	__( 'Registration Form', 'event_espresso' ),
653
+	__('Registration Form', 'event_espresso'),
654 654
 
655 655
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:13
656
-	__( 'primary registrant', 'event_espresso' ),
656
+	__('primary registrant', 'event_espresso'),
657 657
 
658 658
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:17
659
-	__( 'purchaser', 'event_espresso' ),
659
+	__('purchaser', 'event_espresso'),
660 660
 
661 661
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:21
662
-	__( 'registrants', 'event_espresso' ),
662
+	__('registrants', 'event_espresso'),
663 663
 
664 664
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:36
665
-	__( 'Attendee Last Name', 'event_espresso' ),
665
+	__('Attendee Last Name', 'event_espresso'),
666 666
 
667 667
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:44
668
-	__( 'Attendee Address', 'event_espresso' ),
668
+	__('Attendee Address', 'event_espresso'),
669 669
 
670 670
 	// Reference: domains/core/admin/eventEditor/src/ui/registrationForm/constants.ts:9
671
-	__( 'all', 'event_espresso' ),
671
+	__('all', 'event_espresso'),
672 672
 
673 673
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:18
674
-	__( 'Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. 
675
-Please correct the assignments for the highlighted cells.', 'event_espresso' ),
674
+	__('Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. 
675
+Please correct the assignments for the highlighted cells.', 'event_espresso'),
676 676
 
677 677
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:22
678
-	__( 'Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. 
679
-Please correct the assignments for the highlighted cells.', 'event_espresso' ),
678
+	__('Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. 
679
+Please correct the assignments for the highlighted cells.', 'event_espresso'),
680 680
 
681 681
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:32
682
-	__( 'Please Update Assignments', 'event_espresso' ),
682
+	__('Please Update Assignments', 'event_espresso'),
683 683
 
684 684
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:26
685
-	__( 'There seem to be some dates/tickets which have no tickets/dates assigned. Do you want to fix them now?', 'event_espresso' ),
685
+	__('There seem to be some dates/tickets which have no tickets/dates assigned. Do you want to fix them now?', 'event_espresso'),
686 686
 
687 687
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:29
688 688
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:74
689
-	__( 'Alert!', 'event_espresso' ),
689
+	__('Alert!', 'event_espresso'),
690 690
 
691 691
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:42
692 692
 	/* translators: 1 entity id, 2 entity name */
693
-	__( 'Ticket Assignment Manager for Datetime: %1$s - %2$s', 'event_espresso' ),
693
+	__('Ticket Assignment Manager for Datetime: %1$s - %2$s', 'event_espresso'),
694 694
 
695 695
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:49
696 696
 	/* translators: 1 entity id, 2 entity name */
697
-	__( 'Ticket Assignment Manager for Ticket: %1$s - %2$s', 'event_espresso' ),
697
+	__('Ticket Assignment Manager for Ticket: %1$s - %2$s', 'event_espresso'),
698 698
 
699 699
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/TicketAssignmentsManagerModal.tsx:28
700 700
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/Table.tsx:13
701
-	__( 'Ticket Assignment Manager', 'event_espresso' ),
701
+	__('Ticket Assignment Manager', 'event_espresso'),
702 702
 
703 703
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:10
704
-	__( 'existing relation', 'event_espresso' ),
704
+	__('existing relation', 'event_espresso'),
705 705
 
706 706
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:15
707
-	__( 'remove existing relation', 'event_espresso' ),
707
+	__('remove existing relation', 'event_espresso'),
708 708
 
709 709
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:20
710
-	__( 'add new relation', 'event_espresso' ),
710
+	__('add new relation', 'event_espresso'),
711 711
 
712 712
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:25
713
-	__( 'invalid relation', 'event_espresso' ),
713
+	__('invalid relation', 'event_espresso'),
714 714
 
715 715
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/config.ts:29
716
-	__( 'no relation', 'event_espresso' ),
716
+	__('no relation', 'event_espresso'),
717 717
 
718 718
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/BodyCell.tsx:23
719
-	__( 'assign ticket', 'event_espresso' ),
719
+	__('assign ticket', 'event_espresso'),
720 720
 
721 721
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:15
722
-	__( 'Assignments', 'event_espresso' ),
722
+	__('Assignments', 'event_espresso'),
723 723
 
724 724
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:16
725
-	__( 'Event Dates are listed below', 'event_espresso' ),
725
+	__('Event Dates are listed below', 'event_espresso'),
726 726
 
727 727
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:17
728
-	__( 'Tickets are listed along the top', 'event_espresso' ),
728
+	__('Tickets are listed along the top', 'event_espresso'),
729 729
 
730 730
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/table/useGetHeaderRows.tsx:18
731
-	__( 'Click the cell buttons to toggle assigments', 'event_espresso' ),
731
+	__('Click the cell buttons to toggle assigments', 'event_espresso'),
732 732
 
733 733
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/components/useSubmitButtonProps.ts:29
734 734
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:16
@@ -737,1530 +737,1530 @@  discard block
 block discarded – undo
737 737
 	// Reference: packages/tpc/src/buttons/useSubmitButtonProps.tsx:29
738 738
 	// Reference: packages/ui-components/src/Modal/useSubmitButtonProps.tsx:13
739 739
 	// Reference: packages/ui-components/src/Stepper/buttons/Submit.tsx:7
740
-	__( 'Submit', 'event_espresso' ),
740
+	__('Submit', 'event_espresso'),
741 741
 
742 742
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:20
743
-	__( 'All Dates', 'event_espresso' ),
743
+	__('All Dates', 'event_espresso'),
744 744
 
745 745
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:27
746
-	__( 'dates by month', 'event_espresso' ),
746
+	__('dates by month', 'event_espresso'),
747 747
 
748 748
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowExpiredTicketsControl.tsx:16
749
-	__( 'show expired tickets', 'event_espresso' ),
749
+	__('show expired tickets', 'event_espresso'),
750 750
 
751 751
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedDatesControl.tsx:13
752
-	__( 'show trashed dates', 'event_espresso' ),
752
+	__('show trashed dates', 'event_espresso'),
753 753
 
754 754
 	// Reference: domains/core/admin/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedTicketsControl.tsx:16
755
-	__( 'show trashed tickets', 'event_espresso' ),
755
+	__('show trashed tickets', 'event_espresso'),
756 756
 
757 757
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/Container.tsx:38
758 758
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actions/Actions.tsx:25
759
-	__( 'Default tickets', 'event_espresso' ),
759
+	__('Default tickets', 'event_espresso'),
760 760
 
761 761
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/ModalBody.tsx:63
762 762
 	// Reference: packages/edtr-services/src/constants.ts:26
763
-	__( 'ticket', 'event_espresso' ),
763
+	__('ticket', 'event_espresso'),
764 764
 
765 765
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:26
766 766
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:33
767
-	__( 'Set ticket prices', 'event_espresso' ),
767
+	__('Set ticket prices', 'event_espresso'),
768 768
 
769 769
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:31
770
-	__( 'Skip prices - Save', 'event_espresso' ),
770
+	__('Skip prices - Save', 'event_espresso'),
771 771
 
772 772
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:37
773 773
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:57
774
-	__( 'Ticket details', 'event_espresso' ),
774
+	__('Ticket details', 'event_espresso'),
775 775
 
776 776
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/FooterButtons.tsx:38
777
-	__( 'Save', 'event_espresso' ),
777
+	__('Save', 'event_espresso'),
778 778
 
779 779
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/Modal.tsx:22
780 780
 	/* translators: %s ticket id */
781
-	__( 'Edit ticket %s', 'event_espresso' ),
781
+	__('Edit ticket %s', 'event_espresso'),
782 782
 
783 783
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/Modal.tsx:25
784 784
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/Modal.tsx:30
785
-	__( 'New Ticket Details', 'event_espresso' ),
785
+	__('New Ticket Details', 'event_espresso'),
786 786
 
787 787
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:10
788 788
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:10
789
-	__( 'primary information about the ticket', 'event_espresso' ),
789
+	__('primary information about the ticket', 'event_espresso'),
790 790
 
791 791
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:10
792 792
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:10
793
-	__( 'Ticket Details', 'event_espresso' ),
793
+	__('Ticket Details', 'event_espresso'),
794 794
 
795 795
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:12
796 796
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:12
797
-	__( 'apply ticket price modifiers and taxes', 'event_espresso' ),
797
+	__('apply ticket price modifiers and taxes', 'event_espresso'),
798 798
 
799 799
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:14
800 800
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:14
801
-	__( 'Price Calculator', 'event_espresso' ),
801
+	__('Price Calculator', 'event_espresso'),
802 802
 
803 803
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/defaultTickets/multiStep/TicketFormSteps.tsx:16
804 804
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:16
805
-	__( 'Assign Dates', 'event_espresso' ),
805
+	__('Assign Dates', 'event_espresso'),
806 806
 
807 807
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:39
808
-	__( 'Skip prices - assign dates', 'event_espresso' ),
808
+	__('Skip prices - assign dates', 'event_espresso'),
809 809
 
810 810
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/FooterButtons.tsx:50
811
-	__( 'Save and assign dates', 'event_espresso' ),
811
+	__('Save and assign dates', 'event_espresso'),
812 812
 
813 813
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/multiStep/Modal.tsx:26
814 814
 	/* translators: 1 ticket name, 2 ticket id */
815
-	__( 'Edit ticket "%1$s" - %2$s', 'event_espresso' ),
815
+	__('Edit ticket "%1$s" - %2$s', 'event_espresso'),
816 816
 
817 817
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:101
818
-	__( 'Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso' ),
818
+	__('Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso'),
819 819
 
820 820
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:112
821 821
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:121
822
-	__( 'Number of Uses', 'event_espresso' ),
822
+	__('Number of Uses', 'event_espresso'),
823 823
 
824 824
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:118
825
-	__( 'Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso' ),
825
+	__('Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso'),
826 826
 
827 827
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:122
828
-	__( 'Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso' ),
828
+	__('Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso'),
829 829
 
830 830
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:130
831 831
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:129
832
-	__( 'Minimum Quantity', 'event_espresso' ),
832
+	__('Minimum Quantity', 'event_espresso'),
833 833
 
834 834
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:135
835
-	__( 'The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
835
+	__('The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
836 836
 
837 837
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:139
838
-	__( 'Leave blank for no minimum.', 'event_espresso' ),
838
+	__('Leave blank for no minimum.', 'event_espresso'),
839 839
 
840 840
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:145
841 841
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:137
842
-	__( 'Maximum Quantity', 'event_espresso' ),
842
+	__('Maximum Quantity', 'event_espresso'),
843 843
 
844 844
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:151
845
-	__( 'The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
845
+	__('The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
846 846
 
847 847
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:155
848
-	__( 'Leave blank for no maximum.', 'event_espresso' ),
848
+	__('Leave blank for no maximum.', 'event_espresso'),
849 849
 
850 850
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:161
851 851
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:146
852
-	__( 'Required Ticket', 'event_espresso' ),
852
+	__('Required Ticket', 'event_espresso'),
853 853
 
854 854
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:163
855
-	__( 'If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso' ),
855
+	__('If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso'),
856 856
 
857 857
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:175
858
-	__( 'Visibility', 'event_espresso' ),
858
+	__('Visibility', 'event_espresso'),
859 859
 
860 860
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:209
861
-	__( 'Ticket Sales', 'event_espresso' ),
861
+	__('Ticket Sales', 'event_espresso'),
862 862
 
863 863
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:93
864 864
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:112
865
-	__( 'Quantity For Sale', 'event_espresso' ),
865
+	__('Quantity For Sale', 'event_espresso'),
866 866
 
867 867
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.ts:99
868
-	__( 'The maximum number of this ticket available for sale.', 'event_espresso' ),
868
+	__('The maximum number of this ticket available for sale.', 'event_espresso'),
869 869
 
870 870
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketRegistrationsLink.tsx:13
871
-	__( 'total registrations.', 'event_espresso' ),
871
+	__('total registrations.', 'event_espresso'),
872 872
 
873 873
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketRegistrationsLink.tsx:14
874
-	__( 'view ALL registrations for this ticket.', 'event_espresso' ),
874
+	__('view ALL registrations for this ticket.', 'event_espresso'),
875 875
 
876 876
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketSoldLink.tsx:13
877
-	__( 'view approved registrations for this ticket.', 'event_espresso' ),
877
+	__('view approved registrations for this ticket.', 'event_espresso'),
878 878
 
879 879
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:36
880
-	__( 'Available Tickets', 'event_espresso' ),
880
+	__('Available Tickets', 'event_espresso'),
881 881
 
882 882
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:39
883
-	__( 'loading tickets…', 'event_espresso' ),
883
+	__('loading tickets…', 'event_espresso'),
884 884
 
885 885
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:26
886
-	__( 'Number of related dates', 'event_espresso' ),
886
+	__('Number of related dates', 'event_espresso'),
887 887
 
888 888
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:27
889
-	__( 'There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso' ),
889
+	__('There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso'),
890 890
 
891 891
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:37
892
-	__( 'assign dates', 'event_espresso' ),
892
+	__('assign dates', 'event_espresso'),
893 893
 
894 894
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:19
895
-	__( 'Permanently Delete Ticket?', 'event_espresso' ),
895
+	__('Permanently Delete Ticket?', 'event_espresso'),
896 896
 
897 897
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:19
898
-	__( 'Move Ticket to Trash?', 'event_espresso' ),
898
+	__('Move Ticket to Trash?', 'event_espresso'),
899 899
 
900 900
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:22
901
-	__( 'Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso' ),
901
+	__('Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso'),
902 902
 
903 903
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/DeleteTicket.tsx:48
904 904
 	// Reference: packages/ee-components/src/SimpleTicketCard/actions/Trash.tsx:6
905
-	__( 'trash ticket', 'event_espresso' ),
905
+	__('trash ticket', 'event_espresso'),
906 906
 
907 907
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:25
908
-	__( 'ticket main menu', 'event_espresso' ),
908
+	__('ticket main menu', 'event_espresso'),
909 909
 
910 910
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:38
911 911
 	// Reference: packages/ee-components/src/SimpleTicketCard/actions/Edit.tsx:15
912
-	__( 'edit ticket', 'event_espresso' ),
912
+	__('edit ticket', 'event_espresso'),
913 913
 
914 914
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:39
915
-	__( 'copy ticket', 'event_espresso' ),
915
+	__('copy ticket', 'event_espresso'),
916 916
 
917 917
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:44
918
-	__( 'edit ticket details', 'event_espresso' ),
918
+	__('edit ticket details', 'event_espresso'),
919 919
 
920 920
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:48
921
-	__( 'delete tickets', 'event_espresso' ),
921
+	__('delete tickets', 'event_espresso'),
922 922
 
923 923
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:48
924
-	__( 'trash tickets', 'event_espresso' ),
924
+	__('trash tickets', 'event_espresso'),
925 925
 
926 926
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:52
927
-	__( 'edit ticket prices', 'event_espresso' ),
927
+	__('edit ticket prices', 'event_espresso'),
928 928
 
929 929
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:14
930
-	__( 'Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso' ),
930
+	__('Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso'),
931 931
 
932 932
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:15
933
-	__( 'Are you sure you want to trash these tickets?', 'event_espresso' ),
933
+	__('Are you sure you want to trash these tickets?', 'event_espresso'),
934 934
 
935 935
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:16
936
-	__( 'Delete tickets permanently', 'event_espresso' ),
936
+	__('Delete tickets permanently', 'event_espresso'),
937 937
 
938 938
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:16
939
-	__( 'Trash tickets', 'event_espresso' ),
939
+	__('Trash tickets', 'event_espresso'),
940 940
 
941 941
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:21
942
-	__( 'Bulk edit ticket details', 'event_espresso' ),
942
+	__('Bulk edit ticket details', 'event_espresso'),
943 943
 
944 944
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:22
945
-	__( 'any changes will be applied to ALL of the selected tickets.', 'event_espresso' ),
945
+	__('any changes will be applied to ALL of the selected tickets.', 'event_espresso'),
946 946
 
947 947
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/EditPrices.tsx:19
948
-	__( 'Bulk edit ticket prices', 'event_espresso' ),
948
+	__('Bulk edit ticket prices', 'event_espresso'),
949 949
 
950 950
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:20
951
-	__( 'Edit all prices together', 'event_espresso' ),
951
+	__('Edit all prices together', 'event_espresso'),
952 952
 
953 953
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:21
954
-	__( 'Edit all the selected ticket prices dynamically', 'event_espresso' ),
954
+	__('Edit all the selected ticket prices dynamically', 'event_espresso'),
955 955
 
956 956
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:25
957
-	__( 'Edit prices individually', 'event_espresso' ),
957
+	__('Edit prices individually', 'event_espresso'),
958 958
 
959 959
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:26
960
-	__( 'Edit prices for each ticket individually', 'event_espresso' ),
960
+	__('Edit prices for each ticket individually', 'event_espresso'),
961 961
 
962 962
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:14
963 963
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:34
964 964
 	// Reference: packages/form/src/ResetButton.tsx:18
965 965
 	// Reference: packages/tpc/src/buttons/useResetButtonProps.tsx:12
966
-	__( 'Reset', 'event_espresso' ),
966
+	__('Reset', 'event_espresso'),
967 967
 
968 968
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:15
969 969
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:76
970 970
 	// Reference: packages/ui-components/src/Modal/useCancelButtonProps.tsx:10
971
-	__( 'Cancel', 'event_espresso' ),
971
+	__('Cancel', 'event_espresso'),
972 972
 
973 973
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/editSeparately/TPCInstance.tsx:26
974 974
 	/* translators: %s ticket name */
975
-	__( 'Edit prices for Ticket: %s', 'event_espresso' ),
975
+	__('Edit prices for Ticket: %s', 'event_espresso'),
976 976
 
977 977
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:30
978
-	__( 'sales start', 'event_espresso' ),
978
+	__('sales start', 'event_espresso'),
979 979
 
980 980
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:33
981
-	__( 'sales began', 'event_espresso' ),
981
+	__('sales began', 'event_espresso'),
982 982
 
983 983
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:35
984
-	__( 'sales ended', 'event_espresso' ),
984
+	__('sales ended', 'event_espresso'),
985 985
 
986 986
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:36
987
-	__( 'sales end', 'event_espresso' ),
987
+	__('sales end', 'event_espresso'),
988 988
 
989 989
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:50
990
-	__( 'Edit Ticket Sale Dates', 'event_espresso' ),
990
+	__('Edit Ticket Sale Dates', 'event_espresso'),
991 991
 
992 992
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:54
993
-	__( 'edit ticket sales start and end dates', 'event_espresso' ),
993
+	__('edit ticket sales start and end dates', 'event_espresso'),
994 994
 
995 995
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:21
996
-	__( 'quantity', 'event_espresso' ),
996
+	__('quantity', 'event_espresso'),
997 997
 
998 998
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketQuantity.tsx:28
999 999
 	// Reference: packages/edtr-services/src/apollo/mutations/tickets/useUpdateTicketQtyByCapacity.ts:78
1000
-	__( 'Ticket quantity has been adjusted because it cannot be more than the related event date capacity.', 'event_espresso' ),
1000
+	__('Ticket quantity has been adjusted because it cannot be more than the related event date capacity.', 'event_espresso'),
1001 1001
 
1002 1002
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/cardView/TicketQuantity.tsx:51
1003
-	__( 'edit quantity of tickets available…', 'event_espresso' ),
1003
+	__('edit quantity of tickets available…', 'event_espresso'),
1004 1004
 
1005 1005
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:10
1006
-	__( 'Move Ticket to Trash', 'event_espresso' ),
1006
+	__('Move Ticket to Trash', 'event_espresso'),
1007 1007
 
1008 1008
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:15
1009 1009
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:52
1010
-	__( 'On Sale', 'event_espresso' ),
1010
+	__('On Sale', 'event_espresso'),
1011 1011
 
1012 1012
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:17
1013
-	__( 'Pending', 'event_espresso' ),
1013
+	__('Pending', 'event_espresso'),
1014 1014
 
1015 1015
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:7
1016
-	__( 'Edit Ticket Details', 'event_espresso' ),
1016
+	__('Edit Ticket Details', 'event_espresso'),
1017 1017
 
1018 1018
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:8
1019
-	__( 'Manage Date Assignments', 'event_espresso' ),
1019
+	__('Manage Date Assignments', 'event_espresso'),
1020 1020
 
1021 1021
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/config.ts:9
1022 1022
 	// Reference: packages/tpc/src/components/table/Table.tsx:43
1023
-	__( 'Ticket Price Calculator', 'event_espresso' ),
1023
+	__('Ticket Price Calculator', 'event_espresso'),
1024 1024
 
1025 1025
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:39
1026
-	__( 'edit ticket total…', 'event_espresso' ),
1026
+	__('edit ticket total…', 'event_espresso'),
1027 1027
 
1028 1028
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:53
1029
-	__( 'set price…', 'event_espresso' ),
1029
+	__('set price…', 'event_espresso'),
1030 1030
 
1031 1031
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:23
1032
-	__( 'tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso' ),
1032
+	__('tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso'),
1033 1033
 
1034 1034
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:24
1035
-	__( 'tickets list is unlinked and is showing tickets for all event dates', 'event_espresso' ),
1035
+	__('tickets list is unlinked and is showing tickets for all event dates', 'event_espresso'),
1036 1036
 
1037 1037
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:10
1038
-	__( 'ticket sales start and end dates', 'event_espresso' ),
1038
+	__('ticket sales start and end dates', 'event_espresso'),
1039 1039
 
1040 1040
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:15
1041
-	__( 'tickets with 90% or more sold', 'event_espresso' ),
1041
+	__('tickets with 90% or more sold', 'event_espresso'),
1042 1042
 
1043 1043
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:16
1044
-	__( 'tickets with 75% or more sold', 'event_espresso' ),
1044
+	__('tickets with 75% or more sold', 'event_espresso'),
1045 1045
 
1046 1046
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:17
1047
-	__( 'tickets with 50% or more sold', 'event_espresso' ),
1047
+	__('tickets with 50% or more sold', 'event_espresso'),
1048 1048
 
1049 1049
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:19
1050
-	__( 'tickets with less than 50% sold', 'event_espresso' ),
1050
+	__('tickets with less than 50% sold', 'event_espresso'),
1051 1051
 
1052 1052
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:28
1053
-	__( 'all tickets for all dates', 'event_espresso' ),
1053
+	__('all tickets for all dates', 'event_espresso'),
1054 1054
 
1055 1055
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:29
1056
-	__( 'all on sale and sale pending', 'event_espresso' ),
1056
+	__('all on sale and sale pending', 'event_espresso'),
1057 1057
 
1058 1058
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:30
1059
-	__( 'on sale tickets only', 'event_espresso' ),
1059
+	__('on sale tickets only', 'event_espresso'),
1060 1060
 
1061 1061
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:31
1062
-	__( 'sale pending tickets only', 'event_espresso' ),
1062
+	__('sale pending tickets only', 'event_espresso'),
1063 1063
 
1064 1064
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:32
1065
-	__( 'next on sale or sale pending only', 'event_espresso' ),
1065
+	__('next on sale or sale pending only', 'event_espresso'),
1066 1066
 
1067 1067
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:33
1068
-	__( 'sold out tickets only', 'event_espresso' ),
1068
+	__('sold out tickets only', 'event_espresso'),
1069 1069
 
1070 1070
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:34
1071
-	__( 'expired tickets only', 'event_espresso' ),
1071
+	__('expired tickets only', 'event_espresso'),
1072 1072
 
1073 1073
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:35
1074
-	__( 'trashed tickets only', 'event_espresso' ),
1074
+	__('trashed tickets only', 'event_espresso'),
1075 1075
 
1076 1076
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:40
1077
-	__( 'all tickets for above dates', 'event_espresso' ),
1077
+	__('all tickets for above dates', 'event_espresso'),
1078 1078
 
1079 1079
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:44
1080
-	__( 'ticket sale date', 'event_espresso' ),
1080
+	__('ticket sale date', 'event_espresso'),
1081 1081
 
1082 1082
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:45
1083
-	__( 'ticket name', 'event_espresso' ),
1083
+	__('ticket name', 'event_espresso'),
1084 1084
 
1085 1085
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:46
1086
-	__( 'ticket ID', 'event_espresso' ),
1086
+	__('ticket ID', 'event_espresso'),
1087 1087
 
1088 1088
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:52
1089
-	__( 'link', 'event_espresso' ),
1089
+	__('link', 'event_espresso'),
1090 1090
 
1091 1091
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:8
1092
-	__( 'ticket sales start date only', 'event_espresso' ),
1092
+	__('ticket sales start date only', 'event_espresso'),
1093 1093
 
1094 1094
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:9
1095
-	__( 'ticket sales end date only', 'event_espresso' ),
1095
+	__('ticket sales end date only', 'event_espresso'),
1096 1096
 
1097 1097
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:18
1098
-	__( 'Add New Ticket', 'event_espresso' ),
1098
+	__('Add New Ticket', 'event_espresso'),
1099 1099
 
1100 1100
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:32
1101
-	__( 'Add a single ticket and assign the dates to it', 'event_espresso' ),
1101
+	__('Add a single ticket and assign the dates to it', 'event_espresso'),
1102 1102
 
1103 1103
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:34
1104
-	__( 'Single Ticket', 'event_espresso' ),
1104
+	__('Single Ticket', 'event_espresso'),
1105 1105
 
1106 1106
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/TableView.tsx:39
1107
-	__( 'Tickets', 'event_espresso' ),
1107
+	__('Tickets', 'event_espresso'),
1108 1108
 
1109 1109
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:110
1110
-	__( 'Registrations', 'event_espresso' ),
1110
+	__('Registrations', 'event_espresso'),
1111 1111
 
1112 1112
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:51
1113
-	__( 'Goes on Sale', 'event_espresso' ),
1113
+	__('Goes on Sale', 'event_espresso'),
1114 1114
 
1115 1115
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:65
1116
-	__( 'Sale Ends', 'event_espresso' ),
1116
+	__('Sale Ends', 'event_espresso'),
1117 1117
 
1118 1118
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:66
1119
-	__( 'Ends', 'event_espresso' ),
1119
+	__('Ends', 'event_espresso'),
1120 1120
 
1121 1121
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:78
1122
-	__( 'Price', 'event_espresso' ),
1122
+	__('Price', 'event_espresso'),
1123 1123
 
1124 1124
 	// Reference: domains/core/admin/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:88
1125
-	__( 'Quantity', 'event_espresso' ),
1125
+	__('Quantity', 'event_espresso'),
1126 1126
 
1127 1127
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:105
1128
-	__( 'Select a Venue for the Event', 'event_espresso' ),
1128
+	__('Select a Venue for the Event', 'event_espresso'),
1129 1129
 
1130 1130
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:21
1131
-	__( 'Venue Details', 'event_espresso' ),
1131
+	__('Venue Details', 'event_espresso'),
1132 1132
 
1133 1133
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:38
1134
-	__( 'unlimited space', 'event_espresso' ),
1134
+	__('unlimited space', 'event_espresso'),
1135 1135
 
1136 1136
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:41
1137 1137
 	/* translators: %d venue capacity */
1138
-	__( 'Space for up to %d people', 'event_espresso' ),
1138
+	__('Space for up to %d people', 'event_espresso'),
1139 1139
 
1140 1140
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:60
1141
-	__( 'no image', 'event_espresso' ),
1141
+	__('no image', 'event_espresso'),
1142 1142
 
1143 1143
 	// Reference: domains/core/admin/eventEditor/src/ui/venue/VenueDetails.tsx:96
1144
-	__( 'Edit this Venue', 'event_espresso' ),
1144
+	__('Edit this Venue', 'event_espresso'),
1145 1145
 
1146 1146
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:29
1147
-	__( 'Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso' ),
1147
+	__('Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso'),
1148 1148
 
1149 1149
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:40
1150
-	__( 'Skip', 'event_espresso' ),
1150
+	__('Skip', 'event_espresso'),
1151 1151
 
1152 1152
 	// Reference: domains/core/admin/wpPluginsPage/src/exitSurvey/Popup.tsx:42
1153
-	__( 'Sure I\'ll help', 'event_espresso' ),
1153
+	__('Sure I\'ll help', 'event_espresso'),
1154 1154
 
1155 1155
 	// Reference: packages/adapters/src/Pagination/Pagination.tsx:23
1156
-	__( 'pagination', 'event_espresso' ),
1156
+	__('pagination', 'event_espresso'),
1157 1157
 
1158 1158
 	// Reference: packages/adapters/src/TagSelector/TagSelector.tsx:113
1159
-	__( 'toggle menu', 'event_espresso' ),
1159
+	__('toggle menu', 'event_espresso'),
1160 1160
 
1161 1161
 	// Reference: packages/constants/src/datetime.ts:10
1162
-	__( 'Postponed', 'event_espresso' ),
1162
+	__('Postponed', 'event_espresso'),
1163 1163
 
1164 1164
 	// Reference: packages/constants/src/datetime.ts:11
1165
-	__( 'SoldOut', 'event_espresso' ),
1165
+	__('SoldOut', 'event_espresso'),
1166 1166
 
1167 1167
 	// Reference: packages/constants/src/datetime.ts:7
1168 1168
 	// Reference: packages/predicates/src/registration/statusOptions.ts:11
1169
-	__( 'Cancelled', 'event_espresso' ),
1169
+	__('Cancelled', 'event_espresso'),
1170 1170
 
1171 1171
 	// Reference: packages/constants/src/datetime.ts:9
1172
-	__( 'Inactive', 'event_espresso' ),
1172
+	__('Inactive', 'event_espresso'),
1173 1173
 
1174 1174
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:25
1175
-	__( 'error creating %s', 'event_espresso' ),
1175
+	__('error creating %s', 'event_espresso'),
1176 1176
 
1177 1177
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:26
1178
-	__( 'error deleting %s', 'event_espresso' ),
1178
+	__('error deleting %s', 'event_espresso'),
1179 1179
 
1180 1180
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:27
1181
-	__( 'error updating %s', 'event_espresso' ),
1181
+	__('error updating %s', 'event_espresso'),
1182 1182
 
1183 1183
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:28
1184
-	__( 'creating %s', 'event_espresso' ),
1184
+	__('creating %s', 'event_espresso'),
1185 1185
 
1186 1186
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:29
1187
-	__( 'deleting %s', 'event_espresso' ),
1187
+	__('deleting %s', 'event_espresso'),
1188 1188
 
1189 1189
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:30
1190
-	__( 'updating %s', 'event_espresso' ),
1190
+	__('updating %s', 'event_espresso'),
1191 1191
 
1192 1192
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:31
1193
-	__( 'successfully created %s', 'event_espresso' ),
1193
+	__('successfully created %s', 'event_espresso'),
1194 1194
 
1195 1195
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:32
1196
-	__( 'successfully deleted %s', 'event_espresso' ),
1196
+	__('successfully deleted %s', 'event_espresso'),
1197 1197
 
1198 1198
 	// Reference: packages/data/src/mutations/useMutationWithFeedback.ts:33
1199
-	__( 'successfully updated %s', 'event_espresso' ),
1199
+	__('successfully updated %s', 'event_espresso'),
1200 1200
 
1201 1201
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:13
1202
-	__( 'day in range', 'event_espresso' ),
1202
+	__('day in range', 'event_espresso'),
1203 1203
 
1204 1204
 	// Reference: packages/dates/src/components/DateRangePicker/DateRangePickerLegend.tsx:17
1205 1205
 	// Reference: packages/dates/src/components/DateRangePicker/index.tsx:79
1206
-	__( 'end date', 'event_espresso' ),
1206
+	__('end date', 'event_espresso'),
1207 1207
 
1208 1208
 	// Reference: packages/dates/src/components/DateTimePicker.tsx:13
1209 1209
 	// Reference: packages/dates/src/components/TimePicker.tsx:14
1210 1210
 	// Reference: packages/form-builder/src/state/utils.ts:433
1211
-	__( 'time', 'event_espresso' ),
1211
+	__('time', 'event_espresso'),
1212 1212
 
1213 1213
 	// Reference: packages/dates/src/constants.ts:5
1214
-	__( 'End Date & Time must be set later than the Start Date & Time', 'event_espresso' ),
1214
+	__('End Date & Time must be set later than the Start Date & Time', 'event_espresso'),
1215 1215
 
1216 1216
 	// Reference: packages/dates/src/constants.ts:7
1217
-	__( 'Start Date & Time must be set before the End Date & Time', 'event_espresso' ),
1217
+	__('Start Date & Time must be set before the End Date & Time', 'event_espresso'),
1218 1218
 
1219 1219
 	// Reference: packages/dates/src/utils/misc.ts:16
1220
-	__( 'month(s)', 'event_espresso' ),
1220
+	__('month(s)', 'event_espresso'),
1221 1221
 
1222 1222
 	// Reference: packages/dates/src/utils/misc.ts:17
1223
-	__( 'week(s)', 'event_espresso' ),
1223
+	__('week(s)', 'event_espresso'),
1224 1224
 
1225 1225
 	// Reference: packages/dates/src/utils/misc.ts:18
1226
-	__( 'day(s)', 'event_espresso' ),
1226
+	__('day(s)', 'event_espresso'),
1227 1227
 
1228 1228
 	// Reference: packages/dates/src/utils/misc.ts:19
1229
-	__( 'hour(s)', 'event_espresso' ),
1229
+	__('hour(s)', 'event_espresso'),
1230 1230
 
1231 1231
 	// Reference: packages/dates/src/utils/misc.ts:20
1232
-	__( 'minute(s)', 'event_espresso' ),
1232
+	__('minute(s)', 'event_espresso'),
1233 1233
 
1234 1234
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:107
1235
-	__( 'price types initialized', 'event_espresso' ),
1235
+	__('price types initialized', 'event_espresso'),
1236 1236
 
1237 1237
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:117
1238
-	__( 'datetimes initialized', 'event_espresso' ),
1238
+	__('datetimes initialized', 'event_espresso'),
1239 1239
 
1240 1240
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:127
1241
-	__( 'tickets initialized', 'event_espresso' ),
1241
+	__('tickets initialized', 'event_espresso'),
1242 1242
 
1243 1243
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:137
1244
-	__( 'prices initialized', 'event_espresso' ),
1244
+	__('prices initialized', 'event_espresso'),
1245 1245
 
1246 1246
 	// Reference: packages/edtr-services/src/apollo/mutations/useReorderEntities.ts:63
1247
-	__( 'order updated', 'event_espresso' ),
1247
+	__('order updated', 'event_espresso'),
1248 1248
 
1249 1249
 	// Reference: packages/edtr-services/src/constants.ts:24
1250
-	__( 'datetime', 'event_espresso' ),
1250
+	__('datetime', 'event_espresso'),
1251 1251
 
1252 1252
 	// Reference: packages/edtr-services/src/constants.ts:27
1253
-	__( 'price', 'event_espresso' ),
1253
+	__('price', 'event_espresso'),
1254 1254
 
1255 1255
 	// Reference: packages/edtr-services/src/constants.ts:28
1256 1256
 	// Reference: packages/tpc/src/inputs/PriceTypeInput.tsx:19
1257
-	__( 'price type', 'event_espresso' ),
1257
+	__('price type', 'event_espresso'),
1258 1258
 
1259 1259
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:38
1260 1260
 	// Reference: packages/ui-components/src/EditDateRangeButton/EditDateRangeButton.tsx:39
1261
-	__( 'End date has been adjusted', 'event_espresso' ),
1261
+	__('End date has been adjusted', 'event_espresso'),
1262 1262
 
1263 1263
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:59
1264
-	__( 'Required', 'event_espresso' ),
1264
+	__('Required', 'event_espresso'),
1265 1265
 
1266 1266
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:64
1267
-	__( 'Start Date is required', 'event_espresso' ),
1267
+	__('Start Date is required', 'event_espresso'),
1268 1268
 
1269 1269
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:68
1270
-	__( 'End Date is required', 'event_espresso' ),
1270
+	__('End Date is required', 'event_espresso'),
1271 1271
 
1272 1272
 	// Reference: packages/ee-components/src/EntityList/EntityList.tsx:32
1273
-	__( 'no results found', 'event_espresso' ),
1273
+	__('no results found', 'event_espresso'),
1274 1274
 
1275 1275
 	// Reference: packages/ee-components/src/EntityList/EntityList.tsx:33
1276
-	__( 'try changing filter settings', 'event_espresso' ),
1276
+	__('try changing filter settings', 'event_espresso'),
1277 1277
 
1278 1278
 	// Reference: packages/ee-components/src/bulkEdit/ActionCheckbox.tsx:38
1279 1279
 	/* translators: %d entity id */
1280
-	__( 'select entity with id %d', 'event_espresso' ),
1280
+	__('select entity with id %d', 'event_espresso'),
1281 1281
 
1282 1282
 	// Reference: packages/ee-components/src/bulkEdit/ActionCheckbox.tsx:41
1283
-	__( 'select all entities', 'event_espresso' ),
1283
+	__('select all entities', 'event_espresso'),
1284 1284
 
1285 1285
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:20
1286
-	__( 'Note: ', 'event_espresso' ),
1286
+	__('Note: ', 'event_espresso'),
1287 1287
 
1288 1288
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:20
1289
-	__( 'any changes will be applied to ALL of the selected entities.', 'event_espresso' ),
1289
+	__('any changes will be applied to ALL of the selected entities.', 'event_espresso'),
1290 1290
 
1291 1291
 	// Reference: packages/ee-components/src/bulkEdit/details/BulkEditDetails.tsx:27
1292
-	__( 'Bulk edit details', 'event_espresso' ),
1292
+	__('Bulk edit details', 'event_espresso'),
1293 1293
 
1294 1294
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:17
1295
-	__( 'Are you sure you want to bulk update the details?', 'event_espresso' ),
1295
+	__('Are you sure you want to bulk update the details?', 'event_espresso'),
1296 1296
 
1297 1297
 	// Reference: packages/ee-components/src/bulkEdit/details/Submit.tsx:18
1298
-	__( 'Bulk update details', 'event_espresso' ),
1298
+	__('Bulk update details', 'event_espresso'),
1299 1299
 
1300 1300
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:27
1301
-	__( 'reorder dates', 'event_espresso' ),
1301
+	__('reorder dates', 'event_espresso'),
1302 1302
 
1303 1303
 	// Reference: packages/ee-components/src/filterBar/SortByControl/index.tsx:27
1304
-	__( 'reorder tickets', 'event_espresso' ),
1304
+	__('reorder tickets', 'event_espresso'),
1305 1305
 
1306 1306
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:32
1307
-	__( 'delete form element', 'event_espresso' ),
1307
+	__('delete form element', 'event_espresso'),
1308 1308
 
1309 1309
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:49
1310
-	__( 'form element settings', 'event_espresso' ),
1310
+	__('form element settings', 'event_espresso'),
1311 1311
 
1312 1312
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:59
1313
-	__( 'copy form element', 'event_espresso' ),
1313
+	__('copy form element', 'event_espresso'),
1314 1314
 
1315 1315
 	// Reference: packages/form-builder/src/FormElement/FormElementToolbar.tsx:69
1316
-	__( 'click, hold, and drag to reorder form element', 'event_espresso' ),
1316
+	__('click, hold, and drag to reorder form element', 'event_espresso'),
1317 1317
 
1318 1318
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:20
1319
-	__( 'remove option', 'event_espresso' ),
1319
+	__('remove option', 'event_espresso'),
1320 1320
 
1321 1321
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:42
1322
-	__( 'value', 'event_espresso' ),
1322
+	__('value', 'event_espresso'),
1323 1323
 
1324 1324
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:52
1325
-	__( 'label', 'event_espresso' ),
1325
+	__('label', 'event_espresso'),
1326 1326
 
1327 1327
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOption.tsx:63
1328
-	__( 'click, hold, and drag to reorder field option', 'event_espresso' ),
1328
+	__('click, hold, and drag to reorder field option', 'event_espresso'),
1329 1329
 
1330 1330
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:61
1331
-	__( 'Options are the choices you give people to select from.', 'event_espresso' ),
1331
+	__('Options are the choices you give people to select from.', 'event_espresso'),
1332 1332
 
1333 1333
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:63
1334
-	__( 'The value is a simple key that will be saved to the database and the label is what is shown to the user.', 'event_espresso' ),
1334
+	__('The value is a simple key that will be saved to the database and the label is what is shown to the user.', 'event_espresso'),
1335 1335
 
1336 1336
 	// Reference: packages/form-builder/src/FormElement/Tabs/FieldOptions.tsx:96
1337
-	__( 'add new option', 'event_espresso' ),
1337
+	__('add new option', 'event_espresso'),
1338 1338
 
1339 1339
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:26
1340 1340
 	// Reference: packages/form-builder/src/FormSection/Tabs/FormSectionTabs.tsx:25
1341
-	__( 'Styles', 'event_espresso' ),
1341
+	__('Styles', 'event_espresso'),
1342 1342
 
1343 1343
 	// Reference: packages/form-builder/src/FormElement/Tabs/FormElementTabs.tsx:30
1344
-	__( 'Validation', 'event_espresso' ),
1344
+	__('Validation', 'event_espresso'),
1345 1345
 
1346 1346
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:18
1347
-	__( 'Change input type', 'event_espresso' ),
1347
+	__('Change input type', 'event_espresso'),
1348 1348
 
1349 1349
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:19
1350
-	__( 'Some configurations might be lost. Are you sure you want to change the input type?', 'event_espresso' ),
1350
+	__('Some configurations might be lost. Are you sure you want to change the input type?', 'event_espresso'),
1351 1351
 
1352 1352
 	// Reference: packages/form-builder/src/FormElement/Tabs/InputType.tsx:40
1353
-	__( 'type', 'event_espresso' ),
1353
+	__('type', 'event_espresso'),
1354 1354
 
1355 1355
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:26
1356 1356
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:17
1357
-	__( 'public label', 'event_espresso' ),
1357
+	__('public label', 'event_espresso'),
1358 1358
 
1359 1359
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:33
1360 1360
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:22
1361
-	__( 'admin label', 'event_espresso' ),
1361
+	__('admin label', 'event_espresso'),
1362 1362
 
1363 1363
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:40
1364
-	__( 'content', 'event_espresso' ),
1364
+	__('content', 'event_espresso'),
1365 1365
 
1366 1366
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:48
1367
-	__( 'options', 'event_espresso' ),
1367
+	__('options', 'event_espresso'),
1368 1368
 
1369 1369
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:51
1370
-	__( 'placeholder', 'event_espresso' ),
1370
+	__('placeholder', 'event_espresso'),
1371 1371
 
1372 1372
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:57
1373
-	__( 'admin only', 'event_espresso' ),
1373
+	__('admin only', 'event_espresso'),
1374 1374
 
1375 1375
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:62
1376
-	__( 'help text', 'event_espresso' ),
1376
+	__('help text', 'event_espresso'),
1377 1377
 
1378 1378
 	// Reference: packages/form-builder/src/FormElement/Tabs/Settings.tsx:71
1379
-	__( 'maps to', 'event_espresso' ),
1379
+	__('maps to', 'event_espresso'),
1380 1380
 
1381 1381
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:15
1382 1382
 	// Reference: packages/form-builder/src/FormSection/Tabs/Styles.tsx:13
1383
-	__( 'css class', 'event_espresso' ),
1383
+	__('css class', 'event_espresso'),
1384 1384
 
1385 1385
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:20
1386
-	__( 'help text css class', 'event_espresso' ),
1386
+	__('help text css class', 'event_espresso'),
1387 1387
 
1388 1388
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:27
1389
-	__( 'size', 'event_espresso' ),
1389
+	__('size', 'event_espresso'),
1390 1390
 
1391 1391
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:35
1392
-	__( 'step', 'event_espresso' ),
1392
+	__('step', 'event_espresso'),
1393 1393
 
1394 1394
 	// Reference: packages/form-builder/src/FormElement/Tabs/Styles.tsx:41
1395
-	__( 'maxlength', 'event_espresso' ),
1395
+	__('maxlength', 'event_espresso'),
1396 1396
 
1397 1397
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:123
1398
-	__( 'min', 'event_espresso' ),
1398
+	__('min', 'event_espresso'),
1399 1399
 
1400 1400
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:128
1401
-	__( 'max', 'event_espresso' ),
1401
+	__('max', 'event_espresso'),
1402 1402
 
1403 1403
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:28
1404
-	__( 'Germany', 'event_espresso' ),
1404
+	__('Germany', 'event_espresso'),
1405 1405
 
1406 1406
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:32
1407
-	__( 'France', 'event_espresso' ),
1407
+	__('France', 'event_espresso'),
1408 1408
 
1409 1409
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:36
1410
-	__( 'United Kingdom', 'event_espresso' ),
1410
+	__('United Kingdom', 'event_espresso'),
1411 1411
 
1412 1412
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:40
1413
-	__( 'United States', 'event_espresso' ),
1413
+	__('United States', 'event_espresso'),
1414 1414
 
1415 1415
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:44
1416
-	__( 'Custom', 'event_espresso' ),
1416
+	__('Custom', 'event_espresso'),
1417 1417
 
1418 1418
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:54
1419
-	__( 'required', 'event_espresso' ),
1419
+	__('required', 'event_espresso'),
1420 1420
 
1421 1421
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:59
1422
-	__( 'required text', 'event_espresso' ),
1422
+	__('required text', 'event_espresso'),
1423 1423
 
1424 1424
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:66
1425
-	__( 'autocomplete', 'event_espresso' ),
1425
+	__('autocomplete', 'event_espresso'),
1426 1426
 
1427 1427
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:74
1428
-	__( 'custom format', 'event_espresso' ),
1428
+	__('custom format', 'event_espresso'),
1429 1429
 
1430 1430
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:75
1431
-	__( 'format', 'event_espresso' ),
1431
+	__('format', 'event_espresso'),
1432 1432
 
1433 1433
 	// Reference: packages/form-builder/src/FormElement/Tabs/Validation.tsx:83
1434
-	__( 'pattern', 'event_espresso' ),
1434
+	__('pattern', 'event_espresso'),
1435 1435
 
1436 1436
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:110
1437
-	__( 'add new form element', 'event_espresso' ),
1437
+	__('add new form element', 'event_espresso'),
1438 1438
 
1439 1439
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:117
1440 1440
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:52
1441
-	__( 'Add', 'event_espresso' ),
1441
+	__('Add', 'event_espresso'),
1442 1442
 
1443 1443
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:76
1444
-	__( 'Add Form Element', 'event_espresso' ),
1444
+	__('Add Form Element', 'event_espresso'),
1445 1445
 
1446 1446
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:85
1447
-	__( 'form element order can be changed after adding by using the drag handles in the form element toolbar', 'event_espresso' ),
1447
+	__('form element order can be changed after adding by using the drag handles in the form element toolbar', 'event_espresso'),
1448 1448
 
1449 1449
 	// Reference: packages/form-builder/src/FormSection/AddFormElementPopover.tsx:92
1450
-	__( 'load existing form section', 'event_espresso' ),
1450
+	__('load existing form section', 'event_espresso'),
1451 1451
 
1452 1452
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:32
1453
-	__( 'delete form section', 'event_espresso' ),
1453
+	__('delete form section', 'event_espresso'),
1454 1454
 
1455 1455
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:47
1456
-	__( 'form section settings', 'event_espresso' ),
1456
+	__('form section settings', 'event_espresso'),
1457 1457
 
1458 1458
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:57
1459
-	__( 'copy form section', 'event_espresso' ),
1459
+	__('copy form section', 'event_espresso'),
1460 1460
 
1461 1461
 	// Reference: packages/form-builder/src/FormSection/FormSectionToolbar.tsx:74
1462
-	__( 'click, hold, and drag to reorder form section', 'event_espresso' ),
1462
+	__('click, hold, and drag to reorder form section', 'event_espresso'),
1463 1463
 
1464 1464
 	// Reference: packages/form-builder/src/FormSection/FormSections.tsx:26
1465
-	__( 'Add Form Section', 'event_espresso' ),
1465
+	__('Add Form Section', 'event_espresso'),
1466 1466
 
1467 1467
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:47
1468
-	__( 'save form section for use in other forms', 'event_espresso' ),
1468
+	__('save form section for use in other forms', 'event_espresso'),
1469 1469
 
1470 1470
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:51
1471
-	__( 'save as', 'event_espresso' ),
1471
+	__('save as', 'event_espresso'),
1472 1472
 
1473 1473
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:55
1474
-	__( 'default', 'event_espresso' ),
1474
+	__('default', 'event_espresso'),
1475 1475
 
1476 1476
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:58
1477
-	__( ' a copy of this form section will be automatically added to ALL new events', 'event_espresso' ),
1477
+	__(' a copy of this form section will be automatically added to ALL new events', 'event_espresso'),
1478 1478
 
1479 1479
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:61
1480
-	__( 'shared', 'event_espresso' ),
1480
+	__('shared', 'event_espresso'),
1481 1481
 
1482 1482
 	// Reference: packages/form-builder/src/FormSection/SaveSection.tsx:64
1483
-	__( 'a copy of this form section will be saved for use in other events but not loaded by default', 'event_espresso' ),
1483
+	__('a copy of this form section will be saved for use in other events but not loaded by default', 'event_espresso'),
1484 1484
 
1485 1485
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:27
1486
-	__( 'show label', 'event_espresso' ),
1486
+	__('show label', 'event_espresso'),
1487 1487
 
1488 1488
 	// Reference: packages/form-builder/src/FormSection/Tabs/Settings.tsx:33
1489
-	__( 'applies to', 'event_espresso' ),
1489
+	__('applies to', 'event_espresso'),
1490 1490
 
1491 1491
 	// Reference: packages/form-builder/src/constants.ts:102
1492 1492
 	// Reference: packages/form-builder/src/state/utils.ts:436
1493
-	__( 'URL', 'event_espresso' ),
1493
+	__('URL', 'event_espresso'),
1494 1494
 
1495 1495
 	// Reference: packages/form-builder/src/constants.ts:104
1496
-	__( 'adds a text input for entering a URL address', 'event_espresso' ),
1496
+	__('adds a text input for entering a URL address', 'event_espresso'),
1497 1497
 
1498 1498
 	// Reference: packages/form-builder/src/constants.ts:107
1499
-	__( 'Date', 'event_espresso' ),
1499
+	__('Date', 'event_espresso'),
1500 1500
 
1501 1501
 	// Reference: packages/form-builder/src/constants.ts:109
1502
-	__( 'adds a text input that allows users to enter a date directly via keyboard or a datepicker', 'event_espresso' ),
1502
+	__('adds a text input that allows users to enter a date directly via keyboard or a datepicker', 'event_espresso'),
1503 1503
 
1504 1504
 	// Reference: packages/form-builder/src/constants.ts:112
1505 1505
 	// Reference: packages/form-builder/src/state/utils.ts:369
1506
-	__( 'Local Date', 'event_espresso' ),
1506
+	__('Local Date', 'event_espresso'),
1507 1507
 
1508 1508
 	// Reference: packages/form-builder/src/constants.ts:117
1509
-	__( 'Month', 'event_espresso' ),
1509
+	__('Month', 'event_espresso'),
1510 1510
 
1511 1511
 	// Reference: packages/form-builder/src/constants.ts:119
1512
-	__( 'adds a text input that allows users to enter a month and year directly via keyboard or a datepicker', 'event_espresso' ),
1512
+	__('adds a text input that allows users to enter a month and year directly via keyboard or a datepicker', 'event_espresso'),
1513 1513
 
1514 1514
 	// Reference: packages/form-builder/src/constants.ts:122
1515
-	__( 'Time', 'event_espresso' ),
1515
+	__('Time', 'event_espresso'),
1516 1516
 
1517 1517
 	// Reference: packages/form-builder/src/constants.ts:124
1518
-	__( 'adds a text input that allows users to enter a time directly via keyboard or a timepicker', 'event_espresso' ),
1518
+	__('adds a text input that allows users to enter a time directly via keyboard or a timepicker', 'event_espresso'),
1519 1519
 
1520 1520
 	// Reference: packages/form-builder/src/constants.ts:127
1521
-	__( 'Week', 'event_espresso' ),
1521
+	__('Week', 'event_espresso'),
1522 1522
 
1523 1523
 	// Reference: packages/form-builder/src/constants.ts:129
1524
-	__( 'adds a text input that allows users to enter a week and year directly via keyboard or a datepicker', 'event_espresso' ),
1524
+	__('adds a text input that allows users to enter a week and year directly via keyboard or a datepicker', 'event_espresso'),
1525 1525
 
1526 1526
 	// Reference: packages/form-builder/src/constants.ts:132
1527
-	__( 'Day Selector', 'event_espresso' ),
1527
+	__('Day Selector', 'event_espresso'),
1528 1528
 
1529 1529
 	// Reference: packages/form-builder/src/constants.ts:134
1530
-	__( 'adds a dropdown selector that allows users to select the day of the month (01 to 31)', 'event_espresso' ),
1530
+	__('adds a dropdown selector that allows users to select the day of the month (01 to 31)', 'event_espresso'),
1531 1531
 
1532 1532
 	// Reference: packages/form-builder/src/constants.ts:137
1533
-	__( 'Month Selector', 'event_espresso' ),
1533
+	__('Month Selector', 'event_espresso'),
1534 1534
 
1535 1535
 	// Reference: packages/form-builder/src/constants.ts:139
1536
-	__( 'adds a dropdown selector that allows users to select the month of the year (01 to 12)', 'event_espresso' ),
1536
+	__('adds a dropdown selector that allows users to select the month of the year (01 to 12)', 'event_espresso'),
1537 1537
 
1538 1538
 	// Reference: packages/form-builder/src/constants.ts:142
1539
-	__( 'Year Selector', 'event_espresso' ),
1539
+	__('Year Selector', 'event_espresso'),
1540 1540
 
1541 1541
 	// Reference: packages/form-builder/src/constants.ts:144
1542
-	__( 'adds a dropdown selector that allows users to select the year from a configurable range', 'event_espresso' ),
1542
+	__('adds a dropdown selector that allows users to select the year from a configurable range', 'event_espresso'),
1543 1543
 
1544 1544
 	// Reference: packages/form-builder/src/constants.ts:147
1545
-	__( 'Radio Buttons', 'event_espresso' ),
1545
+	__('Radio Buttons', 'event_espresso'),
1546 1546
 
1547 1547
 	// Reference: packages/form-builder/src/constants.ts:149
1548
-	__( 'adds one or more radio buttons that allow users to only select one option from those provided', 'event_espresso' ),
1548
+	__('adds one or more radio buttons that allow users to only select one option from those provided', 'event_espresso'),
1549 1549
 
1550 1550
 	// Reference: packages/form-builder/src/constants.ts:152
1551 1551
 	// Reference: packages/form-builder/src/state/utils.ts:375
1552
-	__( 'Decimal Number', 'event_espresso' ),
1552
+	__('Decimal Number', 'event_espresso'),
1553 1553
 
1554 1554
 	// Reference: packages/form-builder/src/constants.ts:154
1555
-	__( 'adds a text input that only accepts numbers whose value is a decimal (float)', 'event_espresso' ),
1555
+	__('adds a text input that only accepts numbers whose value is a decimal (float)', 'event_espresso'),
1556 1556
 
1557 1557
 	// Reference: packages/form-builder/src/constants.ts:157
1558 1558
 	// Reference: packages/form-builder/src/state/utils.ts:378
1559
-	__( 'Whole Number', 'event_espresso' ),
1559
+	__('Whole Number', 'event_espresso'),
1560 1560
 
1561 1561
 	// Reference: packages/form-builder/src/constants.ts:159
1562
-	__( 'adds a text input that only accepts numbers whose value is an integer (whole number)', 'event_espresso' ),
1562
+	__('adds a text input that only accepts numbers whose value is an integer (whole number)', 'event_espresso'),
1563 1563
 
1564 1564
 	// Reference: packages/form-builder/src/constants.ts:162
1565
-	__( 'Number Range', 'event_espresso' ),
1565
+	__('Number Range', 'event_espresso'),
1566 1566
 
1567 1567
 	// Reference: packages/form-builder/src/constants.ts:167
1568
-	__( 'Phone Number', 'event_espresso' ),
1568
+	__('Phone Number', 'event_espresso'),
1569 1569
 
1570 1570
 	// Reference: packages/form-builder/src/constants.ts:172
1571
-	__( 'Dropdown', 'event_espresso' ),
1571
+	__('Dropdown', 'event_espresso'),
1572 1572
 
1573 1573
 	// Reference: packages/form-builder/src/constants.ts:174
1574
-	__( 'adds a dropdown selector that accepts a single value', 'event_espresso' ),
1574
+	__('adds a dropdown selector that accepts a single value', 'event_espresso'),
1575 1575
 
1576 1576
 	// Reference: packages/form-builder/src/constants.ts:177
1577
-	__( 'Multi Select', 'event_espresso' ),
1577
+	__('Multi Select', 'event_espresso'),
1578 1578
 
1579 1579
 	// Reference: packages/form-builder/src/constants.ts:179
1580
-	__( 'adds a dropdown selector that accepts multiple values', 'event_espresso' ),
1580
+	__('adds a dropdown selector that accepts multiple values', 'event_espresso'),
1581 1581
 
1582 1582
 	// Reference: packages/form-builder/src/constants.ts:182
1583
-	__( 'Toggle/Switch', 'event_espresso' ),
1583
+	__('Toggle/Switch', 'event_espresso'),
1584 1584
 
1585 1585
 	// Reference: packages/form-builder/src/constants.ts:184
1586
-	__( 'adds a toggle or a switch to accept true or false value', 'event_espresso' ),
1586
+	__('adds a toggle or a switch to accept true or false value', 'event_espresso'),
1587 1587
 
1588 1588
 	// Reference: packages/form-builder/src/constants.ts:187
1589
-	__( 'Multi Checkbox', 'event_espresso' ),
1589
+	__('Multi Checkbox', 'event_espresso'),
1590 1590
 
1591 1591
 	// Reference: packages/form-builder/src/constants.ts:189
1592
-	__( 'adds checkboxes that allow users to select zero or more options from those provided', 'event_espresso' ),
1592
+	__('adds checkboxes that allow users to select zero or more options from those provided', 'event_espresso'),
1593 1593
 
1594 1594
 	// Reference: packages/form-builder/src/constants.ts:192
1595
-	__( 'Country Selector', 'event_espresso' ),
1595
+	__('Country Selector', 'event_espresso'),
1596 1596
 
1597 1597
 	// Reference: packages/form-builder/src/constants.ts:194
1598
-	__( 'adds a dropdown selector populated with names of countries that are enabled for the site', 'event_espresso' ),
1598
+	__('adds a dropdown selector populated with names of countries that are enabled for the site', 'event_espresso'),
1599 1599
 
1600 1600
 	// Reference: packages/form-builder/src/constants.ts:197
1601
-	__( 'State Selector', 'event_espresso' ),
1601
+	__('State Selector', 'event_espresso'),
1602 1602
 
1603 1603
 	// Reference: packages/form-builder/src/constants.ts:202
1604
-	__( 'Button', 'event_espresso' ),
1604
+	__('Button', 'event_espresso'),
1605 1605
 
1606 1606
 	// Reference: packages/form-builder/src/constants.ts:204
1607
-	__( 'adds a button to the form that can be used for triggering fucntionality (requires custom coding)', 'event_espresso' ),
1607
+	__('adds a button to the form that can be used for triggering fucntionality (requires custom coding)', 'event_espresso'),
1608 1608
 
1609 1609
 	// Reference: packages/form-builder/src/constants.ts:207
1610
-	__( 'Reset Button', 'event_espresso' ),
1610
+	__('Reset Button', 'event_espresso'),
1611 1611
 
1612 1612
 	// Reference: packages/form-builder/src/constants.ts:209
1613
-	__( 'adds a button that will reset the form back to its original state.', 'event_espresso' ),
1613
+	__('adds a button that will reset the form back to its original state.', 'event_espresso'),
1614 1614
 
1615 1615
 	// Reference: packages/form-builder/src/constants.ts:55
1616
-	__( 'Form Section', 'event_espresso' ),
1616
+	__('Form Section', 'event_espresso'),
1617 1617
 
1618 1618
 	// Reference: packages/form-builder/src/constants.ts:57
1619
-	__( 'Used for creating logical groupings for questions and form elements. Need to add a heading or description? Use the HTML form element.', 'event_espresso' ),
1619
+	__('Used for creating logical groupings for questions and form elements. Need to add a heading or description? Use the HTML form element.', 'event_espresso'),
1620 1620
 
1621 1621
 	// Reference: packages/form-builder/src/constants.ts:62
1622
-	__( 'HTML Block', 'event_espresso' ),
1622
+	__('HTML Block', 'event_espresso'),
1623 1623
 
1624 1624
 	// Reference: packages/form-builder/src/constants.ts:64
1625
-	__( 'allows you to add HTML like headings or text paragraphs to your form', 'event_espresso' ),
1625
+	__('allows you to add HTML like headings or text paragraphs to your form', 'event_espresso'),
1626 1626
 
1627 1627
 	// Reference: packages/form-builder/src/constants.ts:69
1628
-	__( 'adds a text input that only accepts plain text', 'event_espresso' ),
1628
+	__('adds a text input that only accepts plain text', 'event_espresso'),
1629 1629
 
1630 1630
 	// Reference: packages/form-builder/src/constants.ts:72
1631
-	__( 'Plain Text Area', 'event_espresso' ),
1631
+	__('Plain Text Area', 'event_espresso'),
1632 1632
 
1633 1633
 	// Reference: packages/form-builder/src/constants.ts:74
1634
-	__( 'adds a textarea block that only accepts plain text', 'event_espresso' ),
1634
+	__('adds a textarea block that only accepts plain text', 'event_espresso'),
1635 1635
 
1636 1636
 	// Reference: packages/form-builder/src/constants.ts:77
1637
-	__( 'HTML Text Area', 'event_espresso' ),
1637
+	__('HTML Text Area', 'event_espresso'),
1638 1638
 
1639 1639
 	// Reference: packages/form-builder/src/constants.ts:79
1640
-	__( 'adds a textarea block that accepts text including simple HTML markup', 'event_espresso' ),
1640
+	__('adds a textarea block that accepts text including simple HTML markup', 'event_espresso'),
1641 1641
 
1642 1642
 	// Reference: packages/form-builder/src/constants.ts:84
1643
-	__( 'adds a text input that only accepts a valid email address', 'event_espresso' ),
1643
+	__('adds a text input that only accepts a valid email address', 'event_espresso'),
1644 1644
 
1645 1645
 	// Reference: packages/form-builder/src/constants.ts:87
1646
-	__( 'Email Confirmation', 'event_espresso' ),
1646
+	__('Email Confirmation', 'event_espresso'),
1647 1647
 
1648 1648
 	// Reference: packages/form-builder/src/constants.ts:92
1649
-	__( 'Password', 'event_espresso' ),
1649
+	__('Password', 'event_espresso'),
1650 1650
 
1651 1651
 	// Reference: packages/form-builder/src/constants.ts:94
1652
-	__( 'adds a text input that accepts text but masks what the user enters', 'event_espresso' ),
1652
+	__('adds a text input that accepts text but masks what the user enters', 'event_espresso'),
1653 1653
 
1654 1654
 	// Reference: packages/form-builder/src/constants.ts:97
1655
-	__( 'Password Confirmation', 'event_espresso' ),
1655
+	__('Password Confirmation', 'event_espresso'),
1656 1656
 
1657 1657
 	// Reference: packages/form-builder/src/data/useElementMutator.ts:54
1658
-	__( 'element', 'event_espresso' ),
1658
+	__('element', 'event_espresso'),
1659 1659
 
1660 1660
 	// Reference: packages/form-builder/src/data/useSectionMutator.ts:54
1661
-	__( 'section', 'event_espresso' ),
1661
+	__('section', 'event_espresso'),
1662 1662
 
1663 1663
 	// Reference: packages/form-builder/src/state/utils.ts:360
1664
-	__( 'click', 'event_espresso' ),
1664
+	__('click', 'event_espresso'),
1665 1665
 
1666 1666
 	// Reference: packages/form-builder/src/state/utils.ts:363
1667
-	__( 'checkboxes', 'event_espresso' ),
1667
+	__('checkboxes', 'event_espresso'),
1668 1668
 
1669 1669
 	// Reference: packages/form-builder/src/state/utils.ts:366
1670
-	__( 'date', 'event_espresso' ),
1670
+	__('date', 'event_espresso'),
1671 1671
 
1672 1672
 	// Reference: packages/form-builder/src/state/utils.ts:372
1673
-	__( 'day', 'event_espresso' ),
1673
+	__('day', 'event_espresso'),
1674 1674
 
1675 1675
 	// Reference: packages/form-builder/src/state/utils.ts:381
1676
-	__( 'email address', 'event_espresso' ),
1676
+	__('email address', 'event_espresso'),
1677 1677
 
1678 1678
 	// Reference: packages/form-builder/src/state/utils.ts:384
1679
-	__( 'confirm email address', 'event_espresso' ),
1679
+	__('confirm email address', 'event_espresso'),
1680 1680
 
1681 1681
 	// Reference: packages/form-builder/src/state/utils.ts:388
1682
-	__( 'month', 'event_espresso' ),
1682
+	__('month', 'event_espresso'),
1683 1683
 
1684 1684
 	// Reference: packages/form-builder/src/state/utils.ts:391
1685
-	__( 'password', 'event_espresso' ),
1685
+	__('password', 'event_espresso'),
1686 1686
 
1687 1687
 	// Reference: packages/form-builder/src/state/utils.ts:394
1688
-	__( 'confirm password', 'event_espresso' ),
1688
+	__('confirm password', 'event_espresso'),
1689 1689
 
1690 1690
 	// Reference: packages/form-builder/src/state/utils.ts:397
1691
-	__( 'radio buttons', 'event_espresso' ),
1691
+	__('radio buttons', 'event_espresso'),
1692 1692
 
1693 1693
 	// Reference: packages/form-builder/src/state/utils.ts:400
1694
-	__( 'number range', 'event_espresso' ),
1694
+	__('number range', 'event_espresso'),
1695 1695
 
1696 1696
 	// Reference: packages/form-builder/src/state/utils.ts:403
1697
-	__( 'selection dropdown', 'event_espresso' ),
1697
+	__('selection dropdown', 'event_espresso'),
1698 1698
 
1699 1699
 	// Reference: packages/form-builder/src/state/utils.ts:406
1700
-	__( 'country', 'event_espresso' ),
1700
+	__('country', 'event_espresso'),
1701 1701
 
1702 1702
 	// Reference: packages/form-builder/src/state/utils.ts:409
1703
-	__( 'multi-select dropdown', 'event_espresso' ),
1703
+	__('multi-select dropdown', 'event_espresso'),
1704 1704
 
1705 1705
 	// Reference: packages/form-builder/src/state/utils.ts:412
1706
-	__( 'state/province', 'event_espresso' ),
1706
+	__('state/province', 'event_espresso'),
1707 1707
 
1708 1708
 	// Reference: packages/form-builder/src/state/utils.ts:415
1709
-	__( 'on/off switch', 'event_espresso' ),
1709
+	__('on/off switch', 'event_espresso'),
1710 1710
 
1711 1711
 	// Reference: packages/form-builder/src/state/utils.ts:418
1712
-	__( 'reset', 'event_espresso' ),
1712
+	__('reset', 'event_espresso'),
1713 1713
 
1714 1714
 	// Reference: packages/form-builder/src/state/utils.ts:421
1715
-	__( 'phone number', 'event_espresso' ),
1715
+	__('phone number', 'event_espresso'),
1716 1716
 
1717 1717
 	// Reference: packages/form-builder/src/state/utils.ts:424
1718
-	__( 'text', 'event_espresso' ),
1718
+	__('text', 'event_espresso'),
1719 1719
 
1720 1720
 	// Reference: packages/form-builder/src/state/utils.ts:427
1721
-	__( 'simple textarea', 'event_espresso' ),
1721
+	__('simple textarea', 'event_espresso'),
1722 1722
 
1723 1723
 	// Reference: packages/form-builder/src/state/utils.ts:430
1724
-	__( 'html textarea', 'event_espresso' ),
1724
+	__('html textarea', 'event_espresso'),
1725 1725
 
1726 1726
 	// Reference: packages/form-builder/src/state/utils.ts:439
1727
-	__( 'week', 'event_espresso' ),
1727
+	__('week', 'event_espresso'),
1728 1728
 
1729 1729
 	// Reference: packages/form-builder/src/state/utils.ts:442
1730
-	__( 'year', 'event_espresso' ),
1730
+	__('year', 'event_espresso'),
1731 1731
 
1732 1732
 	// Reference: packages/form/src/adapters/WPMediaImage.tsx:12
1733
-	__( 'Select Image', 'event_espresso' ),
1733
+	__('Select Image', 'event_espresso'),
1734 1734
 
1735 1735
 	// Reference: packages/form/src/adapters/WPMediaImage.tsx:44
1736 1736
 	// Reference: packages/rich-text-editor/src/components/AdvancedTextEditor/toolbarButtons/WPMedia.tsx:11
1737 1737
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:12
1738 1738
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityTemplate.tsx:32
1739
-	__( 'Select', 'event_espresso' ),
1739
+	__('Select', 'event_espresso'),
1740 1740
 
1741 1741
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:36
1742 1742
 	/* translators: %d the entry number */
1743
-	__( 'Entry %d', 'event_espresso' ),
1743
+	__('Entry %d', 'event_espresso'),
1744 1744
 
1745 1745
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:11
1746 1746
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:17
1747
-	__( 'sold out', 'event_espresso' ),
1747
+	__('sold out', 'event_espresso'),
1748 1748
 
1749 1749
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:14
1750 1750
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:14
1751
-	__( 'expired', 'event_espresso' ),
1751
+	__('expired', 'event_espresso'),
1752 1752
 
1753 1753
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:17
1754
-	__( 'upcoming', 'event_espresso' ),
1754
+	__('upcoming', 'event_espresso'),
1755 1755
 
1756 1756
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:20
1757
-	__( 'active', 'event_espresso' ),
1757
+	__('active', 'event_espresso'),
1758 1758
 
1759 1759
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:23
1760 1760
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:11
1761
-	__( 'trashed', 'event_espresso' ),
1761
+	__('trashed', 'event_espresso'),
1762 1762
 
1763 1763
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:26
1764
-	__( 'cancelled', 'event_espresso' ),
1764
+	__('cancelled', 'event_espresso'),
1765 1765
 
1766 1766
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:29
1767
-	__( 'postponed', 'event_espresso' ),
1767
+	__('postponed', 'event_espresso'),
1768 1768
 
1769 1769
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:33
1770
-	__( 'inactive', 'event_espresso' ),
1770
+	__('inactive', 'event_espresso'),
1771 1771
 
1772 1772
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:20
1773
-	__( 'pending', 'event_espresso' ),
1773
+	__('pending', 'event_espresso'),
1774 1774
 
1775 1775
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:23
1776
-	__( 'on sale', 'event_espresso' ),
1776
+	__('on sale', 'event_espresso'),
1777 1777
 
1778 1778
 	// Reference: packages/helpers/src/tickets/ticketVisibilityOptions.ts:6
1779
-	__( 'Where the ticket can be viewed throughout the UI. ', 'event_espresso' ),
1779
+	__('Where the ticket can be viewed throughout the UI. ', 'event_espresso'),
1780 1780
 
1781 1781
 	// Reference: packages/predicates/src/registration/statusOptions.ts:16
1782
-	__( 'Declined', 'event_espresso' ),
1782
+	__('Declined', 'event_espresso'),
1783 1783
 
1784 1784
 	// Reference: packages/predicates/src/registration/statusOptions.ts:21
1785
-	__( 'Incomplete', 'event_espresso' ),
1785
+	__('Incomplete', 'event_espresso'),
1786 1786
 
1787 1787
 	// Reference: packages/predicates/src/registration/statusOptions.ts:26
1788
-	__( 'Not Approved', 'event_espresso' ),
1788
+	__('Not Approved', 'event_espresso'),
1789 1789
 
1790 1790
 	// Reference: packages/predicates/src/registration/statusOptions.ts:31
1791
-	__( 'Pending Payment', 'event_espresso' ),
1791
+	__('Pending Payment', 'event_espresso'),
1792 1792
 
1793 1793
 	// Reference: packages/predicates/src/registration/statusOptions.ts:36
1794
-	__( 'Wait List', 'event_espresso' ),
1794
+	__('Wait List', 'event_espresso'),
1795 1795
 
1796 1796
 	// Reference: packages/predicates/src/registration/statusOptions.ts:6
1797
-	__( 'Approved', 'event_espresso' ),
1797
+	__('Approved', 'event_espresso'),
1798 1798
 
1799 1799
 	// Reference: packages/rich-text-editor/src/components/AdvancedTextEditor/toolbarButtons/WPMedia.tsx:9
1800 1800
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:10
1801
-	__( 'Select media', 'event_espresso' ),
1801
+	__('Select media', 'event_espresso'),
1802 1802
 
1803 1803
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/RichTextEditor.tsx:84
1804
-	__( 'Write something…', 'event_espresso' ),
1804
+	__('Write something…', 'event_espresso'),
1805 1805
 
1806 1806
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/Toolbar.tsx:20
1807
-	__( 'RTE Toolbar', 'event_espresso' ),
1807
+	__('RTE Toolbar', 'event_espresso'),
1808 1808
 
1809 1809
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:11
1810
-	__( 'Normal', 'event_espresso' ),
1810
+	__('Normal', 'event_espresso'),
1811 1811
 
1812 1812
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:12
1813
-	__( 'H1', 'event_espresso' ),
1813
+	__('H1', 'event_espresso'),
1814 1814
 
1815 1815
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:13
1816
-	__( 'H2', 'event_espresso' ),
1816
+	__('H2', 'event_espresso'),
1817 1817
 
1818 1818
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:14
1819
-	__( 'H3', 'event_espresso' ),
1819
+	__('H3', 'event_espresso'),
1820 1820
 
1821 1821
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:15
1822
-	__( 'H4', 'event_espresso' ),
1822
+	__('H4', 'event_espresso'),
1823 1823
 
1824 1824
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:16
1825
-	__( 'H5', 'event_espresso' ),
1825
+	__('H5', 'event_espresso'),
1826 1826
 
1827 1827
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:17
1828
-	__( 'H6', 'event_espresso' ),
1828
+	__('H6', 'event_espresso'),
1829 1829
 
1830 1830
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:18
1831
-	__( 'Block quote', 'event_espresso' ),
1831
+	__('Block quote', 'event_espresso'),
1832 1832
 
1833 1833
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/blockType/Component.tsx:19
1834
-	__( 'Code', 'event_espresso' ),
1834
+	__('Code', 'event_espresso'),
1835 1835
 
1836 1836
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:36
1837
-	__( 'Set color', 'event_espresso' ),
1837
+	__('Set color', 'event_espresso'),
1838 1838
 
1839 1839
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:45
1840
-	__( 'Text color', 'event_espresso' ),
1840
+	__('Text color', 'event_espresso'),
1841 1841
 
1842 1842
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/colorPicker/Component.tsx:47
1843
-	__( 'Background color', 'event_espresso' ),
1843
+	__('Background color', 'event_espresso'),
1844 1844
 
1845 1845
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:39
1846
-	__( 'Add image', 'event_espresso' ),
1846
+	__('Add image', 'event_espresso'),
1847 1847
 
1848 1848
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:51
1849
-	__( 'Image URL', 'event_espresso' ),
1849
+	__('Image URL', 'event_espresso'),
1850 1850
 
1851 1851
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:55
1852
-	__( 'Alt text', 'event_espresso' ),
1852
+	__('Alt text', 'event_espresso'),
1853 1853
 
1854 1854
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:56
1855
-	__( 'Width', 'event_espresso' ),
1855
+	__('Width', 'event_espresso'),
1856 1856
 
1857 1857
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/image/Component.tsx:60
1858
-	__( 'Height', 'event_espresso' ),
1858
+	__('Height', 'event_espresso'),
1859 1859
 
1860 1860
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/link/Component.tsx:54
1861
-	__( 'Edit link', 'event_espresso' ),
1861
+	__('Edit link', 'event_espresso'),
1862 1862
 
1863 1863
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/link/Component.tsx:64
1864
-	__( 'URL title', 'event_espresso' ),
1864
+	__('URL title', 'event_espresso'),
1865 1865
 
1866 1866
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:11
1867
-	__( 'Unordered list', 'event_espresso' ),
1867
+	__('Unordered list', 'event_espresso'),
1868 1868
 
1869 1869
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:12
1870
-	__( 'Ordered list', 'event_espresso' ),
1870
+	__('Ordered list', 'event_espresso'),
1871 1871
 
1872 1872
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:13
1873 1873
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:13
1874
-	__( 'Indent', 'event_espresso' ),
1874
+	__('Indent', 'event_espresso'),
1875 1875
 
1876 1876
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/list/Component.tsx:14
1877 1877
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:14
1878
-	__( 'Outdent', 'event_espresso' ),
1878
+	__('Outdent', 'event_espresso'),
1879 1879
 
1880 1880
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:11
1881
-	__( 'Unordered textalign', 'event_espresso' ),
1881
+	__('Unordered textalign', 'event_espresso'),
1882 1882
 
1883 1883
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/Toolbar/controls/textAlign/Component.tsx:12
1884
-	__( 'Ordered textalign', 'event_espresso' ),
1884
+	__('Ordered textalign', 'event_espresso'),
1885 1885
 
1886 1886
 	// Reference: packages/rich-text-editor/src/components/RichTextEditor/render/Image/Toolbar.tsx:32
1887
-	__( 'Image toolbar', 'event_espresso' ),
1887
+	__('Image toolbar', 'event_espresso'),
1888 1888
 
1889 1889
 	// Reference: packages/rich-text-editor/src/components/WithEditMode/WithEditMode.tsx:62
1890 1890
 	// Reference: packages/rich-text-editor/src/rte-old/components/RTEWithEditMode/RTEWithEditMode.tsx:35
1891
-	__( 'Visual editor', 'event_espresso' ),
1891
+	__('Visual editor', 'event_espresso'),
1892 1892
 
1893 1893
 	// Reference: packages/rich-text-editor/src/components/WithEditMode/WithEditMode.tsx:66
1894 1894
 	// Reference: packages/rich-text-editor/src/rte-old/components/RTEWithEditMode/RTEWithEditMode.tsx:39
1895
-	__( 'HTML editor', 'event_espresso' ),
1895
+	__('HTML editor', 'event_espresso'),
1896 1896
 
1897 1897
 	// Reference: packages/rich-text-editor/src/rte-old/components/toolbarButtons/WPMedia.tsx:68
1898
-	__( 'Add Media', 'event_espresso' ),
1898
+	__('Add Media', 'event_espresso'),
1899 1899
 
1900 1900
 	// Reference: packages/tpc/src/buttons/AddPriceModifierButton.tsx:14
1901
-	__( 'add new price modifier after this row', 'event_espresso' ),
1901
+	__('add new price modifier after this row', 'event_espresso'),
1902 1902
 
1903 1903
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:14
1904
-	__( 'Delete all prices', 'event_espresso' ),
1904
+	__('Delete all prices', 'event_espresso'),
1905 1905
 
1906 1906
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:27
1907
-	__( 'Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso' ),
1907
+	__('Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso'),
1908 1908
 
1909 1909
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:31
1910
-	__( 'Delete all prices?', 'event_espresso' ),
1910
+	__('Delete all prices?', 'event_espresso'),
1911 1911
 
1912 1912
 	// Reference: packages/tpc/src/buttons/DeletePriceModifierButton.tsx:12
1913
-	__( 'delete price modifier', 'event_espresso' ),
1913
+	__('delete price modifier', 'event_espresso'),
1914 1914
 
1915 1915
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:14
1916
-	__( 'Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso' ),
1916
+	__('Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso'),
1917 1917
 
1918 1918
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:17
1919
-	__( 'Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso' ),
1919
+	__('Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso'),
1920 1920
 
1921 1921
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:21
1922
-	__( 'Disable reverse calculate', 'event_espresso' ),
1922
+	__('Disable reverse calculate', 'event_espresso'),
1923 1923
 
1924 1924
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:21
1925
-	__( 'Enable reverse calculate', 'event_espresso' ),
1925
+	__('Enable reverse calculate', 'event_espresso'),
1926 1926
 
1927 1927
 	// Reference: packages/tpc/src/buttons/TicketPriceCalculatorButton.tsx:28
1928
-	__( 'ticket price calculator', 'event_espresso' ),
1928
+	__('ticket price calculator', 'event_espresso'),
1929 1929
 
1930 1930
 	// Reference: packages/tpc/src/buttons/taxes/AddDefaultTaxesButton.tsx:9
1931
-	__( 'Add default taxes', 'event_espresso' ),
1931
+	__('Add default taxes', 'event_espresso'),
1932 1932
 
1933 1933
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:10
1934
-	__( 'Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso' ),
1934
+	__('Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso'),
1935 1935
 
1936 1936
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:14
1937
-	__( 'Remove all taxes?', 'event_espresso' ),
1937
+	__('Remove all taxes?', 'event_espresso'),
1938 1938
 
1939 1939
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:7
1940
-	__( 'Remove taxes', 'event_espresso' ),
1940
+	__('Remove taxes', 'event_espresso'),
1941 1941
 
1942 1942
 	// Reference: packages/tpc/src/components/DefaultPricesInfo.tsx:29
1943
-	__( 'Modify default prices.', 'event_espresso' ),
1943
+	__('Modify default prices.', 'event_espresso'),
1944 1944
 
1945 1945
 	// Reference: packages/tpc/src/components/DefaultTaxesInfo.tsx:29
1946
-	__( 'New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso' ),
1946
+	__('New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso'),
1947 1947
 
1948 1948
 	// Reference: packages/tpc/src/components/LockedTicketsBanner.tsx:12
1949
-	__( 'Editing of prices is disabled', 'event_espresso' ),
1949
+	__('Editing of prices is disabled', 'event_espresso'),
1950 1950
 
1951 1951
 	// Reference: packages/tpc/src/components/NoPricesBanner/AddDefaultPricesButton.tsx:9
1952
-	__( 'Add default prices', 'event_espresso' ),
1952
+	__('Add default prices', 'event_espresso'),
1953 1953
 
1954 1954
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:13
1955
-	__( 'This Ticket is Currently Free', 'event_espresso' ),
1955
+	__('This Ticket is Currently Free', 'event_espresso'),
1956 1956
 
1957 1957
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:21
1958 1958
 	/* translators: %s default prices */
1959
-	__( 'Click the button below to load your %s into the calculator.', 'event_espresso' ),
1959
+	__('Click the button below to load your %s into the calculator.', 'event_espresso'),
1960 1960
 
1961 1961
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:22
1962
-	__( 'default prices', 'event_espresso' ),
1962
+	__('default prices', 'event_espresso'),
1963 1963
 
1964 1964
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:29
1965
-	__( 'Additional ticket price modifiers can be added or removed.', 'event_espresso' ),
1965
+	__('Additional ticket price modifiers can be added or removed.', 'event_espresso'),
1966 1966
 
1967 1967
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:32
1968
-	__( 'Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso' ),
1968
+	__('Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso'),
1969 1969
 
1970 1970
 	// Reference: packages/tpc/src/components/TicketPriceCalculatorModal.tsx:32
1971 1971
 	/* translators: %s ticket name */
1972
-	__( 'Price Calculator for Ticket: %s', 'event_espresso' ),
1972
+	__('Price Calculator for Ticket: %s', 'event_espresso'),
1973 1973
 
1974 1974
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:48
1975
-	__( 'Total', 'event_espresso' ),
1975
+	__('Total', 'event_espresso'),
1976 1976
 
1977 1977
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:57
1978
-	__( 'ticket total', 'event_espresso' ),
1978
+	__('ticket total', 'event_espresso'),
1979 1979
 
1980 1980
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:29
1981
-	__( 'Order', 'event_espresso' ),
1981
+	__('Order', 'event_espresso'),
1982 1982
 
1983 1983
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:35
1984
-	__( 'Price Type', 'event_espresso' ),
1984
+	__('Price Type', 'event_espresso'),
1985 1985
 
1986 1986
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:41
1987
-	__( 'Label', 'event_espresso' ),
1987
+	__('Label', 'event_espresso'),
1988 1988
 
1989 1989
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:53
1990
-	__( 'Amount', 'event_espresso' ),
1990
+	__('Amount', 'event_espresso'),
1991 1991
 
1992 1992
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:22
1993
-	__( 'Copy ticket', 'event_espresso' ),
1993
+	__('Copy ticket', 'event_espresso'),
1994 1994
 
1995 1995
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:26
1996
-	__( 'Copy and archive this ticket', 'event_espresso' ),
1996
+	__('Copy and archive this ticket', 'event_espresso'),
1997 1997
 
1998 1998
 	// Reference: packages/tpc/src/hooks/useLockedTicketAction.ts:29
1999
-	__( 'OK', 'event_espresso' ),
1999
+	__('OK', 'event_espresso'),
2000 2000
 
2001 2001
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:34
2002
-	__( 'amount', 'event_espresso' ),
2002
+	__('amount', 'event_espresso'),
2003 2003
 
2004 2004
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:46
2005
-	__( 'amount…', 'event_espresso' ),
2005
+	__('amount…', 'event_espresso'),
2006 2006
 
2007 2007
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:14
2008
-	__( 'description…', 'event_espresso' ),
2008
+	__('description…', 'event_espresso'),
2009 2009
 
2010 2010
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:9
2011
-	__( 'price description', 'event_espresso' ),
2011
+	__('price description', 'event_espresso'),
2012 2012
 
2013 2013
 	// Reference: packages/tpc/src/inputs/PriceIdInput.tsx:6
2014
-	__( 'price id', 'event_espresso' ),
2014
+	__('price id', 'event_espresso'),
2015 2015
 
2016 2016
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:13
2017
-	__( 'label…', 'event_espresso' ),
2017
+	__('label…', 'event_espresso'),
2018 2018
 
2019 2019
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:8
2020
-	__( 'price name', 'event_espresso' ),
2020
+	__('price name', 'event_espresso'),
2021 2021
 
2022 2022
 	// Reference: packages/tpc/src/inputs/PriceOrderInput.tsx:14
2023
-	__( 'price order', 'event_espresso' ),
2023
+	__('price order', 'event_espresso'),
2024 2024
 
2025 2025
 	// Reference: packages/tpc/src/utils/constants.ts:8
2026
-	__( 'Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then trash the old tickets.', 'event_espresso' ),
2026
+	__('Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then trash the old tickets.', 'event_espresso'),
2027 2027
 
2028 2028
 	// Reference: packages/ui-components/src/ActiveFilters/ActiveFilters.tsx:8
2029
-	__( 'active filters:', 'event_espresso' ),
2029
+	__('active filters:', 'event_espresso'),
2030 2030
 
2031 2031
 	// Reference: packages/ui-components/src/ActiveFilters/FilterTag/index.tsx:15
2032 2032
 	/* translators: %s filter name */
2033
-	__( 'remove filter - %s', 'event_espresso' ),
2033
+	__('remove filter - %s', 'event_espresso'),
2034 2034
 
2035 2035
 	// Reference: packages/ui-components/src/Address/Address.tsx:72
2036
-	__( 'Address:', 'event_espresso' ),
2036
+	__('Address:', 'event_espresso'),
2037 2037
 
2038 2038
 	// Reference: packages/ui-components/src/Address/Address.tsx:80
2039
-	__( 'City:', 'event_espresso' ),
2039
+	__('City:', 'event_espresso'),
2040 2040
 
2041 2041
 	// Reference: packages/ui-components/src/Address/Address.tsx:86
2042
-	__( 'State:', 'event_espresso' ),
2042
+	__('State:', 'event_espresso'),
2043 2043
 
2044 2044
 	// Reference: packages/ui-components/src/Address/Address.tsx:92
2045
-	__( 'Country:', 'event_espresso' ),
2045
+	__('Country:', 'event_espresso'),
2046 2046
 
2047 2047
 	// Reference: packages/ui-components/src/Address/Address.tsx:98
2048
-	__( 'Zip:', 'event_espresso' ),
2048
+	__('Zip:', 'event_espresso'),
2049 2049
 
2050 2050
 	// Reference: packages/ui-components/src/CalendarDateRange/CalendarDateRange.tsx:37
2051
-	__( 'to', 'event_espresso' ),
2051
+	__('to', 'event_espresso'),
2052 2052
 
2053 2053
 	// Reference: packages/ui-components/src/CalendarPageDate/CalendarPageDate.tsx:54
2054
-	__( 'TO', 'event_espresso' ),
2054
+	__('TO', 'event_espresso'),
2055 2055
 
2056 2056
 	// Reference: packages/ui-components/src/ColorPicker/ColorPicker.tsx:60
2057
-	__( 'Custom color', 'event_espresso' ),
2057
+	__('Custom color', 'event_espresso'),
2058 2058
 
2059 2059
 	// Reference: packages/ui-components/src/ColorPicker/Swatch.tsx:23
2060 2060
 	/* translators: color name */
2061
-	__( 'Color: %s', 'event_espresso' ),
2061
+	__('Color: %s', 'event_espresso'),
2062 2062
 
2063 2063
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:13
2064
-	__( 'Cyan bluish gray', 'event_espresso' ),
2064
+	__('Cyan bluish gray', 'event_espresso'),
2065 2065
 
2066 2066
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:17
2067
-	__( 'White', 'event_espresso' ),
2067
+	__('White', 'event_espresso'),
2068 2068
 
2069 2069
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:21
2070
-	__( 'Pale pink', 'event_espresso' ),
2070
+	__('Pale pink', 'event_espresso'),
2071 2071
 
2072 2072
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:25
2073
-	__( 'Vivid red', 'event_espresso' ),
2073
+	__('Vivid red', 'event_espresso'),
2074 2074
 
2075 2075
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:29
2076
-	__( 'Luminous vivid orange', 'event_espresso' ),
2076
+	__('Luminous vivid orange', 'event_espresso'),
2077 2077
 
2078 2078
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:33
2079
-	__( 'Luminous vivid amber', 'event_espresso' ),
2079
+	__('Luminous vivid amber', 'event_espresso'),
2080 2080
 
2081 2081
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:37
2082
-	__( 'Light green cyan', 'event_espresso' ),
2082
+	__('Light green cyan', 'event_espresso'),
2083 2083
 
2084 2084
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:41
2085
-	__( 'Vivid green cyan', 'event_espresso' ),
2085
+	__('Vivid green cyan', 'event_espresso'),
2086 2086
 
2087 2087
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:45
2088
-	__( 'Pale cyan blue', 'event_espresso' ),
2088
+	__('Pale cyan blue', 'event_espresso'),
2089 2089
 
2090 2090
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:49
2091
-	__( 'Vivid cyan blue', 'event_espresso' ),
2091
+	__('Vivid cyan blue', 'event_espresso'),
2092 2092
 
2093 2093
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:53
2094
-	__( 'Vivid purple', 'event_espresso' ),
2094
+	__('Vivid purple', 'event_espresso'),
2095 2095
 
2096 2096
 	// Reference: packages/ui-components/src/ColorPicker/constants.ts:9
2097
-	__( 'Black', 'event_espresso' ),
2097
+	__('Black', 'event_espresso'),
2098 2098
 
2099 2099
 	// Reference: packages/ui-components/src/Confirm/ConfirmClose.tsx:7
2100 2100
 	// Reference: packages/ui-components/src/Modal/ModalWithAlert.tsx:23
2101
-	__( 'Are you sure you want to close this?', 'event_espresso' ),
2101
+	__('Are you sure you want to close this?', 'event_espresso'),
2102 2102
 
2103 2103
 	// Reference: packages/ui-components/src/Confirm/ConfirmDelete.tsx:7
2104
-	__( 'Are you sure you want to delete this?', 'event_espresso' ),
2104
+	__('Are you sure you want to delete this?', 'event_espresso'),
2105 2105
 
2106 2106
 	// Reference: packages/ui-components/src/Confirm/useConfirmWithButton.tsx:10
2107
-	__( 'Please confirm this action.', 'event_espresso' ),
2107
+	__('Please confirm this action.', 'event_espresso'),
2108 2108
 
2109 2109
 	// Reference: packages/ui-components/src/Confirm/useConfirmationDialog.tsx:39
2110
-	__( 'cancel', 'event_espresso' ),
2110
+	__('cancel', 'event_espresso'),
2111 2111
 
2112 2112
 	// Reference: packages/ui-components/src/Confirm/useConfirmationDialog.tsx:40
2113
-	__( 'confirm', 'event_espresso' ),
2113
+	__('confirm', 'event_espresso'),
2114 2114
 
2115 2115
 	// Reference: packages/ui-components/src/CurrencyDisplay/CurrencyDisplay.tsx:34
2116
-	__( 'free', 'event_espresso' ),
2116
+	__('free', 'event_espresso'),
2117 2117
 
2118 2118
 	// Reference: packages/ui-components/src/DateTimeRangePicker/DateTimeRangePicker.tsx:117
2119 2119
 	// Reference: packages/ui-components/src/Popover/PopoverForm/PopoverForm.tsx:44
2120
-	__( 'save', 'event_espresso' ),
2120
+	__('save', 'event_espresso'),
2121 2121
 
2122 2122
 	// Reference: packages/ui-components/src/DebugInfo/DebugInfo.tsx:36
2123
-	__( 'Hide Debug Info', 'event_espresso' ),
2123
+	__('Hide Debug Info', 'event_espresso'),
2124 2124
 
2125 2125
 	// Reference: packages/ui-components/src/DebugInfo/DebugInfo.tsx:36
2126
-	__( 'Show Debug Info', 'event_espresso' ),
2126
+	__('Show Debug Info', 'event_espresso'),
2127 2127
 
2128 2128
 	// Reference: packages/ui-components/src/EditDateRangeButton/EditDateRangeButton.tsx:49
2129
-	__( 'Edit Start and End Dates and Times', 'event_espresso' ),
2129
+	__('Edit Start and End Dates and Times', 'event_espresso'),
2130 2130
 
2131 2131
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/CopyEntity.tsx:8
2132
-	__( 'copy', 'event_espresso' ),
2132
+	__('copy', 'event_espresso'),
2133 2133
 
2134 2134
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/EditEntity.tsx:8
2135
-	__( 'edit', 'event_espresso' ),
2135
+	__('edit', 'event_espresso'),
2136 2136
 
2137 2137
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/TrashEntity.tsx:8
2138
-	__( 'trash', 'event_espresso' ),
2138
+	__('trash', 'event_espresso'),
2139 2139
 
2140 2140
 	// Reference: packages/ui-components/src/EntityActionsMenu/entityMenuItems/Untrash.tsx:8
2141
-	__( 'untrash', 'event_espresso' ),
2141
+	__('untrash', 'event_espresso'),
2142 2142
 
2143 2143
 	// Reference: packages/ui-components/src/EntityList/RegistrationsLink/index.tsx:12
2144
-	__( 'click to open the registrations admin page in a new tab or window', 'event_espresso' ),
2144
+	__('click to open the registrations admin page in a new tab or window', 'event_espresso'),
2145 2145
 
2146 2146
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/CardViewFilterButton.tsx:22
2147
-	__( 'card view', 'event_espresso' ),
2147
+	__('card view', 'event_espresso'),
2148 2148
 
2149 2149
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/TableViewFilterButton.tsx:21
2150
-	__( 'table view', 'event_espresso' ),
2150
+	__('table view', 'event_espresso'),
2151 2151
 
2152 2152
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleBulkActionsButton.tsx:8
2153
-	__( 'hide bulk actions', 'event_espresso' ),
2153
+	__('hide bulk actions', 'event_espresso'),
2154 2154
 
2155 2155
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleBulkActionsButton.tsx:8
2156
-	__( 'show bulk actions', 'event_espresso' ),
2156
+	__('show bulk actions', 'event_espresso'),
2157 2157
 
2158 2158
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:9
2159
-	__( 'hide filters', 'event_espresso' ),
2159
+	__('hide filters', 'event_espresso'),
2160 2160
 
2161 2161
 	// Reference: packages/ui-components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:9
2162
-	__( 'show filters', 'event_espresso' ),
2162
+	__('show filters', 'event_espresso'),
2163 2163
 
2164 2164
 	// Reference: packages/ui-components/src/Legend/ToggleLegendButton.tsx:26
2165
-	__( 'hide legend', 'event_espresso' ),
2165
+	__('hide legend', 'event_espresso'),
2166 2166
 
2167 2167
 	// Reference: packages/ui-components/src/Legend/ToggleLegendButton.tsx:26
2168
-	__( 'show legend', 'event_espresso' ),
2168
+	__('show legend', 'event_espresso'),
2169 2169
 
2170 2170
 	// Reference: packages/ui-components/src/LoadingNotice/LoadingNotice.tsx:11
2171
-	__( 'loading…', 'event_espresso' ),
2171
+	__('loading…', 'event_espresso'),
2172 2172
 
2173 2173
 	// Reference: packages/ui-components/src/Modal/Modal.tsx:58
2174
-	__( 'close modal', 'event_espresso' ),
2174
+	__('close modal', 'event_espresso'),
2175 2175
 
2176 2176
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:10
2177
-	__( 'jump to previous', 'event_espresso' ),
2177
+	__('jump to previous', 'event_espresso'),
2178 2178
 
2179 2179
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:11
2180
-	__( 'jump to next', 'event_espresso' ),
2180
+	__('jump to next', 'event_espresso'),
2181 2181
 
2182 2182
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:12
2183
-	__( 'page', 'event_espresso' ),
2183
+	__('page', 'event_espresso'),
2184 2184
 
2185 2185
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:8
2186
-	__( 'previous', 'event_espresso' ),
2186
+	__('previous', 'event_espresso'),
2187 2187
 
2188 2188
 	// Reference: packages/ui-components/src/Pagination/ItemRender.tsx:9
2189
-	__( 'next', 'event_espresso' ),
2189
+	__('next', 'event_espresso'),
2190 2190
 
2191 2191
 	// Reference: packages/ui-components/src/Pagination/PerPage.tsx:37
2192
-	__( 'items per page', 'event_espresso' ),
2192
+	__('items per page', 'event_espresso'),
2193 2193
 
2194 2194
 	// Reference: packages/ui-components/src/Pagination/constants.ts:10
2195 2195
 	/* translators: %s is per page value */
2196
-	__( '%s / page', 'event_espresso' ),
2196
+	__('%s / page', 'event_espresso'),
2197 2197
 
2198 2198
 	// Reference: packages/ui-components/src/Pagination/constants.ts:13
2199
-	__( 'Next Page', 'event_espresso' ),
2199
+	__('Next Page', 'event_espresso'),
2200 2200
 
2201 2201
 	// Reference: packages/ui-components/src/Pagination/constants.ts:14
2202
-	__( 'Previous Page', 'event_espresso' ),
2202
+	__('Previous Page', 'event_espresso'),
2203 2203
 
2204 2204
 	// Reference: packages/ui-components/src/PercentSign/index.tsx:10
2205
-	__( '%', 'event_espresso' ),
2205
+	__('%', 'event_espresso'),
2206 2206
 
2207 2207
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:31
2208 2208
 	/* translators: entity type to select */
2209
-	__( 'Select an existing %s to use as a template.', 'event_espresso' ),
2209
+	__('Select an existing %s to use as a template.', 'event_espresso'),
2210 2210
 
2211 2211
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:38
2212
-	__( 'or', 'event_espresso' ),
2212
+	__('or', 'event_espresso'),
2213 2213
 
2214 2214
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:43
2215 2215
 	/* translators: entity type to add */
2216
-	__( 'Add a new %s and insert details manually', 'event_espresso' ),
2216
+	__('Add a new %s and insert details manually', 'event_espresso'),
2217 2217
 
2218 2218
 	// Reference: packages/ui-components/src/SimpleEntityList/EntityOptionsRow/index.tsx:48
2219
-	__( 'Add New', 'event_espresso' ),
2219
+	__('Add New', 'event_espresso'),
2220 2220
 
2221 2221
 	// Reference: packages/ui-components/src/Stepper/buttons/Next.tsx:8
2222
-	__( 'Next', 'event_espresso' ),
2222
+	__('Next', 'event_espresso'),
2223 2223
 
2224 2224
 	// Reference: packages/ui-components/src/Stepper/buttons/Previous.tsx:8
2225
-	__( 'Previous', 'event_espresso' ),
2225
+	__('Previous', 'event_espresso'),
2226 2226
 
2227 2227
 	// Reference: packages/ui-components/src/Steps/Steps.tsx:31
2228
-	__( 'Steps', 'event_espresso' ),
2228
+	__('Steps', 'event_espresso'),
2229 2229
 
2230 2230
 	// Reference: packages/ui-components/src/TabbableText/index.tsx:21
2231
-	__( 'click to edit…', 'event_espresso' ),
2231
+	__('click to edit…', 'event_espresso'),
2232 2232
 
2233 2233
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:14
2234
-	__( 'The Website\'s Time Zone', 'event_espresso' ),
2234
+	__('The Website\'s Time Zone', 'event_espresso'),
2235 2235
 
2236 2236
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:19
2237
-	__( 'UTC (Greenwich Mean Time)', 'event_espresso' ),
2237
+	__('UTC (Greenwich Mean Time)', 'event_espresso'),
2238 2238
 
2239 2239
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/Content.tsx:9
2240
-	__( 'Your Local Time Zone', 'event_espresso' ),
2240
+	__('Your Local Time Zone', 'event_espresso'),
2241 2241
 
2242 2242
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:27
2243
-	__( 'click for timezone information', 'event_espresso' ),
2243
+	__('click for timezone information', 'event_espresso'),
2244 2244
 
2245 2245
 	// Reference: packages/ui-components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:32
2246
-	__( 'This Date Converted To:', 'event_espresso' ),
2246
+	__('This Date Converted To:', 'event_espresso'),
2247 2247
 
2248 2248
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:120
2249
-	__( 'Add New Venue', 'event_espresso' ),
2249
+	__('Add New Venue', 'event_espresso'),
2250 2250
 
2251 2251
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:36
2252
-	__( '~ no venue ~', 'event_espresso' ),
2252
+	__('~ no venue ~', 'event_espresso'),
2253 2253
 
2254 2254
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:43
2255
-	__( 'assign venue…', 'event_espresso' ),
2255
+	__('assign venue…', 'event_espresso'),
2256 2256
 
2257 2257
 	// Reference: packages/ui-components/src/VenueSelector/VenueSelector.tsx:44
2258
-	__( 'click to select a venue…', 'event_espresso' ),
2258
+	__('click to select a venue…', 'event_espresso'),
2259 2259
 
2260 2260
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:51
2261
-	__( 'select all', 'event_espresso' ),
2261
+	__('select all', 'event_espresso'),
2262 2262
 
2263 2263
 	// Reference: packages/ui-components/src/bulkEdit/BulkActions.tsx:54
2264
-	__( 'apply', 'event_espresso' )
2264
+	__('apply', 'event_espresso')
2265 2265
 );
2266 2266
 /* THIS IS THE END OF THE GENERATED FILE */
Please login to merge, or discard this patch.
core/EE_Session.core.php 2 patches
Indentation   +1312 added lines, -1312 removed lines patch added patch discarded remove patch
@@ -23,1310 +23,1310 @@  discard block
 block discarded – undo
23 23
  */
24 24
 class EE_Session implements SessionIdentifierInterface
25 25
 {
26
-    const session_id_prefix = 'ee_ssn_';
27
-
28
-    const hash_check_prefix = 'ee_shc_';
29
-
30
-    const OPTION_NAME_SETTINGS = 'ee_session_settings';
31
-
32
-    const STATUS_CLOSED = 0;
33
-
34
-    const STATUS_OPEN = 1;
35
-
36
-    const SAVE_STATE_CLEAN = 'clean';
37
-    const SAVE_STATE_DIRTY = 'dirty';
38
-
39
-
40
-    /**
41
-     * instance of the EE_Session object
42
-     *
43
-     * @var EE_Session
44
-     */
45
-    private static $_instance;
46
-
47
-    /**
48
-     * @var CacheStorageInterface $cache_storage
49
-     */
50
-    protected $cache_storage;
51
-
52
-    /**
53
-     * @var EE_Encryption $encryption
54
-     */
55
-    protected $encryption;
56
-
57
-    /**
58
-     * @var SessionStartHandler $session_start_handler
59
-     */
60
-    protected $session_start_handler;
61
-
62
-    /**
63
-     * the session id
64
-     *
65
-     * @var string
66
-     */
67
-    private $_sid;
68
-
69
-    /**
70
-     * session id salt
71
-     *
72
-     * @var string
73
-     */
74
-    private $_sid_salt;
75
-
76
-    /**
77
-     * session data
78
-     *
79
-     * @var array
80
-     */
81
-    private $_session_data = array();
82
-
83
-    /**
84
-     * how long an EE session lasts
85
-     * default session lifespan of 1 hour (for not so instant IPNs)
86
-     *
87
-     * @var SessionLifespan $session_lifespan
88
-     */
89
-    private $session_lifespan;
90
-
91
-    /**
92
-     * session expiration time as Unix timestamp in GMT
93
-     *
94
-     * @var int
95
-     */
96
-    private $_expiration;
97
-
98
-    /**
99
-     * whether or not session has expired at some point
100
-     *
101
-     * @var boolean
102
-     */
103
-    private $_expired = false;
104
-
105
-    /**
106
-     * current time as Unix timestamp in GMT
107
-     *
108
-     * @var int
109
-     */
110
-    private $_time;
111
-
112
-    /**
113
-     * whether to encrypt session data
114
-     *
115
-     * @var bool
116
-     */
117
-    private $_use_encryption;
118
-
119
-    /**
120
-     * well... according to the server...
121
-     *
122
-     * @var null
123
-     */
124
-    private $_user_agent;
125
-
126
-    /**
127
-     * do you really trust the server ?
128
-     *
129
-     * @var null
130
-     */
131
-    private $_ip_address;
132
-
133
-    /**
134
-     * current WP user_id
135
-     *
136
-     * @var null
137
-     */
138
-    private $_wp_user_id;
139
-
140
-    /**
141
-     * array for defining default session vars
142
-     *
143
-     * @var array
144
-     */
145
-    private $_default_session_vars = array(
146
-        'id'            => null,
147
-        'user_id'       => null,
148
-        'ip_address'    => null,
149
-        'user_agent'    => null,
150
-        'init_access'   => null,
151
-        'last_access'   => null,
152
-        'expiration'    => null,
153
-        'pages_visited' => array(),
154
-    );
155
-
156
-    /**
157
-     * timestamp for when last garbage collection cycle was performed
158
-     *
159
-     * @var int $_last_gc
160
-     */
161
-    private $_last_gc;
162
-
163
-    /**
164
-     * @var RequestInterface $request
165
-     */
166
-    protected $request;
167
-
168
-    /**
169
-     * whether session is active or not
170
-     *
171
-     * @var int $status
172
-     */
173
-    private $status = EE_Session::STATUS_CLOSED;
174
-
175
-    /**
176
-     * whether session data has changed therefore requiring a session save
177
-     *
178
-     * @var string $save_state
179
-     */
180
-    private $save_state = EE_Session::SAVE_STATE_CLEAN;
181
-
182
-
183
-    /**
184
-     * @singleton method used to instantiate class object
185
-     * @param CacheStorageInterface $cache_storage
186
-     * @param SessionLifespan|null  $lifespan
187
-     * @param RequestInterface      $request
188
-     * @param SessionStartHandler   $session_start_handler
189
-     * @param EE_Encryption         $encryption
190
-     * @return EE_Session
191
-     * @throws InvalidArgumentException
192
-     * @throws InvalidDataTypeException
193
-     * @throws InvalidInterfaceException
194
-     */
195
-    public static function instance(
196
-        CacheStorageInterface $cache_storage = null,
197
-        SessionLifespan $lifespan = null,
198
-        RequestInterface $request = null,
199
-        SessionStartHandler $session_start_handler = null,
200
-        EE_Encryption $encryption = null
201
-    ) {
202
-        // check if class object is instantiated
203
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
204
-        // add_filter( 'FHEE_load_EE_Session', '__return_false' );
205
-        if (
206
-            ! self::$_instance instanceof EE_Session
207
-            && $cache_storage instanceof CacheStorageInterface
208
-            && $lifespan instanceof SessionLifespan
209
-            && $request instanceof RequestInterface
210
-            && $session_start_handler instanceof SessionStartHandler
211
-            && apply_filters('FHEE_load_EE_Session', true)
212
-        ) {
213
-            self::$_instance = new self(
214
-                $cache_storage,
215
-                $lifespan,
216
-                $request,
217
-                $session_start_handler,
218
-                $encryption
219
-            );
220
-        }
221
-        return self::$_instance;
222
-    }
223
-
224
-
225
-    /**
226
-     * protected constructor to prevent direct creation
227
-     *
228
-     * @param CacheStorageInterface $cache_storage
229
-     * @param SessionLifespan       $lifespan
230
-     * @param RequestInterface      $request
231
-     * @param SessionStartHandler   $session_start_handler
232
-     * @param EE_Encryption         $encryption
233
-     * @throws InvalidArgumentException
234
-     * @throws InvalidDataTypeException
235
-     * @throws InvalidInterfaceException
236
-     */
237
-    protected function __construct(
238
-        CacheStorageInterface $cache_storage,
239
-        SessionLifespan $lifespan,
240
-        RequestInterface $request,
241
-        SessionStartHandler $session_start_handler,
242
-        EE_Encryption $encryption = null
243
-    ) {
244
-        // session loading is turned ON by default,
245
-        // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246
-        // (which currently fires on the init hook at priority 9),
247
-        // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
249
-            return;
250
-        }
251
-        $this->session_start_handler = $session_start_handler;
252
-        $this->session_lifespan = $lifespan;
253
-        $this->request = $request;
254
-        if (! defined('ESPRESSO_SESSION')) {
255
-            define('ESPRESSO_SESSION', true);
256
-        }
257
-        // retrieve session options from db
258
-        $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
-        if (! empty($session_settings)) {
260
-            // cycle though existing session options
261
-            foreach ($session_settings as $var_name => $session_setting) {
262
-                // set values for class properties
263
-                $var_name = '_' . $var_name;
264
-                $this->{$var_name} = $session_setting;
265
-            }
266
-        }
267
-        $this->cache_storage = $cache_storage;
268
-        // are we using encryption?
269
-        $this->_use_encryption = $encryption instanceof EE_Encryption
270
-                                 && EE_Registry::instance()->CFG->admin->encode_session_data();
271
-        // encrypt data via: $this->encryption->encrypt();
272
-        $this->encryption = $encryption;
273
-        // filter hook allows outside functions/classes/plugins to change default empty cart
274
-        $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
275
-        array_merge($this->_default_session_vars, $extra_default_session_vars);
276
-        // apply default session vars
277
-        $this->_set_defaults();
278
-        add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
279
-        // check request for 'clear_session' param
280
-        add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
281
-        // once everything is all said and done,
282
-        add_action('shutdown', array($this, 'update'), 100);
283
-        add_action('shutdown', array($this, 'garbageCollection'), 1000);
284
-        $this->configure_garbage_collection_filters();
285
-    }
286
-
287
-
288
-    /**
289
-     * @return bool
290
-     * @throws InvalidArgumentException
291
-     * @throws InvalidDataTypeException
292
-     * @throws InvalidInterfaceException
293
-     */
294
-    public static function isLoadedAndActive()
295
-    {
296
-        return did_action('AHEE__EE_System__core_loaded_and_ready')
297
-               && EE_Session::instance() instanceof EE_Session
298
-               && EE_Session::instance()->isActive();
299
-    }
300
-
301
-
302
-    /**
303
-     * @return bool
304
-     */
305
-    public function isActive()
306
-    {
307
-        return $this->status === EE_Session::STATUS_OPEN;
308
-    }
309
-
310
-
311
-    /**
312
-     * @return void
313
-     * @throws EE_Error
314
-     * @throws InvalidArgumentException
315
-     * @throws InvalidDataTypeException
316
-     * @throws InvalidInterfaceException
317
-     * @throws InvalidSessionDataException
318
-     * @throws RuntimeException
319
-     * @throws ReflectionException
320
-     */
321
-    public function open_session()
322
-    {
323
-        // Check for an existing session and retrieve it from the database, unless the system is in maintenance level 2.
324
-        if (EE_Maintenance_Mode::instance()->models_can_query() && ! $this->_espresso_session()) {
325
-            // or just start a new one
326
-            $this->_create_espresso_session();
327
-        }
328
-    }
329
-
330
-
331
-    /**
332
-     * @return bool
333
-     */
334
-    public function expired()
335
-    {
336
-        return $this->_expired;
337
-    }
338
-
339
-
340
-    /**
341
-     * @return void
342
-     */
343
-    public function reset_expired()
344
-    {
345
-        $this->_expired = false;
346
-    }
347
-
348
-
349
-    /**
350
-     * @return int
351
-     */
352
-    public function expiration()
353
-    {
354
-        return $this->_expiration;
355
-    }
356
-
357
-
358
-    /**
359
-     * @return int
360
-     */
361
-    public function extension()
362
-    {
363
-        return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
364
-    }
365
-
366
-
367
-    /**
368
-     * @param int $time number of seconds to add to session expiration
369
-     */
370
-    public function extend_expiration($time = 0)
371
-    {
372
-        $time = $time ? $time : $this->extension();
373
-        $this->_expiration += absint($time);
374
-    }
375
-
376
-
377
-    /**
378
-     * @return int
379
-     */
380
-    public function lifespan()
381
-    {
382
-        return $this->session_lifespan->inSeconds();
383
-    }
384
-
385
-
386
-    /**
387
-     * Marks whether the session data has been updated or not.
388
-     * Valid options are:
389
-     *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
390
-     *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
391
-     * default value is EE_Session::SAVE_STATE_DIRTY
392
-     *
393
-     * @param string $save_state
394
-     */
395
-    public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY)
396
-    {
397
-        $valid_save_states = [
398
-            EE_Session::SAVE_STATE_CLEAN,
399
-            EE_Session::SAVE_STATE_DIRTY,
400
-        ];
401
-        if (! in_array($save_state, $valid_save_states, true)) {
402
-            $save_state = EE_Session::SAVE_STATE_DIRTY;
403
-        }
404
-        $this->save_state = $save_state;
405
-    }
406
-
407
-
408
-
409
-    /**
410
-     * This just sets some defaults for the _session data property
411
-     *
412
-     * @return void
413
-     */
414
-    private function _set_defaults()
415
-    {
416
-        // set some defaults
417
-        foreach ($this->_default_session_vars as $key => $default_var) {
418
-            if (is_array($default_var)) {
419
-                $this->_session_data[ $key ] = array();
420
-            } else {
421
-                $this->_session_data[ $key ] = '';
422
-            }
423
-        }
424
-    }
425
-
426
-
427
-    /**
428
-     * @retrieve  session data
429
-     * @return    string
430
-     */
431
-    public function id()
432
-    {
433
-        return $this->_sid;
434
-    }
435
-
436
-
437
-    /**
438
-     * @param \EE_Cart $cart
439
-     * @return bool
440
-     */
441
-    public function set_cart(EE_Cart $cart)
442
-    {
443
-        $this->_session_data['cart'] = $cart;
444
-        $this->setSaveState();
445
-        return true;
446
-    }
447
-
448
-
449
-    /**
450
-     * reset_cart
451
-     */
452
-    public function reset_cart()
453
-    {
454
-        do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
455
-        $this->_session_data['cart'] = null;
456
-        $this->setSaveState();
457
-    }
458
-
459
-
460
-    /**
461
-     * @return \EE_Cart
462
-     */
463
-    public function cart()
464
-    {
465
-        return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
466
-            ? $this->_session_data['cart']
467
-            : null;
468
-    }
469
-
470
-
471
-    /**
472
-     * @param \EE_Checkout $checkout
473
-     * @return bool
474
-     */
475
-    public function set_checkout(EE_Checkout $checkout)
476
-    {
477
-        $this->_session_data['checkout'] = $checkout;
478
-        $this->setSaveState();
479
-        return true;
480
-    }
481
-
482
-
483
-    /**
484
-     * reset_checkout
485
-     */
486
-    public function reset_checkout()
487
-    {
488
-        do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
489
-        $this->_session_data['checkout'] = null;
490
-        $this->setSaveState();
491
-    }
492
-
493
-
494
-    /**
495
-     * @return \EE_Checkout
496
-     */
497
-    public function checkout()
498
-    {
499
-        return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
500
-            ? $this->_session_data['checkout']
501
-            : null;
502
-    }
503
-
504
-
505
-    /**
506
-     * @param \EE_Transaction $transaction
507
-     * @return bool
508
-     * @throws EE_Error
509
-     */
510
-    public function set_transaction(EE_Transaction $transaction)
511
-    {
512
-        // first remove the session from the transaction before we save the transaction in the session
513
-        $transaction->set_txn_session_data(null);
514
-        $this->_session_data['transaction'] = $transaction;
515
-        $this->setSaveState();
516
-        return true;
517
-    }
518
-
519
-
520
-    /**
521
-     * reset_transaction
522
-     */
523
-    public function reset_transaction()
524
-    {
525
-        do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
526
-        $this->_session_data['transaction'] = null;
527
-        $this->setSaveState();
528
-    }
529
-
530
-
531
-    /**
532
-     * @return \EE_Transaction
533
-     */
534
-    public function transaction()
535
-    {
536
-        return isset($this->_session_data['transaction'])
537
-               && $this->_session_data['transaction'] instanceof EE_Transaction
538
-            ? $this->_session_data['transaction']
539
-            : null;
540
-    }
541
-
542
-
543
-    /**
544
-     * retrieve session data
545
-     *
546
-     * @param null $key
547
-     * @param bool $reset_cache
548
-     * @return array|EE_Cart|EE_Checkout|EE_Transaction
549
-     */
550
-    public function get_session_data($key = null, $reset_cache = false)
551
-    {
552
-        if ($reset_cache) {
553
-            $this->reset_cart();
554
-            $this->reset_checkout();
555
-            $this->reset_transaction();
556
-        }
557
-        if (! empty($key)) {
558
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
559
-        }
560
-        return $this->_session_data;
561
-    }
562
-
563
-
564
-    /**
565
-     * Returns TRUE on success, FALSE on fail
566
-     *
567
-     * @param array $data
568
-     * @return bool
569
-     */
570
-    public function set_session_data($data)
571
-    {
572
-        // nothing ??? bad data ??? go home!
573
-        if (empty($data) || ! is_array($data)) {
574
-            EE_Error::add_error(
575
-                esc_html__(
576
-                    'No session data or invalid session data was provided.',
577
-                    'event_espresso'
578
-                ),
579
-                __FILE__,
580
-                __FUNCTION__,
581
-                __LINE__
582
-            );
583
-            return false;
584
-        }
585
-        foreach ($data as $key => $value) {
586
-            if (isset($this->_default_session_vars[ $key ])) {
587
-                EE_Error::add_error(
588
-                    sprintf(
589
-                        esc_html__(
590
-                            'Sorry! %s is a default session datum and can not be reset.',
591
-                            'event_espresso'
592
-                        ),
593
-                        $key
594
-                    ),
595
-                    __FILE__,
596
-                    __FUNCTION__,
597
-                    __LINE__
598
-                );
599
-                return false;
600
-            }
601
-            $this->_session_data[ $key ] = $value;
602
-            $this->setSaveState();
603
-        }
604
-        return true;
605
-    }
606
-
607
-
608
-    /**
609
-     * @initiate session
610
-     * @return bool TRUE on success, FALSE on fail
611
-     * @throws EE_Error
612
-     * @throws InvalidArgumentException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     * @throws InvalidSessionDataException
616
-     * @throws RuntimeException
617
-     * @throws ReflectionException
618
-     */
619
-    private function _espresso_session()
620
-    {
621
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
622
-        $this->session_start_handler->startSession();
623
-        $this->status = EE_Session::STATUS_OPEN;
624
-        // get our modified session ID
625
-        $this->_sid = $this->_generate_session_id();
626
-        // and the visitors IP
627
-        $this->_ip_address = $this->request->ipAddress();
628
-        // set the "user agent"
629
-        $this->_user_agent = $this->request->userAgent();
630
-        // now let's retrieve what's in the db
631
-        $session_data = $this->_retrieve_session_data();
632
-        if (! empty($session_data)) {
633
-            // get the current time in UTC
634
-            $this->_time = $this->_time !== null ? $this->_time : time();
635
-            // and reset the session expiration
636
-            $this->_expiration = isset($session_data['expiration'])
637
-                ? $session_data['expiration']
638
-                : $this->_time + $this->session_lifespan->inSeconds();
639
-        } else {
640
-            // set initial site access time and the session expiration
641
-            $this->_set_init_access_and_expiration();
642
-            // set referer
643
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
644
-                $this->request->getServerParam('HTTP_REFERER')
645
-            );
646
-            // no previous session = go back and create one (on top of the data above)
647
-            return false;
648
-        }
649
-        // now the user agent
650
-        if ($session_data['user_agent'] !== $this->_user_agent) {
651
-            return false;
652
-        }
653
-        // wait a minute... how old are you?
654
-        if ($this->_time > $this->_expiration) {
655
-            // yer too old fer me!
656
-            $this->_expired = true;
657
-            // wipe out everything that isn't a default session datum
658
-            $this->clear_session(__CLASS__, __FUNCTION__);
659
-        }
660
-        // make event espresso session data available to plugin
661
-        $this->_session_data = array_merge($this->_session_data, $session_data);
662
-        return true;
663
-    }
664
-
665
-
666
-    /**
667
-     * _get_session_data
668
-     * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
669
-     * databases
670
-     *
671
-     * @return array
672
-     * @throws EE_Error
673
-     * @throws InvalidArgumentException
674
-     * @throws InvalidSessionDataException
675
-     * @throws InvalidDataTypeException
676
-     * @throws InvalidInterfaceException
677
-     * @throws RuntimeException
678
-     */
679
-    protected function _retrieve_session_data()
680
-    {
681
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
682
-        try {
683
-            // we're using WP's Transient API to store session data using the PHP session ID as the option name
684
-            $session_data = $this->cache_storage->get($ssn_key, false);
685
-            if (empty($session_data)) {
686
-                return array();
687
-            }
688
-            if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
689
-                $hash_check = $this->cache_storage->get(
690
-                    EE_Session::hash_check_prefix . $this->_sid,
691
-                    false
692
-                );
693
-                if ($hash_check && $hash_check !== md5($session_data)) {
694
-                    EE_Error::add_error(
695
-                        sprintf(
696
-                            esc_html__(
697
-                                'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
698
-                                'event_espresso'
699
-                            ),
700
-                            EE_Session::session_id_prefix . $this->_sid
701
-                        ),
702
-                        __FILE__,
703
-                        __FUNCTION__,
704
-                        __LINE__
705
-                    );
706
-                }
707
-            }
708
-        } catch (Exception $e) {
709
-            // let's just eat that error for now and attempt to correct any corrupted data
710
-            global $wpdb;
711
-            $row = $wpdb->get_row(
712
-                $wpdb->prepare(
713
-                    "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
714
-                    '_transient_' . $ssn_key
715
-                )
716
-            );
717
-            $session_data = is_object($row) ? $row->option_value : null;
718
-            if ($session_data) {
719
-                $session_data = preg_replace_callback(
720
-                    '!s:(d+):"(.*?)";!',
721
-                    function ($match) {
722
-                        return $match[1] === strlen($match[2])
723
-                            ? $match[0]
724
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
725
-                    },
726
-                    $session_data
727
-                );
728
-            }
729
-            $session_data = maybe_unserialize($session_data);
730
-        }
731
-        // in case the data is encoded... try to decode it
732
-        $session_data = $this->encryption instanceof EE_Encryption
733
-            ? $this->encryption->base64_string_decode($session_data)
734
-            : $session_data;
735
-        if (! is_array($session_data)) {
736
-            try {
737
-                $session_data = maybe_unserialize($session_data);
738
-            } catch (Exception $e) {
739
-                $msg = esc_html__(
740
-                    'An error occurred while attempting to unserialize the session data.',
741
-                    'event_espresso'
742
-                );
743
-                $msg .= WP_DEBUG
744
-                    ? '<br><pre>'
745
-                      . print_r($session_data, true)
746
-                      . '</pre><br>'
747
-                      . $this->find_serialize_error($session_data)
748
-                    : '';
749
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
750
-                throw new InvalidSessionDataException($msg, 0, $e);
751
-            }
752
-        }
753
-        // just a check to make sure the session array is indeed an array
754
-        if (! is_array($session_data)) {
755
-            // no?!?! then something is wrong
756
-            $msg = esc_html__(
757
-                'The session data is missing, invalid, or corrupted.',
758
-                'event_espresso'
759
-            );
760
-            $msg .= WP_DEBUG
761
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
762
-                : '';
763
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
764
-            throw new InvalidSessionDataException($msg);
765
-        }
766
-        if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
767
-            $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
768
-                $session_data['transaction']
769
-            );
770
-        }
771
-        return $session_data;
772
-    }
773
-
774
-
775
-    /**
776
-     * _generate_session_id
777
-     * Retrieves the PHP session id either directly from the PHP session,
778
-     * or from the request array if it was passed in from an AJAX request.
779
-     * The session id is then salted and hashed (mmm sounds tasty)
780
-     * so that it can be safely used as a request param
781
-     *
782
-     * @return string
783
-     */
784
-    protected function _generate_session_id()
785
-    {
786
-        // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
787
-        $session_id = $this->request->requestParamIsSet('EESID')
788
-            ? $this->request->getRequestParam('EESID')
789
-            : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
790
-        return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
791
-    }
792
-
793
-
794
-    /**
795
-     * _get_sid_salt
796
-     *
797
-     * @return string
798
-     */
799
-    protected function _get_sid_salt()
800
-    {
801
-        // was session id salt already saved to db ?
802
-        if (empty($this->_sid_salt)) {
803
-            // no?  then maybe use WP defined constant
804
-            if (defined('AUTH_SALT')) {
805
-                $this->_sid_salt = AUTH_SALT;
806
-            }
807
-            // if salt doesn't exist or is too short
808
-            if (strlen($this->_sid_salt) < 32) {
809
-                // create a new one
810
-                $this->_sid_salt = wp_generate_password(64);
811
-            }
812
-            // and save it as a permanent session setting
813
-            $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
814
-        }
815
-        return $this->_sid_salt;
816
-    }
817
-
818
-
819
-    /**
820
-     * _set_init_access_and_expiration
821
-     *
822
-     * @return void
823
-     */
824
-    protected function _set_init_access_and_expiration()
825
-    {
826
-        $this->_time = time();
827
-        $this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
828
-        // set initial site access time
829
-        $this->_session_data['init_access'] = $this->_time;
830
-        // and the session expiration
831
-        $this->_session_data['expiration'] = $this->_expiration;
832
-    }
833
-
834
-
835
-    /**
836
-     * @update session data  prior to saving to the db
837
-     * @param bool $new_session
838
-     * @return bool TRUE on success, FALSE on fail
839
-     * @throws EE_Error
840
-     * @throws InvalidArgumentException
841
-     * @throws InvalidDataTypeException
842
-     * @throws InvalidInterfaceException
843
-     * @throws ReflectionException
844
-     */
845
-    public function update($new_session = false)
846
-    {
847
-        $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id'])
848
-            ? $this->_session_data
849
-            : array();
850
-        if (empty($this->_session_data)) {
851
-            $this->_set_defaults();
852
-        }
853
-        $session_data = array();
854
-        foreach ($this->_session_data as $key => $value) {
855
-            switch ($key) {
856
-                case 'id':
857
-                    // session ID
858
-                    $session_data['id'] = $this->_sid;
859
-                    break;
860
-                case 'ip_address':
861
-                    // visitor ip address
862
-                    $session_data['ip_address'] = $this->request->ipAddress();
863
-                    break;
864
-                case 'user_agent':
865
-                    // visitor user_agent
866
-                    $session_data['user_agent'] = $this->_user_agent;
867
-                    break;
868
-                case 'init_access':
869
-                    $session_data['init_access'] = absint($value);
870
-                    break;
871
-                case 'last_access':
872
-                    // current access time
873
-                    $session_data['last_access'] = $this->_time;
874
-                    break;
875
-                case 'expiration':
876
-                    // when the session expires
877
-                    $session_data['expiration'] = ! empty($this->_expiration)
878
-                        ? $this->_expiration
879
-                        : $session_data['init_access'] + $this->session_lifespan->inSeconds();
880
-                    break;
881
-                case 'user_id':
882
-                    // current user if logged in
883
-                    $session_data['user_id'] = $this->_wp_user_id();
884
-                    break;
885
-                case 'pages_visited':
886
-                    $page_visit = $this->_get_page_visit();
887
-                    if ($page_visit) {
888
-                        // set pages visited where the first will be the http referrer
889
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
890
-                        // we'll only save the last 10 page visits.
891
-                        $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
892
-                    }
893
-                    break;
894
-                default:
895
-                    // carry any other data over
896
-                    $session_data[ $key ] = $this->_session_data[ $key ];
897
-            }
898
-        }
899
-        $this->_session_data = $session_data;
900
-        // creating a new session does not require saving to the db just yet
901
-        if (! $new_session) {
902
-            // ready? let's save
903
-            if ($this->_save_session_to_db()) {
904
-                return true;
905
-            }
906
-            return false;
907
-        }
908
-        // meh, why not?
909
-        return true;
910
-    }
911
-
912
-
913
-    /**
914
-     * @create session data array
915
-     * @throws EE_Error
916
-     * @throws InvalidArgumentException
917
-     * @throws InvalidDataTypeException
918
-     * @throws InvalidInterfaceException
919
-     * @throws ReflectionException
920
-     */
921
-    private function _create_espresso_session()
922
-    {
923
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
924
-        // use the update function for now with $new_session arg set to TRUE
925
-        $this->update(true);
926
-    }
927
-
928
-    /**
929
-     * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
930
-     * too). This is used when determining if we want to save the session or not.
931
-     * @since 4.9.67.p
932
-     * @return bool
933
-     */
934
-    private function sessionHasStuffWorthSaving()
935
-    {
936
-        return $this->save_state === EE_Session::SAVE_STATE_DIRTY
937
-               // we may want to eventually remove the following
938
-               // on the assumption that the above check is enough
939
-               || $this->cart() instanceof EE_Cart
940
-               || (
941
-                   isset($this->_session_data['ee_notices'])
942
-                   && (
943
-                       ! empty($this->_session_data['ee_notices']['attention'])
944
-                       || ! empty($this->_session_data['ee_notices']['errors'])
945
-                       || ! empty($this->_session_data['ee_notices']['success'])
946
-                   )
947
-               );
948
-    }
949
-
950
-
951
-    /**
952
-     * _save_session_to_db
953
-     *
954
-     * @param bool $clear_session
955
-     * @return bool
956
-     * @throws EE_Error
957
-     * @throws InvalidArgumentException
958
-     * @throws InvalidDataTypeException
959
-     * @throws InvalidInterfaceException
960
-     * @throws ReflectionException
961
-     */
962
-    private function _save_session_to_db($clear_session = false)
963
-    {
964
-        // don't save sessions for crawlers
965
-        // and unless we're deleting the session data, don't save anything if there isn't a cart
966
-        if (
967
-            $this->request->isBot()
968
-            || (
969
-                ! $clear_session
970
-                && ! $this->sessionHasStuffWorthSaving()
971
-                && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
972
-            )
973
-        ) {
974
-            return false;
975
-        }
976
-        $transaction = $this->transaction();
977
-        if ($transaction instanceof EE_Transaction) {
978
-            if (! $transaction->ID()) {
979
-                $transaction->save();
980
-            }
981
-            $this->_session_data['transaction'] = $transaction->ID();
982
-        }
983
-        // then serialize all of our session data
984
-        $session_data = serialize($this->_session_data);
985
-        // do we need to also encode it to avoid corrupted data when saved to the db?
986
-        $session_data = $this->_use_encryption
987
-            ? $this->encryption->base64_string_encode($session_data)
988
-            : $session_data;
989
-        // maybe save hash check
990
-        if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
991
-            $this->cache_storage->add(
992
-                EE_Session::hash_check_prefix . $this->_sid,
993
-                md5($session_data),
994
-                $this->session_lifespan->inSeconds()
995
-            );
996
-        }
997
-        // we're using the Transient API for storing session data,
998
-        $saved = $this->cache_storage->add(
999
-            EE_Session::session_id_prefix . $this->_sid,
1000
-            $session_data,
1001
-            $this->session_lifespan->inSeconds()
1002
-        );
1003
-        $this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
1004
-        return $saved;
1005
-    }
1006
-
1007
-
1008
-    /**
1009
-     * @get    the full page request the visitor is accessing
1010
-     * @return string
1011
-     */
1012
-    public function _get_page_visit()
1013
-    {
1014
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1015
-        // check for request url
1016
-        if ($this->request->serverParamIsSet('REQUEST_URI')) {
1017
-            $page_id = '?';
1018
-            $e_reg = '';
1019
-            $request_uri = $this->request->getServerParam('REQUEST_URI');
1020
-            $ru_bits = explode('?', $request_uri);
1021
-            $request_uri = $ru_bits[0];
1022
-            $http_host = $this->request->getServerParam('HTTP_HOST');
1023
-            // check for page_id in SERVER REQUEST
1024
-            if ($this->request->requestParamIsSet('page_id')) {
1025
-                // rebuild $e_reg without any of the extra parameters
1026
-                $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1027
-            }
1028
-            // check for $e_reg in SERVER REQUEST
1029
-            if ($this->request->requestParamIsSet('ee')) {
1030
-                // rebuild $e_reg without any of the extra parameters
1031
-                $e_reg = 'ee=' . $this->request->getRequestParam('ee');
1032
-            }
1033
-            $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1034
-        }
1035
-        return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * @the    current wp user id
1041
-     * @return int
1042
-     */
1043
-    public function _wp_user_id()
1044
-    {
1045
-        // if I need to explain the following lines of code, then you shouldn't be looking at this!
1046
-        $this->_wp_user_id = get_current_user_id();
1047
-        return $this->_wp_user_id;
1048
-    }
1049
-
1050
-
1051
-    /**
1052
-     * Clear EE_Session data
1053
-     *
1054
-     * @param string $class
1055
-     * @param string $function
1056
-     * @return void
1057
-     * @throws EE_Error
1058
-     * @throws InvalidArgumentException
1059
-     * @throws InvalidDataTypeException
1060
-     * @throws InvalidInterfaceException
1061
-     * @throws ReflectionException
1062
-     */
1063
-    public function clear_session($class = '', $function = '')
1064
-    {
26
+	const session_id_prefix = 'ee_ssn_';
27
+
28
+	const hash_check_prefix = 'ee_shc_';
29
+
30
+	const OPTION_NAME_SETTINGS = 'ee_session_settings';
31
+
32
+	const STATUS_CLOSED = 0;
33
+
34
+	const STATUS_OPEN = 1;
35
+
36
+	const SAVE_STATE_CLEAN = 'clean';
37
+	const SAVE_STATE_DIRTY = 'dirty';
38
+
39
+
40
+	/**
41
+	 * instance of the EE_Session object
42
+	 *
43
+	 * @var EE_Session
44
+	 */
45
+	private static $_instance;
46
+
47
+	/**
48
+	 * @var CacheStorageInterface $cache_storage
49
+	 */
50
+	protected $cache_storage;
51
+
52
+	/**
53
+	 * @var EE_Encryption $encryption
54
+	 */
55
+	protected $encryption;
56
+
57
+	/**
58
+	 * @var SessionStartHandler $session_start_handler
59
+	 */
60
+	protected $session_start_handler;
61
+
62
+	/**
63
+	 * the session id
64
+	 *
65
+	 * @var string
66
+	 */
67
+	private $_sid;
68
+
69
+	/**
70
+	 * session id salt
71
+	 *
72
+	 * @var string
73
+	 */
74
+	private $_sid_salt;
75
+
76
+	/**
77
+	 * session data
78
+	 *
79
+	 * @var array
80
+	 */
81
+	private $_session_data = array();
82
+
83
+	/**
84
+	 * how long an EE session lasts
85
+	 * default session lifespan of 1 hour (for not so instant IPNs)
86
+	 *
87
+	 * @var SessionLifespan $session_lifespan
88
+	 */
89
+	private $session_lifespan;
90
+
91
+	/**
92
+	 * session expiration time as Unix timestamp in GMT
93
+	 *
94
+	 * @var int
95
+	 */
96
+	private $_expiration;
97
+
98
+	/**
99
+	 * whether or not session has expired at some point
100
+	 *
101
+	 * @var boolean
102
+	 */
103
+	private $_expired = false;
104
+
105
+	/**
106
+	 * current time as Unix timestamp in GMT
107
+	 *
108
+	 * @var int
109
+	 */
110
+	private $_time;
111
+
112
+	/**
113
+	 * whether to encrypt session data
114
+	 *
115
+	 * @var bool
116
+	 */
117
+	private $_use_encryption;
118
+
119
+	/**
120
+	 * well... according to the server...
121
+	 *
122
+	 * @var null
123
+	 */
124
+	private $_user_agent;
125
+
126
+	/**
127
+	 * do you really trust the server ?
128
+	 *
129
+	 * @var null
130
+	 */
131
+	private $_ip_address;
132
+
133
+	/**
134
+	 * current WP user_id
135
+	 *
136
+	 * @var null
137
+	 */
138
+	private $_wp_user_id;
139
+
140
+	/**
141
+	 * array for defining default session vars
142
+	 *
143
+	 * @var array
144
+	 */
145
+	private $_default_session_vars = array(
146
+		'id'            => null,
147
+		'user_id'       => null,
148
+		'ip_address'    => null,
149
+		'user_agent'    => null,
150
+		'init_access'   => null,
151
+		'last_access'   => null,
152
+		'expiration'    => null,
153
+		'pages_visited' => array(),
154
+	);
155
+
156
+	/**
157
+	 * timestamp for when last garbage collection cycle was performed
158
+	 *
159
+	 * @var int $_last_gc
160
+	 */
161
+	private $_last_gc;
162
+
163
+	/**
164
+	 * @var RequestInterface $request
165
+	 */
166
+	protected $request;
167
+
168
+	/**
169
+	 * whether session is active or not
170
+	 *
171
+	 * @var int $status
172
+	 */
173
+	private $status = EE_Session::STATUS_CLOSED;
174
+
175
+	/**
176
+	 * whether session data has changed therefore requiring a session save
177
+	 *
178
+	 * @var string $save_state
179
+	 */
180
+	private $save_state = EE_Session::SAVE_STATE_CLEAN;
181
+
182
+
183
+	/**
184
+	 * @singleton method used to instantiate class object
185
+	 * @param CacheStorageInterface $cache_storage
186
+	 * @param SessionLifespan|null  $lifespan
187
+	 * @param RequestInterface      $request
188
+	 * @param SessionStartHandler   $session_start_handler
189
+	 * @param EE_Encryption         $encryption
190
+	 * @return EE_Session
191
+	 * @throws InvalidArgumentException
192
+	 * @throws InvalidDataTypeException
193
+	 * @throws InvalidInterfaceException
194
+	 */
195
+	public static function instance(
196
+		CacheStorageInterface $cache_storage = null,
197
+		SessionLifespan $lifespan = null,
198
+		RequestInterface $request = null,
199
+		SessionStartHandler $session_start_handler = null,
200
+		EE_Encryption $encryption = null
201
+	) {
202
+		// check if class object is instantiated
203
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
204
+		// add_filter( 'FHEE_load_EE_Session', '__return_false' );
205
+		if (
206
+			! self::$_instance instanceof EE_Session
207
+			&& $cache_storage instanceof CacheStorageInterface
208
+			&& $lifespan instanceof SessionLifespan
209
+			&& $request instanceof RequestInterface
210
+			&& $session_start_handler instanceof SessionStartHandler
211
+			&& apply_filters('FHEE_load_EE_Session', true)
212
+		) {
213
+			self::$_instance = new self(
214
+				$cache_storage,
215
+				$lifespan,
216
+				$request,
217
+				$session_start_handler,
218
+				$encryption
219
+			);
220
+		}
221
+		return self::$_instance;
222
+	}
223
+
224
+
225
+	/**
226
+	 * protected constructor to prevent direct creation
227
+	 *
228
+	 * @param CacheStorageInterface $cache_storage
229
+	 * @param SessionLifespan       $lifespan
230
+	 * @param RequestInterface      $request
231
+	 * @param SessionStartHandler   $session_start_handler
232
+	 * @param EE_Encryption         $encryption
233
+	 * @throws InvalidArgumentException
234
+	 * @throws InvalidDataTypeException
235
+	 * @throws InvalidInterfaceException
236
+	 */
237
+	protected function __construct(
238
+		CacheStorageInterface $cache_storage,
239
+		SessionLifespan $lifespan,
240
+		RequestInterface $request,
241
+		SessionStartHandler $session_start_handler,
242
+		EE_Encryption $encryption = null
243
+	) {
244
+		// session loading is turned ON by default,
245
+		// but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246
+		// (which currently fires on the init hook at priority 9),
247
+		// can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
+		if (! apply_filters('FHEE_load_EE_Session', true)) {
249
+			return;
250
+		}
251
+		$this->session_start_handler = $session_start_handler;
252
+		$this->session_lifespan = $lifespan;
253
+		$this->request = $request;
254
+		if (! defined('ESPRESSO_SESSION')) {
255
+			define('ESPRESSO_SESSION', true);
256
+		}
257
+		// retrieve session options from db
258
+		$session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
+		if (! empty($session_settings)) {
260
+			// cycle though existing session options
261
+			foreach ($session_settings as $var_name => $session_setting) {
262
+				// set values for class properties
263
+				$var_name = '_' . $var_name;
264
+				$this->{$var_name} = $session_setting;
265
+			}
266
+		}
267
+		$this->cache_storage = $cache_storage;
268
+		// are we using encryption?
269
+		$this->_use_encryption = $encryption instanceof EE_Encryption
270
+								 && EE_Registry::instance()->CFG->admin->encode_session_data();
271
+		// encrypt data via: $this->encryption->encrypt();
272
+		$this->encryption = $encryption;
273
+		// filter hook allows outside functions/classes/plugins to change default empty cart
274
+		$extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
275
+		array_merge($this->_default_session_vars, $extra_default_session_vars);
276
+		// apply default session vars
277
+		$this->_set_defaults();
278
+		add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
279
+		// check request for 'clear_session' param
280
+		add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
281
+		// once everything is all said and done,
282
+		add_action('shutdown', array($this, 'update'), 100);
283
+		add_action('shutdown', array($this, 'garbageCollection'), 1000);
284
+		$this->configure_garbage_collection_filters();
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return bool
290
+	 * @throws InvalidArgumentException
291
+	 * @throws InvalidDataTypeException
292
+	 * @throws InvalidInterfaceException
293
+	 */
294
+	public static function isLoadedAndActive()
295
+	{
296
+		return did_action('AHEE__EE_System__core_loaded_and_ready')
297
+			   && EE_Session::instance() instanceof EE_Session
298
+			   && EE_Session::instance()->isActive();
299
+	}
300
+
301
+
302
+	/**
303
+	 * @return bool
304
+	 */
305
+	public function isActive()
306
+	{
307
+		return $this->status === EE_Session::STATUS_OPEN;
308
+	}
309
+
310
+
311
+	/**
312
+	 * @return void
313
+	 * @throws EE_Error
314
+	 * @throws InvalidArgumentException
315
+	 * @throws InvalidDataTypeException
316
+	 * @throws InvalidInterfaceException
317
+	 * @throws InvalidSessionDataException
318
+	 * @throws RuntimeException
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function open_session()
322
+	{
323
+		// Check for an existing session and retrieve it from the database, unless the system is in maintenance level 2.
324
+		if (EE_Maintenance_Mode::instance()->models_can_query() && ! $this->_espresso_session()) {
325
+			// or just start a new one
326
+			$this->_create_espresso_session();
327
+		}
328
+	}
329
+
330
+
331
+	/**
332
+	 * @return bool
333
+	 */
334
+	public function expired()
335
+	{
336
+		return $this->_expired;
337
+	}
338
+
339
+
340
+	/**
341
+	 * @return void
342
+	 */
343
+	public function reset_expired()
344
+	{
345
+		$this->_expired = false;
346
+	}
347
+
348
+
349
+	/**
350
+	 * @return int
351
+	 */
352
+	public function expiration()
353
+	{
354
+		return $this->_expiration;
355
+	}
356
+
357
+
358
+	/**
359
+	 * @return int
360
+	 */
361
+	public function extension()
362
+	{
363
+		return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
364
+	}
365
+
366
+
367
+	/**
368
+	 * @param int $time number of seconds to add to session expiration
369
+	 */
370
+	public function extend_expiration($time = 0)
371
+	{
372
+		$time = $time ? $time : $this->extension();
373
+		$this->_expiration += absint($time);
374
+	}
375
+
376
+
377
+	/**
378
+	 * @return int
379
+	 */
380
+	public function lifespan()
381
+	{
382
+		return $this->session_lifespan->inSeconds();
383
+	}
384
+
385
+
386
+	/**
387
+	 * Marks whether the session data has been updated or not.
388
+	 * Valid options are:
389
+	 *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
390
+	 *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
391
+	 * default value is EE_Session::SAVE_STATE_DIRTY
392
+	 *
393
+	 * @param string $save_state
394
+	 */
395
+	public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY)
396
+	{
397
+		$valid_save_states = [
398
+			EE_Session::SAVE_STATE_CLEAN,
399
+			EE_Session::SAVE_STATE_DIRTY,
400
+		];
401
+		if (! in_array($save_state, $valid_save_states, true)) {
402
+			$save_state = EE_Session::SAVE_STATE_DIRTY;
403
+		}
404
+		$this->save_state = $save_state;
405
+	}
406
+
407
+
408
+
409
+	/**
410
+	 * This just sets some defaults for the _session data property
411
+	 *
412
+	 * @return void
413
+	 */
414
+	private function _set_defaults()
415
+	{
416
+		// set some defaults
417
+		foreach ($this->_default_session_vars as $key => $default_var) {
418
+			if (is_array($default_var)) {
419
+				$this->_session_data[ $key ] = array();
420
+			} else {
421
+				$this->_session_data[ $key ] = '';
422
+			}
423
+		}
424
+	}
425
+
426
+
427
+	/**
428
+	 * @retrieve  session data
429
+	 * @return    string
430
+	 */
431
+	public function id()
432
+	{
433
+		return $this->_sid;
434
+	}
435
+
436
+
437
+	/**
438
+	 * @param \EE_Cart $cart
439
+	 * @return bool
440
+	 */
441
+	public function set_cart(EE_Cart $cart)
442
+	{
443
+		$this->_session_data['cart'] = $cart;
444
+		$this->setSaveState();
445
+		return true;
446
+	}
447
+
448
+
449
+	/**
450
+	 * reset_cart
451
+	 */
452
+	public function reset_cart()
453
+	{
454
+		do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
455
+		$this->_session_data['cart'] = null;
456
+		$this->setSaveState();
457
+	}
458
+
459
+
460
+	/**
461
+	 * @return \EE_Cart
462
+	 */
463
+	public function cart()
464
+	{
465
+		return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
466
+			? $this->_session_data['cart']
467
+			: null;
468
+	}
469
+
470
+
471
+	/**
472
+	 * @param \EE_Checkout $checkout
473
+	 * @return bool
474
+	 */
475
+	public function set_checkout(EE_Checkout $checkout)
476
+	{
477
+		$this->_session_data['checkout'] = $checkout;
478
+		$this->setSaveState();
479
+		return true;
480
+	}
481
+
482
+
483
+	/**
484
+	 * reset_checkout
485
+	 */
486
+	public function reset_checkout()
487
+	{
488
+		do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
489
+		$this->_session_data['checkout'] = null;
490
+		$this->setSaveState();
491
+	}
492
+
493
+
494
+	/**
495
+	 * @return \EE_Checkout
496
+	 */
497
+	public function checkout()
498
+	{
499
+		return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
500
+			? $this->_session_data['checkout']
501
+			: null;
502
+	}
503
+
504
+
505
+	/**
506
+	 * @param \EE_Transaction $transaction
507
+	 * @return bool
508
+	 * @throws EE_Error
509
+	 */
510
+	public function set_transaction(EE_Transaction $transaction)
511
+	{
512
+		// first remove the session from the transaction before we save the transaction in the session
513
+		$transaction->set_txn_session_data(null);
514
+		$this->_session_data['transaction'] = $transaction;
515
+		$this->setSaveState();
516
+		return true;
517
+	}
518
+
519
+
520
+	/**
521
+	 * reset_transaction
522
+	 */
523
+	public function reset_transaction()
524
+	{
525
+		do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
526
+		$this->_session_data['transaction'] = null;
527
+		$this->setSaveState();
528
+	}
529
+
530
+
531
+	/**
532
+	 * @return \EE_Transaction
533
+	 */
534
+	public function transaction()
535
+	{
536
+		return isset($this->_session_data['transaction'])
537
+			   && $this->_session_data['transaction'] instanceof EE_Transaction
538
+			? $this->_session_data['transaction']
539
+			: null;
540
+	}
541
+
542
+
543
+	/**
544
+	 * retrieve session data
545
+	 *
546
+	 * @param null $key
547
+	 * @param bool $reset_cache
548
+	 * @return array|EE_Cart|EE_Checkout|EE_Transaction
549
+	 */
550
+	public function get_session_data($key = null, $reset_cache = false)
551
+	{
552
+		if ($reset_cache) {
553
+			$this->reset_cart();
554
+			$this->reset_checkout();
555
+			$this->reset_transaction();
556
+		}
557
+		if (! empty($key)) {
558
+			return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
559
+		}
560
+		return $this->_session_data;
561
+	}
562
+
563
+
564
+	/**
565
+	 * Returns TRUE on success, FALSE on fail
566
+	 *
567
+	 * @param array $data
568
+	 * @return bool
569
+	 */
570
+	public function set_session_data($data)
571
+	{
572
+		// nothing ??? bad data ??? go home!
573
+		if (empty($data) || ! is_array($data)) {
574
+			EE_Error::add_error(
575
+				esc_html__(
576
+					'No session data or invalid session data was provided.',
577
+					'event_espresso'
578
+				),
579
+				__FILE__,
580
+				__FUNCTION__,
581
+				__LINE__
582
+			);
583
+			return false;
584
+		}
585
+		foreach ($data as $key => $value) {
586
+			if (isset($this->_default_session_vars[ $key ])) {
587
+				EE_Error::add_error(
588
+					sprintf(
589
+						esc_html__(
590
+							'Sorry! %s is a default session datum and can not be reset.',
591
+							'event_espresso'
592
+						),
593
+						$key
594
+					),
595
+					__FILE__,
596
+					__FUNCTION__,
597
+					__LINE__
598
+				);
599
+				return false;
600
+			}
601
+			$this->_session_data[ $key ] = $value;
602
+			$this->setSaveState();
603
+		}
604
+		return true;
605
+	}
606
+
607
+
608
+	/**
609
+	 * @initiate session
610
+	 * @return bool TRUE on success, FALSE on fail
611
+	 * @throws EE_Error
612
+	 * @throws InvalidArgumentException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 * @throws InvalidSessionDataException
616
+	 * @throws RuntimeException
617
+	 * @throws ReflectionException
618
+	 */
619
+	private function _espresso_session()
620
+	{
621
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
622
+		$this->session_start_handler->startSession();
623
+		$this->status = EE_Session::STATUS_OPEN;
624
+		// get our modified session ID
625
+		$this->_sid = $this->_generate_session_id();
626
+		// and the visitors IP
627
+		$this->_ip_address = $this->request->ipAddress();
628
+		// set the "user agent"
629
+		$this->_user_agent = $this->request->userAgent();
630
+		// now let's retrieve what's in the db
631
+		$session_data = $this->_retrieve_session_data();
632
+		if (! empty($session_data)) {
633
+			// get the current time in UTC
634
+			$this->_time = $this->_time !== null ? $this->_time : time();
635
+			// and reset the session expiration
636
+			$this->_expiration = isset($session_data['expiration'])
637
+				? $session_data['expiration']
638
+				: $this->_time + $this->session_lifespan->inSeconds();
639
+		} else {
640
+			// set initial site access time and the session expiration
641
+			$this->_set_init_access_and_expiration();
642
+			// set referer
643
+			$this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
644
+				$this->request->getServerParam('HTTP_REFERER')
645
+			);
646
+			// no previous session = go back and create one (on top of the data above)
647
+			return false;
648
+		}
649
+		// now the user agent
650
+		if ($session_data['user_agent'] !== $this->_user_agent) {
651
+			return false;
652
+		}
653
+		// wait a minute... how old are you?
654
+		if ($this->_time > $this->_expiration) {
655
+			// yer too old fer me!
656
+			$this->_expired = true;
657
+			// wipe out everything that isn't a default session datum
658
+			$this->clear_session(__CLASS__, __FUNCTION__);
659
+		}
660
+		// make event espresso session data available to plugin
661
+		$this->_session_data = array_merge($this->_session_data, $session_data);
662
+		return true;
663
+	}
664
+
665
+
666
+	/**
667
+	 * _get_session_data
668
+	 * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
669
+	 * databases
670
+	 *
671
+	 * @return array
672
+	 * @throws EE_Error
673
+	 * @throws InvalidArgumentException
674
+	 * @throws InvalidSessionDataException
675
+	 * @throws InvalidDataTypeException
676
+	 * @throws InvalidInterfaceException
677
+	 * @throws RuntimeException
678
+	 */
679
+	protected function _retrieve_session_data()
680
+	{
681
+		$ssn_key = EE_Session::session_id_prefix . $this->_sid;
682
+		try {
683
+			// we're using WP's Transient API to store session data using the PHP session ID as the option name
684
+			$session_data = $this->cache_storage->get($ssn_key, false);
685
+			if (empty($session_data)) {
686
+				return array();
687
+			}
688
+			if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
689
+				$hash_check = $this->cache_storage->get(
690
+					EE_Session::hash_check_prefix . $this->_sid,
691
+					false
692
+				);
693
+				if ($hash_check && $hash_check !== md5($session_data)) {
694
+					EE_Error::add_error(
695
+						sprintf(
696
+							esc_html__(
697
+								'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
698
+								'event_espresso'
699
+							),
700
+							EE_Session::session_id_prefix . $this->_sid
701
+						),
702
+						__FILE__,
703
+						__FUNCTION__,
704
+						__LINE__
705
+					);
706
+				}
707
+			}
708
+		} catch (Exception $e) {
709
+			// let's just eat that error for now and attempt to correct any corrupted data
710
+			global $wpdb;
711
+			$row = $wpdb->get_row(
712
+				$wpdb->prepare(
713
+					"SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
714
+					'_transient_' . $ssn_key
715
+				)
716
+			);
717
+			$session_data = is_object($row) ? $row->option_value : null;
718
+			if ($session_data) {
719
+				$session_data = preg_replace_callback(
720
+					'!s:(d+):"(.*?)";!',
721
+					function ($match) {
722
+						return $match[1] === strlen($match[2])
723
+							? $match[0]
724
+							: 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
725
+					},
726
+					$session_data
727
+				);
728
+			}
729
+			$session_data = maybe_unserialize($session_data);
730
+		}
731
+		// in case the data is encoded... try to decode it
732
+		$session_data = $this->encryption instanceof EE_Encryption
733
+			? $this->encryption->base64_string_decode($session_data)
734
+			: $session_data;
735
+		if (! is_array($session_data)) {
736
+			try {
737
+				$session_data = maybe_unserialize($session_data);
738
+			} catch (Exception $e) {
739
+				$msg = esc_html__(
740
+					'An error occurred while attempting to unserialize the session data.',
741
+					'event_espresso'
742
+				);
743
+				$msg .= WP_DEBUG
744
+					? '<br><pre>'
745
+					  . print_r($session_data, true)
746
+					  . '</pre><br>'
747
+					  . $this->find_serialize_error($session_data)
748
+					: '';
749
+				$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
750
+				throw new InvalidSessionDataException($msg, 0, $e);
751
+			}
752
+		}
753
+		// just a check to make sure the session array is indeed an array
754
+		if (! is_array($session_data)) {
755
+			// no?!?! then something is wrong
756
+			$msg = esc_html__(
757
+				'The session data is missing, invalid, or corrupted.',
758
+				'event_espresso'
759
+			);
760
+			$msg .= WP_DEBUG
761
+				? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
762
+				: '';
763
+			$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
764
+			throw new InvalidSessionDataException($msg);
765
+		}
766
+		if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
767
+			$session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
768
+				$session_data['transaction']
769
+			);
770
+		}
771
+		return $session_data;
772
+	}
773
+
774
+
775
+	/**
776
+	 * _generate_session_id
777
+	 * Retrieves the PHP session id either directly from the PHP session,
778
+	 * or from the request array if it was passed in from an AJAX request.
779
+	 * The session id is then salted and hashed (mmm sounds tasty)
780
+	 * so that it can be safely used as a request param
781
+	 *
782
+	 * @return string
783
+	 */
784
+	protected function _generate_session_id()
785
+	{
786
+		// check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
787
+		$session_id = $this->request->requestParamIsSet('EESID')
788
+			? $this->request->getRequestParam('EESID')
789
+			: md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
790
+		return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
791
+	}
792
+
793
+
794
+	/**
795
+	 * _get_sid_salt
796
+	 *
797
+	 * @return string
798
+	 */
799
+	protected function _get_sid_salt()
800
+	{
801
+		// was session id salt already saved to db ?
802
+		if (empty($this->_sid_salt)) {
803
+			// no?  then maybe use WP defined constant
804
+			if (defined('AUTH_SALT')) {
805
+				$this->_sid_salt = AUTH_SALT;
806
+			}
807
+			// if salt doesn't exist or is too short
808
+			if (strlen($this->_sid_salt) < 32) {
809
+				// create a new one
810
+				$this->_sid_salt = wp_generate_password(64);
811
+			}
812
+			// and save it as a permanent session setting
813
+			$this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
814
+		}
815
+		return $this->_sid_salt;
816
+	}
817
+
818
+
819
+	/**
820
+	 * _set_init_access_and_expiration
821
+	 *
822
+	 * @return void
823
+	 */
824
+	protected function _set_init_access_and_expiration()
825
+	{
826
+		$this->_time = time();
827
+		$this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
828
+		// set initial site access time
829
+		$this->_session_data['init_access'] = $this->_time;
830
+		// and the session expiration
831
+		$this->_session_data['expiration'] = $this->_expiration;
832
+	}
833
+
834
+
835
+	/**
836
+	 * @update session data  prior to saving to the db
837
+	 * @param bool $new_session
838
+	 * @return bool TRUE on success, FALSE on fail
839
+	 * @throws EE_Error
840
+	 * @throws InvalidArgumentException
841
+	 * @throws InvalidDataTypeException
842
+	 * @throws InvalidInterfaceException
843
+	 * @throws ReflectionException
844
+	 */
845
+	public function update($new_session = false)
846
+	{
847
+		$this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id'])
848
+			? $this->_session_data
849
+			: array();
850
+		if (empty($this->_session_data)) {
851
+			$this->_set_defaults();
852
+		}
853
+		$session_data = array();
854
+		foreach ($this->_session_data as $key => $value) {
855
+			switch ($key) {
856
+				case 'id':
857
+					// session ID
858
+					$session_data['id'] = $this->_sid;
859
+					break;
860
+				case 'ip_address':
861
+					// visitor ip address
862
+					$session_data['ip_address'] = $this->request->ipAddress();
863
+					break;
864
+				case 'user_agent':
865
+					// visitor user_agent
866
+					$session_data['user_agent'] = $this->_user_agent;
867
+					break;
868
+				case 'init_access':
869
+					$session_data['init_access'] = absint($value);
870
+					break;
871
+				case 'last_access':
872
+					// current access time
873
+					$session_data['last_access'] = $this->_time;
874
+					break;
875
+				case 'expiration':
876
+					// when the session expires
877
+					$session_data['expiration'] = ! empty($this->_expiration)
878
+						? $this->_expiration
879
+						: $session_data['init_access'] + $this->session_lifespan->inSeconds();
880
+					break;
881
+				case 'user_id':
882
+					// current user if logged in
883
+					$session_data['user_id'] = $this->_wp_user_id();
884
+					break;
885
+				case 'pages_visited':
886
+					$page_visit = $this->_get_page_visit();
887
+					if ($page_visit) {
888
+						// set pages visited where the first will be the http referrer
889
+						$this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
890
+						// we'll only save the last 10 page visits.
891
+						$session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
892
+					}
893
+					break;
894
+				default:
895
+					// carry any other data over
896
+					$session_data[ $key ] = $this->_session_data[ $key ];
897
+			}
898
+		}
899
+		$this->_session_data = $session_data;
900
+		// creating a new session does not require saving to the db just yet
901
+		if (! $new_session) {
902
+			// ready? let's save
903
+			if ($this->_save_session_to_db()) {
904
+				return true;
905
+			}
906
+			return false;
907
+		}
908
+		// meh, why not?
909
+		return true;
910
+	}
911
+
912
+
913
+	/**
914
+	 * @create session data array
915
+	 * @throws EE_Error
916
+	 * @throws InvalidArgumentException
917
+	 * @throws InvalidDataTypeException
918
+	 * @throws InvalidInterfaceException
919
+	 * @throws ReflectionException
920
+	 */
921
+	private function _create_espresso_session()
922
+	{
923
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
924
+		// use the update function for now with $new_session arg set to TRUE
925
+		$this->update(true);
926
+	}
927
+
928
+	/**
929
+	 * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
930
+	 * too). This is used when determining if we want to save the session or not.
931
+	 * @since 4.9.67.p
932
+	 * @return bool
933
+	 */
934
+	private function sessionHasStuffWorthSaving()
935
+	{
936
+		return $this->save_state === EE_Session::SAVE_STATE_DIRTY
937
+			   // we may want to eventually remove the following
938
+			   // on the assumption that the above check is enough
939
+			   || $this->cart() instanceof EE_Cart
940
+			   || (
941
+				   isset($this->_session_data['ee_notices'])
942
+				   && (
943
+					   ! empty($this->_session_data['ee_notices']['attention'])
944
+					   || ! empty($this->_session_data['ee_notices']['errors'])
945
+					   || ! empty($this->_session_data['ee_notices']['success'])
946
+				   )
947
+			   );
948
+	}
949
+
950
+
951
+	/**
952
+	 * _save_session_to_db
953
+	 *
954
+	 * @param bool $clear_session
955
+	 * @return bool
956
+	 * @throws EE_Error
957
+	 * @throws InvalidArgumentException
958
+	 * @throws InvalidDataTypeException
959
+	 * @throws InvalidInterfaceException
960
+	 * @throws ReflectionException
961
+	 */
962
+	private function _save_session_to_db($clear_session = false)
963
+	{
964
+		// don't save sessions for crawlers
965
+		// and unless we're deleting the session data, don't save anything if there isn't a cart
966
+		if (
967
+			$this->request->isBot()
968
+			|| (
969
+				! $clear_session
970
+				&& ! $this->sessionHasStuffWorthSaving()
971
+				&& apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
972
+			)
973
+		) {
974
+			return false;
975
+		}
976
+		$transaction = $this->transaction();
977
+		if ($transaction instanceof EE_Transaction) {
978
+			if (! $transaction->ID()) {
979
+				$transaction->save();
980
+			}
981
+			$this->_session_data['transaction'] = $transaction->ID();
982
+		}
983
+		// then serialize all of our session data
984
+		$session_data = serialize($this->_session_data);
985
+		// do we need to also encode it to avoid corrupted data when saved to the db?
986
+		$session_data = $this->_use_encryption
987
+			? $this->encryption->base64_string_encode($session_data)
988
+			: $session_data;
989
+		// maybe save hash check
990
+		if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
991
+			$this->cache_storage->add(
992
+				EE_Session::hash_check_prefix . $this->_sid,
993
+				md5($session_data),
994
+				$this->session_lifespan->inSeconds()
995
+			);
996
+		}
997
+		// we're using the Transient API for storing session data,
998
+		$saved = $this->cache_storage->add(
999
+			EE_Session::session_id_prefix . $this->_sid,
1000
+			$session_data,
1001
+			$this->session_lifespan->inSeconds()
1002
+		);
1003
+		$this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
1004
+		return $saved;
1005
+	}
1006
+
1007
+
1008
+	/**
1009
+	 * @get    the full page request the visitor is accessing
1010
+	 * @return string
1011
+	 */
1012
+	public function _get_page_visit()
1013
+	{
1014
+		$page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1015
+		// check for request url
1016
+		if ($this->request->serverParamIsSet('REQUEST_URI')) {
1017
+			$page_id = '?';
1018
+			$e_reg = '';
1019
+			$request_uri = $this->request->getServerParam('REQUEST_URI');
1020
+			$ru_bits = explode('?', $request_uri);
1021
+			$request_uri = $ru_bits[0];
1022
+			$http_host = $this->request->getServerParam('HTTP_HOST');
1023
+			// check for page_id in SERVER REQUEST
1024
+			if ($this->request->requestParamIsSet('page_id')) {
1025
+				// rebuild $e_reg without any of the extra parameters
1026
+				$page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1027
+			}
1028
+			// check for $e_reg in SERVER REQUEST
1029
+			if ($this->request->requestParamIsSet('ee')) {
1030
+				// rebuild $e_reg without any of the extra parameters
1031
+				$e_reg = 'ee=' . $this->request->getRequestParam('ee');
1032
+			}
1033
+			$page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1034
+		}
1035
+		return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * @the    current wp user id
1041
+	 * @return int
1042
+	 */
1043
+	public function _wp_user_id()
1044
+	{
1045
+		// if I need to explain the following lines of code, then you shouldn't be looking at this!
1046
+		$this->_wp_user_id = get_current_user_id();
1047
+		return $this->_wp_user_id;
1048
+	}
1049
+
1050
+
1051
+	/**
1052
+	 * Clear EE_Session data
1053
+	 *
1054
+	 * @param string $class
1055
+	 * @param string $function
1056
+	 * @return void
1057
+	 * @throws EE_Error
1058
+	 * @throws InvalidArgumentException
1059
+	 * @throws InvalidDataTypeException
1060
+	 * @throws InvalidInterfaceException
1061
+	 * @throws ReflectionException
1062
+	 */
1063
+	public function clear_session($class = '', $function = '')
1064
+	{
1065 1065
 //         echo '
1066 1066
 // <h3 style="color:#999;line-height:.9em;">
1067 1067
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1068 1068
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1069 1069
 // </h3>';
1070
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1071
-        $this->reset_cart();
1072
-        $this->reset_checkout();
1073
-        $this->reset_transaction();
1074
-        // wipe out everything that isn't a default session datum
1075
-        $this->reset_data(array_keys($this->_session_data));
1076
-        // reset initial site access time and the session expiration
1077
-        $this->_set_init_access_and_expiration();
1078
-        $this->setSaveState();
1079
-        $this->_save_session_to_db(true);
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1085
-     *
1086
-     * @param array|mixed $data_to_reset
1087
-     * @param bool        $show_all_notices
1088
-     * @return bool
1089
-     */
1090
-    public function reset_data($data_to_reset = array(), $show_all_notices = false)
1091
-    {
1092
-        // if $data_to_reset is not in an array, then put it in one
1093
-        if (! is_array($data_to_reset)) {
1094
-            $data_to_reset = array($data_to_reset);
1095
-        }
1096
-        // nothing ??? go home!
1097
-        if (empty($data_to_reset)) {
1098
-            EE_Error::add_error(
1099
-                esc_html__(
1100
-                    'No session data could be reset, because no session var name was provided.',
1101
-                    'event_espresso'
1102
-                ),
1103
-                __FILE__,
1104
-                __FUNCTION__,
1105
-                __LINE__
1106
-            );
1107
-            return false;
1108
-        }
1109
-        $return_value = true;
1110
-        // since $data_to_reset is an array, cycle through the values
1111
-        foreach ($data_to_reset as $reset) {
1112
-            // first check to make sure it is a valid session var
1113
-            if (isset($this->_session_data[ $reset ])) {
1114
-                // then check to make sure it is not a default var
1115
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1116
-                    // remove session var
1117
-                    unset($this->_session_data[ $reset ]);
1118
-                    $this->setSaveState();
1119
-                    if ($show_all_notices) {
1120
-                        EE_Error::add_success(
1121
-                            sprintf(
1122
-                                esc_html__('The session variable %s was removed.', 'event_espresso'),
1123
-                                $reset
1124
-                            ),
1125
-                            __FILE__,
1126
-                            __FUNCTION__,
1127
-                            __LINE__
1128
-                        );
1129
-                    }
1130
-                } else {
1131
-                    // yeeeeeeeeerrrrrrrrrrr OUT !!!!
1132
-                    if ($show_all_notices) {
1133
-                        EE_Error::add_error(
1134
-                            sprintf(
1135
-                                esc_html__(
1136
-                                    'Sorry! %s is a default session datum and can not be reset.',
1137
-                                    'event_espresso'
1138
-                                ),
1139
-                                $reset
1140
-                            ),
1141
-                            __FILE__,
1142
-                            __FUNCTION__,
1143
-                            __LINE__
1144
-                        );
1145
-                    }
1146
-                    $return_value = false;
1147
-                }
1148
-            } elseif ($show_all_notices) {
1149
-                // oops! that session var does not exist!
1150
-                EE_Error::add_error(
1151
-                    sprintf(
1152
-                        esc_html__(
1153
-                            'The session item provided, %s, is invalid or does not exist.',
1154
-                            'event_espresso'
1155
-                        ),
1156
-                        $reset
1157
-                    ),
1158
-                    __FILE__,
1159
-                    __FUNCTION__,
1160
-                    __LINE__
1161
-                );
1162
-                $return_value = false;
1163
-            }
1164
-        } // end of foreach
1165
-        return $return_value;
1166
-    }
1167
-
1168
-
1169
-    /**
1170
-     *   wp_loaded
1171
-     *
1172
-     * @throws EE_Error
1173
-     * @throws InvalidDataTypeException
1174
-     * @throws InvalidInterfaceException
1175
-     * @throws InvalidArgumentException
1176
-     * @throws ReflectionException
1177
-     */
1178
-    public function wp_loaded()
1179
-    {
1180
-        if ($this->request->requestParamIsSet('clear_session')) {
1181
-            $this->clear_session(__CLASS__, __FUNCTION__);
1182
-        }
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * Used to reset the entire object (for tests).
1188
-     *
1189
-     * @since 4.3.0
1190
-     * @throws EE_Error
1191
-     * @throws InvalidDataTypeException
1192
-     * @throws InvalidInterfaceException
1193
-     * @throws InvalidArgumentException
1194
-     * @throws ReflectionException
1195
-     */
1196
-    public function reset_instance()
1197
-    {
1198
-        $this->clear_session();
1199
-        self::$_instance = null;
1200
-    }
1201
-
1202
-
1203
-    public function configure_garbage_collection_filters()
1204
-    {
1205
-        // run old filter we had for controlling session cleanup
1206
-        $expired_session_transient_delete_query_limit = absint(
1207
-            apply_filters(
1208
-                'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1209
-                50
1210
-            )
1211
-        );
1212
-        // is there a value? or one that is different than the default 50 records?
1213
-        if ($expired_session_transient_delete_query_limit === 0) {
1214
-            // hook into TransientCacheStorage in case Session cleanup was turned off
1215
-            add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1216
-        } elseif ($expired_session_transient_delete_query_limit !== 50) {
1217
-            // or use that for the new transient cleanup query limit
1218
-            add_filter(
1219
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1220
-                function () use ($expired_session_transient_delete_query_limit) {
1221
-                    return $expired_session_transient_delete_query_limit;
1222
-                }
1223
-            );
1224
-        }
1225
-    }
1226
-
1227
-
1228
-    /**
1229
-     * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1230
-     * @param $data1
1231
-     * @return string
1232
-     */
1233
-    private function find_serialize_error($data1)
1234
-    {
1235
-        $error = '<pre>';
1236
-        $data2 = preg_replace_callback(
1237
-            '!s:(\d+):"(.*?)";!',
1238
-            function ($match) {
1239
-                return ($match[1] === strlen($match[2]))
1240
-                    ? $match[0]
1241
-                    : 's:'
1242
-                      . strlen($match[2])
1243
-                      . ':"'
1244
-                      . $match[2]
1245
-                      . '";';
1246
-            },
1247
-            $data1
1248
-        );
1249
-        $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1250
-        $error .= $data1 . PHP_EOL;
1251
-        $error .= $data2 . PHP_EOL;
1252
-        for ($i = 0; $i < $max; $i++) {
1253
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1254
-                $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1255
-                $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1256
-                $error .= "\t-> Line Number = $i" . PHP_EOL;
1257
-                $start = ($i - 20);
1258
-                $start = ($start < 0) ? 0 : $start;
1259
-                $length = 40;
1260
-                $point = $max - $i;
1261
-                if ($point < 20) {
1262
-                    $rlength = 1;
1263
-                    $rpoint = -$point;
1264
-                } else {
1265
-                    $rpoint = $length - 20;
1266
-                    $rlength = 1;
1267
-                }
1268
-                $error .= "\t-> Section Data1  = ";
1269
-                $error .= substr_replace(
1270
-                    substr($data1, $start, $length),
1271
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1272
-                    $rpoint,
1273
-                    $rlength
1274
-                );
1275
-                $error .= PHP_EOL;
1276
-                $error .= "\t-> Section Data2  = ";
1277
-                $error .= substr_replace(
1278
-                    substr($data2, $start, $length),
1279
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1280
-                    $rpoint,
1281
-                    $rlength
1282
-                );
1283
-                $error .= PHP_EOL;
1284
-            }
1285
-        }
1286
-        $error .= '</pre>';
1287
-        return $error;
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     * Saves an  array of settings used for configuring aspects of session behaviour
1293
-     *
1294
-     * @param array $updated_settings
1295
-     */
1296
-    private function updateSessionSettings(array $updated_settings = array())
1297
-    {
1298
-        // add existing settings, but only if not included in incoming $updated_settings array
1299
-        $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1300
-        update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * garbage_collection
1306
-     */
1307
-    public function garbageCollection()
1308
-    {
1309
-        // only perform during regular requests if last garbage collection was over an hour ago
1310
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1311
-            $this->_last_gc = time();
1312
-            $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1313
-            /** @type WPDB $wpdb */
1314
-            global $wpdb;
1315
-            // filter the query limit. Set to 0 to turn off garbage collection
1316
-            $expired_session_transient_delete_query_limit = absint(
1317
-                apply_filters(
1318
-                    'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1319
-                    50
1320
-                )
1321
-            );
1322
-            // non-zero LIMIT means take out the trash
1323
-            if ($expired_session_transient_delete_query_limit) {
1324
-                $session_key = str_replace('_', '\_', EE_Session::session_id_prefix);
1325
-                $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1326
-                // since transient expiration timestamps are set in the future, we can compare against NOW
1327
-                // but we only want to pick up any trash that's been around for more than a day
1328
-                $expiration = time() - DAY_IN_SECONDS;
1329
-                $SQL = "
1070
+		do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1071
+		$this->reset_cart();
1072
+		$this->reset_checkout();
1073
+		$this->reset_transaction();
1074
+		// wipe out everything that isn't a default session datum
1075
+		$this->reset_data(array_keys($this->_session_data));
1076
+		// reset initial site access time and the session expiration
1077
+		$this->_set_init_access_and_expiration();
1078
+		$this->setSaveState();
1079
+		$this->_save_session_to_db(true);
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1085
+	 *
1086
+	 * @param array|mixed $data_to_reset
1087
+	 * @param bool        $show_all_notices
1088
+	 * @return bool
1089
+	 */
1090
+	public function reset_data($data_to_reset = array(), $show_all_notices = false)
1091
+	{
1092
+		// if $data_to_reset is not in an array, then put it in one
1093
+		if (! is_array($data_to_reset)) {
1094
+			$data_to_reset = array($data_to_reset);
1095
+		}
1096
+		// nothing ??? go home!
1097
+		if (empty($data_to_reset)) {
1098
+			EE_Error::add_error(
1099
+				esc_html__(
1100
+					'No session data could be reset, because no session var name was provided.',
1101
+					'event_espresso'
1102
+				),
1103
+				__FILE__,
1104
+				__FUNCTION__,
1105
+				__LINE__
1106
+			);
1107
+			return false;
1108
+		}
1109
+		$return_value = true;
1110
+		// since $data_to_reset is an array, cycle through the values
1111
+		foreach ($data_to_reset as $reset) {
1112
+			// first check to make sure it is a valid session var
1113
+			if (isset($this->_session_data[ $reset ])) {
1114
+				// then check to make sure it is not a default var
1115
+				if (! array_key_exists($reset, $this->_default_session_vars)) {
1116
+					// remove session var
1117
+					unset($this->_session_data[ $reset ]);
1118
+					$this->setSaveState();
1119
+					if ($show_all_notices) {
1120
+						EE_Error::add_success(
1121
+							sprintf(
1122
+								esc_html__('The session variable %s was removed.', 'event_espresso'),
1123
+								$reset
1124
+							),
1125
+							__FILE__,
1126
+							__FUNCTION__,
1127
+							__LINE__
1128
+						);
1129
+					}
1130
+				} else {
1131
+					// yeeeeeeeeerrrrrrrrrrr OUT !!!!
1132
+					if ($show_all_notices) {
1133
+						EE_Error::add_error(
1134
+							sprintf(
1135
+								esc_html__(
1136
+									'Sorry! %s is a default session datum and can not be reset.',
1137
+									'event_espresso'
1138
+								),
1139
+								$reset
1140
+							),
1141
+							__FILE__,
1142
+							__FUNCTION__,
1143
+							__LINE__
1144
+						);
1145
+					}
1146
+					$return_value = false;
1147
+				}
1148
+			} elseif ($show_all_notices) {
1149
+				// oops! that session var does not exist!
1150
+				EE_Error::add_error(
1151
+					sprintf(
1152
+						esc_html__(
1153
+							'The session item provided, %s, is invalid or does not exist.',
1154
+							'event_espresso'
1155
+						),
1156
+						$reset
1157
+					),
1158
+					__FILE__,
1159
+					__FUNCTION__,
1160
+					__LINE__
1161
+				);
1162
+				$return_value = false;
1163
+			}
1164
+		} // end of foreach
1165
+		return $return_value;
1166
+	}
1167
+
1168
+
1169
+	/**
1170
+	 *   wp_loaded
1171
+	 *
1172
+	 * @throws EE_Error
1173
+	 * @throws InvalidDataTypeException
1174
+	 * @throws InvalidInterfaceException
1175
+	 * @throws InvalidArgumentException
1176
+	 * @throws ReflectionException
1177
+	 */
1178
+	public function wp_loaded()
1179
+	{
1180
+		if ($this->request->requestParamIsSet('clear_session')) {
1181
+			$this->clear_session(__CLASS__, __FUNCTION__);
1182
+		}
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * Used to reset the entire object (for tests).
1188
+	 *
1189
+	 * @since 4.3.0
1190
+	 * @throws EE_Error
1191
+	 * @throws InvalidDataTypeException
1192
+	 * @throws InvalidInterfaceException
1193
+	 * @throws InvalidArgumentException
1194
+	 * @throws ReflectionException
1195
+	 */
1196
+	public function reset_instance()
1197
+	{
1198
+		$this->clear_session();
1199
+		self::$_instance = null;
1200
+	}
1201
+
1202
+
1203
+	public function configure_garbage_collection_filters()
1204
+	{
1205
+		// run old filter we had for controlling session cleanup
1206
+		$expired_session_transient_delete_query_limit = absint(
1207
+			apply_filters(
1208
+				'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1209
+				50
1210
+			)
1211
+		);
1212
+		// is there a value? or one that is different than the default 50 records?
1213
+		if ($expired_session_transient_delete_query_limit === 0) {
1214
+			// hook into TransientCacheStorage in case Session cleanup was turned off
1215
+			add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1216
+		} elseif ($expired_session_transient_delete_query_limit !== 50) {
1217
+			// or use that for the new transient cleanup query limit
1218
+			add_filter(
1219
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1220
+				function () use ($expired_session_transient_delete_query_limit) {
1221
+					return $expired_session_transient_delete_query_limit;
1222
+				}
1223
+			);
1224
+		}
1225
+	}
1226
+
1227
+
1228
+	/**
1229
+	 * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1230
+	 * @param $data1
1231
+	 * @return string
1232
+	 */
1233
+	private function find_serialize_error($data1)
1234
+	{
1235
+		$error = '<pre>';
1236
+		$data2 = preg_replace_callback(
1237
+			'!s:(\d+):"(.*?)";!',
1238
+			function ($match) {
1239
+				return ($match[1] === strlen($match[2]))
1240
+					? $match[0]
1241
+					: 's:'
1242
+					  . strlen($match[2])
1243
+					  . ':"'
1244
+					  . $match[2]
1245
+					  . '";';
1246
+			},
1247
+			$data1
1248
+		);
1249
+		$max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1250
+		$error .= $data1 . PHP_EOL;
1251
+		$error .= $data2 . PHP_EOL;
1252
+		for ($i = 0; $i < $max; $i++) {
1253
+			if (@$data1[ $i ] !== @$data2[ $i ]) {
1254
+				$error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1255
+				$error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1256
+				$error .= "\t-> Line Number = $i" . PHP_EOL;
1257
+				$start = ($i - 20);
1258
+				$start = ($start < 0) ? 0 : $start;
1259
+				$length = 40;
1260
+				$point = $max - $i;
1261
+				if ($point < 20) {
1262
+					$rlength = 1;
1263
+					$rpoint = -$point;
1264
+				} else {
1265
+					$rpoint = $length - 20;
1266
+					$rlength = 1;
1267
+				}
1268
+				$error .= "\t-> Section Data1  = ";
1269
+				$error .= substr_replace(
1270
+					substr($data1, $start, $length),
1271
+					"<b style=\"color:green\">{$data1[ $i ]}</b>",
1272
+					$rpoint,
1273
+					$rlength
1274
+				);
1275
+				$error .= PHP_EOL;
1276
+				$error .= "\t-> Section Data2  = ";
1277
+				$error .= substr_replace(
1278
+					substr($data2, $start, $length),
1279
+					"<b style=\"color:red\">{$data2[ $i ]}</b>",
1280
+					$rpoint,
1281
+					$rlength
1282
+				);
1283
+				$error .= PHP_EOL;
1284
+			}
1285
+		}
1286
+		$error .= '</pre>';
1287
+		return $error;
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 * Saves an  array of settings used for configuring aspects of session behaviour
1293
+	 *
1294
+	 * @param array $updated_settings
1295
+	 */
1296
+	private function updateSessionSettings(array $updated_settings = array())
1297
+	{
1298
+		// add existing settings, but only if not included in incoming $updated_settings array
1299
+		$updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1300
+		update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * garbage_collection
1306
+	 */
1307
+	public function garbageCollection()
1308
+	{
1309
+		// only perform during regular requests if last garbage collection was over an hour ago
1310
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1311
+			$this->_last_gc = time();
1312
+			$this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1313
+			/** @type WPDB $wpdb */
1314
+			global $wpdb;
1315
+			// filter the query limit. Set to 0 to turn off garbage collection
1316
+			$expired_session_transient_delete_query_limit = absint(
1317
+				apply_filters(
1318
+					'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1319
+					50
1320
+				)
1321
+			);
1322
+			// non-zero LIMIT means take out the trash
1323
+			if ($expired_session_transient_delete_query_limit) {
1324
+				$session_key = str_replace('_', '\_', EE_Session::session_id_prefix);
1325
+				$hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1326
+				// since transient expiration timestamps are set in the future, we can compare against NOW
1327
+				// but we only want to pick up any trash that's been around for more than a day
1328
+				$expiration = time() - DAY_IN_SECONDS;
1329
+				$SQL = "
1330 1330
                     SELECT option_name
1331 1331
                     FROM {$wpdb->options}
1332 1332
                     WHERE
@@ -1335,17 +1335,17 @@  discard block
 block discarded – undo
1335 1335
                     AND option_value < {$expiration}
1336 1336
                     LIMIT {$expired_session_transient_delete_query_limit}
1337 1337
                 ";
1338
-                // produces something like:
1339
-                // SELECT option_name FROM wp_options
1340
-                // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1341
-                // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1342
-                // AND option_value < 1508368198 LIMIT 50
1343
-                $expired_sessions = $wpdb->get_col($SQL);
1344
-                // valid results?
1345
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1346
-                    $this->cache_storage->deleteMany($expired_sessions, true);
1347
-                }
1348
-            }
1349
-        }
1350
-    }
1338
+				// produces something like:
1339
+				// SELECT option_name FROM wp_options
1340
+				// WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1341
+				// OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1342
+				// AND option_value < 1508368198 LIMIT 50
1343
+				$expired_sessions = $wpdb->get_col($SQL);
1344
+				// valid results?
1345
+				if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1346
+					$this->cache_storage->deleteMany($expired_sessions, true);
1347
+				}
1348
+			}
1349
+		}
1350
+	}
1351 1351
 }
Please login to merge, or discard this patch.
Spacing   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -245,22 +245,22 @@  discard block
 block discarded – undo
245 245
         // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246 246
         // (which currently fires on the init hook at priority 9),
247 247
         // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
248
+        if ( ! apply_filters('FHEE_load_EE_Session', true)) {
249 249
             return;
250 250
         }
251 251
         $this->session_start_handler = $session_start_handler;
252 252
         $this->session_lifespan = $lifespan;
253 253
         $this->request = $request;
254
-        if (! defined('ESPRESSO_SESSION')) {
254
+        if ( ! defined('ESPRESSO_SESSION')) {
255 255
             define('ESPRESSO_SESSION', true);
256 256
         }
257 257
         // retrieve session options from db
258 258
         $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
-        if (! empty($session_settings)) {
259
+        if ( ! empty($session_settings)) {
260 260
             // cycle though existing session options
261 261
             foreach ($session_settings as $var_name => $session_setting) {
262 262
                 // set values for class properties
263
-                $var_name = '_' . $var_name;
263
+                $var_name = '_'.$var_name;
264 264
                 $this->{$var_name} = $session_setting;
265 265
             }
266 266
         }
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
             EE_Session::SAVE_STATE_CLEAN,
399 399
             EE_Session::SAVE_STATE_DIRTY,
400 400
         ];
401
-        if (! in_array($save_state, $valid_save_states, true)) {
401
+        if ( ! in_array($save_state, $valid_save_states, true)) {
402 402
             $save_state = EE_Session::SAVE_STATE_DIRTY;
403 403
         }
404 404
         $this->save_state = $save_state;
@@ -416,9 +416,9 @@  discard block
 block discarded – undo
416 416
         // set some defaults
417 417
         foreach ($this->_default_session_vars as $key => $default_var) {
418 418
             if (is_array($default_var)) {
419
-                $this->_session_data[ $key ] = array();
419
+                $this->_session_data[$key] = array();
420 420
             } else {
421
-                $this->_session_data[ $key ] = '';
421
+                $this->_session_data[$key] = '';
422 422
             }
423 423
         }
424 424
     }
@@ -554,8 +554,8 @@  discard block
 block discarded – undo
554 554
             $this->reset_checkout();
555 555
             $this->reset_transaction();
556 556
         }
557
-        if (! empty($key)) {
558
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
557
+        if ( ! empty($key)) {
558
+            return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null;
559 559
         }
560 560
         return $this->_session_data;
561 561
     }
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
             return false;
584 584
         }
585 585
         foreach ($data as $key => $value) {
586
-            if (isset($this->_default_session_vars[ $key ])) {
586
+            if (isset($this->_default_session_vars[$key])) {
587 587
                 EE_Error::add_error(
588 588
                     sprintf(
589 589
                         esc_html__(
@@ -598,7 +598,7 @@  discard block
 block discarded – undo
598 598
                 );
599 599
                 return false;
600 600
             }
601
-            $this->_session_data[ $key ] = $value;
601
+            $this->_session_data[$key] = $value;
602 602
             $this->setSaveState();
603 603
         }
604 604
         return true;
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         $this->_user_agent = $this->request->userAgent();
630 630
         // now let's retrieve what's in the db
631 631
         $session_data = $this->_retrieve_session_data();
632
-        if (! empty($session_data)) {
632
+        if ( ! empty($session_data)) {
633 633
             // get the current time in UTC
634 634
             $this->_time = $this->_time !== null ? $this->_time : time();
635 635
             // and reset the session expiration
@@ -640,7 +640,7 @@  discard block
 block discarded – undo
640 640
             // set initial site access time and the session expiration
641 641
             $this->_set_init_access_and_expiration();
642 642
             // set referer
643
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
643
+            $this->_session_data['pages_visited'][$this->_session_data['init_access']] = esc_attr(
644 644
                 $this->request->getServerParam('HTTP_REFERER')
645 645
             );
646 646
             // no previous session = go back and create one (on top of the data above)
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
      */
679 679
     protected function _retrieve_session_data()
680 680
     {
681
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
681
+        $ssn_key = EE_Session::session_id_prefix.$this->_sid;
682 682
         try {
683 683
             // we're using WP's Transient API to store session data using the PHP session ID as the option name
684 684
             $session_data = $this->cache_storage->get($ssn_key, false);
@@ -687,7 +687,7 @@  discard block
 block discarded – undo
687 687
             }
688 688
             if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
689 689
                 $hash_check = $this->cache_storage->get(
690
-                    EE_Session::hash_check_prefix . $this->_sid,
690
+                    EE_Session::hash_check_prefix.$this->_sid,
691 691
                     false
692 692
                 );
693 693
                 if ($hash_check && $hash_check !== md5($session_data)) {
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
                                 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
698 698
                                 'event_espresso'
699 699
                             ),
700
-                            EE_Session::session_id_prefix . $this->_sid
700
+                            EE_Session::session_id_prefix.$this->_sid
701 701
                         ),
702 702
                         __FILE__,
703 703
                         __FUNCTION__,
@@ -711,17 +711,17 @@  discard block
 block discarded – undo
711 711
             $row = $wpdb->get_row(
712 712
                 $wpdb->prepare(
713 713
                     "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
714
-                    '_transient_' . $ssn_key
714
+                    '_transient_'.$ssn_key
715 715
                 )
716 716
             );
717 717
             $session_data = is_object($row) ? $row->option_value : null;
718 718
             if ($session_data) {
719 719
                 $session_data = preg_replace_callback(
720 720
                     '!s:(d+):"(.*?)";!',
721
-                    function ($match) {
721
+                    function($match) {
722 722
                         return $match[1] === strlen($match[2])
723 723
                             ? $match[0]
724
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
724
+                            : 's:'.strlen($match[2]).':"'.$match[2].'";';
725 725
                     },
726 726
                     $session_data
727 727
                 );
@@ -732,7 +732,7 @@  discard block
 block discarded – undo
732 732
         $session_data = $this->encryption instanceof EE_Encryption
733 733
             ? $this->encryption->base64_string_decode($session_data)
734 734
             : $session_data;
735
-        if (! is_array($session_data)) {
735
+        if ( ! is_array($session_data)) {
736 736
             try {
737 737
                 $session_data = maybe_unserialize($session_data);
738 738
             } catch (Exception $e) {
@@ -746,21 +746,21 @@  discard block
 block discarded – undo
746 746
                       . '</pre><br>'
747 747
                       . $this->find_serialize_error($session_data)
748 748
                     : '';
749
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
749
+                $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
750 750
                 throw new InvalidSessionDataException($msg, 0, $e);
751 751
             }
752 752
         }
753 753
         // just a check to make sure the session array is indeed an array
754
-        if (! is_array($session_data)) {
754
+        if ( ! is_array($session_data)) {
755 755
             // no?!?! then something is wrong
756 756
             $msg = esc_html__(
757 757
                 'The session data is missing, invalid, or corrupted.',
758 758
                 'event_espresso'
759 759
             );
760 760
             $msg .= WP_DEBUG
761
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
761
+                ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data)
762 762
                 : '';
763
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
763
+            $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
764 764
             throw new InvalidSessionDataException($msg);
765 765
         }
766 766
         if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
@@ -786,7 +786,7 @@  discard block
 block discarded – undo
786 786
         // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
787 787
         $session_id = $this->request->requestParamIsSet('EESID')
788 788
             ? $this->request->getRequestParam('EESID')
789
-            : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
789
+            : md5(session_id().get_current_blog_id().$this->_get_sid_salt());
790 790
         return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
791 791
     }
792 792
 
@@ -886,19 +886,19 @@  discard block
 block discarded – undo
886 886
                     $page_visit = $this->_get_page_visit();
887 887
                     if ($page_visit) {
888 888
                         // set pages visited where the first will be the http referrer
889
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
889
+                        $this->_session_data['pages_visited'][$this->_time] = $page_visit;
890 890
                         // we'll only save the last 10 page visits.
891 891
                         $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
892 892
                     }
893 893
                     break;
894 894
                 default:
895 895
                     // carry any other data over
896
-                    $session_data[ $key ] = $this->_session_data[ $key ];
896
+                    $session_data[$key] = $this->_session_data[$key];
897 897
             }
898 898
         }
899 899
         $this->_session_data = $session_data;
900 900
         // creating a new session does not require saving to the db just yet
901
-        if (! $new_session) {
901
+        if ( ! $new_session) {
902 902
             // ready? let's save
903 903
             if ($this->_save_session_to_db()) {
904 904
                 return true;
@@ -975,7 +975,7 @@  discard block
 block discarded – undo
975 975
         }
976 976
         $transaction = $this->transaction();
977 977
         if ($transaction instanceof EE_Transaction) {
978
-            if (! $transaction->ID()) {
978
+            if ( ! $transaction->ID()) {
979 979
                 $transaction->save();
980 980
             }
981 981
             $this->_session_data['transaction'] = $transaction->ID();
@@ -989,14 +989,14 @@  discard block
 block discarded – undo
989 989
         // maybe save hash check
990 990
         if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
991 991
             $this->cache_storage->add(
992
-                EE_Session::hash_check_prefix . $this->_sid,
992
+                EE_Session::hash_check_prefix.$this->_sid,
993 993
                 md5($session_data),
994 994
                 $this->session_lifespan->inSeconds()
995 995
             );
996 996
         }
997 997
         // we're using the Transient API for storing session data,
998 998
         $saved = $this->cache_storage->add(
999
-            EE_Session::session_id_prefix . $this->_sid,
999
+            EE_Session::session_id_prefix.$this->_sid,
1000 1000
             $session_data,
1001 1001
             $this->session_lifespan->inSeconds()
1002 1002
         );
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
      */
1012 1012
     public function _get_page_visit()
1013 1013
     {
1014
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1014
+        $page_visit = home_url('/').'wp-admin/admin-ajax.php';
1015 1015
         // check for request url
1016 1016
         if ($this->request->serverParamIsSet('REQUEST_URI')) {
1017 1017
             $page_id = '?';
@@ -1023,14 +1023,14 @@  discard block
 block discarded – undo
1023 1023
             // check for page_id in SERVER REQUEST
1024 1024
             if ($this->request->requestParamIsSet('page_id')) {
1025 1025
                 // rebuild $e_reg without any of the extra parameters
1026
-                $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1026
+                $page_id .= 'page_id='.$this->request->getRequestParam('page_id', 0, 'int').'&amp;';
1027 1027
             }
1028 1028
             // check for $e_reg in SERVER REQUEST
1029 1029
             if ($this->request->requestParamIsSet('ee')) {
1030 1030
                 // rebuild $e_reg without any of the extra parameters
1031
-                $e_reg = 'ee=' . $this->request->getRequestParam('ee');
1031
+                $e_reg = 'ee='.$this->request->getRequestParam('ee');
1032 1032
             }
1033
-            $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1033
+            $page_visit = esc_url(rtrim($http_host.$request_uri.$page_id.$e_reg, '?'));
1034 1034
         }
1035 1035
         return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1036 1036
     }
@@ -1067,7 +1067,7 @@  discard block
 block discarded – undo
1067 1067
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1068 1068
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1069 1069
 // </h3>';
1070
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1070
+        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()');
1071 1071
         $this->reset_cart();
1072 1072
         $this->reset_checkout();
1073 1073
         $this->reset_transaction();
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
     public function reset_data($data_to_reset = array(), $show_all_notices = false)
1091 1091
     {
1092 1092
         // if $data_to_reset is not in an array, then put it in one
1093
-        if (! is_array($data_to_reset)) {
1093
+        if ( ! is_array($data_to_reset)) {
1094 1094
             $data_to_reset = array($data_to_reset);
1095 1095
         }
1096 1096
         // nothing ??? go home!
@@ -1110,11 +1110,11 @@  discard block
 block discarded – undo
1110 1110
         // since $data_to_reset is an array, cycle through the values
1111 1111
         foreach ($data_to_reset as $reset) {
1112 1112
             // first check to make sure it is a valid session var
1113
-            if (isset($this->_session_data[ $reset ])) {
1113
+            if (isset($this->_session_data[$reset])) {
1114 1114
                 // then check to make sure it is not a default var
1115
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1115
+                if ( ! array_key_exists($reset, $this->_default_session_vars)) {
1116 1116
                     // remove session var
1117
-                    unset($this->_session_data[ $reset ]);
1117
+                    unset($this->_session_data[$reset]);
1118 1118
                     $this->setSaveState();
1119 1119
                     if ($show_all_notices) {
1120 1120
                         EE_Error::add_success(
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
             // or use that for the new transient cleanup query limit
1218 1218
             add_filter(
1219 1219
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1220
-                function () use ($expired_session_transient_delete_query_limit) {
1220
+                function() use ($expired_session_transient_delete_query_limit) {
1221 1221
                     return $expired_session_transient_delete_query_limit;
1222 1222
                 }
1223 1223
             );
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
         $error = '<pre>';
1236 1236
         $data2 = preg_replace_callback(
1237 1237
             '!s:(\d+):"(.*?)";!',
1238
-            function ($match) {
1238
+            function($match) {
1239 1239
                 return ($match[1] === strlen($match[2]))
1240 1240
                     ? $match[0]
1241 1241
                     : 's:'
@@ -1247,13 +1247,13 @@  discard block
 block discarded – undo
1247 1247
             $data1
1248 1248
         );
1249 1249
         $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1250
-        $error .= $data1 . PHP_EOL;
1251
-        $error .= $data2 . PHP_EOL;
1250
+        $error .= $data1.PHP_EOL;
1251
+        $error .= $data2.PHP_EOL;
1252 1252
         for ($i = 0; $i < $max; $i++) {
1253
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1254
-                $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1255
-                $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1256
-                $error .= "\t-> Line Number = $i" . PHP_EOL;
1253
+            if (@$data1[$i] !== @$data2[$i]) {
1254
+                $error .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL;
1255
+                $error .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL;
1256
+                $error .= "\t-> Line Number = $i".PHP_EOL;
1257 1257
                 $start = ($i - 20);
1258 1258
                 $start = ($start < 0) ? 0 : $start;
1259 1259
                 $length = 40;
@@ -1268,7 +1268,7 @@  discard block
 block discarded – undo
1268 1268
                 $error .= "\t-> Section Data1  = ";
1269 1269
                 $error .= substr_replace(
1270 1270
                     substr($data1, $start, $length),
1271
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1271
+                    "<b style=\"color:green\">{$data1[$i]}</b>",
1272 1272
                     $rpoint,
1273 1273
                     $rlength
1274 1274
                 );
@@ -1276,7 +1276,7 @@  discard block
 block discarded – undo
1276 1276
                 $error .= "\t-> Section Data2  = ";
1277 1277
                 $error .= substr_replace(
1278 1278
                     substr($data2, $start, $length),
1279
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1279
+                    "<b style=\"color:red\">{$data2[$i]}</b>",
1280 1280
                     $rpoint,
1281 1281
                     $rlength
1282 1282
                 );
@@ -1307,7 +1307,7 @@  discard block
 block discarded – undo
1307 1307
     public function garbageCollection()
1308 1308
     {
1309 1309
         // only perform during regular requests if last garbage collection was over an hour ago
1310
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1310
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1311 1311
             $this->_last_gc = time();
1312 1312
             $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1313 1313
             /** @type WPDB $wpdb */
@@ -1342,7 +1342,7 @@  discard block
 block discarded – undo
1342 1342
                 // AND option_value < 1508368198 LIMIT 50
1343 1343
                 $expired_sessions = $wpdb->get_col($SQL);
1344 1344
                 // valid results?
1345
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1345
+                if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1346 1346
                     $this->cache_storage->deleteMany($expired_sessions, true);
1347 1347
                 }
1348 1348
             }
Please login to merge, or discard this patch.
core/libraries/payment_methods/EE_Gateway.lib.php 1 patch
Indentation   +531 added lines, -531 removed lines patch added patch discarded remove patch
@@ -23,535 +23,535 @@
 block discarded – undo
23 23
  */
24 24
 abstract class EE_Gateway
25 25
 {
26
-    /**
27
-     * a constant used as a possible value for $_currencies_supported to indicate
28
-     * that ALL currencies are supported by this gateway
29
-     */
30
-    const all_currencies_supported = 'all_currencies_supported';
31
-
32
-    /**
33
-     * Where values are 3-letter currency codes
34
-     *
35
-     * @var array|string
36
-     */
37
-    protected $_currencies_supported = [];
38
-
39
-    /**
40
-     * Whether this gateway can support SENDING a refund request (ie, initiated by
41
-     * admin in EE's wp-admin page)
42
-     *
43
-     * @var boolean
44
-     */
45
-    protected $_supports_sending_refunds = false;
46
-
47
-    /**
48
-     * Whether this gateway can support RECEIVING a refund request from the payment
49
-     * provider (ie, initiated by admin on the payment prover's website who sends an IPN to EE)
50
-     *
51
-     * @var boolean
52
-     */
53
-    protected $_supports_receiving_refunds = false;
54
-
55
-    /**
56
-     * Model for querying for existing payments
57
-     *
58
-     * @var EEMI_Payment
59
-     */
60
-    protected $_pay_model;
61
-
62
-    /**
63
-     * Model used for adding to the payments log
64
-     *
65
-     * @var EEM_Change_Log
66
-     */
67
-    protected $_pay_log;
68
-
69
-    /**
70
-     * Used for formatting some input to gateways
71
-     *
72
-     * @var EEH_Template
73
-     */
74
-    protected $_template;
75
-
76
-    /**
77
-     * Concrete class that implements EEHI_Money, used by most gateways
78
-     *
79
-     * @var EEH_Money
80
-     */
81
-    protected $_money;
82
-
83
-    /**
84
-     * Concrete class that implements EEHI_Line_Item, used for manipulating the line item tree
85
-     *
86
-     * @var EEH_Line_Item
87
-     */
88
-    protected $_line_item;
89
-
90
-    /**
91
-     * @var GatewayDataFormatterInterface
92
-     */
93
-    protected $_gateway_data_formatter;
94
-
95
-    /**
96
-     * @var FormatterInterface
97
-     */
98
-    protected $_unsupported_character_remover;
99
-
100
-    /**
101
-     * The ID of the payment method using this gateway
102
-     *
103
-     * @var int
104
-     */
105
-    protected $_ID;
106
-
107
-    /**
108
-     * @var $_debug_mode boolean whether to send requests to teh sandbox site or not
109
-     */
110
-    protected $_debug_mode;
111
-
112
-    /**
113
-     * @var string $_name name to show for this payment method
114
-     */
115
-    protected $_name;
116
-
117
-    /**
118
-     * @var string name to show for this payment method to admin-type users
119
-     */
120
-    protected $_admin_name;
121
-
122
-
123
-    /**
124
-     * EE_Gateway constructor
125
-     */
126
-    public function __construct()
127
-    {
128
-    }
129
-
130
-
131
-    /**
132
-     * We don't want to serialize models as they often have circular structures
133
-     * (eg a payment model has a reference to each payment model object; and most
134
-     * payments have a transaction, most transactions have a payment method;
135
-     * most payment methods have a payment method type; most payment method types
136
-     * have a gateway. And if a gateway serializes its models, we start at the
137
-     * beginning again)
138
-     *
139
-     * @return array
140
-     */
141
-    public function __sleep()
142
-    {
143
-        $properties = get_object_vars($this);
144
-        unset($properties['_pay_model'], $properties['_pay_log']);
145
-        return array_keys($properties);
146
-    }
147
-
148
-
149
-    /**
150
-     * Returns whether this gateway should support SENDING refunds
151
-     * see $_supports_sending_refunds
152
-     *
153
-     * @return bool
154
-     */
155
-    public function supports_sending_refunds(): bool
156
-    {
157
-        return $this->_supports_sending_refunds;
158
-    }
159
-
160
-
161
-    /**
162
-     * Returns whether this gateway should support RECEIVING refunds
163
-     * see $_supports_receiving_refunds
164
-     *
165
-     * @return bool
166
-     */
167
-    public function supports_receiving_refunds(): bool
168
-    {
169
-        return $this->_supports_receiving_refunds;
170
-    }
171
-
172
-
173
-    /**
174
-     * Tries to refund the payment specified, taking into account the extra
175
-     * refund info. Note that if the gateway's _supports_sending_refunds is false,
176
-     * this should just throw an exception.
177
-     *
178
-     * @param EE_Payment|null $payment
179
-     * @param array|null      $refund_info
180
-     * @return EE_Payment|null
181
-     */
182
-    public function do_direct_refund(?EE_Payment $payment, ?array $refund_info = null): ?EE_Payment
183
-    {
184
-        return null;
185
-    }
186
-
187
-
188
-    /**
189
-     * Sets the payment method's settings so the gateway knows where to send the request
190
-     * etc
191
-     *
192
-     * @param array $settings_array
193
-     */
194
-    public function set_settings(array $settings_array)
195
-    {
196
-        foreach ($settings_array as $name => $value) {
197
-            $property_name          = "_" . $name;
198
-            $this->{$property_name} = $value;
199
-        }
200
-    }
201
-
202
-
203
-    /**
204
-     * See this class description
205
-     *
206
-     * @param EEM_Payment $payment_model
207
-     */
208
-    public function set_payment_model(EEM_Payment $payment_model)
209
-    {
210
-        $this->_pay_model = $payment_model;
211
-    }
212
-
213
-
214
-    /**
215
-     * See this class description
216
-     *
217
-     * @param EEM_Change_Log $payment_log_model
218
-     */
219
-    public function set_payment_log(EEM_Change_Log $payment_log_model)
220
-    {
221
-        $this->_pay_log = $payment_log_model;
222
-    }
223
-
224
-
225
-    /**
226
-     * See this class description
227
-     *
228
-     * @param EEH_Template $template_helper
229
-     */
230
-    public function set_template_helper(EEH_Template $template_helper)
231
-    {
232
-        $this->_template = $template_helper;
233
-    }
234
-
235
-
236
-    /**
237
-     * See this class description
238
-     *
239
-     * @param EEH_Line_Item $line_item_helper
240
-     */
241
-    public function set_line_item_helper(EEH_Line_Item $line_item_helper)
242
-    {
243
-        $this->_line_item = $line_item_helper;
244
-    }
245
-
246
-
247
-    /**
248
-     * See this class description
249
-     *
250
-     * @param EEH_Money $money_helper
251
-     */
252
-    public function set_money_helper(EEH_Money $money_helper)
253
-    {
254
-        $this->_money = $money_helper;
255
-    }
256
-
257
-
258
-    /**
259
-     * Sets the gateway data formatter helper
260
-     *
261
-     * @param GatewayDataFormatterInterface|null $gateway_data_formatter
262
-     * @throws InvalidEntityException if it's not set properly
263
-     */
264
-    public function set_gateway_data_formatter(?GatewayDataFormatterInterface $gateway_data_formatter)
265
-    {
266
-        if (! $gateway_data_formatter instanceof GatewayDataFormatterInterface) {
267
-            throw new InvalidEntityException(
268
-                is_object($gateway_data_formatter)
269
-                    ? get_class($gateway_data_formatter)
270
-                    : esc_html__('Not an object', 'event_espresso'),
271
-                '\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
272
-            );
273
-        }
274
-        $this->_gateway_data_formatter = $gateway_data_formatter;
275
-    }
276
-
277
-
278
-    /**
279
-     * Gets the gateway data formatter
280
-     *
281
-     * @return GatewayDataFormatterInterface
282
-     * @throws InvalidEntityException if it's not set properly
283
-     */
284
-    protected function _get_gateway_formatter(): GatewayDataFormatterInterface
285
-    {
286
-        if (! $this->_gateway_data_formatter instanceof GatewayDataFormatterInterface) {
287
-            throw new InvalidEntityException(
288
-                is_object($this->_gateway_data_formatter)
289
-                    ? get_class($this->_gateway_data_formatter)
290
-                    : esc_html__('Not an object', 'event_espresso'),
291
-                '\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
292
-            );
293
-        }
294
-        return $this->_gateway_data_formatter;
295
-    }
296
-
297
-
298
-    /**
299
-     * Sets the helper which will remove unsupported characters for most gateways
300
-     *
301
-     * @param FormatterInterface|null $formatter
302
-     * @return void
303
-     * @throws InvalidEntityException
304
-     */
305
-    public function set_unsupported_character_remover(?FormatterInterface $formatter)
306
-    {
307
-        if (! $formatter instanceof FormatterInterface) {
308
-            throw new InvalidEntityException(
309
-                is_object($formatter)
310
-                    ? get_class($formatter)
311
-                    : esc_html__('Not an object', 'event_espresso'),
312
-                '\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
313
-            );
314
-        }
315
-        $this->_unsupported_character_remover = $formatter;
316
-    }
317
-
318
-
319
-    /**
320
-     * Gets the helper which removes characters which gateways might not support, like emojis etc.
321
-     *
322
-     * @return FormatterInterface
323
-     * @throws InvalidEntityException
324
-     */
325
-    protected function _get_unsupported_character_remover(): FormatterInterface
326
-    {
327
-        if (! $this->_unsupported_character_remover instanceof FormatterInterface) {
328
-            throw new InvalidEntityException(
329
-                is_object($this->_unsupported_character_remover)
330
-                    ? get_class($this->_unsupported_character_remover)
331
-                    : esc_html__('Not an object', 'event_espresso'),
332
-                '\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
333
-            );
334
-        }
335
-        return $this->_unsupported_character_remover;
336
-    }
337
-
338
-
339
-    /**
340
-     * @param array|string      $message
341
-     * @param mixed             $object_logged
342
-     * @throws EE_Error
343
-     * @throws ReflectionException
344
-     */
345
-    public function log($message, $object_logged)
346
-    {
347
-        if ($object_logged instanceof EE_Payment) {
348
-            $type = 'Payment';
349
-            $id   = $object_logged->ID();
350
-        } elseif ($object_logged instanceof EE_Transaction) {
351
-            $type = 'Transaction';
352
-            $id   = $object_logged->ID();
353
-        } else {
354
-            $type = 'Payment_Method';
355
-            $id   = $this->_ID;
356
-        }
357
-        // only log if we're going to store it for longer than the minimum time
358
-        $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
359
-        if ($reg_config->gateway_log_lifespan !== '1 second') {
360
-            $this->_pay_log->gateway_log($message, $id, $type);
361
-        }
362
-    }
363
-
364
-
365
-    /**
366
-     * Formats the amount so it can generally be sent to gateways
367
-     *
368
-     * @param float $amount
369
-     * @return string
370
-     * @deprecated since 4.9.31 insetad use
371
-     *             EventEspresso\core\services\payment_methods\gateways\GatewayDataFormatter::format_currency()
372
-     */
373
-    public function format_currency(float $amount): string
374
-    {
375
-        return $this->_get_gateway_formatter()->formatCurrency($amount);
376
-    }
377
-
378
-
379
-    /**
380
-     * Returns either an array of all the currency codes supported,
381
-     * or a string indicating they are all supported (EE_gateway::all_currencies_supported)
382
-     *
383
-     * @return array|string
384
-     */
385
-    public function currencies_supported()
386
-    {
387
-        return $this->_currencies_supported;
388
-    }
389
-
390
-
391
-    /**
392
-     * Returns what a simple summing of items and taxes for this transaction. This
393
-     * can be used to determine if some more complex line items, like promotions,
394
-     * surcharges, or cancellations occurred (in which case we might want to forget
395
-     * about creating an itemized list of purchases and instead only send the total due)
396
-     *
397
-     * @param EE_Transaction $transaction
398
-     * @return float
399
-     * @throws EE_Error
400
-     * @throws ReflectionException
401
-     */
402
-    protected function _sum_items_and_taxes(EE_Transaction $transaction)
403
-    {
404
-        $total_line_item = $transaction->total_line_item();
405
-        $total           = 0;
406
-        foreach ($total_line_item->get_items() as $item_line_item) {
407
-            $total += max($item_line_item->total(), 0);
408
-        }
409
-        foreach ($total_line_item->tax_descendants() as $tax_line_item) {
410
-            $total += max($tax_line_item->total(), 0);
411
-        }
412
-        return $total;
413
-    }
414
-
415
-
416
-    /**
417
-     * Determines whether we can easily itemize the transaction using only
418
-     * items and taxes (ie, no promotions or surcharges or cancellations needed)
419
-     *
420
-     * @param EE_Payment $payment
421
-     * @return boolean
422
-     * @throws EE_Error
423
-     * @throws ReflectionException
424
-     */
425
-    protected function _can_easily_itemize_transaction_for(EE_Payment $payment): bool
426
-    {
427
-        return $this->_money->compare_floats(
428
-            $this->_sum_items_and_taxes($payment->transaction()),
429
-            $payment->transaction()->total()
430
-        )
431
-               && $this->_money->compare_floats(
432
-                   $payment->amount(),
433
-                   $payment->transaction()->total()
434
-               );
435
-    }
436
-
437
-
438
-    /**
439
-     * Handles updating the transaction and any other related data based on the payment.
440
-     * You may be tempted to do this as part of do_direct_payment or handle_payment_update,
441
-     * but doing so on those functions might be too early. It's possible that the changes
442
-     * you make to teh transaction or registration or line items may just get overwritten
443
-     * at that point. Instead, you should store any info you need on the payment during those
444
-     * functions, and use that information at this step, which client code will decide
445
-     * for you when it should be called.
446
-     *
447
-     * @param EE_Payment $payment
448
-     * @return void
449
-     */
450
-    public function update_txn_based_on_payment($payment)
451
-    {
452
-        // maybe update the transaction or line items or registrations
453
-        // but most gateways don't need to do this, because they only update the payment
454
-    }
455
-
456
-
457
-    /**
458
-     * Gets the first event for this payment (it's possible that it could be for multiple)
459
-     *
460
-     * @param EE_Payment $payment
461
-     * @return EE_Event|null
462
-     * @deprecated since 4.9.31 instead use EE_Payment::get_first_event()
463
-     */
464
-    protected function _get_first_event_for_payment(EE_Payment $payment): ?EE_Event
465
-    {
466
-        return $payment->get_first_event();
467
-    }
468
-
469
-
470
-    /**
471
-     * Gets the name of the first event for which is being paid
472
-     *
473
-     * @param EE_Payment $payment
474
-     * @return string
475
-     * @deprecated since 4.9.31 instead use EE_Payment::get_first_event_name()
476
-     */
477
-    protected function _get_first_event_name_for_payment(EE_Payment $payment): string
478
-    {
479
-        return $payment->get_first_event_name();
480
-    }
481
-
482
-
483
-    /**
484
-     * Gets the text to use for a gateway's line item name when this is a partial payment
485
-     *
486
-     * @param EE_Payment $payment
487
-     * @return string
488
-     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment)
489
-     */
490
-    protected function _format_partial_payment_line_item_name(EE_Payment $payment): string
491
-    {
492
-        return $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment);
493
-    }
494
-
495
-
496
-    /**
497
-     * Gets the text to use for a gateway's line item description when this is a partial payment
498
-     *
499
-     * @param EE_Payment $payment
500
-     * @return string
501
-     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc()
502
-     */
503
-    protected function _format_partial_payment_line_item_desc(EE_Payment $payment): string
504
-    {
505
-        return $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc($payment);
506
-    }
507
-
508
-
509
-    /**
510
-     * Gets the name to use for a line item when sending line items to the gateway
511
-     *
512
-     * @param EE_Line_Item $line_item
513
-     * @param EE_Payment   $payment
514
-     * @return string
515
-     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemName($line_item,$payment)
516
-     */
517
-    protected function _format_line_item_name(EE_Line_Item $line_item, EE_Payment $payment): string
518
-    {
519
-        return $this->_get_gateway_formatter()->formatLineItemName($line_item, $payment);
520
-    }
521
-
522
-
523
-    /**
524
-     * Gets the description to use for a line item when sending line items to the gateway
525
-     *
526
-     * @param EE_Line_Item $line_item
527
-     * @param EE_Payment   $payment
528
-     * @return string
529
-     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment))
530
-     */
531
-    protected function _format_line_item_desc(EE_Line_Item $line_item, EE_Payment $payment): string
532
-    {
533
-        return $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment);
534
-    }
535
-
536
-
537
-    /**
538
-     * Gets the order description that should generlly be sent to gateways
539
-     *
540
-     * @param EE_Payment $payment
541
-     * @return string
542
-     * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatOrderDescription($payment)
543
-     */
544
-    protected function _format_order_description(EE_Payment $payment): string
545
-    {
546
-        return $this->_get_gateway_formatter()->formatOrderDescription($payment);
547
-    }
548
-
549
-
550
-    /**
551
-     * @return bool
552
-     */
553
-    public function isInSandboxMode(): bool
554
-    {
555
-        return $this->_debug_mode;
556
-    }
26
+	/**
27
+	 * a constant used as a possible value for $_currencies_supported to indicate
28
+	 * that ALL currencies are supported by this gateway
29
+	 */
30
+	const all_currencies_supported = 'all_currencies_supported';
31
+
32
+	/**
33
+	 * Where values are 3-letter currency codes
34
+	 *
35
+	 * @var array|string
36
+	 */
37
+	protected $_currencies_supported = [];
38
+
39
+	/**
40
+	 * Whether this gateway can support SENDING a refund request (ie, initiated by
41
+	 * admin in EE's wp-admin page)
42
+	 *
43
+	 * @var boolean
44
+	 */
45
+	protected $_supports_sending_refunds = false;
46
+
47
+	/**
48
+	 * Whether this gateway can support RECEIVING a refund request from the payment
49
+	 * provider (ie, initiated by admin on the payment prover's website who sends an IPN to EE)
50
+	 *
51
+	 * @var boolean
52
+	 */
53
+	protected $_supports_receiving_refunds = false;
54
+
55
+	/**
56
+	 * Model for querying for existing payments
57
+	 *
58
+	 * @var EEMI_Payment
59
+	 */
60
+	protected $_pay_model;
61
+
62
+	/**
63
+	 * Model used for adding to the payments log
64
+	 *
65
+	 * @var EEM_Change_Log
66
+	 */
67
+	protected $_pay_log;
68
+
69
+	/**
70
+	 * Used for formatting some input to gateways
71
+	 *
72
+	 * @var EEH_Template
73
+	 */
74
+	protected $_template;
75
+
76
+	/**
77
+	 * Concrete class that implements EEHI_Money, used by most gateways
78
+	 *
79
+	 * @var EEH_Money
80
+	 */
81
+	protected $_money;
82
+
83
+	/**
84
+	 * Concrete class that implements EEHI_Line_Item, used for manipulating the line item tree
85
+	 *
86
+	 * @var EEH_Line_Item
87
+	 */
88
+	protected $_line_item;
89
+
90
+	/**
91
+	 * @var GatewayDataFormatterInterface
92
+	 */
93
+	protected $_gateway_data_formatter;
94
+
95
+	/**
96
+	 * @var FormatterInterface
97
+	 */
98
+	protected $_unsupported_character_remover;
99
+
100
+	/**
101
+	 * The ID of the payment method using this gateway
102
+	 *
103
+	 * @var int
104
+	 */
105
+	protected $_ID;
106
+
107
+	/**
108
+	 * @var $_debug_mode boolean whether to send requests to teh sandbox site or not
109
+	 */
110
+	protected $_debug_mode;
111
+
112
+	/**
113
+	 * @var string $_name name to show for this payment method
114
+	 */
115
+	protected $_name;
116
+
117
+	/**
118
+	 * @var string name to show for this payment method to admin-type users
119
+	 */
120
+	protected $_admin_name;
121
+
122
+
123
+	/**
124
+	 * EE_Gateway constructor
125
+	 */
126
+	public function __construct()
127
+	{
128
+	}
129
+
130
+
131
+	/**
132
+	 * We don't want to serialize models as they often have circular structures
133
+	 * (eg a payment model has a reference to each payment model object; and most
134
+	 * payments have a transaction, most transactions have a payment method;
135
+	 * most payment methods have a payment method type; most payment method types
136
+	 * have a gateway. And if a gateway serializes its models, we start at the
137
+	 * beginning again)
138
+	 *
139
+	 * @return array
140
+	 */
141
+	public function __sleep()
142
+	{
143
+		$properties = get_object_vars($this);
144
+		unset($properties['_pay_model'], $properties['_pay_log']);
145
+		return array_keys($properties);
146
+	}
147
+
148
+
149
+	/**
150
+	 * Returns whether this gateway should support SENDING refunds
151
+	 * see $_supports_sending_refunds
152
+	 *
153
+	 * @return bool
154
+	 */
155
+	public function supports_sending_refunds(): bool
156
+	{
157
+		return $this->_supports_sending_refunds;
158
+	}
159
+
160
+
161
+	/**
162
+	 * Returns whether this gateway should support RECEIVING refunds
163
+	 * see $_supports_receiving_refunds
164
+	 *
165
+	 * @return bool
166
+	 */
167
+	public function supports_receiving_refunds(): bool
168
+	{
169
+		return $this->_supports_receiving_refunds;
170
+	}
171
+
172
+
173
+	/**
174
+	 * Tries to refund the payment specified, taking into account the extra
175
+	 * refund info. Note that if the gateway's _supports_sending_refunds is false,
176
+	 * this should just throw an exception.
177
+	 *
178
+	 * @param EE_Payment|null $payment
179
+	 * @param array|null      $refund_info
180
+	 * @return EE_Payment|null
181
+	 */
182
+	public function do_direct_refund(?EE_Payment $payment, ?array $refund_info = null): ?EE_Payment
183
+	{
184
+		return null;
185
+	}
186
+
187
+
188
+	/**
189
+	 * Sets the payment method's settings so the gateway knows where to send the request
190
+	 * etc
191
+	 *
192
+	 * @param array $settings_array
193
+	 */
194
+	public function set_settings(array $settings_array)
195
+	{
196
+		foreach ($settings_array as $name => $value) {
197
+			$property_name          = "_" . $name;
198
+			$this->{$property_name} = $value;
199
+		}
200
+	}
201
+
202
+
203
+	/**
204
+	 * See this class description
205
+	 *
206
+	 * @param EEM_Payment $payment_model
207
+	 */
208
+	public function set_payment_model(EEM_Payment $payment_model)
209
+	{
210
+		$this->_pay_model = $payment_model;
211
+	}
212
+
213
+
214
+	/**
215
+	 * See this class description
216
+	 *
217
+	 * @param EEM_Change_Log $payment_log_model
218
+	 */
219
+	public function set_payment_log(EEM_Change_Log $payment_log_model)
220
+	{
221
+		$this->_pay_log = $payment_log_model;
222
+	}
223
+
224
+
225
+	/**
226
+	 * See this class description
227
+	 *
228
+	 * @param EEH_Template $template_helper
229
+	 */
230
+	public function set_template_helper(EEH_Template $template_helper)
231
+	{
232
+		$this->_template = $template_helper;
233
+	}
234
+
235
+
236
+	/**
237
+	 * See this class description
238
+	 *
239
+	 * @param EEH_Line_Item $line_item_helper
240
+	 */
241
+	public function set_line_item_helper(EEH_Line_Item $line_item_helper)
242
+	{
243
+		$this->_line_item = $line_item_helper;
244
+	}
245
+
246
+
247
+	/**
248
+	 * See this class description
249
+	 *
250
+	 * @param EEH_Money $money_helper
251
+	 */
252
+	public function set_money_helper(EEH_Money $money_helper)
253
+	{
254
+		$this->_money = $money_helper;
255
+	}
256
+
257
+
258
+	/**
259
+	 * Sets the gateway data formatter helper
260
+	 *
261
+	 * @param GatewayDataFormatterInterface|null $gateway_data_formatter
262
+	 * @throws InvalidEntityException if it's not set properly
263
+	 */
264
+	public function set_gateway_data_formatter(?GatewayDataFormatterInterface $gateway_data_formatter)
265
+	{
266
+		if (! $gateway_data_formatter instanceof GatewayDataFormatterInterface) {
267
+			throw new InvalidEntityException(
268
+				is_object($gateway_data_formatter)
269
+					? get_class($gateway_data_formatter)
270
+					: esc_html__('Not an object', 'event_espresso'),
271
+				'\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
272
+			);
273
+		}
274
+		$this->_gateway_data_formatter = $gateway_data_formatter;
275
+	}
276
+
277
+
278
+	/**
279
+	 * Gets the gateway data formatter
280
+	 *
281
+	 * @return GatewayDataFormatterInterface
282
+	 * @throws InvalidEntityException if it's not set properly
283
+	 */
284
+	protected function _get_gateway_formatter(): GatewayDataFormatterInterface
285
+	{
286
+		if (! $this->_gateway_data_formatter instanceof GatewayDataFormatterInterface) {
287
+			throw new InvalidEntityException(
288
+				is_object($this->_gateway_data_formatter)
289
+					? get_class($this->_gateway_data_formatter)
290
+					: esc_html__('Not an object', 'event_espresso'),
291
+				'\\EventEspresso\\core\\services\\payment_methods\\gateways\\GatewayDataFormatterInterface'
292
+			);
293
+		}
294
+		return $this->_gateway_data_formatter;
295
+	}
296
+
297
+
298
+	/**
299
+	 * Sets the helper which will remove unsupported characters for most gateways
300
+	 *
301
+	 * @param FormatterInterface|null $formatter
302
+	 * @return void
303
+	 * @throws InvalidEntityException
304
+	 */
305
+	public function set_unsupported_character_remover(?FormatterInterface $formatter)
306
+	{
307
+		if (! $formatter instanceof FormatterInterface) {
308
+			throw new InvalidEntityException(
309
+				is_object($formatter)
310
+					? get_class($formatter)
311
+					: esc_html__('Not an object', 'event_espresso'),
312
+				'\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
313
+			);
314
+		}
315
+		$this->_unsupported_character_remover = $formatter;
316
+	}
317
+
318
+
319
+	/**
320
+	 * Gets the helper which removes characters which gateways might not support, like emojis etc.
321
+	 *
322
+	 * @return FormatterInterface
323
+	 * @throws InvalidEntityException
324
+	 */
325
+	protected function _get_unsupported_character_remover(): FormatterInterface
326
+	{
327
+		if (! $this->_unsupported_character_remover instanceof FormatterInterface) {
328
+			throw new InvalidEntityException(
329
+				is_object($this->_unsupported_character_remover)
330
+					? get_class($this->_unsupported_character_remover)
331
+					: esc_html__('Not an object', 'event_espresso'),
332
+				'\\EventEspresso\\core\\services\\formatters\\FormatterInterface'
333
+			);
334
+		}
335
+		return $this->_unsupported_character_remover;
336
+	}
337
+
338
+
339
+	/**
340
+	 * @param array|string      $message
341
+	 * @param mixed             $object_logged
342
+	 * @throws EE_Error
343
+	 * @throws ReflectionException
344
+	 */
345
+	public function log($message, $object_logged)
346
+	{
347
+		if ($object_logged instanceof EE_Payment) {
348
+			$type = 'Payment';
349
+			$id   = $object_logged->ID();
350
+		} elseif ($object_logged instanceof EE_Transaction) {
351
+			$type = 'Transaction';
352
+			$id   = $object_logged->ID();
353
+		} else {
354
+			$type = 'Payment_Method';
355
+			$id   = $this->_ID;
356
+		}
357
+		// only log if we're going to store it for longer than the minimum time
358
+		$reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
359
+		if ($reg_config->gateway_log_lifespan !== '1 second') {
360
+			$this->_pay_log->gateway_log($message, $id, $type);
361
+		}
362
+	}
363
+
364
+
365
+	/**
366
+	 * Formats the amount so it can generally be sent to gateways
367
+	 *
368
+	 * @param float $amount
369
+	 * @return string
370
+	 * @deprecated since 4.9.31 insetad use
371
+	 *             EventEspresso\core\services\payment_methods\gateways\GatewayDataFormatter::format_currency()
372
+	 */
373
+	public function format_currency(float $amount): string
374
+	{
375
+		return $this->_get_gateway_formatter()->formatCurrency($amount);
376
+	}
377
+
378
+
379
+	/**
380
+	 * Returns either an array of all the currency codes supported,
381
+	 * or a string indicating they are all supported (EE_gateway::all_currencies_supported)
382
+	 *
383
+	 * @return array|string
384
+	 */
385
+	public function currencies_supported()
386
+	{
387
+		return $this->_currencies_supported;
388
+	}
389
+
390
+
391
+	/**
392
+	 * Returns what a simple summing of items and taxes for this transaction. This
393
+	 * can be used to determine if some more complex line items, like promotions,
394
+	 * surcharges, or cancellations occurred (in which case we might want to forget
395
+	 * about creating an itemized list of purchases and instead only send the total due)
396
+	 *
397
+	 * @param EE_Transaction $transaction
398
+	 * @return float
399
+	 * @throws EE_Error
400
+	 * @throws ReflectionException
401
+	 */
402
+	protected function _sum_items_and_taxes(EE_Transaction $transaction)
403
+	{
404
+		$total_line_item = $transaction->total_line_item();
405
+		$total           = 0;
406
+		foreach ($total_line_item->get_items() as $item_line_item) {
407
+			$total += max($item_line_item->total(), 0);
408
+		}
409
+		foreach ($total_line_item->tax_descendants() as $tax_line_item) {
410
+			$total += max($tax_line_item->total(), 0);
411
+		}
412
+		return $total;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Determines whether we can easily itemize the transaction using only
418
+	 * items and taxes (ie, no promotions or surcharges or cancellations needed)
419
+	 *
420
+	 * @param EE_Payment $payment
421
+	 * @return boolean
422
+	 * @throws EE_Error
423
+	 * @throws ReflectionException
424
+	 */
425
+	protected function _can_easily_itemize_transaction_for(EE_Payment $payment): bool
426
+	{
427
+		return $this->_money->compare_floats(
428
+			$this->_sum_items_and_taxes($payment->transaction()),
429
+			$payment->transaction()->total()
430
+		)
431
+			   && $this->_money->compare_floats(
432
+				   $payment->amount(),
433
+				   $payment->transaction()->total()
434
+			   );
435
+	}
436
+
437
+
438
+	/**
439
+	 * Handles updating the transaction and any other related data based on the payment.
440
+	 * You may be tempted to do this as part of do_direct_payment or handle_payment_update,
441
+	 * but doing so on those functions might be too early. It's possible that the changes
442
+	 * you make to teh transaction or registration or line items may just get overwritten
443
+	 * at that point. Instead, you should store any info you need on the payment during those
444
+	 * functions, and use that information at this step, which client code will decide
445
+	 * for you when it should be called.
446
+	 *
447
+	 * @param EE_Payment $payment
448
+	 * @return void
449
+	 */
450
+	public function update_txn_based_on_payment($payment)
451
+	{
452
+		// maybe update the transaction or line items or registrations
453
+		// but most gateways don't need to do this, because they only update the payment
454
+	}
455
+
456
+
457
+	/**
458
+	 * Gets the first event for this payment (it's possible that it could be for multiple)
459
+	 *
460
+	 * @param EE_Payment $payment
461
+	 * @return EE_Event|null
462
+	 * @deprecated since 4.9.31 instead use EE_Payment::get_first_event()
463
+	 */
464
+	protected function _get_first_event_for_payment(EE_Payment $payment): ?EE_Event
465
+	{
466
+		return $payment->get_first_event();
467
+	}
468
+
469
+
470
+	/**
471
+	 * Gets the name of the first event for which is being paid
472
+	 *
473
+	 * @param EE_Payment $payment
474
+	 * @return string
475
+	 * @deprecated since 4.9.31 instead use EE_Payment::get_first_event_name()
476
+	 */
477
+	protected function _get_first_event_name_for_payment(EE_Payment $payment): string
478
+	{
479
+		return $payment->get_first_event_name();
480
+	}
481
+
482
+
483
+	/**
484
+	 * Gets the text to use for a gateway's line item name when this is a partial payment
485
+	 *
486
+	 * @param EE_Payment $payment
487
+	 * @return string
488
+	 * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment)
489
+	 */
490
+	protected function _format_partial_payment_line_item_name(EE_Payment $payment): string
491
+	{
492
+		return $this->_get_gateway_formatter()->formatPartialPaymentLineItemName($payment);
493
+	}
494
+
495
+
496
+	/**
497
+	 * Gets the text to use for a gateway's line item description when this is a partial payment
498
+	 *
499
+	 * @param EE_Payment $payment
500
+	 * @return string
501
+	 * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc()
502
+	 */
503
+	protected function _format_partial_payment_line_item_desc(EE_Payment $payment): string
504
+	{
505
+		return $this->_get_gateway_formatter()->formatPartialPaymentLineItemDesc($payment);
506
+	}
507
+
508
+
509
+	/**
510
+	 * Gets the name to use for a line item when sending line items to the gateway
511
+	 *
512
+	 * @param EE_Line_Item $line_item
513
+	 * @param EE_Payment   $payment
514
+	 * @return string
515
+	 * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemName($line_item,$payment)
516
+	 */
517
+	protected function _format_line_item_name(EE_Line_Item $line_item, EE_Payment $payment): string
518
+	{
519
+		return $this->_get_gateway_formatter()->formatLineItemName($line_item, $payment);
520
+	}
521
+
522
+
523
+	/**
524
+	 * Gets the description to use for a line item when sending line items to the gateway
525
+	 *
526
+	 * @param EE_Line_Item $line_item
527
+	 * @param EE_Payment   $payment
528
+	 * @return string
529
+	 * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment))
530
+	 */
531
+	protected function _format_line_item_desc(EE_Line_Item $line_item, EE_Payment $payment): string
532
+	{
533
+		return $this->_get_gateway_formatter()->formatLineItemDesc($line_item, $payment);
534
+	}
535
+
536
+
537
+	/**
538
+	 * Gets the order description that should generlly be sent to gateways
539
+	 *
540
+	 * @param EE_Payment $payment
541
+	 * @return string
542
+	 * @deprecated since 4.9.31 instead use $this->_get_gateway_formatter()->formatOrderDescription($payment)
543
+	 */
544
+	protected function _format_order_description(EE_Payment $payment): string
545
+	{
546
+		return $this->_get_gateway_formatter()->formatOrderDescription($payment);
547
+	}
548
+
549
+
550
+	/**
551
+	 * @return bool
552
+	 */
553
+	public function isInSandboxMode(): bool
554
+	{
555
+		return $this->_debug_mode;
556
+	}
557 557
 }
Please login to merge, or discard this patch.
form_sections/inputs/EE_Checkbox_Dropdown_Selector_Input.input.php 1 patch
Indentation   +53 added lines, -53 removed lines patch added patch discarded remove patch
@@ -12,64 +12,64 @@
 block discarded – undo
12 12
  */
13 13
 class EE_Checkbox_Dropdown_Selector_Input extends EE_Form_Input_With_Options_Base
14 14
 {
15
-    /**
16
-     * @var string text to display on the select button itself
17
-     */
18
-    protected $_select_button_text;
15
+	/**
16
+	 * @var string text to display on the select button itself
17
+	 */
18
+	protected $_select_button_text;
19 19
 
20
-    /**
21
-     * @param array $answer_options
22
-     * @param array $input_settings
23
-     */
24
-    public function __construct($answer_options, $input_settings = array())
25
-    {
26
-        $this->_select_button_text = EEH_Array::is_set(
27
-            $input_settings,
28
-            'select_button_text',
29
-            esc_html__('Select', 'event_espresso')
30
-        );
31
-        $display_strategy = new EE_Checkbox_Dropdown_Selector_Display_Strategy();
32
-        $this->_set_display_strategy($display_strategy);
33
-        $this->load_iframe_assets($display_strategy);
34
-        $this->_add_validation_strategy(
35
-            new EE_Many_Valued_Validation_Strategy(
36
-                array(
37
-                    new EE_Enum_Validation_Strategy(
38
-                        isset($input_settings['validation_error_message'])
39
-                            ? $input_settings['validation_error_message']
40
-                            : null
41
-                    ),
42
-                )
43
-            )
44
-        );
45
-        $this->_multiple_selections = true;
46
-        parent::__construct($answer_options, $input_settings);
47
-    }
20
+	/**
21
+	 * @param array $answer_options
22
+	 * @param array $input_settings
23
+	 */
24
+	public function __construct($answer_options, $input_settings = array())
25
+	{
26
+		$this->_select_button_text = EEH_Array::is_set(
27
+			$input_settings,
28
+			'select_button_text',
29
+			esc_html__('Select', 'event_espresso')
30
+		);
31
+		$display_strategy = new EE_Checkbox_Dropdown_Selector_Display_Strategy();
32
+		$this->_set_display_strategy($display_strategy);
33
+		$this->load_iframe_assets($display_strategy);
34
+		$this->_add_validation_strategy(
35
+			new EE_Many_Valued_Validation_Strategy(
36
+				array(
37
+					new EE_Enum_Validation_Strategy(
38
+						isset($input_settings['validation_error_message'])
39
+							? $input_settings['validation_error_message']
40
+							: null
41
+					),
42
+				)
43
+			)
44
+		);
45
+		$this->_multiple_selections = true;
46
+		parent::__construct($answer_options, $input_settings);
47
+	}
48 48
 
49
-    /*
49
+	/*
50 50
      * Returns the text to display in the select button
51 51
      */
52
-    public function select_button_text()
53
-    {
54
-        return $this->_select_button_text;
55
-    }
52
+	public function select_button_text()
53
+	{
54
+		return $this->_select_button_text;
55
+	}
56 56
 
57
-    /*
57
+	/*
58 58
      * add css and js for iframes
59 59
      */
60
-    protected function load_iframe_assets(EE_Checkbox_Dropdown_Selector_Display_Strategy $display_strategy)
61
-    {
62
-        add_filter(
63
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
64
-            array($display_strategy, 'iframe_css')
65
-        );
66
-        add_filter(
67
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
68
-            array($display_strategy, 'iframe_js')
69
-        );
70
-        add_filter(
71
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
72
-            array($display_strategy, 'iframe_css')
73
-        );
74
-    }
60
+	protected function load_iframe_assets(EE_Checkbox_Dropdown_Selector_Display_Strategy $display_strategy)
61
+	{
62
+		add_filter(
63
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
64
+			array($display_strategy, 'iframe_css')
65
+		);
66
+		add_filter(
67
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
68
+			array($display_strategy, 'iframe_js')
69
+		);
70
+		add_filter(
71
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
72
+			array($display_strategy, 'iframe_css')
73
+		);
74
+	}
75 75
 }
Please login to merge, or discard this patch.