Completed
Branch dev (c88ce1)
by
unknown
08:25 queued 05:52
created
admin_pages/transactions/help_tabs/transactions_overview.help_tab.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -8,15 +8,15 @@
 block discarded – undo
8 8
     <strong><?php esc_html_e('Recommendations', 'event_espresso'); ?></strong>
9 9
     <br />
10 10
     <?php esc_html_e(
11
-        'To learn more about the options on this page, take a look at the different tabs that appear on the left side of the page.',
12
-        'event_espresso'
13
-    ); ?>
11
+		'To learn more about the options on this page, take a look at the different tabs that appear on the left side of the page.',
12
+		'event_espresso'
13
+	); ?>
14 14
 </p>
15 15
 <p>
16 16
     <strong><?php esc_html_e('Screen Options', 'event_espresso'); ?></strong>
17 17
     <br />
18 18
     <?php esc_html_e(
19
-        'You can customize the information that is shown on this page by toggling the Screen Options tab. Then you can add or remove checkmarks to hide or show certain content and even adjust the pagination for transactions.',
20
-        'event_espresso'
21
-    ); ?>
19
+		'You can customize the information that is shown on this page by toggling the Screen Options tab. Then you can add or remove checkmarks to hide or show certain content and even adjust the pagination for transactions.',
20
+		'event_espresso'
21
+	); ?>
22 22
 </p>
23 23
\ No newline at end of file
Please login to merge, or discard this patch.
admin_pages/registration_form/Registration_Form_Admin_Page.core.php 1 patch
Indentation   +756 added lines, -756 removed lines patch added patch discarded remove patch
@@ -16,699 +16,699 @@  discard block
 block discarded – undo
16 16
 class Registration_Form_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * holds the specific question object for the question details screen
21
-     *
22
-     * @var EE_Question $_question
23
-     */
24
-    protected $_question;
25
-
26
-    /**
27
-     * holds the specific question group object for the question group details screen
28
-     *
29
-     * @var EE_Question_Group $_question_group
30
-     */
31
-    protected $_question_group;
32
-
33
-    /**
34
-     *_question_model EEM_Question model instance (for queries)
35
-     *
36
-     * @var EEM_Question $_question_model ;
37
-     */
38
-    protected $_question_model;
39
-
40
-    /**
41
-     * _question_group_model EEM_Question_group instance (for queries)
42
-     *
43
-     * @var EEM_Question_Group $_question_group_model
44
-     */
45
-    protected $_question_group_model;
46
-
47
-
48
-    /**
49
-     * @Constructor
50
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
51
-     * @throws EE_Error
52
-     * @throws ReflectionException
53
-     */
54
-    public function __construct($routing = true)
55
-    {
56
-        require_once(EE_MODELS . 'EEM_Question.model.php');
57
-        require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
-        $this->_question_model       = EEM_Question::instance();
59
-        $this->_question_group_model = EEM_Question_Group::instance();
60
-        parent::__construct($routing);
61
-    }
62
-
63
-
64
-    protected function _init_page_props()
65
-    {
66
-        $this->page_slug        = REGISTRATION_FORM_PG_SLUG;
67
-        $this->page_label       = esc_html__('Registration Form', 'event_espresso');
68
-        $this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
69
-        $this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
-    }
71
-
72
-
73
-    protected function _ajax_hooks()
74
-    {
75
-    }
76
-
77
-
78
-    protected function _define_page_props()
79
-    {
80
-        $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
-        $this->_labels           = [
82
-            'buttons' => [
83
-                'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
-            ],
85
-        ];
86
-    }
87
-
88
-
89
-    /**
90
-     *_set_page_routes
91
-     */
92
-    protected function _set_page_routes()
93
-    {
94
-        $qst_id             =
95
-            ! empty($this->_req_data['QST_ID'])
96
-                ? $this->_req_data['QST_ID']
97
-                : 0;
98
-        $this->_page_routes = [
99
-            'default' => [
100
-                'func'       => '_questions_overview_list_table',
101
-                'capability' => 'ee_read_questions',
102
-            ],
103
-
104
-            'edit_question' => [
105
-                'func'       => '_edit_question',
106
-                'capability' => 'ee_edit_question',
107
-                'obj_id'     => $qst_id,
108
-                'args'       => ['edit'],
109
-            ],
110
-
111
-            'question_groups' => [
112
-                'func'       => '_questions_groups_preview',
113
-                'capability' => 'ee_read_question_groups',
114
-            ],
115
-
116
-            'update_question' => [
117
-                'func'       => '_insert_or_update_question',
118
-                'args'       => ['new_question' => false],
119
-                'capability' => 'ee_edit_question',
120
-                'obj_id'     => $qst_id,
121
-                'noheader'   => true,
122
-            ],
123
-        ];
124
-    }
125
-
126
-
127
-    protected function _set_page_config()
128
-    {
129
-        $this->_page_config = [
130
-            'default' => [
131
-                'nav'           => [
132
-                    'label' => esc_html__('Questions', 'event_espresso'),
133
-                    'order' => 10,
134
-                ],
135
-                'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
136
-                'metaboxes'     => $this->_default_espresso_metaboxes,
137
-                'help_tabs'     => [
138
-                    'registration_form_questions_overview_help_tab'                           => [
139
-                        'title'    => esc_html__('Questions Overview', 'event_espresso'),
140
-                        'filename' => 'registration_form_questions_overview',
141
-                    ],
142
-                    'registration_form_questions_overview_table_column_headings_help_tab'     => [
143
-                        'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
144
-                        'filename' => 'registration_form_questions_overview_table_column_headings',
145
-                    ],
146
-                    'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
147
-                        'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
148
-                        'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
149
-                    ],
150
-                ],
151
-                'require_nonce' => false,
152
-                'qtips'         => [
153
-                    'EE_Registration_Form_Tips',
154
-                ]/**/
155
-            ],
156
-
157
-            'question_groups' => [
158
-                'nav'           => [
159
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
160
-                    'order' => 20,
161
-                ],
162
-                'metaboxes'     => $this->_default_espresso_metaboxes,
163
-                'help_tabs'     => [
164
-                    'registration_form_question_groups_help_tab' => [
165
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
166
-                        'filename' => 'registration_form_question_groups',
167
-                    ],
168
-                ],
169
-                'require_nonce' => false,
170
-            ],
171
-
172
-            'edit_question' => [
173
-                'nav'           => [
174
-                    'label'      => esc_html__('Edit Question', 'event_espresso'),
175
-                    'order'      => 15,
176
-                    'persistent' => false,
177
-                    'url'        => isset($this->_req_data['question_id'])
178
-                        ? add_query_arg(
179
-                            ['question_id' => $this->_req_data['question_id']],
180
-                            $this->_current_page_view_url
181
-                        )
182
-                        : $this->_admin_base_url,
183
-                ],
184
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
185
-                'help_tabs'     => [
186
-                    'registration_form_edit_question_group_help_tab' => [
187
-                        'title'    => esc_html__('Edit Question', 'event_espresso'),
188
-                        'filename' => 'registration_form_edit_question',
189
-                    ],
190
-                ],
191
-                'require_nonce' => false,
192
-            ],
193
-        ];
194
-    }
195
-
196
-
197
-    protected function _add_screen_options()
198
-    {
199
-        // todo
200
-    }
201
-
202
-
203
-    protected function _add_screen_options_default()
204
-    {
205
-        $page_title              = $this->_admin_page_title;
206
-        $this->_admin_page_title = esc_html__('Questions', 'event_espresso');
207
-        $this->_per_page_screen_option();
208
-        $this->_admin_page_title = $page_title;
209
-    }
210
-
211
-
212
-    protected function _add_screen_options_question_groups()
213
-    {
214
-        $page_title              = $this->_admin_page_title;
215
-        $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
216
-        $this->_per_page_screen_option();
217
-        $this->_admin_page_title = $page_title;
218
-    }
219
-
220
-
221
-    // none of the below group are currently used for Event Categories
222
-    protected function _add_feature_pointers()
223
-    {
224
-    }
225
-
226
-
227
-    public function load_scripts_styles()
228
-    {
229
-        wp_register_style(
230
-            'espresso_registration',
231
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
232
-            [],
233
-            EVENT_ESPRESSO_VERSION
234
-        );
235
-        wp_enqueue_style('espresso_registration');
236
-    }
237
-
238
-
239
-    public function admin_init()
240
-    {
241
-    }
242
-
243
-
244
-    public function admin_notices()
245
-    {
246
-    }
247
-
248
-
249
-    public function admin_footer_scripts()
250
-    {
251
-    }
252
-
253
-
254
-    public function load_scripts_styles_default()
255
-    {
256
-    }
257
-
258
-
259
-    /**
260
-     * @throws EE_Error
261
-     */
262
-    public function load_scripts_styles_add_question()
263
-    {
264
-        $this->load_scripts_styles_question_details();
265
-    }
266
-
267
-
268
-    /**
269
-     * @throws EE_Error
270
-     */
271
-    public function load_scripts_styles_edit_question()
272
-    {
273
-        $this->load_scripts_styles_question_details();
274
-    }
275
-
276
-
277
-    /**
278
-     * Loads the JS required for adding or editing a question
279
-     *
280
-     * @throws EE_Error
281
-     * @throws EE_Error
282
-     */
283
-    protected function load_scripts_styles_question_details()
284
-    {
285
-        $this->load_scripts_styles_forms();
286
-        wp_register_script(
287
-            'espresso_registration_form_single',
288
-            REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
289
-            ['jquery-ui-sortable'],
290
-            EVENT_ESPRESSO_VERSION,
291
-            true
292
-        );
293
-        wp_enqueue_script('espresso_registration_form_single');
294
-        wp_localize_script(
295
-            'espresso_registration_form_single',
296
-            'ee_question_data',
297
-            [
298
-                'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
299
-                'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
300
-            ]
301
-        );
302
-    }
303
-
304
-
305
-    public function recaptcha_info_help_tab()
306
-    {
307
-        $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
308
-        EEH_Template::display_template($template, []);
309
-    }
310
-
311
-
312
-    public function load_scripts_styles_forms()
313
-    {
314
-        // styles
315
-        wp_enqueue_style('espresso-ui-theme');
316
-        // scripts
317
-        wp_enqueue_script('ee_admin_js');
318
-    }
319
-
320
-
321
-    protected function _set_list_table_views_default()
322
-    {
323
-        $this->_views = [
324
-            'all' => [
325
-                'slug'  => 'all',
326
-                'label' => esc_html__('View All Questions', 'event_espresso'),
327
-                'count' => 0,
328
-            ],
329
-        ];
330
-
331
-        if (
332
-            EE_Registry::instance()->CAP->current_user_can(
333
-                'ee_delete_questions',
334
-                'espresso_registration_form_trash_questions'
335
-            )
336
-        ) {
337
-            $this->_views['trash'] = [
338
-                'slug'  => 'trash',
339
-                'label' => esc_html__('Trash', 'event_espresso'),
340
-                'count' => 0,
341
-            ];
342
-        }
343
-    }
344
-
345
-
346
-    /**
347
-     * This just previews the question groups tab that comes in caffeinated.
348
-     *
349
-     * @return void html
350
-     * @throws EE_Error
351
-     */
352
-    protected function _questions_groups_preview()
353
-    {
354
-        $this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
355
-        $this->_template_args['preview_img']  =
356
-            '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
357
-            . esc_attr__(
358
-                'Preview Question Groups Overview List Table screenshot',
359
-                'event_espresso'
360
-            ) . '" />';
361
-        $this->_template_args['preview_text'] = '<strong>'
362
-                                                . esc_html__(
363
-                                                    'Question Groups 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 Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
364
-                                                    'event_espresso'
365
-                                                ) . '</strong>';
366
-        $this->display_admin_caf_preview_page('question_groups_tab');
367
-    }
368
-
369
-
370
-    /**
371
-     * Extracts the question field's values from the POST request to update or insert them
372
-     *
373
-     * @param EEM_Base $model
374
-     * @return array where each key is the name of a model's field/db column, and each value is its value.
375
-     * @throws EE_Error
376
-     */
377
-    protected function _set_column_values_for(EEM_Base $model)
378
-    {
379
-        $question_model = EEM_Question::instance();
380
-        $set_column_values = [];
381
-
382
-        // some initial checks for proper values.
383
-        // if QST_admin_only, then no matter what QST_required is we disable.
384
-        if (! empty($this->_req_data['QST_admin_only'])) {
385
-            $this->_req_data['QST_required'] = 0;
386
-        }
387
-        // if the question shouldn't have a max length, don't let them set one
388
-        if (
389
-            ! isset(
390
-                $this->_req_data['QST_type'],
391
-                $this->_req_data['QST_max']
392
-            )
393
-            || ! in_array(
394
-                $this->_req_data['QST_type'],
395
-                $question_model->questionTypesWithMaxLength(),
396
-                true
397
-            )
398
-        ) {
399
-            // they're not allowed to set the max
400
-            $this->_req_data['QST_max'] = null;
401
-        }
402
-        foreach ($model->field_settings() as $fieldName => $settings) {
403
-            // basically if QSG_identifier is empty or not set
404
-            if (
405
-                $fieldName === 'QSG_identifier'
406
-                && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))
407
-            ) {
408
-                $QSG_name = $this->_req_data['QSG_name'] ?? '';
409
-                $set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
410
-            } elseif (
411
-                $fieldName === 'QST_admin_label'
412
-                && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))
413
-            ) {
414
-                // the admin label is blank, use a slug version of the question text
415
-                $QST_text = $this->_req_data['QST_display_text'] ?? '';
416
-                $set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
417
-            } elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
418
-                $set_column_values[ $fieldName ] = 0;
419
-            } elseif ($fieldName === 'QST_max') {
420
-                $qst_system = $question_model->get_var(
421
-                    [
422
-                        [
423
-                            'QST_ID' => $this->_req_data['QST_ID'] ?? 0,
424
-                        ],
425
-                    ],
426
-                    'QST_system'
427
-                );
428
-                $max_max    = $question_model->absolute_max_for_system_question((string) $qst_system);
429
-                if (empty($this->_req_data['QST_max']) || $this->_req_data['QST_max'] > $max_max) {
430
-                    $set_column_values[ $fieldName ] = $max_max;
431
-                }
432
-            }
433
-
434
-
435
-            // only add a property to the array if it's not null (otherwise the model should just use the default value)
436
-            if (
437
-                ! isset($set_column_values[ $fieldName ]) && isset($this->_req_data[ $fieldName ])
438
-            ) {
439
-                $set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
440
-            }
441
-        }
442
-        // validation fo this data to be performed by the model before insertion.
443
-        return $set_column_values;
444
-    }
445
-
446
-
447
-    /**
448
-     *_questions_overview_list_table
449
-     *
450
-     * @throws EE_Error
451
-     */
452
-    protected function _questions_overview_list_table()
453
-    {
454
-        $this->_search_btn_label = esc_html__('Questions', 'event_espresso');
455
-        $this->display_admin_list_table_page_with_sidebar();
456
-    }
457
-
458
-
459
-    /**
460
-     * _edit_question
461
-     *
462
-     * @throws EE_Error
463
-     * @throws ReflectionException
464
-     */
465
-    protected function _edit_question()
466
-    {
467
-        $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
468
-            ? absint($this->_req_data['QST_ID'])
469
-            : false;
470
-
471
-        switch ($this->_req_action) {
472
-            case 'add_question':
473
-                $this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
474
-                break;
475
-            case 'edit_question':
476
-                $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
477
-                break;
478
-            default:
479
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
480
-        }
481
-
482
-        // add PRC_ID to title if editing
483
-        $this->_admin_page_title =
484
-            $ID
485
-                ? $this->_admin_page_title . ' # ' . $ID
486
-                : $this->_admin_page_title;
487
-        if ($ID) {
488
-            $question                 = $this->_question_model->get_one_by_ID($ID);
489
-            $additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
490
-            $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
491
-        } else {
492
-            $question = EE_Question::new_instance();
493
-            $question->set_order_to_latest();
494
-            $this->_set_add_edit_form_tags('insert_question');
495
-        }
496
-        if ($question->system_ID() === EEM_Attendee::system_question_phone) {
497
-            $question_types = array_intersect_key(
498
-                EEM_Question::instance()->allowed_question_types(),
499
-                array_flip(
500
-                    [
501
-                        EEM_Question::QST_type_text,
502
-                        EEM_Question::QST_type_us_phone,
503
-                    ]
504
-                )
505
-            );
506
-        } else {
507
-            $question_types = $question->has_answers()
508
-                ? $this->_question_model->question_types_in_same_category($question->type())
509
-                : $this->_question_model->allowed_question_types();
510
-        }
511
-        $this->_template_args['QST_ID']                     = $ID;
512
-        $this->_template_args['question']                   = $question;
513
-        $this->_template_args['question_types']             = $question_types;
514
-        $this->_template_args['max_max']                    =
515
-            EEM_Question::instance()->absolute_max_for_system_question(
516
-                $question->system_ID()
517
-            );
518
-        $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
519
-        $this->_set_publish_post_box_vars('id', $ID);
520
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
521
-            REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
522
-            $this->_template_args,
523
-            true
524
-        );
525
-
526
-        // the details template wrapper
527
-        $this->display_admin_page_with_sidebar();
528
-    }
529
-
530
-
531
-    /**
532
-     * @return string
533
-     * @throws EE_Error
534
-     * @throws ReflectionException
535
-     */
536
-    protected function _get_question_type_descriptions()
537
-    {
538
-        EE_Registry::instance()->load_helper('HTML');
539
-        $descriptions               = '';
540
-        $question_type_descriptions = EEM_Question::instance()->question_descriptions();
541
-        foreach ($question_type_descriptions as $type => $question_type_description) {
542
-            if ($type == 'HTML_TEXTAREA') {
543
-                $html                      = new EE_Simple_HTML_Validation_Strategy();
544
-                $question_type_description .= sprintf(
545
-                    esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
546
-                    '<br/>',
547
-                    $html->get_list_of_allowed_tags()
548
-                );
549
-            }
550
-            $descriptions .= EEH_HTML::p(
551
-                $question_type_description,
552
-                'question_type_description-' . $type,
553
-                'question_type_description description',
554
-                'display:none;'
555
-            );
556
-        }
557
-        return $descriptions;
558
-    }
559
-
560
-
561
-    /**
562
-     * @param bool|true $new_question
563
-     * @throws EE_Error
564
-     * @throws ReflectionException
565
-     */
566
-    protected function _insert_or_update_question($new_question = true)
567
-    {
568
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
569
-        $set_column_values = $this->_set_column_values_for($this->_question_model);
570
-        if ($new_question) {
571
-            $question    = EE_Question::new_instance($set_column_values);
572
-            $action_desc = 'added';
573
-        } else {
574
-            $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
575
-            foreach ($set_column_values as $field => $new_value) {
576
-                $question->set($field, $new_value);
577
-            }
578
-            $action_desc = 'updated';
579
-        }
580
-        $success = $question->save();
581
-        $ID      = $question->ID();
582
-        if ($ID && $question->should_have_question_options()) {
583
-            // save the related options
584
-            // trash removed options, save old ones
585
-            // get list of all options
586
-            $options = $question->options();
587
-            if (! empty($options)) {
588
-                foreach ($options as $option_ID => $option) {
589
-                    $option_req_index = $this->_get_option_req_data_index($option_ID);
590
-                    if ($option_req_index !== false) {
591
-                        $option->save($this->_req_data['question_options'][ $option_req_index ]);
592
-                    } else {
593
-                        // not found, remove it
594
-                        $option->delete();
595
-                    }
596
-                }
597
-            }
598
-            // save new related options
599
-            foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
600
-                // skip $index that is from our sample
601
-                if ($index === 'xxcountxx') {
602
-                    continue;
603
-                }
604
-                // note we allow saving blank options.
605
-                if (empty($option_req_data['QSO_ID'])) {
606
-                    // no ID! save it!
607
-                    $new_option = EE_Question_Option::new_instance(
608
-                        [
609
-                            'QSO_value' => $option_req_data['QSO_value'],
610
-                            'QSO_desc'  => $option_req_data['QSO_desc'],
611
-                            'QSO_order' => $option_req_data['QSO_order'],
612
-                            'QST_ID'    => $question->ID(),
613
-                        ]
614
-                    );
615
-                    $new_option->save();
616
-                }
617
-            }
618
-        }
619
-        $query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
620
-        if ($success !== 0) {
621
-            $msg = $new_question
622
-                ? sprintf(
623
-                    esc_html__('The %s has been created', 'event_espresso'),
624
-                    $this->_question_model->item_name()
625
-                )
626
-                : sprintf(
627
-                    esc_html__('The %s has been updated', 'event_espresso'),
628
-                    $this->_question_model->item_name()
629
-                );
630
-            EE_Error::add_success($msg);
631
-        }
632
-
633
-        $this->_redirect_after_action(false, '', $action_desc, $query_args, true);
634
-    }
635
-
636
-
637
-    /**
638
-     * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
639
-     * by ID
640
-     * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
641
-     * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
642
-     *
643
-     * @param int $ID of the question option to find
644
-     * @return int index in question_options array if successful, FALSE if unsuccessful
645
-     */
646
-    protected function _get_option_req_data_index($ID)
647
-    {
648
-        $req_data_for_question_options = $this->_req_data['question_options'];
649
-        foreach ($req_data_for_question_options as $num => $option_data) {
650
-            if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
651
-                return $num;
652
-            }
653
-        }
654
-        return false;
655
-    }
656
-
657
-
658
-
659
-
660
-    /***********/
661
-    /* QUERIES */
662
-    /**
663
-     * For internal use in getting all the query parameters
664
-     * (because it's pretty well the same between question, question groups,
665
-     * and for both when searching for trashed and untrashed ones)
666
-     *
667
-     * @param EEM_Base $model either EEM_Question or EEM_Question_Group
668
-     * @param int      $per_page
669
-     * @param int      $current_page
670
-     * @return array model query params, @see
671
-     *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
672
-     */
673
-    protected function get_query_params($model, $per_page = 10, $current_page = 10)
674
-    {
675
-        $query_params             = [];
676
-        $offset                   = ($current_page - 1) * $per_page;
677
-        $query_params['limit']    = [$offset, $per_page];
678
-        $order                    =
679
-            (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
680
-                ? $this->_req_data['order']
681
-                : 'ASC';
682
-        $orderby_field            =
683
-            $model instanceof EEM_Question
684
-                ? 'QST_ID'
685
-                : 'QSG_order';
686
-        $field_to_order_by        =
687
-            empty($this->_req_data['orderby'])
688
-                ? $orderby_field
689
-                : $this->_req_data['orderby'];
690
-        $query_params['order_by'] = [$field_to_order_by => $order];
691
-        $search_string            =
692
-            array_key_exists('s', $this->_req_data)
693
-                ? $this->_req_data['s']
694
-                : null;
695
-        if (! empty($search_string)) {
696
-            if ($model instanceof EEM_Question_Group) {
697
-                $query_params[0] = [
698
-                    'OR' => [
699
-                        'QSG_name' => ['LIKE', "%$search_string%"],
700
-                        'QSG_desc' => ['LIKE', "%$search_string%"],
701
-                    ],
702
-                ];
703
-            } else {
704
-                $query_params[0] = [
705
-                    'QST_display_text' => ['LIKE', "%$search_string%"],
706
-                ];
707
-            }
708
-        }
709
-
710
-        // capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
711
-        /*if ( $model instanceof EEM_Question_Group ) {
19
+	/**
20
+	 * holds the specific question object for the question details screen
21
+	 *
22
+	 * @var EE_Question $_question
23
+	 */
24
+	protected $_question;
25
+
26
+	/**
27
+	 * holds the specific question group object for the question group details screen
28
+	 *
29
+	 * @var EE_Question_Group $_question_group
30
+	 */
31
+	protected $_question_group;
32
+
33
+	/**
34
+	 *_question_model EEM_Question model instance (for queries)
35
+	 *
36
+	 * @var EEM_Question $_question_model ;
37
+	 */
38
+	protected $_question_model;
39
+
40
+	/**
41
+	 * _question_group_model EEM_Question_group instance (for queries)
42
+	 *
43
+	 * @var EEM_Question_Group $_question_group_model
44
+	 */
45
+	protected $_question_group_model;
46
+
47
+
48
+	/**
49
+	 * @Constructor
50
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
51
+	 * @throws EE_Error
52
+	 * @throws ReflectionException
53
+	 */
54
+	public function __construct($routing = true)
55
+	{
56
+		require_once(EE_MODELS . 'EEM_Question.model.php');
57
+		require_once(EE_MODELS . 'EEM_Question_Group.model.php');
58
+		$this->_question_model       = EEM_Question::instance();
59
+		$this->_question_group_model = EEM_Question_Group::instance();
60
+		parent::__construct($routing);
61
+	}
62
+
63
+
64
+	protected function _init_page_props()
65
+	{
66
+		$this->page_slug        = REGISTRATION_FORM_PG_SLUG;
67
+		$this->page_label       = esc_html__('Registration Form', 'event_espresso');
68
+		$this->_admin_base_url  = REGISTRATION_FORM_ADMIN_URL;
69
+		$this->_admin_base_path = REGISTRATION_FORM_ADMIN;
70
+	}
71
+
72
+
73
+	protected function _ajax_hooks()
74
+	{
75
+	}
76
+
77
+
78
+	protected function _define_page_props()
79
+	{
80
+		$this->_admin_page_title = esc_html__('Registration Form', 'event_espresso');
81
+		$this->_labels           = [
82
+			'buttons' => [
83
+				'edit_question' => esc_html__('Edit Question', 'event_espresso'),
84
+			],
85
+		];
86
+	}
87
+
88
+
89
+	/**
90
+	 *_set_page_routes
91
+	 */
92
+	protected function _set_page_routes()
93
+	{
94
+		$qst_id             =
95
+			! empty($this->_req_data['QST_ID'])
96
+				? $this->_req_data['QST_ID']
97
+				: 0;
98
+		$this->_page_routes = [
99
+			'default' => [
100
+				'func'       => '_questions_overview_list_table',
101
+				'capability' => 'ee_read_questions',
102
+			],
103
+
104
+			'edit_question' => [
105
+				'func'       => '_edit_question',
106
+				'capability' => 'ee_edit_question',
107
+				'obj_id'     => $qst_id,
108
+				'args'       => ['edit'],
109
+			],
110
+
111
+			'question_groups' => [
112
+				'func'       => '_questions_groups_preview',
113
+				'capability' => 'ee_read_question_groups',
114
+			],
115
+
116
+			'update_question' => [
117
+				'func'       => '_insert_or_update_question',
118
+				'args'       => ['new_question' => false],
119
+				'capability' => 'ee_edit_question',
120
+				'obj_id'     => $qst_id,
121
+				'noheader'   => true,
122
+			],
123
+		];
124
+	}
125
+
126
+
127
+	protected function _set_page_config()
128
+	{
129
+		$this->_page_config = [
130
+			'default' => [
131
+				'nav'           => [
132
+					'label' => esc_html__('Questions', 'event_espresso'),
133
+					'order' => 10,
134
+				],
135
+				'list_table'    => 'Registration_Form_Questions_Admin_List_Table',
136
+				'metaboxes'     => $this->_default_espresso_metaboxes,
137
+				'help_tabs'     => [
138
+					'registration_form_questions_overview_help_tab'                           => [
139
+						'title'    => esc_html__('Questions Overview', 'event_espresso'),
140
+						'filename' => 'registration_form_questions_overview',
141
+					],
142
+					'registration_form_questions_overview_table_column_headings_help_tab'     => [
143
+						'title'    => esc_html__('Questions Overview Table Column Headings', 'event_espresso'),
144
+						'filename' => 'registration_form_questions_overview_table_column_headings',
145
+					],
146
+					'registration_form_questions_overview_views_bulk_actions_search_help_tab' => [
147
+						'title'    => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'),
148
+						'filename' => 'registration_form_questions_overview_views_bulk_actions_search',
149
+					],
150
+				],
151
+				'require_nonce' => false,
152
+				'qtips'         => [
153
+					'EE_Registration_Form_Tips',
154
+				]/**/
155
+			],
156
+
157
+			'question_groups' => [
158
+				'nav'           => [
159
+					'label' => esc_html__('Question Groups', 'event_espresso'),
160
+					'order' => 20,
161
+				],
162
+				'metaboxes'     => $this->_default_espresso_metaboxes,
163
+				'help_tabs'     => [
164
+					'registration_form_question_groups_help_tab' => [
165
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
166
+						'filename' => 'registration_form_question_groups',
167
+					],
168
+				],
169
+				'require_nonce' => false,
170
+			],
171
+
172
+			'edit_question' => [
173
+				'nav'           => [
174
+					'label'      => esc_html__('Edit Question', 'event_espresso'),
175
+					'order'      => 15,
176
+					'persistent' => false,
177
+					'url'        => isset($this->_req_data['question_id'])
178
+						? add_query_arg(
179
+							['question_id' => $this->_req_data['question_id']],
180
+							$this->_current_page_view_url
181
+						)
182
+						: $this->_admin_base_url,
183
+				],
184
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
185
+				'help_tabs'     => [
186
+					'registration_form_edit_question_group_help_tab' => [
187
+						'title'    => esc_html__('Edit Question', 'event_espresso'),
188
+						'filename' => 'registration_form_edit_question',
189
+					],
190
+				],
191
+				'require_nonce' => false,
192
+			],
193
+		];
194
+	}
195
+
196
+
197
+	protected function _add_screen_options()
198
+	{
199
+		// todo
200
+	}
201
+
202
+
203
+	protected function _add_screen_options_default()
204
+	{
205
+		$page_title              = $this->_admin_page_title;
206
+		$this->_admin_page_title = esc_html__('Questions', 'event_espresso');
207
+		$this->_per_page_screen_option();
208
+		$this->_admin_page_title = $page_title;
209
+	}
210
+
211
+
212
+	protected function _add_screen_options_question_groups()
213
+	{
214
+		$page_title              = $this->_admin_page_title;
215
+		$this->_admin_page_title = esc_html__('Question Groups', 'event_espresso');
216
+		$this->_per_page_screen_option();
217
+		$this->_admin_page_title = $page_title;
218
+	}
219
+
220
+
221
+	// none of the below group are currently used for Event Categories
222
+	protected function _add_feature_pointers()
223
+	{
224
+	}
225
+
226
+
227
+	public function load_scripts_styles()
228
+	{
229
+		wp_register_style(
230
+			'espresso_registration',
231
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css',
232
+			[],
233
+			EVENT_ESPRESSO_VERSION
234
+		);
235
+		wp_enqueue_style('espresso_registration');
236
+	}
237
+
238
+
239
+	public function admin_init()
240
+	{
241
+	}
242
+
243
+
244
+	public function admin_notices()
245
+	{
246
+	}
247
+
248
+
249
+	public function admin_footer_scripts()
250
+	{
251
+	}
252
+
253
+
254
+	public function load_scripts_styles_default()
255
+	{
256
+	}
257
+
258
+
259
+	/**
260
+	 * @throws EE_Error
261
+	 */
262
+	public function load_scripts_styles_add_question()
263
+	{
264
+		$this->load_scripts_styles_question_details();
265
+	}
266
+
267
+
268
+	/**
269
+	 * @throws EE_Error
270
+	 */
271
+	public function load_scripts_styles_edit_question()
272
+	{
273
+		$this->load_scripts_styles_question_details();
274
+	}
275
+
276
+
277
+	/**
278
+	 * Loads the JS required for adding or editing a question
279
+	 *
280
+	 * @throws EE_Error
281
+	 * @throws EE_Error
282
+	 */
283
+	protected function load_scripts_styles_question_details()
284
+	{
285
+		$this->load_scripts_styles_forms();
286
+		wp_register_script(
287
+			'espresso_registration_form_single',
288
+			REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js',
289
+			['jquery-ui-sortable'],
290
+			EVENT_ESPRESSO_VERSION,
291
+			true
292
+		);
293
+		wp_enqueue_script('espresso_registration_form_single');
294
+		wp_localize_script(
295
+			'espresso_registration_form_single',
296
+			'ee_question_data',
297
+			[
298
+				'question_types_with_max'    => EEM_Question::instance()->questionTypesWithMaxLength(),
299
+				'question_type_with_options' => EEM_Question::instance()->question_types_with_options(),
300
+			]
301
+		);
302
+	}
303
+
304
+
305
+	public function recaptcha_info_help_tab()
306
+	{
307
+		$template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php';
308
+		EEH_Template::display_template($template, []);
309
+	}
310
+
311
+
312
+	public function load_scripts_styles_forms()
313
+	{
314
+		// styles
315
+		wp_enqueue_style('espresso-ui-theme');
316
+		// scripts
317
+		wp_enqueue_script('ee_admin_js');
318
+	}
319
+
320
+
321
+	protected function _set_list_table_views_default()
322
+	{
323
+		$this->_views = [
324
+			'all' => [
325
+				'slug'  => 'all',
326
+				'label' => esc_html__('View All Questions', 'event_espresso'),
327
+				'count' => 0,
328
+			],
329
+		];
330
+
331
+		if (
332
+			EE_Registry::instance()->CAP->current_user_can(
333
+				'ee_delete_questions',
334
+				'espresso_registration_form_trash_questions'
335
+			)
336
+		) {
337
+			$this->_views['trash'] = [
338
+				'slug'  => 'trash',
339
+				'label' => esc_html__('Trash', 'event_espresso'),
340
+				'count' => 0,
341
+			];
342
+		}
343
+	}
344
+
345
+
346
+	/**
347
+	 * This just previews the question groups tab that comes in caffeinated.
348
+	 *
349
+	 * @return void html
350
+	 * @throws EE_Error
351
+	 */
352
+	protected function _questions_groups_preview()
353
+	{
354
+		$this->_admin_page_title              = esc_html__('Question Groups (Preview)', 'event_espresso');
355
+		$this->_template_args['preview_img']  =
356
+			'<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="'
357
+			. esc_attr__(
358
+				'Preview Question Groups Overview List Table screenshot',
359
+				'event_espresso'
360
+			) . '" />';
361
+		$this->_template_args['preview_text'] = '<strong>'
362
+												. esc_html__(
363
+													'Question Groups 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 Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.',
364
+													'event_espresso'
365
+												) . '</strong>';
366
+		$this->display_admin_caf_preview_page('question_groups_tab');
367
+	}
368
+
369
+
370
+	/**
371
+	 * Extracts the question field's values from the POST request to update or insert them
372
+	 *
373
+	 * @param EEM_Base $model
374
+	 * @return array where each key is the name of a model's field/db column, and each value is its value.
375
+	 * @throws EE_Error
376
+	 */
377
+	protected function _set_column_values_for(EEM_Base $model)
378
+	{
379
+		$question_model = EEM_Question::instance();
380
+		$set_column_values = [];
381
+
382
+		// some initial checks for proper values.
383
+		// if QST_admin_only, then no matter what QST_required is we disable.
384
+		if (! empty($this->_req_data['QST_admin_only'])) {
385
+			$this->_req_data['QST_required'] = 0;
386
+		}
387
+		// if the question shouldn't have a max length, don't let them set one
388
+		if (
389
+			! isset(
390
+				$this->_req_data['QST_type'],
391
+				$this->_req_data['QST_max']
392
+			)
393
+			|| ! in_array(
394
+				$this->_req_data['QST_type'],
395
+				$question_model->questionTypesWithMaxLength(),
396
+				true
397
+			)
398
+		) {
399
+			// they're not allowed to set the max
400
+			$this->_req_data['QST_max'] = null;
401
+		}
402
+		foreach ($model->field_settings() as $fieldName => $settings) {
403
+			// basically if QSG_identifier is empty or not set
404
+			if (
405
+				$fieldName === 'QSG_identifier'
406
+				&& (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))
407
+			) {
408
+				$QSG_name = $this->_req_data['QSG_name'] ?? '';
409
+				$set_column_values[ $fieldName ] = sanitize_title($QSG_name) . '-' . uniqid('', true);
410
+			} elseif (
411
+				$fieldName === 'QST_admin_label'
412
+				&& (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))
413
+			) {
414
+				// the admin label is blank, use a slug version of the question text
415
+				$QST_text = $this->_req_data['QST_display_text'] ?? '';
416
+				$set_column_values[ $fieldName ] = sanitize_title(wp_trim_words($QST_text, 10));
417
+			} elseif ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) {
418
+				$set_column_values[ $fieldName ] = 0;
419
+			} elseif ($fieldName === 'QST_max') {
420
+				$qst_system = $question_model->get_var(
421
+					[
422
+						[
423
+							'QST_ID' => $this->_req_data['QST_ID'] ?? 0,
424
+						],
425
+					],
426
+					'QST_system'
427
+				);
428
+				$max_max    = $question_model->absolute_max_for_system_question((string) $qst_system);
429
+				if (empty($this->_req_data['QST_max']) || $this->_req_data['QST_max'] > $max_max) {
430
+					$set_column_values[ $fieldName ] = $max_max;
431
+				}
432
+			}
433
+
434
+
435
+			// only add a property to the array if it's not null (otherwise the model should just use the default value)
436
+			if (
437
+				! isset($set_column_values[ $fieldName ]) && isset($this->_req_data[ $fieldName ])
438
+			) {
439
+				$set_column_values[ $fieldName ] = $this->_req_data[ $fieldName ];
440
+			}
441
+		}
442
+		// validation fo this data to be performed by the model before insertion.
443
+		return $set_column_values;
444
+	}
445
+
446
+
447
+	/**
448
+	 *_questions_overview_list_table
449
+	 *
450
+	 * @throws EE_Error
451
+	 */
452
+	protected function _questions_overview_list_table()
453
+	{
454
+		$this->_search_btn_label = esc_html__('Questions', 'event_espresso');
455
+		$this->display_admin_list_table_page_with_sidebar();
456
+	}
457
+
458
+
459
+	/**
460
+	 * _edit_question
461
+	 *
462
+	 * @throws EE_Error
463
+	 * @throws ReflectionException
464
+	 */
465
+	protected function _edit_question()
466
+	{
467
+		$ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID'])
468
+			? absint($this->_req_data['QST_ID'])
469
+			: false;
470
+
471
+		switch ($this->_req_action) {
472
+			case 'add_question':
473
+				$this->_admin_page_title = esc_html__('Add Question', 'event_espresso');
474
+				break;
475
+			case 'edit_question':
476
+				$this->_admin_page_title = esc_html__('Edit Question', 'event_espresso');
477
+				break;
478
+			default:
479
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
480
+		}
481
+
482
+		// add PRC_ID to title if editing
483
+		$this->_admin_page_title =
484
+			$ID
485
+				? $this->_admin_page_title . ' # ' . $ID
486
+				: $this->_admin_page_title;
487
+		if ($ID) {
488
+			$question                 = $this->_question_model->get_one_by_ID($ID);
489
+			$additional_hidden_fields = ['QST_ID' => ['type' => 'hidden', 'value' => $ID]];
490
+			$this->_set_add_edit_form_tags('update_question', $additional_hidden_fields);
491
+		} else {
492
+			$question = EE_Question::new_instance();
493
+			$question->set_order_to_latest();
494
+			$this->_set_add_edit_form_tags('insert_question');
495
+		}
496
+		if ($question->system_ID() === EEM_Attendee::system_question_phone) {
497
+			$question_types = array_intersect_key(
498
+				EEM_Question::instance()->allowed_question_types(),
499
+				array_flip(
500
+					[
501
+						EEM_Question::QST_type_text,
502
+						EEM_Question::QST_type_us_phone,
503
+					]
504
+				)
505
+			);
506
+		} else {
507
+			$question_types = $question->has_answers()
508
+				? $this->_question_model->question_types_in_same_category($question->type())
509
+				: $this->_question_model->allowed_question_types();
510
+		}
511
+		$this->_template_args['QST_ID']                     = $ID;
512
+		$this->_template_args['question']                   = $question;
513
+		$this->_template_args['question_types']             = $question_types;
514
+		$this->_template_args['max_max']                    =
515
+			EEM_Question::instance()->absolute_max_for_system_question(
516
+				$question->system_ID()
517
+			);
518
+		$this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions();
519
+		$this->_set_publish_post_box_vars('id', $ID);
520
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
521
+			REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php',
522
+			$this->_template_args,
523
+			true
524
+		);
525
+
526
+		// the details template wrapper
527
+		$this->display_admin_page_with_sidebar();
528
+	}
529
+
530
+
531
+	/**
532
+	 * @return string
533
+	 * @throws EE_Error
534
+	 * @throws ReflectionException
535
+	 */
536
+	protected function _get_question_type_descriptions()
537
+	{
538
+		EE_Registry::instance()->load_helper('HTML');
539
+		$descriptions               = '';
540
+		$question_type_descriptions = EEM_Question::instance()->question_descriptions();
541
+		foreach ($question_type_descriptions as $type => $question_type_description) {
542
+			if ($type == 'HTML_TEXTAREA') {
543
+				$html                      = new EE_Simple_HTML_Validation_Strategy();
544
+				$question_type_description .= sprintf(
545
+					esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'),
546
+					'<br/>',
547
+					$html->get_list_of_allowed_tags()
548
+				);
549
+			}
550
+			$descriptions .= EEH_HTML::p(
551
+				$question_type_description,
552
+				'question_type_description-' . $type,
553
+				'question_type_description description',
554
+				'display:none;'
555
+			);
556
+		}
557
+		return $descriptions;
558
+	}
559
+
560
+
561
+	/**
562
+	 * @param bool|true $new_question
563
+	 * @throws EE_Error
564
+	 * @throws ReflectionException
565
+	 */
566
+	protected function _insert_or_update_question($new_question = true)
567
+	{
568
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
569
+		$set_column_values = $this->_set_column_values_for($this->_question_model);
570
+		if ($new_question) {
571
+			$question    = EE_Question::new_instance($set_column_values);
572
+			$action_desc = 'added';
573
+		} else {
574
+			$question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID']));
575
+			foreach ($set_column_values as $field => $new_value) {
576
+				$question->set($field, $new_value);
577
+			}
578
+			$action_desc = 'updated';
579
+		}
580
+		$success = $question->save();
581
+		$ID      = $question->ID();
582
+		if ($ID && $question->should_have_question_options()) {
583
+			// save the related options
584
+			// trash removed options, save old ones
585
+			// get list of all options
586
+			$options = $question->options();
587
+			if (! empty($options)) {
588
+				foreach ($options as $option_ID => $option) {
589
+					$option_req_index = $this->_get_option_req_data_index($option_ID);
590
+					if ($option_req_index !== false) {
591
+						$option->save($this->_req_data['question_options'][ $option_req_index ]);
592
+					} else {
593
+						// not found, remove it
594
+						$option->delete();
595
+					}
596
+				}
597
+			}
598
+			// save new related options
599
+			foreach ($this->_req_data['question_options'] as $index => $option_req_data) {
600
+				// skip $index that is from our sample
601
+				if ($index === 'xxcountxx') {
602
+					continue;
603
+				}
604
+				// note we allow saving blank options.
605
+				if (empty($option_req_data['QSO_ID'])) {
606
+					// no ID! save it!
607
+					$new_option = EE_Question_Option::new_instance(
608
+						[
609
+							'QSO_value' => $option_req_data['QSO_value'],
610
+							'QSO_desc'  => $option_req_data['QSO_desc'],
611
+							'QSO_order' => $option_req_data['QSO_order'],
612
+							'QST_ID'    => $question->ID(),
613
+						]
614
+					);
615
+					$new_option->save();
616
+				}
617
+			}
618
+		}
619
+		$query_args = ['action' => 'edit_question', 'QST_ID' => $ID];
620
+		if ($success !== 0) {
621
+			$msg = $new_question
622
+				? sprintf(
623
+					esc_html__('The %s has been created', 'event_espresso'),
624
+					$this->_question_model->item_name()
625
+				)
626
+				: sprintf(
627
+					esc_html__('The %s has been updated', 'event_espresso'),
628
+					$this->_question_model->item_name()
629
+				);
630
+			EE_Error::add_success($msg);
631
+		}
632
+
633
+		$this->_redirect_after_action(false, '', $action_desc, $query_args, true);
634
+	}
635
+
636
+
637
+	/**
638
+	 * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not
639
+	 * by ID
640
+	 * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously).
641
+	 * So, this function gets the index in that request data array called question_options. Returns FALSE if not found.
642
+	 *
643
+	 * @param int $ID of the question option to find
644
+	 * @return int index in question_options array if successful, FALSE if unsuccessful
645
+	 */
646
+	protected function _get_option_req_data_index($ID)
647
+	{
648
+		$req_data_for_question_options = $this->_req_data['question_options'];
649
+		foreach ($req_data_for_question_options as $num => $option_data) {
650
+			if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) {
651
+				return $num;
652
+			}
653
+		}
654
+		return false;
655
+	}
656
+
657
+
658
+
659
+
660
+	/***********/
661
+	/* QUERIES */
662
+	/**
663
+	 * For internal use in getting all the query parameters
664
+	 * (because it's pretty well the same between question, question groups,
665
+	 * and for both when searching for trashed and untrashed ones)
666
+	 *
667
+	 * @param EEM_Base $model either EEM_Question or EEM_Question_Group
668
+	 * @param int      $per_page
669
+	 * @param int      $current_page
670
+	 * @return array model query params, @see
671
+	 *               https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
672
+	 */
673
+	protected function get_query_params($model, $per_page = 10, $current_page = 10)
674
+	{
675
+		$query_params             = [];
676
+		$offset                   = ($current_page - 1) * $per_page;
677
+		$query_params['limit']    = [$offset, $per_page];
678
+		$order                    =
679
+			(isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
680
+				? $this->_req_data['order']
681
+				: 'ASC';
682
+		$orderby_field            =
683
+			$model instanceof EEM_Question
684
+				? 'QST_ID'
685
+				: 'QSG_order';
686
+		$field_to_order_by        =
687
+			empty($this->_req_data['orderby'])
688
+				? $orderby_field
689
+				: $this->_req_data['orderby'];
690
+		$query_params['order_by'] = [$field_to_order_by => $order];
691
+		$search_string            =
692
+			array_key_exists('s', $this->_req_data)
693
+				? $this->_req_data['s']
694
+				: null;
695
+		if (! empty($search_string)) {
696
+			if ($model instanceof EEM_Question_Group) {
697
+				$query_params[0] = [
698
+					'OR' => [
699
+						'QSG_name' => ['LIKE', "%$search_string%"],
700
+						'QSG_desc' => ['LIKE', "%$search_string%"],
701
+					],
702
+				];
703
+			} else {
704
+				$query_params[0] = [
705
+					'QST_display_text' => ['LIKE', "%$search_string%"],
706
+				];
707
+			}
708
+		}
709
+
710
+		// capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented)
711
+		/*if ( $model instanceof EEM_Question_Group ) {
712 712
             if ( ! EE_Registry::instance()->CAP->current_user_can( 'edit_others_question_groups', 'espresso_registration_form_edit_question_group' ) ) {
713 713
                 $query_params[0] = array(
714 714
                     'AND' => array(
@@ -738,67 +738,67 @@  discard block
 block discarded – undo
738 738
             }
739 739
         }/**/
740 740
 
741
-        return $query_params;
742
-    }
743
-
744
-
745
-    /**
746
-     * @param int        $per_page
747
-     * @param int        $current_page
748
-     * @param bool|false $count
749
-     * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]|int
750
-     * @throws EE_Error
751
-     */
752
-    public function get_questions($per_page = 10, $current_page = 1, $count = false)
753
-    {
754
-        $QST          = EEM_Question::instance();
755
-        $query_params = $this->get_query_params($QST, $per_page, $current_page);
756
-        if ($count) {
757
-            $where   =
758
-                isset($query_params[0])
759
-                    ? [$query_params[0]]
760
-                    : [];
761
-            $results = $QST->count($where);
762
-        } else {
763
-            $results = $QST->get_all($query_params);
764
-        }
765
-        return $results;
766
-    }
767
-
768
-
769
-    /**
770
-     * @param            $per_page
771
-     * @param int        $current_page
772
-     * @param bool|false $count
773
-     * @return EE_Soft_Delete_Base_Class[]|int
774
-     * @throws EE_Error
775
-     */
776
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
777
-    {
778
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
779
-        $where        =
780
-            isset($query_params[0])
781
-                ? [$query_params[0]]
782
-                : [];
783
-        return $count
784
-            ? EEM_Question::instance()->count_deleted($where)
785
-            : EEM_Question::instance()->get_all_deleted($query_params);
786
-    }
787
-
788
-
789
-    /**
790
-     * @param            $per_page
791
-     * @param int        $current_page
792
-     * @param bool|false $count
793
-     * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]
794
-     * @throws EE_Error
795
-     */
796
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
797
-    {
798
-        $questionGroupModel = EEM_Question_Group::instance();
799
-        // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
800
-        return $questionGroupModel->get_all(
801
-            $this->get_query_params($questionGroupModel, $per_page, $current_page)
802
-        );
803
-    }
741
+		return $query_params;
742
+	}
743
+
744
+
745
+	/**
746
+	 * @param int        $per_page
747
+	 * @param int        $current_page
748
+	 * @param bool|false $count
749
+	 * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]|int
750
+	 * @throws EE_Error
751
+	 */
752
+	public function get_questions($per_page = 10, $current_page = 1, $count = false)
753
+	{
754
+		$QST          = EEM_Question::instance();
755
+		$query_params = $this->get_query_params($QST, $per_page, $current_page);
756
+		if ($count) {
757
+			$where   =
758
+				isset($query_params[0])
759
+					? [$query_params[0]]
760
+					: [];
761
+			$results = $QST->count($where);
762
+		} else {
763
+			$results = $QST->get_all($query_params);
764
+		}
765
+		return $results;
766
+	}
767
+
768
+
769
+	/**
770
+	 * @param            $per_page
771
+	 * @param int        $current_page
772
+	 * @param bool|false $count
773
+	 * @return EE_Soft_Delete_Base_Class[]|int
774
+	 * @throws EE_Error
775
+	 */
776
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
777
+	{
778
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
779
+		$where        =
780
+			isset($query_params[0])
781
+				? [$query_params[0]]
782
+				: [];
783
+		return $count
784
+			? EEM_Question::instance()->count_deleted($where)
785
+			: EEM_Question::instance()->get_all_deleted($query_params);
786
+	}
787
+
788
+
789
+	/**
790
+	 * @param            $per_page
791
+	 * @param int        $current_page
792
+	 * @param bool|false $count
793
+	 * @return EE_Base_Class[]|EE_Question_Group[]|EE_Soft_Delete_Base_Class[]
794
+	 * @throws EE_Error
795
+	 */
796
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
797
+	{
798
+		$questionGroupModel = EEM_Question_Group::instance();
799
+		// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
800
+		return $questionGroupModel->get_all(
801
+			$this->get_query_params($questionGroupModel, $per_page, $current_page)
802
+		);
803
+	}
804 804
 }
Please login to merge, or discard this patch.
admin_pages/payments/help_tabs/payment_methods_overview.help_tab.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -12,62 +12,62 @@  discard block
 block discarded – undo
12 12
         <strong><?php esc_html_e('Name', 'event_espresso'); ?></strong>
13 13
         <br>
14 14
         <?php esc_html_e(
15
-            'The name of the payment method as customers see it in the registration form, in emails, in receipts, etc.',
16
-            'event_espresso'
17
-        ); ?>
15
+			'The name of the payment method as customers see it in the registration form, in emails, in receipts, etc.',
16
+			'event_espresso'
17
+		); ?>
18 18
     </li>
19 19
     <li>
20 20
         <strong><?php esc_html_e('Description', 'event_espresso'); ?></strong>
21 21
         <br />
22 22
         <?php esc_html_e(
23
-            'The description of how to use the payment method as customers will see it. This is mostly only seen during registration.',
24
-            'event_espresso'
25
-        ); ?>
23
+			'The description of how to use the payment method as customers will see it. This is mostly only seen during registration.',
24
+			'event_espresso'
25
+		); ?>
26 26
     </li>
27 27
     <li>
28 28
         <strong><?php esc_html_e('Admin-Only Name', 'event_espresso'); ?></strong>
29 29
         <br />
30 30
         <?php esc_html_e(
31
-            'The name of the payment method as seen internally by site administrators and staff.',
32
-            'event_espresso'
33
-        ); ?>
31
+			'The name of the payment method as seen internally by site administrators and staff.',
32
+			'event_espresso'
33
+		); ?>
34 34
     </li>
35 35
     <li>
36 36
         <strong><?php esc_html_e('Admin-Only Description', 'event_espresso'); ?></strong>
37 37
         <br />
38 38
         <?php esc_html_e(
39
-            'The description of the payment method as seen internally by site administrators and staff.',
40
-            'event_espresso'
41
-        ); ?>
39
+			'The description of the payment method as seen internally by site administrators and staff.',
40
+			'event_espresso'
41
+		); ?>
42 42
     </li>
43 43
     <li>
44 44
         <strong><?php esc_html_e('Debug (sandbox) Mode', 'event_espresso'); ?></strong>
45 45
         <br />
46 46
         <?php esc_html_e(
47
-            'Many payment methods have a debug/sandbox mode where payments are not processed but are only simulated. This is helpful when setup and debugging.',
48
-            'event_espresso'
49
-        ); ?>
47
+			'Many payment methods have a debug/sandbox mode where payments are not processed but are only simulated. This is helpful when setup and debugging.',
48
+			'event_espresso'
49
+		); ?>
50 50
     </li>
51 51
     <li>
52 52
         <strong><?php esc_html_e('Open by Default', 'event_espresso'); ?></strong>
53 53
         <br />
54 54
         <?php esc_html_e(
55
-            'If checked, this payment method will be selected by default (assuming no other valid payment methods are also marked as open by default.)',
56
-            'event_espresso'
57
-        ); ?>
55
+			'If checked, this payment method will be selected by default (assuming no other valid payment methods are also marked as open by default.)',
56
+			'event_espresso'
57
+		); ?>
58 58
     </li>
59 59
     <li>
60 60
         <strong><?php esc_html_e('Button URL', 'event_espresso'); ?></strong>
61 61
         <br />
62 62
         <?php
63
-        printf(
64
-            esc_html__(
65
-                'The URL of the button image for this payment method in the registration process. You may use any uploaded image on your website (click %s next to the field to select). If left blank, the default button image will be used.',
66
-                'event_espresso'
67
-            ),
68
-            '<img src="' . admin_url('images/media-button-image.gif') . '">'
69
-        );
70
-        ?>
63
+		printf(
64
+			esc_html__(
65
+				'The URL of the button image for this payment method in the registration process. You may use any uploaded image on your website (click %s next to the field to select). If left blank, the default button image will be used.',
66
+				'event_espresso'
67
+			),
68
+			'<img src="' . admin_url('images/media-button-image.gif') . '">'
69
+		);
70
+		?>
71 71
     </li>
72 72
     <li>
73 73
         <strong><?php esc_html_e('Usable From', 'event_espresso'); ?></strong>
@@ -76,15 +76,15 @@  discard block
 block discarded – undo
76 76
         <ul>
77 77
             <li>
78 78
                 <?php esc_html_e(
79
-                    'Front-end Registration Page: the payment method will appear as an option during the normal registration process to customers and they can use it to process payments.',
80
-                    'event_espresso'
81
-                ); ?>
79
+					'Front-end Registration Page: the payment method will appear as an option during the normal registration process to customers and they can use it to process payments.',
80
+					'event_espresso'
81
+				); ?>
82 82
             </li>
83 83
             <li>
84 84
                 <?php esc_html_e(
85
-                    'Admin Registration Page: when recording payments made from the transaction admin page, the payment method will appear as an option. Note: currently payments can only be RECORDED from the admin, they cannot be PROCESSED.',
86
-                    'event_espresso'
87
-                ); ?>
85
+					'Admin Registration Page: when recording payments made from the transaction admin page, the payment method will appear as an option. Note: currently payments can only be RECORDED from the admin, they cannot be PROCESSED.',
86
+					'event_espresso'
87
+				); ?>
88 88
             </li>
89 89
         </ul>
90 90
     </li>
@@ -92,14 +92,14 @@  discard block
 block discarded – undo
92 92
 <strong><?php esc_html_e('Recommendations', 'event_espresso'); ?></strong>
93 93
 <br />
94 94
 <?php esc_html_e(
95
-    'To learn more about the options on this page, take a look at the different tabs that appear on the left side of the page.',
96
-    'event_espresso'
95
+	'To learn more about the options on this page, take a look at the different tabs that appear on the left side of the page.',
96
+	'event_espresso'
97 97
 ); ?>
98 98
 <p>
99 99
     <strong><?php esc_html_e('Screen Options', 'event_espresso'); ?></strong>
100 100
     <br />
101 101
     <?php esc_html_e(
102
-        'You can customize the information that is shown on this page by toggling the Screen Options tab. Then you can add or remove checkmarks to hide or show certain content.',
103
-        'event_espresso'
104
-    ); ?>
102
+		'You can customize the information that is shown on this page by toggling the Screen Options tab. Then you can add or remove checkmarks to hide or show certain content.',
103
+		'event_espresso'
104
+	); ?>
105 105
 </p>
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/Pricing_Admin_Page.core.php 1 patch
Indentation   +1403 added lines, -1403 removed lines patch added patch discarded remove patch
@@ -12,1411 +12,1411 @@
 block discarded – undo
12 12
 class Pricing_Admin_Page extends EE_Admin_Page
13 13
 {
14 14
 
15
-    /**
16
-     *    constructor
17
-     *
18
-     * @Constructor
19
-     * @access public
20
-     * @param bool $routing
21
-     * @return Pricing_Admin_Page
22
-     */
23
-    public function __construct($routing = true)
24
-    {
25
-        parent::__construct($routing);
26
-    }
27
-
28
-
29
-    protected function _init_page_props()
30
-    {
31
-        $this->page_slug = PRICING_PG_SLUG;
32
-        $this->page_label = PRICING_LABEL;
33
-        $this->_admin_base_url = PRICING_ADMIN_URL;
34
-        $this->_admin_base_path = PRICING_ADMIN;
35
-    }
36
-
37
-
38
-    protected function _ajax_hooks()
39
-    {
40
-        add_action('wp_ajax_espresso_update_prices_order', array($this, 'update_price_order'));
41
-    }
42
-
43
-
44
-    protected function _define_page_props()
45
-    {
46
-        $this->_admin_page_title = PRICING_LABEL;
47
-        $this->_labels = array(
48
-            'buttons' => array(
49
-                'add'         => esc_html__('Add New Default Price', 'event_espresso'),
50
-                'edit'        => esc_html__('Edit Default Price', 'event_espresso'),
51
-                'delete'      => esc_html__('Delete Default Price', 'event_espresso'),
52
-                'add_type'    => esc_html__('Add New Default Price Type', 'event_espresso'),
53
-                'edit_type'   => esc_html__('Edit Price Type', 'event_espresso'),
54
-                'delete_type' => esc_html__('Delete Price Type', 'event_espresso'),
55
-            ),
56
-        );
57
-    }
58
-
59
-
60
-    /**
61
-     *        an array for storing request actions and their corresponding methods
62
-     *
63
-     * @access private
64
-     * @return void
65
-     */
66
-    protected function _set_page_routes()
67
-    {
68
-        $prc_id = ! empty($this->_req_data['PRC_ID']) && ! is_array($this->_req_data['PRC_ID'])
69
-            ? $this->_req_data['PRC_ID'] : 0;
70
-        $prt_id = ! empty($this->_req_data['PRT_ID']) && ! is_array($this->_req_data['PRT_ID'])
71
-            ? $this->_req_data['PRT_ID'] : 0;
72
-        $this->_page_routes = array(
73
-            'default'                     => array(
74
-                'func'       => '_price_overview_list_table',
75
-                'capability' => 'ee_read_default_prices',
76
-            ),
77
-            'add_new_price'               => array(
78
-                'func'       => '_edit_price_details',
79
-                'args'       => array('new_price' => true),
80
-                'capability' => 'ee_edit_default_prices',
81
-            ),
82
-            'edit_price'                  => array(
83
-                'func'       => '_edit_price_details',
84
-                'args'       => array('new_price' => false),
85
-                'capability' => 'ee_edit_default_price',
86
-                'obj_id'     => $prc_id,
87
-            ),
88
-            'insert_price'                => array(
89
-                'func'       => '_insert_or_update_price',
90
-                'args'       => array('new_price' => true),
91
-                'noheader'   => true,
92
-                'capability' => 'ee_edit_default_prices',
93
-            ),
94
-            'update_price'                => array(
95
-                'func'       => '_insert_or_update_price',
96
-                'args'       => array('new_price' => false),
97
-                'noheader'   => true,
98
-                'capability' => 'ee_edit_default_price',
99
-                'obj_id'     => $prc_id,
100
-            ),
101
-            'trash_price'                 => array(
102
-                'func'       => '_trash_or_restore_price',
103
-                'args'       => array('trash' => true),
104
-                'noheader'   => true,
105
-                'capability' => 'ee_delete_default_price',
106
-                'obj_id'     => $prc_id,
107
-            ),
108
-            'restore_price'               => array(
109
-                'func'       => '_trash_or_restore_price',
110
-                'args'       => array('trash' => false),
111
-                'noheader'   => true,
112
-                'capability' => 'ee_delete_default_price',
113
-                'obj_id'     => $prc_id,
114
-            ),
115
-            'delete_price'                => array(
116
-                'func'       => '_delete_price',
117
-                'noheader'   => true,
118
-                'capability' => 'ee_delete_default_price',
119
-                'obj_id'     => $prc_id,
120
-            ),
121
-            'espresso_update_price_order' => array(
122
-                'func'       => 'update_price_order',
123
-                'noheader'   => true,
124
-                'capability' => 'ee_edit_default_prices',
125
-            ),
126
-            // price types
127
-            'price_types'                 => array(
128
-                'func'       => '_price_types_overview_list_table',
129
-                'capability' => 'ee_read_default_price_types',
130
-            ),
131
-            'add_new_price_type'          => array(
132
-                'func'       => '_edit_price_type_details',
133
-                'capability' => 'ee_edit_default_price_types',
134
-            ),
135
-            'edit_price_type'             => array(
136
-                'func'       => '_edit_price_type_details',
137
-                'capability' => 'ee_edit_default_price_type',
138
-                'obj_id'     => $prt_id,
139
-            ),
140
-            'insert_price_type'           => array(
141
-                'func'       => '_insert_or_update_price_type',
142
-                'args'       => array('new_price_type' => true),
143
-                'noheader'   => true,
144
-                'capability' => 'ee_edit_default_price_types',
145
-            ),
146
-            'update_price_type'           => array(
147
-                'func'       => '_insert_or_update_price_type',
148
-                'args'       => array('new_price_type' => false),
149
-                'noheader'   => true,
150
-                'capability' => 'ee_edit_default_price_type',
151
-                'obj_id'     => $prt_id,
152
-            ),
153
-            'trash_price_type'            => array(
154
-                'func'       => '_trash_or_restore_price_type',
155
-                'args'       => array('trash' => true),
156
-                'noheader'   => true,
157
-                'capability' => 'ee_delete_default_price_type',
158
-                'obj_id'     => $prt_id,
159
-            ),
160
-            'restore_price_type'          => array(
161
-                'func'       => '_trash_or_restore_price_type',
162
-                'args'       => array('trash' => false),
163
-                'noheader'   => true,
164
-                'capability' => 'ee_delete_default_price_type',
165
-                'obj_id'     => $prt_id,
166
-            ),
167
-            'delete_price_type'           => array(
168
-                'func'       => '_delete_price_type',
169
-                'noheader'   => true,
170
-                'capability' => 'ee_delete_default_price_type',
171
-                'obj_id'     => $prt_id,
172
-            ),
173
-            'tax_settings'                => array(
174
-                'func'       => '_tax_settings',
175
-                'capability' => 'manage_options',
176
-            ),
177
-            'update_tax_settings'         => array(
178
-                'func'       => '_update_tax_settings',
179
-                'capability' => 'manage_options',
180
-                'noheader'   => true,
181
-            ),
182
-        );
183
-    }
184
-
185
-
186
-    protected function _set_page_config()
187
-    {
188
-
189
-        $this->_page_config = array(
190
-            'default'            => array(
191
-                'nav'           => array(
192
-                    'label' => esc_html__('Default Pricing', 'event_espresso'),
193
-                    'order' => 10,
194
-                ),
195
-                'list_table'    => 'Prices_List_Table',
196
-                'help_tabs'     => array(
197
-                    'pricing_default_pricing_help_tab'                           => array(
198
-                        'title'    => esc_html__('Default Pricing', 'event_espresso'),
199
-                        'filename' => 'pricing_default_pricing',
200
-                    ),
201
-                    'pricing_default_pricing_table_column_headings_help_tab'     => array(
202
-                        'title'    => esc_html__('Default Pricing Table Column Headings', 'event_espresso'),
203
-                        'filename' => 'pricing_default_pricing_table_column_headings',
204
-                    ),
205
-                    'pricing_default_pricing_views_bulk_actions_search_help_tab' => array(
206
-                        'title'    => esc_html__('Default Pricing Views & Bulk Actions & Search', 'event_espresso'),
207
-                        'filename' => 'pricing_default_pricing_views_bulk_actions_search',
208
-                    ),
209
-                ),
210
-                'require_nonce' => false,
211
-            ),
212
-            'add_new_price'      => array(
213
-                'nav'           => array(
214
-                    'label'      => esc_html__('Add New Default Price', 'event_espresso'),
215
-                    'order'      => 20,
216
-                    'persistent' => false,
217
-                ),
218
-                'help_tabs'     => array(
219
-                    'add_new_default_price_help_tab' => array(
220
-                        'title'    => esc_html__('Add New Default Price', 'event_espresso'),
221
-                        'filename' => 'pricing_add_new_default_price',
222
-                    ),
223
-                ),
224
-                'metaboxes'     => array('_publish_post_box', '_espresso_news_post_box', '_price_details_meta_boxes'),
225
-                'require_nonce' => false,
226
-            ),
227
-            'edit_price'         => array(
228
-                'nav'           => array(
229
-                    'label'      => esc_html__('Edit Default Price', 'event_espresso'),
230
-                    'order'      => 20,
231
-                    'url'        => isset($this->_req_data['id']) ? add_query_arg(
232
-                        array('id' => $this->_req_data['id']),
233
-                        $this->_current_page_view_url
234
-                    ) : $this->_admin_base_url,
235
-                    'persistent' => false,
236
-                ),
237
-                'metaboxes'     => array('_publish_post_box', '_espresso_news_post_box', '_price_details_meta_boxes'),
238
-                'help_tabs'     => array(
239
-                    'edit_default_price_help_tab' => array(
240
-                        'title'    => esc_html__('Edit Default Price', 'event_espresso'),
241
-                        'filename' => 'pricing_edit_default_price',
242
-                    ),
243
-                ),
244
-                'require_nonce' => false,
245
-            ),
246
-            'price_types'        => array(
247
-                'nav'           => array(
248
-                    'label' => esc_html__('Price Types', 'event_espresso'),
249
-                    'order' => 30,
250
-                ),
251
-                'list_table'    => 'Price_Types_List_Table',
252
-                'help_tabs'     => array(
253
-                    'pricing_price_types_help_tab'                           => array(
254
-                        'title'    => esc_html__('Price Types', 'event_espresso'),
255
-                        'filename' => 'pricing_price_types',
256
-                    ),
257
-                    'pricing_price_types_table_column_headings_help_tab'     => array(
258
-                        'title'    => esc_html__('Price Types Table Column Headings', 'event_espresso'),
259
-                        'filename' => 'pricing_price_types_table_column_headings',
260
-                    ),
261
-                    'pricing_price_types_views_bulk_actions_search_help_tab' => array(
262
-                        'title'    => esc_html__('Price Types Views & Bulk Actions & Search', 'event_espresso'),
263
-                        'filename' => 'pricing_price_types_views_bulk_actions_search',
264
-                    ),
265
-                ),
266
-                'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
267
-                'require_nonce' => false,
268
-            ),
269
-            'add_new_price_type' => array(
270
-                'nav'           => array(
271
-                    'label'      => esc_html__('Add New Price Type', 'event_espresso'),
272
-                    'order'      => 40,
273
-                    'persistent' => false,
274
-                ),
275
-                'help_tabs'     => array(
276
-                    'add_new_price_type_help_tab' => array(
277
-                        'title'    => esc_html__('Add New Price Type', 'event_espresso'),
278
-                        'filename' => 'pricing_add_new_price_type',
279
-                    ),
280
-                ),
281
-                'metaboxes'     => array(
282
-                    '_publish_post_box',
283
-                    '_espresso_news_post_box',
284
-                    '_price_type_details_meta_boxes',
285
-                ),
286
-                'require_nonce' => false,
287
-            ),
288
-            'edit_price_type'    => array(
289
-                'nav'       => array(
290
-                    'label'      => esc_html__('Edit Price Type', 'event_espresso'),
291
-                    'order'      => 40,
292
-                    'persistent' => false,
293
-                ),
294
-                'help_tabs' => array(
295
-                    'edit_price_type_help_tab' => array(
296
-                        'title'    => esc_html__('Edit Price Type', 'event_espresso'),
297
-                        'filename' => 'pricing_edit_price_type',
298
-                    ),
299
-                ),
300
-                'metaboxes' => array('_publish_post_box', '_espresso_news_post_box', '_price_type_details_meta_boxes'),
301
-
302
-                'require_nonce' => false,
303
-            ),
304
-            'tax_settings'       => array(
305
-                'nav'           => array(
306
-                    'label' => esc_html__('Tax Settings', 'event_espresso'),
307
-                    'order' => 40,
308
-                ),
309
-                'labels'        => array(
310
-                    'publishbox' => esc_html__('Update Tax Settings', 'event_espresso'),
311
-                ),
312
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
313
-                'require_nonce' => true,
314
-            ),
315
-        );
316
-    }
317
-
318
-
319
-    protected function _add_screen_options()
320
-    {
321
-        // todo
322
-    }
323
-
324
-
325
-    protected function _add_screen_options_default()
326
-    {
327
-        $this->_per_page_screen_option();
328
-    }
329
-
330
-
331
-    protected function _add_screen_options_price_types()
332
-    {
333
-        $page_title = $this->_admin_page_title;
334
-        $this->_admin_page_title = esc_html__('Price Types', 'event_espresso');
335
-        $this->_per_page_screen_option();
336
-        $this->_admin_page_title = $page_title;
337
-    }
338
-
339
-
340
-    protected function _add_feature_pointers()
341
-    {
342
-    }
343
-
344
-
345
-    public function load_scripts_styles()
346
-    {
347
-        // styles
348
-        wp_enqueue_style('espresso-ui-theme');
349
-        wp_register_style(
350
-            'espresso_PRICING',
351
-            PRICING_ASSETS_URL . 'espresso_pricing_admin.css',
352
-            array(),
353
-            EVENT_ESPRESSO_VERSION
354
-        );
355
-        wp_enqueue_style('espresso_PRICING');
356
-
357
-        // scripts
358
-        wp_enqueue_script('ee_admin_js');
359
-        wp_enqueue_script('jquery-ui-position');
360
-        wp_enqueue_script('jquery-ui-widget');
361
-        // wp_enqueue_script('jquery-ui-dialog');
362
-        // wp_enqueue_script('jquery-ui-draggable');
363
-        // wp_enqueue_script('jquery-ui-datepicker');
364
-        wp_register_script(
365
-            'espresso_PRICING',
366
-            PRICING_ASSETS_URL . 'espresso_pricing_admin.js',
367
-            array('jquery'),
368
-            EVENT_ESPRESSO_VERSION,
369
-            true
370
-        );
371
-        wp_enqueue_script('espresso_PRICING');
372
-    }
373
-
374
-
375
-    public function load_scripts_styles_default()
376
-    {
377
-        wp_enqueue_script('espresso_ajax_table_sorting');
378
-    }
379
-
380
-
381
-    public function admin_footer_scripts()
382
-    {
383
-    }
384
-
385
-    public function admin_init()
386
-    {
387
-    }
388
-
389
-    public function admin_notices()
390
-    {
391
-    }
392
-
393
-
394
-    protected function _set_list_table_views_default()
395
-    {
396
-        $this->_views = array(
397
-            'all' => array(
398
-                'slug'        => 'all',
399
-                'label'       => esc_html__('View All Default Pricing', 'event_espresso'),
400
-                'count'       => 0,
401
-                'bulk_action' => array(
402
-                    'trash_price' => esc_html__('Move to Trash', 'event_espresso'),
403
-                ),
404
-            ),
405
-        );
406
-
407
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_default_prices', 'pricing_trash_price')) {
408
-            $this->_views['trashed'] = array(
409
-                'slug'        => 'trashed',
410
-                'label'       => esc_html__('Trash', 'event_espresso'),
411
-                'count'       => 0,
412
-                'bulk_action' => array(
413
-                    'restore_price' => esc_html__('Restore from Trash', 'event_espresso'),
414
-                    'delete_price'  => esc_html__('Delete Permanently', 'event_espresso'),
415
-                ),
416
-            );
417
-        }
418
-    }
419
-
420
-
421
-    protected function _set_list_table_views_price_types()
422
-    {
423
-        $this->_views = array(
424
-            'all' => array(
425
-                'slug'        => 'all',
426
-                'label'       => esc_html__('All', 'event_espresso'),
427
-                'count'       => 0,
428
-                'bulk_action' => array(
429
-                    'trash_price_type' => esc_html__('Move to Trash', 'event_espresso'),
430
-                ),
431
-            ),
432
-        );
433
-
434
-        if (
435
-            EE_Registry::instance()->CAP->current_user_can(
436
-                'ee_delete_default_price_types',
437
-                'pricing_trash_price_type'
438
-            )
439
-        ) {
440
-            $this->_views['trashed'] = array(
441
-                'slug'        => 'trashed',
442
-                'label'       => esc_html__('Trash', 'event_espresso'),
443
-                'count'       => 0,
444
-                'bulk_action' => array(
445
-                    'restore_price_type' => esc_html__('Restore from Trash', 'event_espresso'),
446
-                    'delete_price_type'  => esc_html__('Delete Permanently', 'event_espresso'),
447
-                ),
448
-            );
449
-        }
450
-    }
451
-
452
-
453
-    /**
454
-     *        generates HTML for main Prices Admin page
455
-     *
456
-     * @access protected
457
-     * @return void
458
-     */
459
-    protected function _price_overview_list_table()
460
-    {
461
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
462
-            'add_new_price',
463
-            'add',
464
-            array(),
465
-            'add-new-h2'
466
-        );
467
-        $this->admin_page_title .= $this->_learn_more_about_pricing_link();
468
-        $this->_search_btn_label = esc_html__('Default Prices', 'event_espresso');
469
-        $this->display_admin_list_table_page_with_no_sidebar();
470
-    }
471
-
472
-
473
-    /**
474
-     *    retrieve data for Prices List table
475
-     *
476
-     * @access public
477
-     * @param  int     $per_page how many prices displayed per page
478
-     * @param  boolean $count    return the count or objects
479
-     * @param  boolean $trashed  whether the current view is of the trash can - eww yuck!
480
-     * @return mixed (int|array)  int = count || array of price objects
481
-     */
482
-    public function get_prices_overview_data($per_page = 10, $count = false, $trashed = false)
483
-    {
484
-
485
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
486
-        // start with an empty array
487
-        $event_pricing = array();
488
-
489
-        require_once(PRICING_ADMIN . 'Prices_List_Table.class.php');
490
-        require_once(EE_MODELS . 'EEM_Price.model.php');
491
-        // $PRC = EEM_Price::instance();
492
-
493
-        $this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? '' : $this->_req_data['orderby'];
494
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
495
-            : 'ASC';
496
-
497
-        switch ($this->_req_data['orderby']) {
498
-            case 'name':
499
-                $orderby = array('PRC_name' => $order);
500
-                break;
501
-            case 'type':
502
-                $orderby = array('Price_Type.PRT_name' => $order);
503
-                break;
504
-            case 'amount':
505
-                $orderby = array('PRC_amount' => $order);
506
-                break;
507
-            default:
508
-                $orderby = array('PRC_order' => $order, 'Price_Type.PRT_order' => $order, 'PRC_ID' => $order);
509
-        }
510
-
511
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
512
-            ? $this->_req_data['paged'] : 1;
513
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
514
-            ? $this->_req_data['perpage'] : $per_page;
515
-
516
-        $_where = array(
517
-            'PRC_is_default' => 1,
518
-            'PRC_deleted'    => $trashed,
519
-        );
520
-
521
-        $offset = ($current_page - 1) * $per_page;
522
-        $limit = array($offset, $per_page);
523
-
524
-        if (isset($this->_req_data['s'])) {
525
-            $sstr = '%' . $this->_req_data['s'] . '%';
526
-            $_where['OR'] = array(
527
-                'PRC_name'            => array('LIKE', $sstr),
528
-                'PRC_desc'            => array('LIKE', $sstr),
529
-                'PRC_amount'          => array('LIKE', $sstr),
530
-                'Price_Type.PRT_name' => array('LIKE', $sstr),
531
-            );
532
-        }
533
-
534
-        $query_params = array(
535
-            $_where,
536
-            'order_by' => $orderby,
537
-            'limit'    => $limit,
538
-            'group_by' => 'PRC_ID',
539
-        );
540
-
541
-        if ($count) {
542
-            return $trashed ? EEM_Price::instance()->count(array($_where))
543
-                : EEM_Price::instance()->count_deleted_and_undeleted(array($_where));
544
-        } else {
545
-            return EEM_Price::instance()->get_all_deleted_and_undeleted($query_params);
546
-        }
547
-    }
548
-
549
-
550
-    /**
551
-     *        _price_details
552
-     *
553
-     * @access protected
554
-     * @return void
555
-     */
556
-    protected function _edit_price_details()
557
-    {
558
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
559
-        // grab price ID
560
-        $PRC_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id']) ? absint($this->_req_data['id'])
561
-            : false;
562
-        // change page title based on request action
563
-        switch ($this->_req_action) {
564
-            case 'add_new_price':
565
-                $this->_admin_page_title = esc_html__('Add New Price', 'event_espresso');
566
-                break;
567
-            case 'edit_price':
568
-                $this->_admin_page_title = esc_html__('Edit Price', 'event_espresso');
569
-                break;
570
-            default:
571
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
572
-        }
573
-        // add PRC_ID to title if editing
574
-        $this->_admin_page_title = $PRC_ID ? $this->_admin_page_title . ' # ' . $PRC_ID : $this->_admin_page_title;
575
-
576
-        // get prices
577
-        require_once(EE_MODELS . 'EEM_Price.model.php');
578
-        $PRC = EEM_Price::instance();
579
-
580
-        if ($PRC_ID) {
581
-            $price = $PRC->get_one_by_ID($PRC_ID);
582
-            $additional_hidden_fields = array(
583
-                'PRC_ID' => array('type' => 'hidden', 'value' => $PRC_ID),
584
-            );
585
-            $this->_set_add_edit_form_tags('update_price', $additional_hidden_fields);
586
-        } else {
587
-            $price = $PRC->get_new_price();
588
-            $this->_set_add_edit_form_tags('insert_price');
589
-        }
590
-
591
-        $this->_template_args['PRC_ID'] = $PRC_ID;
592
-        $this->_template_args['price'] = $price;
593
-
594
-        // get price types
595
-        require_once(EE_MODELS . 'EEM_Price_Type.model.php');
596
-        $PRT = EEM_Price_Type::instance();
597
-        $price_types = $PRT->get_all(array(array('PBT_ID' => array('!=', 1))));
598
-        $price_type_names = array();
599
-        if (empty($price_types)) {
600
-            $msg = esc_html__(
601
-                'You have no price types defined. Please add a price type before adding a price.',
602
-                'event_espresso'
603
-            );
604
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
605
-            exit();
606
-        } else {
607
-            foreach ($price_types as $type) {
608
-                // if ($type->is_global()) {
609
-                $price_type_names[] = array('id' => $type->ID(), 'text' => $type->name());
610
-            // }
611
-            }
612
-        }
613
-
614
-        $this->_template_args['price_types'] = $price_type_names;
615
-        $this->_template_args['learn_more_about_pricing_link'] = $this->_learn_more_about_pricing_link();
616
-
617
-        $this->_set_publish_post_box_vars('id', $PRC_ID);
618
-        // the details template wrapper
619
-        $this->display_admin_page_with_sidebar();
620
-    }
621
-
622
-
623
-    /**
624
-     *        declare price details page metaboxes
625
-     *
626
-     * @access protected
627
-     * @return void
628
-     */
629
-    protected function _price_details_meta_boxes()
630
-    {
631
-        add_meta_box(
632
-            'edit-price-details-mbox',
633
-            esc_html__('Default Price Details', 'event_espresso'),
634
-            array($this, '_edit_price_details_meta_box'),
635
-            $this->wp_page_slug,
636
-            'normal',
637
-            'high'
638
-        );
639
-    }
640
-
641
-
642
-    /**
643
-     *        _edit_price_details_meta_box
644
-     *
645
-     * @access public
646
-     * @return void
647
-     */
648
-    public function _edit_price_details_meta_box()
649
-    {
650
-        echo EEH_Template::display_template(
651
-            PRICING_TEMPLATE_PATH . 'pricing_details_main_meta_box.template.php',
652
-            $this->_template_args,
653
-            true
654
-        );
655
-    }
656
-
657
-
658
-    /**
659
-     * @return array
660
-     * @throws EE_Error
661
-     * @throws ReflectionException
662
-     */
663
-    protected function set_price_column_values()
664
-    {
665
-        $PRC_order = 0;
666
-        $PRT_ID = absint($this->_req_data['PRT_ID']);
667
-        if ($PRT_ID) {
668
-            /** @var EE_Price_Type $price_type */
669
-            $price_type = EEM_Price_Type::instance()->get_one_by_ID($PRT_ID);
670
-            if ($price_type instanceof EE_Price_Type) {
671
-                $PRC_order = $price_type->order();
672
-            }
673
-        }
674
-        return array(
675
-            'PRT_ID'         => $PRT_ID,
676
-            'PRC_amount'     => $this->_req_data['PRC_amount'],
677
-            'PRC_name'       => $this->_req_data['PRC_name'],
678
-            'PRC_desc'       => $this->_req_data['PRC_desc'],
679
-            'PRC_is_default' => 1,
680
-            'PRC_overrides'  => null,
681
-            'PRC_order'      => $PRC_order,
682
-            'PRC_deleted'    => 0,
683
-            'PRC_parent'     => 0,
684
-        );
685
-    }
686
-
687
-
688
-    /**
689
-     * @param boolean $insert - whether to insert or update
690
-     * @return void
691
-     * @throws EE_Error
692
-     * @throws ReflectionException
693
-     */
694
-    protected function _insert_or_update_price($insert = false)
695
-    {
696
-        require_once(EE_MODELS . 'EEM_Price.model.php');
697
-        $PRC = EEM_Price::instance();
698
-
699
-        // why be so pessimistic ???  : (
700
-        $success = 0;
701
-
702
-        $set_column_values = $this->set_price_column_values();
703
-        // is this a new Price ?
704
-        if ($insert) {
705
-            // run the insert
706
-            if ($PRC_ID = $PRC->insert($set_column_values)) {
707
-                // make sure this new price modifier is attached to the ticket but ONLY if it is not a tax type
708
-                $PR = EEM_price::instance()->get_one_by_ID($PRC_ID);
709
-                if ($PR instanceof EE_Price && $PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
710
-                    $ticket = EEM_Ticket::instance()->get_one_by_ID(1);
711
-                    $ticket->_add_relation_to($PR, 'Price');
712
-                    $ticket->save();
713
-                }
714
-                $success = 1;
715
-            } else {
716
-                $PRC_ID = false;
717
-                $success = 0;
718
-            }
719
-            $action_desc = 'created';
720
-        } else {
721
-            $PRC_ID = absint($this->_req_data['PRC_ID']);
722
-            // run the update
723
-            $where_cols_n_values = array('PRC_ID' => $PRC_ID);
724
-            if ($PRC->update($set_column_values, array($where_cols_n_values))) {
725
-                $success = 1;
726
-            }
727
-
728
-            $PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
729
-            if ($PR instanceof EE_Price && $PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
730
-                // if this is $PRC_ID == 1,
731
-                // then we need to update the default ticket attached to this price so the TKT_price value is updated.
732
-                if ($PRC_ID === 1) {
733
-                    $ticket = $PR->get_first_related('Ticket');
734
-                    if ($ticket) {
735
-                        $ticket->set('TKT_price', $PR->get('PRC_amount'));
736
-                        $ticket->set('TKT_name', $PR->get('PRC_name'));
737
-                        $ticket->set('TKT_description', $PR->get('PRC_desc'));
738
-                        $ticket->save();
739
-                    }
740
-                } else {
741
-                    // we make sure this price is attached to base ticket. but ONLY if its not a tax ticket type.
742
-                    $ticket = EEM_Ticket::instance()->get_one_by_ID(1);
743
-                    $ticket->_add_relation_to($PRC_ID, 'Price');
744
-                    $ticket->save();
745
-                }
746
-            }
747
-
748
-            $action_desc = 'updated';
749
-        }
750
-
751
-        $query_args = array('action' => 'edit_price', 'id' => $PRC_ID);
752
-
753
-        $this->_redirect_after_action($success, 'Prices', $action_desc, $query_args);
754
-    }
755
-
756
-
757
-    /**
758
-     *        _trash_or_restore_price
759
-     *
760
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
761
-     * @access protected
762
-     * @return void
763
-     */
764
-    protected function _trash_or_restore_price($trash = true)
765
-    {
766
-
767
-        // echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
768
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
769
-
770
-        require_once(EE_MODELS . 'EEM_Price.model.php');
771
-        $PRC = EEM_Price::instance();
772
-
773
-        $success = 1;
774
-        $PRC_deleted = $trash ? true : false;
775
-
776
-        // get base ticket for updating
777
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(1);
778
-        // Checkboxes
779
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
780
-            // if array has more than one element than success message should be plural
781
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
782
-            // cycle thru checkboxes
783
-            while (list($PRC_ID, $value) = each($this->_req_data['checkbox'])) {
784
-                if (! $PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), absint($PRC_ID))) {
785
-                    $success = 0;
786
-                } else {
787
-                    $PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
788
-                    if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
789
-                        // if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
790
-                        if ($PRC_deleted) {
791
-                            $ticket->_remove_relation_to($PRC_ID, 'Price');
792
-                        } else {
793
-                            $ticket->_add_relation_to($PRC_ID, 'Price');
794
-                        }
795
-                        $ticket->save();
796
-                    }
797
-                }
798
-            }
799
-        } else {
800
-            // grab single id and delete
801
-            $PRC_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
802
-            if (empty($PRC_ID) || ! $PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), $PRC_ID)) {
803
-                $success = 0;
804
-            } else {
805
-                $PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
806
-                if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
807
-                    // if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
808
-                    if ($PRC_deleted) {
809
-                        $ticket->_remove_relation_to($PRC_ID, 'Price');
810
-                    } else {
811
-                        $ticket->_add_relation_to($PRC_ID, 'Price');
812
-                    }
813
-                    $ticket->save();
814
-                }
815
-            }
816
-        }
817
-        $query_args = array(
818
-            'action' => 'default',
819
-        );
820
-
821
-        if ($success) {
822
-            if ($trash) {
823
-                $msg = $success == 2
824
-                    ? esc_html__('The Prices have been trashed.', 'event_espresso')
825
-                    : esc_html__(
826
-                        'The Price has been trashed.',
827
-                        'event_espresso'
828
-                    );
829
-            } else {
830
-                $msg = $success == 2
831
-                    ? esc_html__('The Prices have been restored.', 'event_espresso')
832
-                    : esc_html__(
833
-                        'The Price has been restored.',
834
-                        'event_espresso'
835
-                    );
836
-            }
837
-
838
-            EE_Error::add_success($msg);
839
-        }
840
-
841
-        $this->_redirect_after_action(false, '', '', $query_args, true);
842
-    }
843
-
844
-
845
-    /**
846
-     *        _delete_price
847
-     *
848
-     * @access protected
849
-     * @return void
850
-     */
851
-    protected function _delete_price()
852
-    {
853
-
854
-        // echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
855
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
856
-
857
-        require_once(EE_MODELS . 'EEM_Price.model.php');
858
-        $PRC = EEM_Price::instance();
859
-
860
-        $success = 1;
861
-        // Checkboxes
862
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
863
-            // if array has more than one element than success message should be plural
864
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
865
-            // cycle thru bulk action checkboxes
866
-            while (list($PRC_ID, $value) = each($this->_req_data['checkbox'])) {
867
-                if (! $PRC->delete_permanently_by_ID(absint($PRC_ID))) {
868
-                    $success = 0;
869
-                }
870
-            }
871
-        } else {
872
-            // grab single id and delete
873
-            $PRC_ID = absint($this->_req_data['id']);
874
-            if (! $PRC->delete_permanently_by_ID($PRC_ID)) {
875
-                $success = 0;
876
-            }
877
-        }
878
-
879
-        $this->_redirect_after_action($success, 'Prices', 'deleted', array());
880
-    }
881
-
882
-
883
-    public function update_price_order()
884
-    {
885
-        $success = esc_html__('Price order was updated successfully.', 'event_espresso');
886
-
887
-        // grab our row IDs
888
-        $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids']) ? explode(
889
-            ',',
890
-            rtrim(
891
-                $this->_req_data['row_ids'],
892
-                ','
893
-            )
894
-        ) : false;
895
-
896
-        if (is_array($row_ids)) {
897
-            for ($i = 0; $i < count($row_ids); $i++) {
898
-                // Update the prices when re-ordering
899
-                $id = absint($row_ids[ $i ]);
900
-                if (
901
-                    EEM_Price::instance()->update(
902
-                        array('PRC_order' => $i + 1),
903
-                        array(array('PRC_ID' => $id))
904
-                    ) === false
905
-                ) {
906
-                    $success = false;
907
-                }
908
-            }
909
-        } else {
910
-            $success = false;
911
-        }
912
-
913
-        $errors = ! $success ? esc_html__('An error occurred. The price order was not updated.', 'event_espresso') : false;
914
-
915
-        echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
916
-        die();
917
-    }
918
-
919
-
920
-
921
-
922
-
923
-
924
-    /**************************************************************************************************************************************************************
15
+	/**
16
+	 *    constructor
17
+	 *
18
+	 * @Constructor
19
+	 * @access public
20
+	 * @param bool $routing
21
+	 * @return Pricing_Admin_Page
22
+	 */
23
+	public function __construct($routing = true)
24
+	{
25
+		parent::__construct($routing);
26
+	}
27
+
28
+
29
+	protected function _init_page_props()
30
+	{
31
+		$this->page_slug = PRICING_PG_SLUG;
32
+		$this->page_label = PRICING_LABEL;
33
+		$this->_admin_base_url = PRICING_ADMIN_URL;
34
+		$this->_admin_base_path = PRICING_ADMIN;
35
+	}
36
+
37
+
38
+	protected function _ajax_hooks()
39
+	{
40
+		add_action('wp_ajax_espresso_update_prices_order', array($this, 'update_price_order'));
41
+	}
42
+
43
+
44
+	protected function _define_page_props()
45
+	{
46
+		$this->_admin_page_title = PRICING_LABEL;
47
+		$this->_labels = array(
48
+			'buttons' => array(
49
+				'add'         => esc_html__('Add New Default Price', 'event_espresso'),
50
+				'edit'        => esc_html__('Edit Default Price', 'event_espresso'),
51
+				'delete'      => esc_html__('Delete Default Price', 'event_espresso'),
52
+				'add_type'    => esc_html__('Add New Default Price Type', 'event_espresso'),
53
+				'edit_type'   => esc_html__('Edit Price Type', 'event_espresso'),
54
+				'delete_type' => esc_html__('Delete Price Type', 'event_espresso'),
55
+			),
56
+		);
57
+	}
58
+
59
+
60
+	/**
61
+	 *        an array for storing request actions and their corresponding methods
62
+	 *
63
+	 * @access private
64
+	 * @return void
65
+	 */
66
+	protected function _set_page_routes()
67
+	{
68
+		$prc_id = ! empty($this->_req_data['PRC_ID']) && ! is_array($this->_req_data['PRC_ID'])
69
+			? $this->_req_data['PRC_ID'] : 0;
70
+		$prt_id = ! empty($this->_req_data['PRT_ID']) && ! is_array($this->_req_data['PRT_ID'])
71
+			? $this->_req_data['PRT_ID'] : 0;
72
+		$this->_page_routes = array(
73
+			'default'                     => array(
74
+				'func'       => '_price_overview_list_table',
75
+				'capability' => 'ee_read_default_prices',
76
+			),
77
+			'add_new_price'               => array(
78
+				'func'       => '_edit_price_details',
79
+				'args'       => array('new_price' => true),
80
+				'capability' => 'ee_edit_default_prices',
81
+			),
82
+			'edit_price'                  => array(
83
+				'func'       => '_edit_price_details',
84
+				'args'       => array('new_price' => false),
85
+				'capability' => 'ee_edit_default_price',
86
+				'obj_id'     => $prc_id,
87
+			),
88
+			'insert_price'                => array(
89
+				'func'       => '_insert_or_update_price',
90
+				'args'       => array('new_price' => true),
91
+				'noheader'   => true,
92
+				'capability' => 'ee_edit_default_prices',
93
+			),
94
+			'update_price'                => array(
95
+				'func'       => '_insert_or_update_price',
96
+				'args'       => array('new_price' => false),
97
+				'noheader'   => true,
98
+				'capability' => 'ee_edit_default_price',
99
+				'obj_id'     => $prc_id,
100
+			),
101
+			'trash_price'                 => array(
102
+				'func'       => '_trash_or_restore_price',
103
+				'args'       => array('trash' => true),
104
+				'noheader'   => true,
105
+				'capability' => 'ee_delete_default_price',
106
+				'obj_id'     => $prc_id,
107
+			),
108
+			'restore_price'               => array(
109
+				'func'       => '_trash_or_restore_price',
110
+				'args'       => array('trash' => false),
111
+				'noheader'   => true,
112
+				'capability' => 'ee_delete_default_price',
113
+				'obj_id'     => $prc_id,
114
+			),
115
+			'delete_price'                => array(
116
+				'func'       => '_delete_price',
117
+				'noheader'   => true,
118
+				'capability' => 'ee_delete_default_price',
119
+				'obj_id'     => $prc_id,
120
+			),
121
+			'espresso_update_price_order' => array(
122
+				'func'       => 'update_price_order',
123
+				'noheader'   => true,
124
+				'capability' => 'ee_edit_default_prices',
125
+			),
126
+			// price types
127
+			'price_types'                 => array(
128
+				'func'       => '_price_types_overview_list_table',
129
+				'capability' => 'ee_read_default_price_types',
130
+			),
131
+			'add_new_price_type'          => array(
132
+				'func'       => '_edit_price_type_details',
133
+				'capability' => 'ee_edit_default_price_types',
134
+			),
135
+			'edit_price_type'             => array(
136
+				'func'       => '_edit_price_type_details',
137
+				'capability' => 'ee_edit_default_price_type',
138
+				'obj_id'     => $prt_id,
139
+			),
140
+			'insert_price_type'           => array(
141
+				'func'       => '_insert_or_update_price_type',
142
+				'args'       => array('new_price_type' => true),
143
+				'noheader'   => true,
144
+				'capability' => 'ee_edit_default_price_types',
145
+			),
146
+			'update_price_type'           => array(
147
+				'func'       => '_insert_or_update_price_type',
148
+				'args'       => array('new_price_type' => false),
149
+				'noheader'   => true,
150
+				'capability' => 'ee_edit_default_price_type',
151
+				'obj_id'     => $prt_id,
152
+			),
153
+			'trash_price_type'            => array(
154
+				'func'       => '_trash_or_restore_price_type',
155
+				'args'       => array('trash' => true),
156
+				'noheader'   => true,
157
+				'capability' => 'ee_delete_default_price_type',
158
+				'obj_id'     => $prt_id,
159
+			),
160
+			'restore_price_type'          => array(
161
+				'func'       => '_trash_or_restore_price_type',
162
+				'args'       => array('trash' => false),
163
+				'noheader'   => true,
164
+				'capability' => 'ee_delete_default_price_type',
165
+				'obj_id'     => $prt_id,
166
+			),
167
+			'delete_price_type'           => array(
168
+				'func'       => '_delete_price_type',
169
+				'noheader'   => true,
170
+				'capability' => 'ee_delete_default_price_type',
171
+				'obj_id'     => $prt_id,
172
+			),
173
+			'tax_settings'                => array(
174
+				'func'       => '_tax_settings',
175
+				'capability' => 'manage_options',
176
+			),
177
+			'update_tax_settings'         => array(
178
+				'func'       => '_update_tax_settings',
179
+				'capability' => 'manage_options',
180
+				'noheader'   => true,
181
+			),
182
+		);
183
+	}
184
+
185
+
186
+	protected function _set_page_config()
187
+	{
188
+
189
+		$this->_page_config = array(
190
+			'default'            => array(
191
+				'nav'           => array(
192
+					'label' => esc_html__('Default Pricing', 'event_espresso'),
193
+					'order' => 10,
194
+				),
195
+				'list_table'    => 'Prices_List_Table',
196
+				'help_tabs'     => array(
197
+					'pricing_default_pricing_help_tab'                           => array(
198
+						'title'    => esc_html__('Default Pricing', 'event_espresso'),
199
+						'filename' => 'pricing_default_pricing',
200
+					),
201
+					'pricing_default_pricing_table_column_headings_help_tab'     => array(
202
+						'title'    => esc_html__('Default Pricing Table Column Headings', 'event_espresso'),
203
+						'filename' => 'pricing_default_pricing_table_column_headings',
204
+					),
205
+					'pricing_default_pricing_views_bulk_actions_search_help_tab' => array(
206
+						'title'    => esc_html__('Default Pricing Views & Bulk Actions & Search', 'event_espresso'),
207
+						'filename' => 'pricing_default_pricing_views_bulk_actions_search',
208
+					),
209
+				),
210
+				'require_nonce' => false,
211
+			),
212
+			'add_new_price'      => array(
213
+				'nav'           => array(
214
+					'label'      => esc_html__('Add New Default Price', 'event_espresso'),
215
+					'order'      => 20,
216
+					'persistent' => false,
217
+				),
218
+				'help_tabs'     => array(
219
+					'add_new_default_price_help_tab' => array(
220
+						'title'    => esc_html__('Add New Default Price', 'event_espresso'),
221
+						'filename' => 'pricing_add_new_default_price',
222
+					),
223
+				),
224
+				'metaboxes'     => array('_publish_post_box', '_espresso_news_post_box', '_price_details_meta_boxes'),
225
+				'require_nonce' => false,
226
+			),
227
+			'edit_price'         => array(
228
+				'nav'           => array(
229
+					'label'      => esc_html__('Edit Default Price', 'event_espresso'),
230
+					'order'      => 20,
231
+					'url'        => isset($this->_req_data['id']) ? add_query_arg(
232
+						array('id' => $this->_req_data['id']),
233
+						$this->_current_page_view_url
234
+					) : $this->_admin_base_url,
235
+					'persistent' => false,
236
+				),
237
+				'metaboxes'     => array('_publish_post_box', '_espresso_news_post_box', '_price_details_meta_boxes'),
238
+				'help_tabs'     => array(
239
+					'edit_default_price_help_tab' => array(
240
+						'title'    => esc_html__('Edit Default Price', 'event_espresso'),
241
+						'filename' => 'pricing_edit_default_price',
242
+					),
243
+				),
244
+				'require_nonce' => false,
245
+			),
246
+			'price_types'        => array(
247
+				'nav'           => array(
248
+					'label' => esc_html__('Price Types', 'event_espresso'),
249
+					'order' => 30,
250
+				),
251
+				'list_table'    => 'Price_Types_List_Table',
252
+				'help_tabs'     => array(
253
+					'pricing_price_types_help_tab'                           => array(
254
+						'title'    => esc_html__('Price Types', 'event_espresso'),
255
+						'filename' => 'pricing_price_types',
256
+					),
257
+					'pricing_price_types_table_column_headings_help_tab'     => array(
258
+						'title'    => esc_html__('Price Types Table Column Headings', 'event_espresso'),
259
+						'filename' => 'pricing_price_types_table_column_headings',
260
+					),
261
+					'pricing_price_types_views_bulk_actions_search_help_tab' => array(
262
+						'title'    => esc_html__('Price Types Views & Bulk Actions & Search', 'event_espresso'),
263
+						'filename' => 'pricing_price_types_views_bulk_actions_search',
264
+					),
265
+				),
266
+				'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
267
+				'require_nonce' => false,
268
+			),
269
+			'add_new_price_type' => array(
270
+				'nav'           => array(
271
+					'label'      => esc_html__('Add New Price Type', 'event_espresso'),
272
+					'order'      => 40,
273
+					'persistent' => false,
274
+				),
275
+				'help_tabs'     => array(
276
+					'add_new_price_type_help_tab' => array(
277
+						'title'    => esc_html__('Add New Price Type', 'event_espresso'),
278
+						'filename' => 'pricing_add_new_price_type',
279
+					),
280
+				),
281
+				'metaboxes'     => array(
282
+					'_publish_post_box',
283
+					'_espresso_news_post_box',
284
+					'_price_type_details_meta_boxes',
285
+				),
286
+				'require_nonce' => false,
287
+			),
288
+			'edit_price_type'    => array(
289
+				'nav'       => array(
290
+					'label'      => esc_html__('Edit Price Type', 'event_espresso'),
291
+					'order'      => 40,
292
+					'persistent' => false,
293
+				),
294
+				'help_tabs' => array(
295
+					'edit_price_type_help_tab' => array(
296
+						'title'    => esc_html__('Edit Price Type', 'event_espresso'),
297
+						'filename' => 'pricing_edit_price_type',
298
+					),
299
+				),
300
+				'metaboxes' => array('_publish_post_box', '_espresso_news_post_box', '_price_type_details_meta_boxes'),
301
+
302
+				'require_nonce' => false,
303
+			),
304
+			'tax_settings'       => array(
305
+				'nav'           => array(
306
+					'label' => esc_html__('Tax Settings', 'event_espresso'),
307
+					'order' => 40,
308
+				),
309
+				'labels'        => array(
310
+					'publishbox' => esc_html__('Update Tax Settings', 'event_espresso'),
311
+				),
312
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
313
+				'require_nonce' => true,
314
+			),
315
+		);
316
+	}
317
+
318
+
319
+	protected function _add_screen_options()
320
+	{
321
+		// todo
322
+	}
323
+
324
+
325
+	protected function _add_screen_options_default()
326
+	{
327
+		$this->_per_page_screen_option();
328
+	}
329
+
330
+
331
+	protected function _add_screen_options_price_types()
332
+	{
333
+		$page_title = $this->_admin_page_title;
334
+		$this->_admin_page_title = esc_html__('Price Types', 'event_espresso');
335
+		$this->_per_page_screen_option();
336
+		$this->_admin_page_title = $page_title;
337
+	}
338
+
339
+
340
+	protected function _add_feature_pointers()
341
+	{
342
+	}
343
+
344
+
345
+	public function load_scripts_styles()
346
+	{
347
+		// styles
348
+		wp_enqueue_style('espresso-ui-theme');
349
+		wp_register_style(
350
+			'espresso_PRICING',
351
+			PRICING_ASSETS_URL . 'espresso_pricing_admin.css',
352
+			array(),
353
+			EVENT_ESPRESSO_VERSION
354
+		);
355
+		wp_enqueue_style('espresso_PRICING');
356
+
357
+		// scripts
358
+		wp_enqueue_script('ee_admin_js');
359
+		wp_enqueue_script('jquery-ui-position');
360
+		wp_enqueue_script('jquery-ui-widget');
361
+		// wp_enqueue_script('jquery-ui-dialog');
362
+		// wp_enqueue_script('jquery-ui-draggable');
363
+		// wp_enqueue_script('jquery-ui-datepicker');
364
+		wp_register_script(
365
+			'espresso_PRICING',
366
+			PRICING_ASSETS_URL . 'espresso_pricing_admin.js',
367
+			array('jquery'),
368
+			EVENT_ESPRESSO_VERSION,
369
+			true
370
+		);
371
+		wp_enqueue_script('espresso_PRICING');
372
+	}
373
+
374
+
375
+	public function load_scripts_styles_default()
376
+	{
377
+		wp_enqueue_script('espresso_ajax_table_sorting');
378
+	}
379
+
380
+
381
+	public function admin_footer_scripts()
382
+	{
383
+	}
384
+
385
+	public function admin_init()
386
+	{
387
+	}
388
+
389
+	public function admin_notices()
390
+	{
391
+	}
392
+
393
+
394
+	protected function _set_list_table_views_default()
395
+	{
396
+		$this->_views = array(
397
+			'all' => array(
398
+				'slug'        => 'all',
399
+				'label'       => esc_html__('View All Default Pricing', 'event_espresso'),
400
+				'count'       => 0,
401
+				'bulk_action' => array(
402
+					'trash_price' => esc_html__('Move to Trash', 'event_espresso'),
403
+				),
404
+			),
405
+		);
406
+
407
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_default_prices', 'pricing_trash_price')) {
408
+			$this->_views['trashed'] = array(
409
+				'slug'        => 'trashed',
410
+				'label'       => esc_html__('Trash', 'event_espresso'),
411
+				'count'       => 0,
412
+				'bulk_action' => array(
413
+					'restore_price' => esc_html__('Restore from Trash', 'event_espresso'),
414
+					'delete_price'  => esc_html__('Delete Permanently', 'event_espresso'),
415
+				),
416
+			);
417
+		}
418
+	}
419
+
420
+
421
+	protected function _set_list_table_views_price_types()
422
+	{
423
+		$this->_views = array(
424
+			'all' => array(
425
+				'slug'        => 'all',
426
+				'label'       => esc_html__('All', 'event_espresso'),
427
+				'count'       => 0,
428
+				'bulk_action' => array(
429
+					'trash_price_type' => esc_html__('Move to Trash', 'event_espresso'),
430
+				),
431
+			),
432
+		);
433
+
434
+		if (
435
+			EE_Registry::instance()->CAP->current_user_can(
436
+				'ee_delete_default_price_types',
437
+				'pricing_trash_price_type'
438
+			)
439
+		) {
440
+			$this->_views['trashed'] = array(
441
+				'slug'        => 'trashed',
442
+				'label'       => esc_html__('Trash', 'event_espresso'),
443
+				'count'       => 0,
444
+				'bulk_action' => array(
445
+					'restore_price_type' => esc_html__('Restore from Trash', 'event_espresso'),
446
+					'delete_price_type'  => esc_html__('Delete Permanently', 'event_espresso'),
447
+				),
448
+			);
449
+		}
450
+	}
451
+
452
+
453
+	/**
454
+	 *        generates HTML for main Prices Admin page
455
+	 *
456
+	 * @access protected
457
+	 * @return void
458
+	 */
459
+	protected function _price_overview_list_table()
460
+	{
461
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
462
+			'add_new_price',
463
+			'add',
464
+			array(),
465
+			'add-new-h2'
466
+		);
467
+		$this->admin_page_title .= $this->_learn_more_about_pricing_link();
468
+		$this->_search_btn_label = esc_html__('Default Prices', 'event_espresso');
469
+		$this->display_admin_list_table_page_with_no_sidebar();
470
+	}
471
+
472
+
473
+	/**
474
+	 *    retrieve data for Prices List table
475
+	 *
476
+	 * @access public
477
+	 * @param  int     $per_page how many prices displayed per page
478
+	 * @param  boolean $count    return the count or objects
479
+	 * @param  boolean $trashed  whether the current view is of the trash can - eww yuck!
480
+	 * @return mixed (int|array)  int = count || array of price objects
481
+	 */
482
+	public function get_prices_overview_data($per_page = 10, $count = false, $trashed = false)
483
+	{
484
+
485
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
486
+		// start with an empty array
487
+		$event_pricing = array();
488
+
489
+		require_once(PRICING_ADMIN . 'Prices_List_Table.class.php');
490
+		require_once(EE_MODELS . 'EEM_Price.model.php');
491
+		// $PRC = EEM_Price::instance();
492
+
493
+		$this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? '' : $this->_req_data['orderby'];
494
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
495
+			: 'ASC';
496
+
497
+		switch ($this->_req_data['orderby']) {
498
+			case 'name':
499
+				$orderby = array('PRC_name' => $order);
500
+				break;
501
+			case 'type':
502
+				$orderby = array('Price_Type.PRT_name' => $order);
503
+				break;
504
+			case 'amount':
505
+				$orderby = array('PRC_amount' => $order);
506
+				break;
507
+			default:
508
+				$orderby = array('PRC_order' => $order, 'Price_Type.PRT_order' => $order, 'PRC_ID' => $order);
509
+		}
510
+
511
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
512
+			? $this->_req_data['paged'] : 1;
513
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
514
+			? $this->_req_data['perpage'] : $per_page;
515
+
516
+		$_where = array(
517
+			'PRC_is_default' => 1,
518
+			'PRC_deleted'    => $trashed,
519
+		);
520
+
521
+		$offset = ($current_page - 1) * $per_page;
522
+		$limit = array($offset, $per_page);
523
+
524
+		if (isset($this->_req_data['s'])) {
525
+			$sstr = '%' . $this->_req_data['s'] . '%';
526
+			$_where['OR'] = array(
527
+				'PRC_name'            => array('LIKE', $sstr),
528
+				'PRC_desc'            => array('LIKE', $sstr),
529
+				'PRC_amount'          => array('LIKE', $sstr),
530
+				'Price_Type.PRT_name' => array('LIKE', $sstr),
531
+			);
532
+		}
533
+
534
+		$query_params = array(
535
+			$_where,
536
+			'order_by' => $orderby,
537
+			'limit'    => $limit,
538
+			'group_by' => 'PRC_ID',
539
+		);
540
+
541
+		if ($count) {
542
+			return $trashed ? EEM_Price::instance()->count(array($_where))
543
+				: EEM_Price::instance()->count_deleted_and_undeleted(array($_where));
544
+		} else {
545
+			return EEM_Price::instance()->get_all_deleted_and_undeleted($query_params);
546
+		}
547
+	}
548
+
549
+
550
+	/**
551
+	 *        _price_details
552
+	 *
553
+	 * @access protected
554
+	 * @return void
555
+	 */
556
+	protected function _edit_price_details()
557
+	{
558
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
559
+		// grab price ID
560
+		$PRC_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id']) ? absint($this->_req_data['id'])
561
+			: false;
562
+		// change page title based on request action
563
+		switch ($this->_req_action) {
564
+			case 'add_new_price':
565
+				$this->_admin_page_title = esc_html__('Add New Price', 'event_espresso');
566
+				break;
567
+			case 'edit_price':
568
+				$this->_admin_page_title = esc_html__('Edit Price', 'event_espresso');
569
+				break;
570
+			default:
571
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
572
+		}
573
+		// add PRC_ID to title if editing
574
+		$this->_admin_page_title = $PRC_ID ? $this->_admin_page_title . ' # ' . $PRC_ID : $this->_admin_page_title;
575
+
576
+		// get prices
577
+		require_once(EE_MODELS . 'EEM_Price.model.php');
578
+		$PRC = EEM_Price::instance();
579
+
580
+		if ($PRC_ID) {
581
+			$price = $PRC->get_one_by_ID($PRC_ID);
582
+			$additional_hidden_fields = array(
583
+				'PRC_ID' => array('type' => 'hidden', 'value' => $PRC_ID),
584
+			);
585
+			$this->_set_add_edit_form_tags('update_price', $additional_hidden_fields);
586
+		} else {
587
+			$price = $PRC->get_new_price();
588
+			$this->_set_add_edit_form_tags('insert_price');
589
+		}
590
+
591
+		$this->_template_args['PRC_ID'] = $PRC_ID;
592
+		$this->_template_args['price'] = $price;
593
+
594
+		// get price types
595
+		require_once(EE_MODELS . 'EEM_Price_Type.model.php');
596
+		$PRT = EEM_Price_Type::instance();
597
+		$price_types = $PRT->get_all(array(array('PBT_ID' => array('!=', 1))));
598
+		$price_type_names = array();
599
+		if (empty($price_types)) {
600
+			$msg = esc_html__(
601
+				'You have no price types defined. Please add a price type before adding a price.',
602
+				'event_espresso'
603
+			);
604
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
605
+			exit();
606
+		} else {
607
+			foreach ($price_types as $type) {
608
+				// if ($type->is_global()) {
609
+				$price_type_names[] = array('id' => $type->ID(), 'text' => $type->name());
610
+			// }
611
+			}
612
+		}
613
+
614
+		$this->_template_args['price_types'] = $price_type_names;
615
+		$this->_template_args['learn_more_about_pricing_link'] = $this->_learn_more_about_pricing_link();
616
+
617
+		$this->_set_publish_post_box_vars('id', $PRC_ID);
618
+		// the details template wrapper
619
+		$this->display_admin_page_with_sidebar();
620
+	}
621
+
622
+
623
+	/**
624
+	 *        declare price details page metaboxes
625
+	 *
626
+	 * @access protected
627
+	 * @return void
628
+	 */
629
+	protected function _price_details_meta_boxes()
630
+	{
631
+		add_meta_box(
632
+			'edit-price-details-mbox',
633
+			esc_html__('Default Price Details', 'event_espresso'),
634
+			array($this, '_edit_price_details_meta_box'),
635
+			$this->wp_page_slug,
636
+			'normal',
637
+			'high'
638
+		);
639
+	}
640
+
641
+
642
+	/**
643
+	 *        _edit_price_details_meta_box
644
+	 *
645
+	 * @access public
646
+	 * @return void
647
+	 */
648
+	public function _edit_price_details_meta_box()
649
+	{
650
+		echo EEH_Template::display_template(
651
+			PRICING_TEMPLATE_PATH . 'pricing_details_main_meta_box.template.php',
652
+			$this->_template_args,
653
+			true
654
+		);
655
+	}
656
+
657
+
658
+	/**
659
+	 * @return array
660
+	 * @throws EE_Error
661
+	 * @throws ReflectionException
662
+	 */
663
+	protected function set_price_column_values()
664
+	{
665
+		$PRC_order = 0;
666
+		$PRT_ID = absint($this->_req_data['PRT_ID']);
667
+		if ($PRT_ID) {
668
+			/** @var EE_Price_Type $price_type */
669
+			$price_type = EEM_Price_Type::instance()->get_one_by_ID($PRT_ID);
670
+			if ($price_type instanceof EE_Price_Type) {
671
+				$PRC_order = $price_type->order();
672
+			}
673
+		}
674
+		return array(
675
+			'PRT_ID'         => $PRT_ID,
676
+			'PRC_amount'     => $this->_req_data['PRC_amount'],
677
+			'PRC_name'       => $this->_req_data['PRC_name'],
678
+			'PRC_desc'       => $this->_req_data['PRC_desc'],
679
+			'PRC_is_default' => 1,
680
+			'PRC_overrides'  => null,
681
+			'PRC_order'      => $PRC_order,
682
+			'PRC_deleted'    => 0,
683
+			'PRC_parent'     => 0,
684
+		);
685
+	}
686
+
687
+
688
+	/**
689
+	 * @param boolean $insert - whether to insert or update
690
+	 * @return void
691
+	 * @throws EE_Error
692
+	 * @throws ReflectionException
693
+	 */
694
+	protected function _insert_or_update_price($insert = false)
695
+	{
696
+		require_once(EE_MODELS . 'EEM_Price.model.php');
697
+		$PRC = EEM_Price::instance();
698
+
699
+		// why be so pessimistic ???  : (
700
+		$success = 0;
701
+
702
+		$set_column_values = $this->set_price_column_values();
703
+		// is this a new Price ?
704
+		if ($insert) {
705
+			// run the insert
706
+			if ($PRC_ID = $PRC->insert($set_column_values)) {
707
+				// make sure this new price modifier is attached to the ticket but ONLY if it is not a tax type
708
+				$PR = EEM_price::instance()->get_one_by_ID($PRC_ID);
709
+				if ($PR instanceof EE_Price && $PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
710
+					$ticket = EEM_Ticket::instance()->get_one_by_ID(1);
711
+					$ticket->_add_relation_to($PR, 'Price');
712
+					$ticket->save();
713
+				}
714
+				$success = 1;
715
+			} else {
716
+				$PRC_ID = false;
717
+				$success = 0;
718
+			}
719
+			$action_desc = 'created';
720
+		} else {
721
+			$PRC_ID = absint($this->_req_data['PRC_ID']);
722
+			// run the update
723
+			$where_cols_n_values = array('PRC_ID' => $PRC_ID);
724
+			if ($PRC->update($set_column_values, array($where_cols_n_values))) {
725
+				$success = 1;
726
+			}
727
+
728
+			$PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
729
+			if ($PR instanceof EE_Price && $PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
730
+				// if this is $PRC_ID == 1,
731
+				// then we need to update the default ticket attached to this price so the TKT_price value is updated.
732
+				if ($PRC_ID === 1) {
733
+					$ticket = $PR->get_first_related('Ticket');
734
+					if ($ticket) {
735
+						$ticket->set('TKT_price', $PR->get('PRC_amount'));
736
+						$ticket->set('TKT_name', $PR->get('PRC_name'));
737
+						$ticket->set('TKT_description', $PR->get('PRC_desc'));
738
+						$ticket->save();
739
+					}
740
+				} else {
741
+					// we make sure this price is attached to base ticket. but ONLY if its not a tax ticket type.
742
+					$ticket = EEM_Ticket::instance()->get_one_by_ID(1);
743
+					$ticket->_add_relation_to($PRC_ID, 'Price');
744
+					$ticket->save();
745
+				}
746
+			}
747
+
748
+			$action_desc = 'updated';
749
+		}
750
+
751
+		$query_args = array('action' => 'edit_price', 'id' => $PRC_ID);
752
+
753
+		$this->_redirect_after_action($success, 'Prices', $action_desc, $query_args);
754
+	}
755
+
756
+
757
+	/**
758
+	 *        _trash_or_restore_price
759
+	 *
760
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
761
+	 * @access protected
762
+	 * @return void
763
+	 */
764
+	protected function _trash_or_restore_price($trash = true)
765
+	{
766
+
767
+		// echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
768
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
769
+
770
+		require_once(EE_MODELS . 'EEM_Price.model.php');
771
+		$PRC = EEM_Price::instance();
772
+
773
+		$success = 1;
774
+		$PRC_deleted = $trash ? true : false;
775
+
776
+		// get base ticket for updating
777
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(1);
778
+		// Checkboxes
779
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
780
+			// if array has more than one element than success message should be plural
781
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
782
+			// cycle thru checkboxes
783
+			while (list($PRC_ID, $value) = each($this->_req_data['checkbox'])) {
784
+				if (! $PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), absint($PRC_ID))) {
785
+					$success = 0;
786
+				} else {
787
+					$PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
788
+					if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
789
+						// if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
790
+						if ($PRC_deleted) {
791
+							$ticket->_remove_relation_to($PRC_ID, 'Price');
792
+						} else {
793
+							$ticket->_add_relation_to($PRC_ID, 'Price');
794
+						}
795
+						$ticket->save();
796
+					}
797
+				}
798
+			}
799
+		} else {
800
+			// grab single id and delete
801
+			$PRC_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
802
+			if (empty($PRC_ID) || ! $PRC->update_by_ID(array('PRC_deleted' => $PRC_deleted), $PRC_ID)) {
803
+				$success = 0;
804
+			} else {
805
+				$PR = EEM_Price::instance()->get_one_by_ID($PRC_ID);
806
+				if ($PR->type_obj()->base_type() !== EEM_Price_Type::base_type_tax) {
807
+					// if trashing then remove relations to base default ticket.  If restoring then add back to base default ticket
808
+					if ($PRC_deleted) {
809
+						$ticket->_remove_relation_to($PRC_ID, 'Price');
810
+					} else {
811
+						$ticket->_add_relation_to($PRC_ID, 'Price');
812
+					}
813
+					$ticket->save();
814
+				}
815
+			}
816
+		}
817
+		$query_args = array(
818
+			'action' => 'default',
819
+		);
820
+
821
+		if ($success) {
822
+			if ($trash) {
823
+				$msg = $success == 2
824
+					? esc_html__('The Prices have been trashed.', 'event_espresso')
825
+					: esc_html__(
826
+						'The Price has been trashed.',
827
+						'event_espresso'
828
+					);
829
+			} else {
830
+				$msg = $success == 2
831
+					? esc_html__('The Prices have been restored.', 'event_espresso')
832
+					: esc_html__(
833
+						'The Price has been restored.',
834
+						'event_espresso'
835
+					);
836
+			}
837
+
838
+			EE_Error::add_success($msg);
839
+		}
840
+
841
+		$this->_redirect_after_action(false, '', '', $query_args, true);
842
+	}
843
+
844
+
845
+	/**
846
+	 *        _delete_price
847
+	 *
848
+	 * @access protected
849
+	 * @return void
850
+	 */
851
+	protected function _delete_price()
852
+	{
853
+
854
+		// echo '<h3>'. __CLASS__ . '->' . __FUNCTION__ . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h3>';
855
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
856
+
857
+		require_once(EE_MODELS . 'EEM_Price.model.php');
858
+		$PRC = EEM_Price::instance();
859
+
860
+		$success = 1;
861
+		// Checkboxes
862
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
863
+			// if array has more than one element than success message should be plural
864
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
865
+			// cycle thru bulk action checkboxes
866
+			while (list($PRC_ID, $value) = each($this->_req_data['checkbox'])) {
867
+				if (! $PRC->delete_permanently_by_ID(absint($PRC_ID))) {
868
+					$success = 0;
869
+				}
870
+			}
871
+		} else {
872
+			// grab single id and delete
873
+			$PRC_ID = absint($this->_req_data['id']);
874
+			if (! $PRC->delete_permanently_by_ID($PRC_ID)) {
875
+				$success = 0;
876
+			}
877
+		}
878
+
879
+		$this->_redirect_after_action($success, 'Prices', 'deleted', array());
880
+	}
881
+
882
+
883
+	public function update_price_order()
884
+	{
885
+		$success = esc_html__('Price order was updated successfully.', 'event_espresso');
886
+
887
+		// grab our row IDs
888
+		$row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids']) ? explode(
889
+			',',
890
+			rtrim(
891
+				$this->_req_data['row_ids'],
892
+				','
893
+			)
894
+		) : false;
895
+
896
+		if (is_array($row_ids)) {
897
+			for ($i = 0; $i < count($row_ids); $i++) {
898
+				// Update the prices when re-ordering
899
+				$id = absint($row_ids[ $i ]);
900
+				if (
901
+					EEM_Price::instance()->update(
902
+						array('PRC_order' => $i + 1),
903
+						array(array('PRC_ID' => $id))
904
+					) === false
905
+				) {
906
+					$success = false;
907
+				}
908
+			}
909
+		} else {
910
+			$success = false;
911
+		}
912
+
913
+		$errors = ! $success ? esc_html__('An error occurred. The price order was not updated.', 'event_espresso') : false;
914
+
915
+		echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
916
+		die();
917
+	}
918
+
919
+
920
+
921
+
922
+
923
+
924
+	/**************************************************************************************************************************************************************
925 925
      ********************************************************************  TICKET PRICE TYPES  ******************************************************************
926 926
      **************************************************************************************************************************************************************/
927 927
 
928 928
 
929
-    /**
930
-     *        generates HTML for main Prices Admin page
931
-     *
932
-     * @access protected
933
-     * @return void
934
-     */
935
-    protected function _price_types_overview_list_table()
936
-    {
937
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
938
-            'add_new_price_type',
939
-            'add_type',
940
-            array(),
941
-            'add-new-h2'
942
-        );
943
-        $this->admin_page_title .= $this->_learn_more_about_pricing_link();
944
-        $this->_search_btn_label = esc_html__('Price Types', 'event_espresso');
945
-        $this->display_admin_list_table_page_with_no_sidebar();
946
-    }
947
-
948
-
949
-    /**
950
-     *    retrieve data for Price Types List table
951
-     *
952
-     * @access public
953
-     * @param  int     $per_page how many prices displayed per page
954
-     * @param  boolean $count    return the count or objects
955
-     * @param  boolean $trashed  whether the current view is of the trash can - eww yuck!
956
-     * @return mixed (int|array)  int = count || array of price objects
957
-     */
958
-    public function get_price_types_overview_data($per_page = 10, $count = false, $trashed = false)
959
-    {
960
-
961
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
962
-        // start with an empty array
963
-
964
-        require_once(PRICING_ADMIN . 'Price_Types_List_Table.class.php');
965
-        require_once(EE_MODELS . 'EEM_Price_Type.model.php');
966
-
967
-        $this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? '' : $this->_req_data['orderby'];
968
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
969
-            : 'ASC';
970
-        switch ($this->_req_data['orderby']) {
971
-            case 'name':
972
-                $orderby = array('PRT_name' => $order);
973
-                break;
974
-            default:
975
-                $orderby = array('PRT_order' => $order);
976
-        }
977
-
978
-
979
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
980
-            ? $this->_req_data['paged'] : 1;
981
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
982
-            ? $this->_req_data['perpage'] : $per_page;
983
-
984
-        $offset = ($current_page - 1) * $per_page;
985
-        $limit = array($offset, $per_page);
986
-
987
-        $_where = array('PRT_deleted' => $trashed, 'PBT_ID' => array('!=', 1));
988
-
989
-        if (isset($this->_req_data['s'])) {
990
-            $sstr = '%' . $this->_req_data['s'] . '%';
991
-            $_where['OR'] = array(
992
-                'PRT_name' => array('LIKE', $sstr),
993
-            );
994
-        }
995
-        $query_params = array(
996
-            $_where,
997
-            'order_by' => $orderby,
998
-            'limit'    => $limit,
999
-        );
1000
-        if ($count) {
1001
-            return EEM_Price_Type::instance()->count_deleted_and_undeleted($query_params);
1002
-        } else {
1003
-            return EEM_Price_Type::instance()->get_all_deleted_and_undeleted($query_params);
1004
-        }
1005
-
1006
-        // EEH_Debug_Tools::printr( $price_types, '$price_types  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     *        _edit_price_type_details
1012
-     *
1013
-     * @access protected
1014
-     * @return void
1015
-     */
1016
-    protected function _edit_price_type_details()
1017
-    {
1018
-
1019
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1020
-
1021
-
1022
-        // grab price type ID
1023
-        $PRT_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id']) ? absint($this->_req_data['id'])
1024
-            : false;
1025
-        // change page title based on request action
1026
-        switch ($this->_req_action) {
1027
-            case 'add_new_price_type':
1028
-                $this->_admin_page_title = esc_html__('Add New Price Type', 'event_espresso');
1029
-                break;
1030
-            case 'edit_price_type':
1031
-                $this->_admin_page_title = esc_html__('Edit Price Type', 'event_espresso');
1032
-                break;
1033
-            default:
1034
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
1035
-        }
1036
-        // add PRT_ID to title if editing
1037
-        $this->_admin_page_title = $PRT_ID ? $this->_admin_page_title . ' # ' . $PRT_ID : $this->_admin_page_title;
1038
-
1039
-        if ($PRT_ID) {
1040
-            $price_type = EEM_Price_Type::instance()->get_one_by_ID($PRT_ID);
1041
-            $additional_hidden_fields = array('PRT_ID' => array('type' => 'hidden', 'value' => $PRT_ID));
1042
-            $this->_set_add_edit_form_tags('update_price_type', $additional_hidden_fields);
1043
-        } else {
1044
-            $price_type = EEM_Price_Type::instance()->get_new_price_type();
1045
-            $this->_set_add_edit_form_tags('insert_price_type');
1046
-        }
1047
-
1048
-        $this->_template_args['PRT_ID'] = $PRT_ID;
1049
-        $this->_template_args['price_type'] = $price_type;
1050
-
1051
-
1052
-        $base_types = EEM_Price_Type::instance()->get_base_types();
1053
-        $select_values = array();
1054
-        foreach ($base_types as $ref => $text) {
1055
-            if ($ref == EEM_Price_Type::base_type_base_price) {
1056
-                // do not allow creation of base_type_base_prices because that's a system only base type.
1057
-                continue;
1058
-            }
1059
-            $values[] = array('id' => $ref, 'text' => $text);
1060
-        }
1061
-
1062
-
1063
-        $this->_template_args['base_type_select'] = EEH_Form_Fields::select_input(
1064
-            'base_type',
1065
-            $values,
1066
-            $price_type->base_type(),
1067
-            'id="price-type-base-type-slct"'
1068
-        );
1069
-        $this->_template_args['learn_more_about_pricing_link'] = $this->_learn_more_about_pricing_link();
1070
-        $redirect_URL = add_query_arg(array('action' => 'price_types'), $this->_admin_base_url);
1071
-        $this->_set_publish_post_box_vars('id', $PRT_ID, false, $redirect_URL);
1072
-        // the details template wrapper
1073
-        $this->display_admin_page_with_sidebar();
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     *        declare price type details page metaboxes
1079
-     *
1080
-     * @access protected
1081
-     * @return void
1082
-     */
1083
-    protected function _price_type_details_meta_boxes()
1084
-    {
1085
-        add_meta_box(
1086
-            'edit-price-details-mbox',
1087
-            esc_html__('Price Type Details', 'event_espresso'),
1088
-            array($this, '_edit_price_type_details_meta_box'),
1089
-            $this->wp_page_slug,
1090
-            'normal',
1091
-            'high'
1092
-        );
1093
-    }
1094
-
1095
-
1096
-    /**
1097
-     *        _edit_price_type_details_meta_box
1098
-     *
1099
-     * @access public
1100
-     * @return void
1101
-     */
1102
-    public function _edit_price_type_details_meta_box()
1103
-    {
1104
-        echo EEH_Template::display_template(
1105
-            PRICING_TEMPLATE_PATH . 'pricing_type_details_main_meta_box.template.php',
1106
-            $this->_template_args,
1107
-            true
1108
-        );
1109
-    }
1110
-
1111
-
1112
-    /**
1113
-     *        set_price_type_column_values
1114
-     *
1115
-     * @access protected
1116
-     * @return void
1117
-     */
1118
-    protected function set_price_type_column_values()
1119
-    {
1120
-
1121
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1122
-
1123
-        $base_type = ! empty($this->_req_data['base_type']) ? $this->_req_data['base_type']
1124
-            : EEM_Price_Type::base_type_base_price;
1125
-
1126
-        switch ($base_type) {
1127
-            case EEM_Price_Type::base_type_base_price:
1128
-                $this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_base_price;
1129
-                $this->_req_data['PRT_is_percent'] = 0;
1130
-                $this->_req_data['PRT_order'] = 0;
1131
-                break;
1132
-
1133
-            case EEM_Price_Type::base_type_discount:
1134
-                $this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_discount;
1135
-                break;
1136
-
1137
-            case EEM_Price_Type::base_type_surcharge:
1138
-                $this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_surcharge;
1139
-                break;
1140
-
1141
-            case EEM_Price_Type::base_type_tax:
1142
-                $this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_tax;
1143
-                $this->_req_data['PRT_is_percent'] = 1;
1144
-                break;
1145
-        }/**/
1146
-
1147
-        $set_column_values = array(
1148
-            'PRT_name'       => $this->_req_data['PRT_name'],
1149
-            'PBT_ID'         => absint($this->_req_data['PBT_ID']),
1150
-            'PRT_is_percent' => absint($this->_req_data['PRT_is_percent']),
1151
-            'PRT_order'      => absint($this->_req_data['PRT_order']),
1152
-            'PRT_deleted'    => 0,
1153
-        );
1154
-
1155
-        return $set_column_values;
1156
-    }
1157
-
1158
-
1159
-    /**
1160
-     *        _insert_or_update_price_type
1161
-     *
1162
-     * @param boolean $new_price_type - whether to insert or update
1163
-     * @access protected
1164
-     * @return void
1165
-     */
1166
-    protected function _insert_or_update_price_type($new_price_type = false)
1167
-    {
1168
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1169
-
1170
-        require_once(EE_MODELS . 'EEM_Price_Type.model.php');
1171
-        $PRT = EEM_Price_Type::instance();
1172
-
1173
-        // why be so pessimistic ???  : (
1174
-        $success = 0;
1175
-
1176
-        $set_column_values = $this->set_price_type_column_values();
1177
-        // is this a new Price ?
1178
-        if ($new_price_type) {
1179
-            // run the insert
1180
-            if ($PRT_ID = $PRT->insert($set_column_values)) {
1181
-                $success = 1;
1182
-            }
1183
-            $action_desc = 'created';
1184
-        } else {
1185
-            $PRT_ID = absint($this->_req_data['PRT_ID']);
1186
-            // run the update
1187
-            $where_cols_n_values = array('PRT_ID' => $PRT_ID);
1188
-            if ($PRT->update($set_column_values, array($where_cols_n_values))) {
1189
-                $success = 1;
1190
-            }
1191
-            $action_desc = 'updated';
1192
-        }
1193
-
1194
-        $query_args = array('action' => 'edit_price_type', 'id' => $PRT_ID);
1195
-        $this->_redirect_after_action($success, 'Price Type', $action_desc, $query_args);
1196
-    }
1197
-
1198
-
1199
-    /**
1200
-     *        _trash_or_restore_price_type
1201
-     *
1202
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
1203
-     * @access protected
1204
-     * @return void
1205
-     */
1206
-    protected function _trash_or_restore_price_type($trash = true)
1207
-    {
1208
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1209
-
1210
-        require_once(EE_MODELS . 'EEM_Price_Type.model.php');
1211
-        $PRT = EEM_Price_Type::instance();
1212
-
1213
-        $success = 1;
1214
-        $PRT_deleted = $trash ? true : false;
1215
-        // Checkboxes
1216
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1217
-            // if array has more than one element than success message should be plural
1218
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1219
-            $what = count($this->_req_data['checkbox']) > 1 ? 'Price Types' : 'Price Type';
1220
-            // cycle thru checkboxes
1221
-            while (list($PRT_ID, $value) = each($this->_req_data['checkbox'])) {
1222
-                if (! $PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
1223
-                    $success = 0;
1224
-                }
1225
-            }
1226
-        } else {
1227
-            // grab single id and delete
1228
-            $PRT_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
1229
-            if (empty($PRT_ID) || ! $PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
1230
-                $success = 0;
1231
-            }
1232
-            $what = 'Price Type';
1233
-        }
1234
-
1235
-        $query_args = array('action' => 'price_types');
1236
-        if ($success) {
1237
-            if ($trash) {
1238
-                $msg = $success > 1
1239
-                    ? esc_html__('The Price Types have been trashed.', 'event_espresso')
1240
-                    : esc_html__(
1241
-                        'The Price Type has been trashed.',
1242
-                        'event_espresso'
1243
-                    );
1244
-            } else {
1245
-                $msg = $success > 1
1246
-                    ? esc_html__('The Price Types have been restored.', 'event_espresso')
1247
-                    : esc_html__(
1248
-                        'The Price Type has been restored.',
1249
-                        'event_espresso'
1250
-                    );
1251
-            }
1252
-            EE_Error::add_success($msg);
1253
-        }
1254
-
1255
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     *        _delete_price_type
1261
-     *
1262
-     * @access protected
1263
-     * @return void
1264
-     */
1265
-    protected function _delete_price_type()
1266
-    {
1267
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1268
-
1269
-        $PRT = EEM_Price_Type::instance();
1270
-
1271
-        $success = 1;
1272
-        // Checkboxes
1273
-        if (! empty($this->_req_data['checkbox'])) {
1274
-            // if array has more than one element than success message should be plural
1275
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1276
-            $what = $PRT->item_name($success);
1277
-            // cycle thru bulk action checkboxes
1278
-            while (list($PRT_ID, $value) = each($this->_req_data['checkbox'])) {
1279
-                if (! $PRT->delete_permanently_by_ID($PRT_ID)) {
1280
-                    $success = 0;
1281
-                }
1282
-            }
1283
-        }
1284
-
1285
-
1286
-        $query_args = array('action' => 'price_types');
1287
-        $this->_redirect_after_action($success, $what, 'deleted', $query_args);
1288
-    }
1289
-
1290
-
1291
-    /**
1292
-     *        _learn_more_about_pricing_link
1293
-     *
1294
-     * @access protected
1295
-     * @return string
1296
-     */
1297
-    protected function _learn_more_about_pricing_link()
1298
-    {
1299
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >' . esc_html__(
1300
-            'learn more about how pricing works',
1301
-            'event_espresso'
1302
-        ) . '</a>';
1303
-    }
1304
-
1305
-
1306
-    protected function _tax_settings()
1307
-    {
1308
-        $this->_set_add_edit_form_tags('update_tax_settings');
1309
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
1310
-        $this->_template_args['admin_page_content'] = $this->tax_settings_form()->get_html();
1311
-        $this->display_admin_page_with_sidebar();
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * @return \EE_Form_Section_Proper
1317
-     * @throws \EE_Error
1318
-     */
1319
-    protected function tax_settings_form()
1320
-    {
1321
-        return new EE_Form_Section_Proper(
1322
-            array(
1323
-                'name'            => 'tax_settings_form',
1324
-                'html_id'         => 'tax_settings_form',
1325
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1326
-                'subsections'     => apply_filters(
1327
-                    'FHEE__Pricing_Admin_Page__tax_settings_form__form_subsections',
1328
-                    array(
1329
-                        'tax_settings' => new EE_Form_Section_Proper(
1330
-                            array(
1331
-                                'name'            => 'tax_settings_tbl',
1332
-                                'html_id'         => 'tax_settings_tbl',
1333
-                                'html_class'      => 'form-table',
1334
-                                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1335
-                                'subsections'     => array(
1336
-                                    'prices_displayed_including_taxes' => new EE_Yes_No_Input(
1337
-                                        array(
1338
-                                            'html_label_text'         => esc_html__(
1339
-                                                "Show Prices With Taxes Included?",
1340
-                                                'event_espresso'
1341
-                                            ),
1342
-                                            'html_help_text'          => esc_html__(
1343
-                                                'Indicates whether or not to display prices with the taxes included',
1344
-                                                'event_espresso'
1345
-                                            ),
1346
-                                            'default'                 => isset(
1347
-                                                EE_Registry::instance()
1348
-                                                    ->CFG
1349
-                                                    ->tax_settings
1350
-                                                    ->prices_displayed_including_taxes
1351
-                                            )
1352
-                                                ? EE_Registry::instance()
1353
-                                                    ->CFG
1354
-                                                    ->tax_settings
1355
-                                                    ->prices_displayed_including_taxes
1356
-                                                : true,
1357
-                                            'display_html_label_text' => false,
1358
-                                        )
1359
-                                    ),
1360
-                                ),
1361
-                            )
1362
-                        ),
1363
-                    )
1364
-                ),
1365
-            )
1366
-        );
1367
-    }
1368
-
1369
-
1370
-    /**
1371
-     * _update_tax_settings
1372
-     *
1373
-     * @since 4.9.13
1374
-     * @return void
1375
-     */
1376
-    public function _update_tax_settings()
1377
-    {
1378
-        if (! isset(EE_Registry::instance()->CFG->tax_settings)) {
1379
-            EE_Registry::instance()->CFG->tax_settings = new EE_Tax_Config();
1380
-        }
1381
-        try {
1382
-            $tax_form = $this->tax_settings_form();
1383
-            // check for form submission
1384
-            if ($tax_form->was_submitted()) {
1385
-                // capture form data
1386
-                $tax_form->receive_form_submission();
1387
-                // validate form data
1388
-                if ($tax_form->is_valid()) {
1389
-                    // grab validated data from form
1390
-                    $valid_data = $tax_form->valid_data();
1391
-                    // set data on config
1392
-                    EE_Registry::instance()
1393
-                        ->CFG
1394
-                        ->tax_settings
1395
-                        ->prices_displayed_including_taxes
1396
-                        = $valid_data['tax_settings']['prices_displayed_including_taxes'];
1397
-                } else {
1398
-                    if ($tax_form->submission_error_message() !== '') {
1399
-                        EE_Error::add_error(
1400
-                            $tax_form->submission_error_message(),
1401
-                            __FILE__,
1402
-                            __FUNCTION__,
1403
-                            __LINE__
1404
-                        );
1405
-                    }
1406
-                }
1407
-            }
1408
-        } catch (EE_Error $e) {
1409
-            EE_Error::add_error($e->get_error(), __FILE__, __FUNCTION__, __LINE__);
1410
-        }
1411
-
1412
-        $what = 'Tax Settings';
1413
-        $success = $this->_update_espresso_configuration(
1414
-            $what,
1415
-            EE_Registry::instance()->CFG->tax_settings,
1416
-            __FILE__,
1417
-            __FUNCTION__,
1418
-            __LINE__
1419
-        );
1420
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'tax_settings'));
1421
-    }
929
+	/**
930
+	 *        generates HTML for main Prices Admin page
931
+	 *
932
+	 * @access protected
933
+	 * @return void
934
+	 */
935
+	protected function _price_types_overview_list_table()
936
+	{
937
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
938
+			'add_new_price_type',
939
+			'add_type',
940
+			array(),
941
+			'add-new-h2'
942
+		);
943
+		$this->admin_page_title .= $this->_learn_more_about_pricing_link();
944
+		$this->_search_btn_label = esc_html__('Price Types', 'event_espresso');
945
+		$this->display_admin_list_table_page_with_no_sidebar();
946
+	}
947
+
948
+
949
+	/**
950
+	 *    retrieve data for Price Types List table
951
+	 *
952
+	 * @access public
953
+	 * @param  int     $per_page how many prices displayed per page
954
+	 * @param  boolean $count    return the count or objects
955
+	 * @param  boolean $trashed  whether the current view is of the trash can - eww yuck!
956
+	 * @return mixed (int|array)  int = count || array of price objects
957
+	 */
958
+	public function get_price_types_overview_data($per_page = 10, $count = false, $trashed = false)
959
+	{
960
+
961
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
962
+		// start with an empty array
963
+
964
+		require_once(PRICING_ADMIN . 'Price_Types_List_Table.class.php');
965
+		require_once(EE_MODELS . 'EEM_Price_Type.model.php');
966
+
967
+		$this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? '' : $this->_req_data['orderby'];
968
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
969
+			: 'ASC';
970
+		switch ($this->_req_data['orderby']) {
971
+			case 'name':
972
+				$orderby = array('PRT_name' => $order);
973
+				break;
974
+			default:
975
+				$orderby = array('PRT_order' => $order);
976
+		}
977
+
978
+
979
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
980
+			? $this->_req_data['paged'] : 1;
981
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
982
+			? $this->_req_data['perpage'] : $per_page;
983
+
984
+		$offset = ($current_page - 1) * $per_page;
985
+		$limit = array($offset, $per_page);
986
+
987
+		$_where = array('PRT_deleted' => $trashed, 'PBT_ID' => array('!=', 1));
988
+
989
+		if (isset($this->_req_data['s'])) {
990
+			$sstr = '%' . $this->_req_data['s'] . '%';
991
+			$_where['OR'] = array(
992
+				'PRT_name' => array('LIKE', $sstr),
993
+			);
994
+		}
995
+		$query_params = array(
996
+			$_where,
997
+			'order_by' => $orderby,
998
+			'limit'    => $limit,
999
+		);
1000
+		if ($count) {
1001
+			return EEM_Price_Type::instance()->count_deleted_and_undeleted($query_params);
1002
+		} else {
1003
+			return EEM_Price_Type::instance()->get_all_deleted_and_undeleted($query_params);
1004
+		}
1005
+
1006
+		// EEH_Debug_Tools::printr( $price_types, '$price_types  <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span>', 'auto' );
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 *        _edit_price_type_details
1012
+	 *
1013
+	 * @access protected
1014
+	 * @return void
1015
+	 */
1016
+	protected function _edit_price_type_details()
1017
+	{
1018
+
1019
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1020
+
1021
+
1022
+		// grab price type ID
1023
+		$PRT_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id']) ? absint($this->_req_data['id'])
1024
+			: false;
1025
+		// change page title based on request action
1026
+		switch ($this->_req_action) {
1027
+			case 'add_new_price_type':
1028
+				$this->_admin_page_title = esc_html__('Add New Price Type', 'event_espresso');
1029
+				break;
1030
+			case 'edit_price_type':
1031
+				$this->_admin_page_title = esc_html__('Edit Price Type', 'event_espresso');
1032
+				break;
1033
+			default:
1034
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
1035
+		}
1036
+		// add PRT_ID to title if editing
1037
+		$this->_admin_page_title = $PRT_ID ? $this->_admin_page_title . ' # ' . $PRT_ID : $this->_admin_page_title;
1038
+
1039
+		if ($PRT_ID) {
1040
+			$price_type = EEM_Price_Type::instance()->get_one_by_ID($PRT_ID);
1041
+			$additional_hidden_fields = array('PRT_ID' => array('type' => 'hidden', 'value' => $PRT_ID));
1042
+			$this->_set_add_edit_form_tags('update_price_type', $additional_hidden_fields);
1043
+		} else {
1044
+			$price_type = EEM_Price_Type::instance()->get_new_price_type();
1045
+			$this->_set_add_edit_form_tags('insert_price_type');
1046
+		}
1047
+
1048
+		$this->_template_args['PRT_ID'] = $PRT_ID;
1049
+		$this->_template_args['price_type'] = $price_type;
1050
+
1051
+
1052
+		$base_types = EEM_Price_Type::instance()->get_base_types();
1053
+		$select_values = array();
1054
+		foreach ($base_types as $ref => $text) {
1055
+			if ($ref == EEM_Price_Type::base_type_base_price) {
1056
+				// do not allow creation of base_type_base_prices because that's a system only base type.
1057
+				continue;
1058
+			}
1059
+			$values[] = array('id' => $ref, 'text' => $text);
1060
+		}
1061
+
1062
+
1063
+		$this->_template_args['base_type_select'] = EEH_Form_Fields::select_input(
1064
+			'base_type',
1065
+			$values,
1066
+			$price_type->base_type(),
1067
+			'id="price-type-base-type-slct"'
1068
+		);
1069
+		$this->_template_args['learn_more_about_pricing_link'] = $this->_learn_more_about_pricing_link();
1070
+		$redirect_URL = add_query_arg(array('action' => 'price_types'), $this->_admin_base_url);
1071
+		$this->_set_publish_post_box_vars('id', $PRT_ID, false, $redirect_URL);
1072
+		// the details template wrapper
1073
+		$this->display_admin_page_with_sidebar();
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 *        declare price type details page metaboxes
1079
+	 *
1080
+	 * @access protected
1081
+	 * @return void
1082
+	 */
1083
+	protected function _price_type_details_meta_boxes()
1084
+	{
1085
+		add_meta_box(
1086
+			'edit-price-details-mbox',
1087
+			esc_html__('Price Type Details', 'event_espresso'),
1088
+			array($this, '_edit_price_type_details_meta_box'),
1089
+			$this->wp_page_slug,
1090
+			'normal',
1091
+			'high'
1092
+		);
1093
+	}
1094
+
1095
+
1096
+	/**
1097
+	 *        _edit_price_type_details_meta_box
1098
+	 *
1099
+	 * @access public
1100
+	 * @return void
1101
+	 */
1102
+	public function _edit_price_type_details_meta_box()
1103
+	{
1104
+		echo EEH_Template::display_template(
1105
+			PRICING_TEMPLATE_PATH . 'pricing_type_details_main_meta_box.template.php',
1106
+			$this->_template_args,
1107
+			true
1108
+		);
1109
+	}
1110
+
1111
+
1112
+	/**
1113
+	 *        set_price_type_column_values
1114
+	 *
1115
+	 * @access protected
1116
+	 * @return void
1117
+	 */
1118
+	protected function set_price_type_column_values()
1119
+	{
1120
+
1121
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1122
+
1123
+		$base_type = ! empty($this->_req_data['base_type']) ? $this->_req_data['base_type']
1124
+			: EEM_Price_Type::base_type_base_price;
1125
+
1126
+		switch ($base_type) {
1127
+			case EEM_Price_Type::base_type_base_price:
1128
+				$this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_base_price;
1129
+				$this->_req_data['PRT_is_percent'] = 0;
1130
+				$this->_req_data['PRT_order'] = 0;
1131
+				break;
1132
+
1133
+			case EEM_Price_Type::base_type_discount:
1134
+				$this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_discount;
1135
+				break;
1136
+
1137
+			case EEM_Price_Type::base_type_surcharge:
1138
+				$this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_surcharge;
1139
+				break;
1140
+
1141
+			case EEM_Price_Type::base_type_tax:
1142
+				$this->_req_data['PBT_ID'] = EEM_Price_Type::base_type_tax;
1143
+				$this->_req_data['PRT_is_percent'] = 1;
1144
+				break;
1145
+		}/**/
1146
+
1147
+		$set_column_values = array(
1148
+			'PRT_name'       => $this->_req_data['PRT_name'],
1149
+			'PBT_ID'         => absint($this->_req_data['PBT_ID']),
1150
+			'PRT_is_percent' => absint($this->_req_data['PRT_is_percent']),
1151
+			'PRT_order'      => absint($this->_req_data['PRT_order']),
1152
+			'PRT_deleted'    => 0,
1153
+		);
1154
+
1155
+		return $set_column_values;
1156
+	}
1157
+
1158
+
1159
+	/**
1160
+	 *        _insert_or_update_price_type
1161
+	 *
1162
+	 * @param boolean $new_price_type - whether to insert or update
1163
+	 * @access protected
1164
+	 * @return void
1165
+	 */
1166
+	protected function _insert_or_update_price_type($new_price_type = false)
1167
+	{
1168
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1169
+
1170
+		require_once(EE_MODELS . 'EEM_Price_Type.model.php');
1171
+		$PRT = EEM_Price_Type::instance();
1172
+
1173
+		// why be so pessimistic ???  : (
1174
+		$success = 0;
1175
+
1176
+		$set_column_values = $this->set_price_type_column_values();
1177
+		// is this a new Price ?
1178
+		if ($new_price_type) {
1179
+			// run the insert
1180
+			if ($PRT_ID = $PRT->insert($set_column_values)) {
1181
+				$success = 1;
1182
+			}
1183
+			$action_desc = 'created';
1184
+		} else {
1185
+			$PRT_ID = absint($this->_req_data['PRT_ID']);
1186
+			// run the update
1187
+			$where_cols_n_values = array('PRT_ID' => $PRT_ID);
1188
+			if ($PRT->update($set_column_values, array($where_cols_n_values))) {
1189
+				$success = 1;
1190
+			}
1191
+			$action_desc = 'updated';
1192
+		}
1193
+
1194
+		$query_args = array('action' => 'edit_price_type', 'id' => $PRT_ID);
1195
+		$this->_redirect_after_action($success, 'Price Type', $action_desc, $query_args);
1196
+	}
1197
+
1198
+
1199
+	/**
1200
+	 *        _trash_or_restore_price_type
1201
+	 *
1202
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
1203
+	 * @access protected
1204
+	 * @return void
1205
+	 */
1206
+	protected function _trash_or_restore_price_type($trash = true)
1207
+	{
1208
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1209
+
1210
+		require_once(EE_MODELS . 'EEM_Price_Type.model.php');
1211
+		$PRT = EEM_Price_Type::instance();
1212
+
1213
+		$success = 1;
1214
+		$PRT_deleted = $trash ? true : false;
1215
+		// Checkboxes
1216
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1217
+			// if array has more than one element than success message should be plural
1218
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1219
+			$what = count($this->_req_data['checkbox']) > 1 ? 'Price Types' : 'Price Type';
1220
+			// cycle thru checkboxes
1221
+			while (list($PRT_ID, $value) = each($this->_req_data['checkbox'])) {
1222
+				if (! $PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
1223
+					$success = 0;
1224
+				}
1225
+			}
1226
+		} else {
1227
+			// grab single id and delete
1228
+			$PRT_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
1229
+			if (empty($PRT_ID) || ! $PRT->update_by_ID(array('PRT_deleted' => $PRT_deleted), $PRT_ID)) {
1230
+				$success = 0;
1231
+			}
1232
+			$what = 'Price Type';
1233
+		}
1234
+
1235
+		$query_args = array('action' => 'price_types');
1236
+		if ($success) {
1237
+			if ($trash) {
1238
+				$msg = $success > 1
1239
+					? esc_html__('The Price Types have been trashed.', 'event_espresso')
1240
+					: esc_html__(
1241
+						'The Price Type has been trashed.',
1242
+						'event_espresso'
1243
+					);
1244
+			} else {
1245
+				$msg = $success > 1
1246
+					? esc_html__('The Price Types have been restored.', 'event_espresso')
1247
+					: esc_html__(
1248
+						'The Price Type has been restored.',
1249
+						'event_espresso'
1250
+					);
1251
+			}
1252
+			EE_Error::add_success($msg);
1253
+		}
1254
+
1255
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 *        _delete_price_type
1261
+	 *
1262
+	 * @access protected
1263
+	 * @return void
1264
+	 */
1265
+	protected function _delete_price_type()
1266
+	{
1267
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1268
+
1269
+		$PRT = EEM_Price_Type::instance();
1270
+
1271
+		$success = 1;
1272
+		// Checkboxes
1273
+		if (! empty($this->_req_data['checkbox'])) {
1274
+			// if array has more than one element than success message should be plural
1275
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1276
+			$what = $PRT->item_name($success);
1277
+			// cycle thru bulk action checkboxes
1278
+			while (list($PRT_ID, $value) = each($this->_req_data['checkbox'])) {
1279
+				if (! $PRT->delete_permanently_by_ID($PRT_ID)) {
1280
+					$success = 0;
1281
+				}
1282
+			}
1283
+		}
1284
+
1285
+
1286
+		$query_args = array('action' => 'price_types');
1287
+		$this->_redirect_after_action($success, $what, 'deleted', $query_args);
1288
+	}
1289
+
1290
+
1291
+	/**
1292
+	 *        _learn_more_about_pricing_link
1293
+	 *
1294
+	 * @access protected
1295
+	 * @return string
1296
+	 */
1297
+	protected function _learn_more_about_pricing_link()
1298
+	{
1299
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >' . esc_html__(
1300
+			'learn more about how pricing works',
1301
+			'event_espresso'
1302
+		) . '</a>';
1303
+	}
1304
+
1305
+
1306
+	protected function _tax_settings()
1307
+	{
1308
+		$this->_set_add_edit_form_tags('update_tax_settings');
1309
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
1310
+		$this->_template_args['admin_page_content'] = $this->tax_settings_form()->get_html();
1311
+		$this->display_admin_page_with_sidebar();
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * @return \EE_Form_Section_Proper
1317
+	 * @throws \EE_Error
1318
+	 */
1319
+	protected function tax_settings_form()
1320
+	{
1321
+		return new EE_Form_Section_Proper(
1322
+			array(
1323
+				'name'            => 'tax_settings_form',
1324
+				'html_id'         => 'tax_settings_form',
1325
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1326
+				'subsections'     => apply_filters(
1327
+					'FHEE__Pricing_Admin_Page__tax_settings_form__form_subsections',
1328
+					array(
1329
+						'tax_settings' => new EE_Form_Section_Proper(
1330
+							array(
1331
+								'name'            => 'tax_settings_tbl',
1332
+								'html_id'         => 'tax_settings_tbl',
1333
+								'html_class'      => 'form-table',
1334
+								'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1335
+								'subsections'     => array(
1336
+									'prices_displayed_including_taxes' => new EE_Yes_No_Input(
1337
+										array(
1338
+											'html_label_text'         => esc_html__(
1339
+												"Show Prices With Taxes Included?",
1340
+												'event_espresso'
1341
+											),
1342
+											'html_help_text'          => esc_html__(
1343
+												'Indicates whether or not to display prices with the taxes included',
1344
+												'event_espresso'
1345
+											),
1346
+											'default'                 => isset(
1347
+												EE_Registry::instance()
1348
+													->CFG
1349
+													->tax_settings
1350
+													->prices_displayed_including_taxes
1351
+											)
1352
+												? EE_Registry::instance()
1353
+													->CFG
1354
+													->tax_settings
1355
+													->prices_displayed_including_taxes
1356
+												: true,
1357
+											'display_html_label_text' => false,
1358
+										)
1359
+									),
1360
+								),
1361
+							)
1362
+						),
1363
+					)
1364
+				),
1365
+			)
1366
+		);
1367
+	}
1368
+
1369
+
1370
+	/**
1371
+	 * _update_tax_settings
1372
+	 *
1373
+	 * @since 4.9.13
1374
+	 * @return void
1375
+	 */
1376
+	public function _update_tax_settings()
1377
+	{
1378
+		if (! isset(EE_Registry::instance()->CFG->tax_settings)) {
1379
+			EE_Registry::instance()->CFG->tax_settings = new EE_Tax_Config();
1380
+		}
1381
+		try {
1382
+			$tax_form = $this->tax_settings_form();
1383
+			// check for form submission
1384
+			if ($tax_form->was_submitted()) {
1385
+				// capture form data
1386
+				$tax_form->receive_form_submission();
1387
+				// validate form data
1388
+				if ($tax_form->is_valid()) {
1389
+					// grab validated data from form
1390
+					$valid_data = $tax_form->valid_data();
1391
+					// set data on config
1392
+					EE_Registry::instance()
1393
+						->CFG
1394
+						->tax_settings
1395
+						->prices_displayed_including_taxes
1396
+						= $valid_data['tax_settings']['prices_displayed_including_taxes'];
1397
+				} else {
1398
+					if ($tax_form->submission_error_message() !== '') {
1399
+						EE_Error::add_error(
1400
+							$tax_form->submission_error_message(),
1401
+							__FILE__,
1402
+							__FUNCTION__,
1403
+							__LINE__
1404
+						);
1405
+					}
1406
+				}
1407
+			}
1408
+		} catch (EE_Error $e) {
1409
+			EE_Error::add_error($e->get_error(), __FILE__, __FUNCTION__, __LINE__);
1410
+		}
1411
+
1412
+		$what = 'Tax Settings';
1413
+		$success = $this->_update_espresso_configuration(
1414
+			$what,
1415
+			EE_Registry::instance()->CFG->tax_settings,
1416
+			__FILE__,
1417
+			__FUNCTION__,
1418
+			__LINE__
1419
+		);
1420
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'tax_settings'));
1421
+	}
1422 1422
 }
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 1 patch
Indentation   +1195 added lines, -1195 removed lines patch added patch discarded remove patch
@@ -16,1199 +16,1199 @@
 block discarded – undo
16 16
 class Payments_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * Variables used for when we're re-sorting the logs results,
21
-     * in case we needed to do two queries, and we need to resort
22
-     *
23
-     * @var string
24
-     */
25
-    private $_sort_logs_again_direction;
26
-
27
-
28
-    /**
29
-     * @Constructor
30
-     * @access public
31
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
-     * @throws EE_Error
33
-     * @throws InvalidArgumentException
34
-     * @throws InvalidDataTypeException
35
-     * @throws InvalidInterfaceException
36
-     * @throws ReflectionException
37
-     */
38
-    public function __construct($routing = true)
39
-    {
40
-        parent::__construct($routing);
41
-    }
42
-
43
-
44
-    protected function _init_page_props()
45
-    {
46
-        $this->page_slug = EE_PAYMENTS_PG_SLUG;
47
-        $this->page_label = esc_html__('Payment Methods', 'event_espresso');
48
-        $this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
-    }
51
-
52
-
53
-    protected function _ajax_hooks()
54
-    {
55
-        // todo: all hooks for ajax goes here.
56
-    }
57
-
58
-
59
-    protected function _define_page_props()
60
-    {
61
-        $this->_admin_page_title = $this->page_label;
62
-        $this->_labels = array(
63
-            'publishbox' => esc_html__('Update Settings', 'event_espresso'),
64
-        );
65
-    }
66
-
67
-
68
-    protected function _set_page_routes()
69
-    {
70
-        /**
71
-         * note that with payment method capabilities, although we've implemented
72
-         * capability mapping which will be used for accessing payment methods owned by
73
-         * other users.  This is not fully implemented yet in the payment method ui.
74
-         * Currently, only the "plural" caps are in active use.
75
-         * When cap mapping is implemented, some routes will need to use the singular form of
76
-         * capability method and also include the $id of the payment method for the route.
77
-         **/
78
-        $this->_page_routes = array(
79
-            'default'                   => array(
80
-                'func'       => '_payment_methods_list',
81
-                'capability' => 'ee_edit_payment_methods',
82
-            ),
83
-            'payment_settings'          => array(
84
-                'func'       => '_payment_settings',
85
-                'capability' => 'ee_manage_gateways',
86
-            ),
87
-            'activate_payment_method'   => array(
88
-                'func'       => '_activate_payment_method',
89
-                'noheader'   => true,
90
-                'capability' => 'ee_edit_payment_methods',
91
-            ),
92
-            'deactivate_payment_method' => array(
93
-                'func'       => '_deactivate_payment_method',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_delete_payment_methods',
96
-            ),
97
-            'update_payment_method'     => array(
98
-                'func'               => '_update_payment_method',
99
-                'noheader'           => true,
100
-                'headers_sent_route' => 'default',
101
-                'capability'         => 'ee_edit_payment_methods',
102
-            ),
103
-            'update_payment_settings'   => array(
104
-                'func'       => '_update_payment_settings',
105
-                'noheader'   => true,
106
-                'capability' => 'ee_manage_gateways',
107
-            ),
108
-            'payment_log'               => array(
109
-                'func'       => '_payment_log_overview_list_table',
110
-                'capability' => 'ee_read_payment_methods',
111
-            ),
112
-            'payment_log_details'       => array(
113
-                'func'       => '_payment_log_details',
114
-                'capability' => 'ee_read_payment_methods',
115
-            ),
116
-        );
117
-    }
118
-
119
-
120
-    /**
121
-     * @throws EE_Error
122
-     * @throws ReflectionException
123
-     */
124
-    protected function _set_page_config()
125
-    {
126
-        $payment_method_list_config = array(
127
-            'nav'           => array(
128
-                'label' => esc_html__('Payment Methods', 'event_espresso'),
129
-                'order' => 10,
130
-            ),
131
-            'metaboxes'     => $this->_default_espresso_metaboxes,
132
-            'help_tabs'     => array_merge(
133
-                array(
134
-                    'payment_methods_overview_help_tab' => array(
135
-                        'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
136
-                        'filename' => 'payment_methods_overview',
137
-                    ),
138
-                ),
139
-                $this->_add_payment_method_help_tabs()
140
-            ),
141
-            'require_nonce' => false,
142
-        );
143
-        $this->_page_config = array(
144
-            'default'          => $payment_method_list_config,
145
-            'payment_settings' => array(
146
-                'nav'           => array(
147
-                    'label' => esc_html__('Settings', 'event_espresso'),
148
-                    'order' => 20,
149
-                ),
150
-                'help_tabs'     => array(
151
-                    'payment_methods_settings_help_tab' => array(
152
-                        'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
153
-                        'filename' => 'payment_methods_settings',
154
-                    ),
155
-                ),
156
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
157
-                'require_nonce' => false,
158
-            ),
159
-            'payment_log'      => array(
160
-                'nav'           => array(
161
-                    'label' => esc_html__("Logs", 'event_espresso'),
162
-                    'order' => 30,
163
-                ),
164
-                'list_table'    => 'Payment_Log_Admin_List_Table',
165
-                'metaboxes'     => $this->_default_espresso_metaboxes,
166
-                'require_nonce' => false,
167
-            ),
168
-        );
169
-    }
170
-
171
-
172
-    /**
173
-     * @return array
174
-     * @throws DomainException
175
-     * @throws EE_Error
176
-     * @throws InvalidArgumentException
177
-     * @throws InvalidDataTypeException
178
-     * @throws InvalidInterfaceException
179
-     * @throws ReflectionException
180
-     */
181
-    protected function _add_payment_method_help_tabs()
182
-    {
183
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
184
-        $payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
185
-        $all_pmt_help_tabs_config = array();
186
-        foreach ($payment_method_types as $payment_method_type) {
187
-            if (
188
-                ! EE_Registry::instance()->CAP->current_user_can(
189
-                    $payment_method_type->cap_name(),
190
-                    'specific_payment_method_type_access'
191
-                )
192
-            ) {
193
-                continue;
194
-            }
195
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
196
-                $template_args = isset($config['template_args']) ? $config['template_args'] : array();
197
-                $template_args['admin_page_obj'] = $this;
198
-                $all_pmt_help_tabs_config[ $help_tab_name ] = array(
199
-                    'title'   => $config['title'],
200
-                    'content' => EEH_Template::display_template(
201
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
202
-                        $template_args,
203
-                        true
204
-                    ),
205
-                );
206
-            }
207
-        }
208
-        return $all_pmt_help_tabs_config;
209
-    }
210
-
211
-
212
-    // none of the below group are currently used for Gateway Settings
213
-    protected function _add_screen_options()
214
-    {
215
-    }
216
-
217
-
218
-    protected function _add_feature_pointers()
219
-    {
220
-    }
221
-
222
-
223
-    public function admin_init()
224
-    {
225
-    }
226
-
227
-
228
-    public function admin_notices()
229
-    {
230
-    }
231
-
232
-
233
-    public function admin_footer_scripts()
234
-    {
235
-    }
236
-
237
-
238
-    public function load_scripts_styles()
239
-    {
240
-        // styles
241
-        wp_enqueue_style('espresso-ui-theme');
242
-        wp_register_style(
243
-            'espresso_payments',
244
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
245
-            [],
246
-            EVENT_ESPRESSO_VERSION
247
-        );
248
-        // scripts
249
-        wp_enqueue_script('ee_admin_js');
250
-        wp_enqueue_script('ee-text-links');
251
-        wp_enqueue_script(
252
-            'espresso_payments',
253
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
254
-            ['ee-datepicker'],
255
-            EVENT_ESPRESSO_VERSION,
256
-            true
257
-        );
258
-    }
259
-
260
-
261
-    public function load_scripts_styles_default()
262
-    {
263
-        wp_enqueue_style('espresso_payments');
264
-        wp_enqueue_style('ee-text-links');
265
-    }
266
-
267
-
268
-    public function load_scripts_styles_payment_log_details()
269
-    {
270
-        wp_enqueue_style('espresso_payments');
271
-    }
272
-
273
-
274
-    /**
275
-     * @throws EE_Error
276
-     * @throws ReflectionException
277
-     */
278
-    protected function _payment_methods_list()
279
-    {
280
-        /**
281
-         * first let's ensure payment methods have been set up.
282
-         * We do this here because when people activate a payment method for the first time (as an addon),
283
-         * it may not set up its capabilities or get registered correctly due to the loading process.
284
-         * However, people MUST set up the details for the payment method,
285
-         * so it's safe to do a recheck here.
286
-         */
287
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
288
-        EEM_Payment_Method::instance()->verify_button_urls();
289
-        // set up tabs, one for each payment method type
290
-        $tabs = array();
291
-        $payment_methods = array();
292
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
293
-            // we don't want to show admin-only PMTs for now
294
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
295
-                continue;
296
-            }
297
-            // check access
298
-            if (
299
-                ! EE_Registry::instance()->CAP->current_user_can(
300
-                    $pmt_obj->cap_name(),
301
-                    'specific_payment_method_type_access'
302
-                )
303
-            ) {
304
-                continue;
305
-            }
306
-            // check for any active pms of that type
307
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
308
-            if (! $payment_method instanceof EE_Payment_Method) {
309
-                $payment_method = EE_Payment_Method::new_instance(
310
-                    array(
311
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
312
-                        'PMD_type'       => $pmt_obj->system_name(),
313
-                        'PMD_name'       => $pmt_obj->pretty_name(),
314
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
315
-                    )
316
-                );
317
-            }
318
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
319
-        }
320
-        $payment_methods = apply_filters(
321
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
322
-            $payment_methods
323
-        );
324
-        foreach ($payment_methods as $payment_method) {
325
-            if ($payment_method instanceof EE_Payment_Method) {
326
-                add_meta_box(
327
-                    // html id
328
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
329
-                    // title
330
-                    sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
331
-                    // callback
332
-                    array($this, 'payment_method_settings_meta_box'),
333
-                    // post type
334
-                    null,
335
-                    // context
336
-                    'normal',
337
-                    // priority
338
-                    'default',
339
-                    // callback args
340
-                    array('payment_method' => $payment_method)
341
-                );
342
-                // setup for tabbed content
343
-                $tabs[ $payment_method->slug() ] = array(
344
-                    'label' => $payment_method->admin_name(),
345
-                    'class' => $payment_method->active() ? 'gateway-active' : '',
346
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
347
-                    'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
348
-                    'slug'  => $payment_method->slug(),
349
-                );
350
-            }
351
-        }
352
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
353
-            $tabs,
354
-            'payment_method_links',
355
-            '|',
356
-            $this->_get_active_payment_method_slug()
357
-        );
358
-        $this->display_admin_page_with_sidebar();
359
-    }
360
-
361
-
362
-    /**
363
-     *   _get_active_payment_method_slug
364
-     *
365
-     * @return string
366
-     * @throws EE_Error
367
-     */
368
-    protected function _get_active_payment_method_slug()
369
-    {
370
-        $payment_method_slug = false;
371
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
372
-        if (isset($this->_req_data['payment_method'])) {
373
-            // if they provided the current payment method, use it
374
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
375
-        }
376
-        /** @var EE_Payment_Method $payment_method */
377
-        $payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
378
-        // if that didn't work or wasn't provided, find another way to select the current pm
379
-        if (! $this->_verify_payment_method($payment_method)) {
380
-            // like, looking for an active one
381
-            $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
382
-            // test that one as well
383
-            if ($this->_verify_payment_method($payment_method)) {
384
-                $payment_method_slug = $payment_method->slug();
385
-            } else {
386
-                $payment_method_slug = 'paypal_standard';
387
-            }
388
-        }
389
-        return $payment_method_slug;
390
-    }
391
-
392
-
393
-    /**
394
-     *    payment_method_settings_meta_box
395
-     *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
396
-     *    capabilities to access it
397
-     *
398
-     * @param EE_Payment_Method $payment_method
399
-     * @return boolean
400
-     * @throws EE_Error
401
-     */
402
-    protected function _verify_payment_method($payment_method)
403
-    {
404
-        if (
405
-            $payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
406
-            && EE_Registry::instance()->CAP->current_user_can(
407
-                $payment_method->type_obj()->cap_name(),
408
-                'specific_payment_method_type_access'
409
-            )
410
-        ) {
411
-            return true;
412
-        }
413
-        return false;
414
-    }
415
-
416
-
417
-    /**
418
-     *    payment_method_settings_meta_box
419
-     *
420
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
421
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
422
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
423
-     * @return void
424
-     * @throws EE_Error
425
-     * @throws ReflectionException
426
-     */
427
-    public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
428
-    {
429
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
430
-            ? $metabox['args']['payment_method'] : null;
431
-        if (! $payment_method instanceof EE_Payment_Method) {
432
-            throw new EE_Error(
433
-                esc_html__(
434
-                    'Payment method metabox setup incorrectly. No Payment method object was supplied',
435
-                    'event_espresso'
436
-                )
437
-            );
438
-        }
439
-        $payment_method_scopes = $payment_method->active();
440
-        // if the payment method really exists show its form, otherwise the activation template
441
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
442
-            $form = $this->_generate_payment_method_settings_form($payment_method);
443
-            if ($form->form_data_present_in($this->_req_data)) {
444
-                $form->receive_form_submission($this->_req_data);
445
-            }
446
-            echo $form->form_open() . $form->get_html_and_js() . $form->form_close(); // already escaped
447
-        } else {
448
-            echo $this->_activate_payment_method_button($payment_method)->get_html_and_js(); // already escaped
449
-        }
450
-    }
451
-
452
-
453
-    /**
454
-     * Gets the form for all the settings related to this payment method type
455
-     *
456
-     * @access protected
457
-     * @param EE_Payment_Method $payment_method
458
-     * @return EE_Form_Section_Proper
459
-     * @throws EE_Error
460
-     */
461
-    protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method = null)
462
-    {
463
-        if (! $payment_method instanceof EE_Payment_Method) {
464
-            return new EE_Form_Section_Proper();
465
-        }
466
-        return new EE_Form_Section_Proper(
467
-            array(
468
-                'name'            => $payment_method->slug() . '_settings_form',
469
-                'html_id'         => $payment_method->slug() . '_settings_form',
470
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
471
-                    array(
472
-                        'action'         => 'update_payment_method',
473
-                        'payment_method' => $payment_method->slug(),
474
-                    ),
475
-                    EE_PAYMENTS_ADMIN_URL
476
-                ),
477
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
478
-                'subsections'     => apply_filters(
479
-                    'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
480
-                    array(
481
-                        'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
482
-                        'currency_support'        => $this->_currency_support($payment_method),
483
-                        'payment_method_settings' => $this->_payment_method_settings($payment_method),
484
-                        'update'                  => $this->_update_payment_method_button($payment_method),
485
-                        'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
486
-                        'fine_print'              => $this->_fine_print(),
487
-                    ),
488
-                    $payment_method
489
-                ),
490
-            )
491
-        );
492
-    }
493
-
494
-
495
-    /**
496
-     * _pci_dss_compliance
497
-     *
498
-     * @access protected
499
-     * @param EE_Payment_Method $payment_method
500
-     * @return EE_Form_Section_HTML
501
-     * @throws EE_Error
502
-     */
503
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
504
-    {
505
-        if ($payment_method->type_obj()->requires_https()) {
506
-            return new EE_Form_Section_HTML(
507
-                EEH_HTML::table(
508
-                    EEH_HTML::tr(
509
-                        EEH_HTML::th(
510
-                            EEH_HTML::label(
511
-                                EEH_HTML::strong(
512
-                                    esc_html__('IMPORTANT', 'event_espresso'),
513
-                                    '',
514
-                                    'important-notice'
515
-                                )
516
-                            )
517
-                        ) .
518
-                        EEH_HTML::td(
519
-                            EEH_HTML::strong(
520
-                                esc_html__(
521
-                                    'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
522
-                                    'event_espresso'
523
-                                )
524
-                            )
525
-                            .
526
-                            EEH_HTML::br()
527
-                            .
528
-                            esc_html__('Learn more about ', 'event_espresso')
529
-                            . EEH_HTML::link(
530
-                                'https://www.pcisecuritystandards.org/merchants/index.php',
531
-                                esc_html__('PCI DSS compliance', 'event_espresso')
532
-                            )
533
-                        )
534
-                    )
535
-                )
536
-            );
537
-        }
538
-        return new EE_Form_Section_HTML('');
539
-    }
540
-
541
-
542
-    /**
543
-     * _currency_support
544
-     *
545
-     * @access protected
546
-     * @param EE_Payment_Method $payment_method
547
-     * @return EE_Form_Section_HTML
548
-     * @throws EE_Error
549
-     */
550
-    protected function _currency_support(EE_Payment_Method $payment_method)
551
-    {
552
-        if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
553
-            return new EE_Form_Section_HTML(
554
-                EEH_HTML::table(
555
-                    EEH_HTML::tr(
556
-                        EEH_HTML::th(
557
-                            EEH_HTML::label(
558
-                                EEH_HTML::strong(
559
-                                    esc_html__('IMPORTANT', 'event_espresso'),
560
-                                    '',
561
-                                    'important-notice'
562
-                                )
563
-                            )
564
-                        ) .
565
-                        EEH_HTML::td(
566
-                            EEH_HTML::strong(
567
-                                sprintf(
568
-                                    esc_html__(
569
-                                        'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
570
-                                        'event_espresso'
571
-                                    ),
572
-                                    EE_Config::instance()->currency->code
573
-                                )
574
-                            )
575
-                        )
576
-                    )
577
-                )
578
-            );
579
-        }
580
-        return new EE_Form_Section_HTML('');
581
-    }
582
-
583
-
584
-    /**
585
-     * _update_payment_method_button
586
-     *
587
-     * @access protected
588
-     * @param EE_Payment_Method $payment_method
589
-     * @return EE_Payment_Method_Form
590
-     * @throws EE_Error
591
-     */
592
-    protected function _payment_method_settings(EE_Payment_Method $payment_method)
593
-    {
594
-        // modify the form, so we only have/show fields that will be implemented for this version
595
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
596
-    }
597
-
598
-
599
-    /**
600
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
601
-     *
602
-     * @param EE_Form_Section_Proper $form_section
603
-     * @param string                 $payment_method_name
604
-     * @return EE_Payment_Method_Form
605
-     * @throws EE_Error
606
-     */
607
-    protected function _simplify_form($form_section, $payment_method_name = '')
608
-    {
609
-        if ($form_section instanceof EE_Payment_Method_Form) {
610
-            $form_section->exclude(
611
-                array(
612
-                    'PMD_type', // don't want them changing the type
613
-                    'PMD_slug', // or the slug (probably never)
614
-                    'PMD_wp_user', // or the user's ID
615
-                    'Currency' // or the currency, until the rest of EE supports simultaneous currencies
616
-                )
617
-            );
618
-            return $form_section;
619
-        } else {
620
-            throw new EE_Error(
621
-                sprintf(
622
-                    esc_html__(
623
-                        'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
624
-                        'event_espresso'
625
-                    ),
626
-                    $payment_method_name
627
-                )
628
-            );
629
-        }
630
-    }
631
-
632
-
633
-    /**
634
-     * _update_payment_method_button
635
-     *
636
-     * @access protected
637
-     * @param EE_Payment_Method $payment_method
638
-     * @return EE_Form_Section_HTML
639
-     * @throws EE_Error
640
-     */
641
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method)
642
-    {
643
-        $update_button = new EE_Submit_Input(
644
-            array(
645
-                'name'       => 'submit',
646
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
647
-                'default'    => sprintf(
648
-                    esc_html__('Update %s Payment Settings', 'event_espresso'),
649
-                    $payment_method->admin_name()
650
-                ),
651
-                'html_label' => EEH_HTML::nbsp(),
652
-            )
653
-        );
654
-        return new EE_Form_Section_HTML(
655
-            EEH_HTML::table(
656
-                EEH_HTML::no_row(EEH_HTML::br(2)) .
657
-                EEH_HTML::tr(
658
-                    EEH_HTML::th(esc_html__('Update Settings', 'event_espresso')) .
659
-                    EEH_HTML::td(
660
-                        $update_button->get_html_for_input()
661
-                    )
662
-                )
663
-            )
664
-        );
665
-    }
666
-
667
-
668
-    /**
669
-     * _deactivate_payment_method_button
670
-     *
671
-     * @access protected
672
-     * @param EE_Payment_Method $payment_method
673
-     * @return EE_Form_Section_HTML
674
-     */
675
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
676
-    {
677
-        $link_text_and_title = sprintf(
678
-            esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
679
-            $payment_method->admin_name()
680
-        );
681
-        return new EE_Form_Section_HTML(
682
-            EEH_HTML::table(
683
-                EEH_HTML::tr(
684
-                    EEH_HTML::th(esc_html__('Deactivate Payment Method', 'event_espresso')) .
685
-                    EEH_HTML::td(
686
-                        EEH_HTML::link(
687
-                            EE_Admin_Page::add_query_args_and_nonce(
688
-                                array(
689
-                                    'action'         => 'deactivate_payment_method',
690
-                                    'payment_method' => $payment_method->slug(),
691
-                                ),
692
-                                EE_PAYMENTS_ADMIN_URL
693
-                            ),
694
-                            $link_text_and_title,
695
-                            $link_text_and_title,
696
-                            'deactivate_' . $payment_method->slug(),
697
-                            'espresso-button button-secondary'
698
-                        )
699
-                    )
700
-                )
701
-            )
702
-        );
703
-    }
704
-
705
-
706
-    /**
707
-     * _activate_payment_method_button
708
-     *
709
-     * @access protected
710
-     * @param EE_Payment_Method $payment_method
711
-     * @return EE_Form_Section_Proper
712
-     * @throws EE_Error
713
-     */
714
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
715
-    {
716
-        $link_text_and_title = sprintf(
717
-            esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
718
-            $payment_method->admin_name()
719
-        );
720
-        return new EE_Form_Section_Proper(
721
-            array(
722
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
723
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
724
-                'action'          => '#',
725
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
726
-                'subsections'     => apply_filters(
727
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
728
-                    array(
729
-                        new EE_Form_Section_HTML(
730
-                            EEH_HTML::table(
731
-                                EEH_HTML::tr(
732
-                                    EEH_HTML::td(
733
-                                        $payment_method->type_obj()->introductory_html(),
734
-                                        '',
735
-                                        '',
736
-                                        '',
737
-                                        'colspan="2"'
738
-                                    )
739
-                                ) .
740
-                                EEH_HTML::tr(
741
-                                    EEH_HTML::th(
742
-                                        EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
743
-                                    ) .
744
-                                    EEH_HTML::td(
745
-                                        EEH_HTML::link(
746
-                                            EE_Admin_Page::add_query_args_and_nonce(
747
-                                                array(
748
-                                                    'action'              => 'activate_payment_method',
749
-                                                    'payment_method_type' => $payment_method->type(),
750
-                                                ),
751
-                                                EE_PAYMENTS_ADMIN_URL
752
-                                            ),
753
-                                            $link_text_and_title,
754
-                                            $link_text_and_title,
755
-                                            'activate_' . $payment_method->slug(),
756
-                                            'espresso-button-green button-primary'
757
-                                        )
758
-                                    )
759
-                                )
760
-                            )
761
-                        ),
762
-                    ),
763
-                    $payment_method
764
-                ),
765
-            )
766
-        );
767
-    }
768
-
769
-
770
-    /**
771
-     * _fine_print
772
-     *
773
-     * @access protected
774
-     * @return EE_Form_Section_HTML
775
-     */
776
-    protected function _fine_print()
777
-    {
778
-        return new EE_Form_Section_HTML(
779
-            EEH_HTML::table(
780
-                EEH_HTML::tr(
781
-                    EEH_HTML::th() .
782
-                    EEH_HTML::td(
783
-                        EEH_HTML::p(esc_html__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
784
-                    )
785
-                )
786
-            )
787
-        );
788
-    }
789
-
790
-
791
-    /**
792
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
793
-     *
794
-     * @throws EE_Error
795
-     * @throws ReflectionException
796
-     * @global WP_User $current_user
797
-     */
798
-    protected function _activate_payment_method()
799
-    {
800
-        if (isset($this->_req_data['payment_method_type'])) {
801
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
802
-            // see if one exists
803
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
804
-            $payment_method = EE_Payment_Method_Manager::instance()
805
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
806
-            $this->_redirect_after_action(
807
-                1,
808
-                'Payment Method',
809
-                'activated',
810
-                array('action' => 'default', 'payment_method' => $payment_method->slug())
811
-            );
812
-        } else {
813
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
814
-        }
815
-    }
816
-
817
-
818
-    /**
819
-     * @throws EE_Error
820
-     * @throws ReflectionException
821
-     */
822
-    protected function _deactivate_payment_method()
823
-    {
824
-        if (isset($this->_req_data['payment_method'])) {
825
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
826
-            // deactivate it
827
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
828
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
829
-            $this->_redirect_after_action(
830
-                $count_updated,
831
-                'Payment Method',
832
-                'deactivated',
833
-                array('action' => 'default', 'payment_method' => $payment_method_slug)
834
-            );
835
-        } else {
836
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
837
-        }
838
-    }
839
-
840
-
841
-    /**
842
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
843
-     * processing because we first need to identify WHICH form was processed and which payment method
844
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
845
-     * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
846
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
847
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
848
-     *
849
-     * @return void
850
-     * @throws EE_Error
851
-     * @throws ReflectionException
852
-     */
853
-    protected function _update_payment_method()
854
-    {
855
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
856
-            // ok let's find which gateway form to use based on the form input
857
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
858
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
859
-            $correct_pmt_form_to_use = null;
860
-            $payment_method = null;
861
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
862
-                if ($payment_method instanceof EE_Payment_Method) {
863
-                    // get the form and simplify it, like what we do when we display it
864
-                    $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
865
-                    if ($pmt_form->form_data_present_in($this->_req_data)) {
866
-                        $correct_pmt_form_to_use = $pmt_form;
867
-                        break;
868
-                    }
869
-                }
870
-            }
871
-            // if we couldn't find the correct payment method type...
872
-            if (! $correct_pmt_form_to_use) {
873
-                EE_Error::add_error(
874
-                    esc_html__(
875
-                        "We could not find which payment method type your form submission related to. Please contact support",
876
-                        'event_espresso'
877
-                    ),
878
-                    __FILE__,
879
-                    __FUNCTION__,
880
-                    __LINE__
881
-                );
882
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
883
-            }
884
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
885
-            if ($correct_pmt_form_to_use->is_valid()) {
886
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
887
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
888
-                    throw new EE_Error(
889
-                        sprintf(
890
-                            esc_html__(
891
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
892
-                                'event_espresso'
893
-                            ),
894
-                            'payment_method_settings'
895
-                        )
896
-                    );
897
-                }
898
-                $payment_settings_subform->save();
899
-                /** @var $pm EE_Payment_Method */
900
-                $this->_redirect_after_action(
901
-                    true,
902
-                    'Payment Method',
903
-                    'updated',
904
-                    array('action' => 'default', 'payment_method' => $payment_method->slug())
905
-                );
906
-            } else {
907
-                EE_Error::add_error(
908
-                    sprintf(
909
-                        esc_html__(
910
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
911
-                            'event_espresso'
912
-                        ),
913
-                        $payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
914
-                            : esc_html__('"(unknown)"', 'event_espresso')
915
-                    ),
916
-                    __FILE__,
917
-                    __FUNCTION__,
918
-                    __LINE__
919
-                );
920
-            }
921
-        }
922
-    }
923
-
924
-
925
-    /**
926
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
927
-     * @throws DomainException
928
-     * @throws EE_Error
929
-     * @throws InvalidArgumentException
930
-     * @throws InvalidDataTypeException
931
-     * @throws InvalidInterfaceException
932
-     */
933
-    protected function _payment_settings()
934
-    {
935
-        $form = $this->getPaymentSettingsForm();
936
-        $this->_set_add_edit_form_tags('update_payment_settings');
937
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
938
-        $this->_template_args['admin_page_content'] =  $form->get_html_and_js();
939
-        $this->display_admin_page_with_sidebar();
940
-    }
941
-
942
-
943
-    /**
944
-     *        _update_payment_settings
945
-     *
946
-     * @access protected
947
-     * @return void
948
-     * @throws EE_Error
949
-     * @throws InvalidArgumentException
950
-     * @throws InvalidDataTypeException
951
-     * @throws InvalidInterfaceException
952
-     */
953
-    protected function _update_payment_settings()
954
-    {
955
-        $form = $this->getPaymentSettingsForm();
956
-        if ($form->was_submitted($this->_req_data)) {
957
-            $form->receive_form_submission($this->_req_data);
958
-            if ($form->is_valid()) {
959
-                /**
960
-                 * @var $reg_config EE_Registration_Config
961
-                 */
962
-                $loader = LoaderFactory::getLoader();
963
-                $reg_config = $loader->getShared('EE_Registration_Config');
964
-                $valid_data = $form->valid_data();
965
-                $reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
966
-                $reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
967
-            }
968
-        }
969
-        EE_Registry::instance()->CFG = apply_filters(
970
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
971
-            EE_Registry::instance()->CFG
972
-        );
973
-
974
-        $what = esc_html__('Payment Settings', 'event_espresso');
975
-        $success = $this->_update_espresso_configuration(
976
-            $what,
977
-            EE_Registry::instance()->CFG,
978
-            __FILE__,
979
-            __FUNCTION__,
980
-            __LINE__
981
-        );
982
-        $this->_redirect_after_action(
983
-            $success,
984
-            $what,
985
-            esc_html__('updated', 'event_espresso'),
986
-            array('action' => 'payment_settings')
987
-        );
988
-    }
989
-
990
-
991
-    /**
992
-     * Gets the form used for updating payment settings
993
-     *
994
-     * @return EE_Form_Section_Proper
995
-     * @throws EE_Error
996
-     * @throws InvalidArgumentException
997
-     * @throws InvalidDataTypeException
998
-     * @throws InvalidInterfaceException
999
-     */
1000
-    protected function getPaymentSettingsForm()
1001
-    {
1002
-        /**
1003
-         * @var $reg_config EE_Registration_Config
1004
-         */
1005
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1006
-        return new EE_Form_Section_Proper(
1007
-            array(
1008
-                'name' => 'payment-settings',
1009
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1010
-                'subsections' => array(
1011
-                    'show_pending_payment_options' => new EE_Yes_No_Input(
1012
-                        array(
1013
-                            'html_name' => 'show_pending_payment_options',
1014
-                            'default' => $reg_config->show_pending_payment_options,
1015
-                            'html_help_text' => esc_html__(
1016
-                                "If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
1017
-                                'event_espresso'
1018
-                            )
1019
-                        )
1020
-                    ),
1021
-                    'gateway_log_lifespan' => new EE_Select_Input(
1022
-                        $reg_config->gatewayLogLifespanOptions(),
1023
-                        array(
1024
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1025
-                            'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
1026
-                            'default' => $reg_config->gateway_log_lifespan,
1027
-                        )
1028
-                    )
1029
-                )
1030
-            )
1031
-        );
1032
-    }
1033
-
1034
-
1035
-    /**
1036
-     * @throws EE_Error
1037
-     */
1038
-    protected function _payment_log_overview_list_table()
1039
-    {
1040
-        $this->display_admin_list_table_page_with_sidebar();
1041
-    }
1042
-
1043
-
1044
-    protected function _set_list_table_views_payment_log()
1045
-    {
1046
-        $this->_views = array(
1047
-            'all' => array(
1048
-                'slug'  => 'all',
1049
-                'label' => esc_html__('View All Logs', 'event_espresso'),
1050
-                'count' => 0,
1051
-            ),
1052
-        );
1053
-    }
1054
-
1055
-
1056
-    /**
1057
-     * @param int  $per_page
1058
-     * @param int  $current_page
1059
-     * @param bool $count
1060
-     * @return array|int
1061
-     * @throws EE_Error
1062
-     * @throws ReflectionException
1063
-     */
1064
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1065
-    {
1066
-        EE_Registry::instance()->load_model('Change_Log');
1067
-        // we may need to do multiple queries (joining differently), so we actually want an array of query params
1068
-        $query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1069
-        // check if they've selected a specific payment method
1070
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1071
-            $query_params[0]['OR*pm_or_pay_pm'] = array(
1072
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1073
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1074
-            );
1075
-        }
1076
-        // take into account search
1077
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1078
-            $similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1079
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1080
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1081
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1082
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1083
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1084
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1085
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1086
-            $query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1087
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1088
-            $query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1089
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1090
-        }
1091
-        if (
1092
-            isset($this->_req_data['payment-filter-start-date'])
1093
-            && isset($this->_req_data['payment-filter-end-date'])
1094
-        ) {
1095
-            // add date
1096
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1097
-            $end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1098
-            // make sure our timestamps start and end right at the boundaries for each day
1099
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1100
-            $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1101
-            // convert to timestamps
1102
-            $start_date = strtotime($start_date);
1103
-            $end_date = strtotime($end_date);
1104
-            // makes sure start date is the lowest value and vice versa
1105
-            $start_date = min($start_date, $end_date);
1106
-            $end_date = max($start_date, $end_date);
1107
-            // convert for query
1108
-            $start_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1109
-                'LOG_time',
1110
-                date('Y-m-d H:i:s', $start_date),
1111
-                'Y-m-d H:i:s'
1112
-            );
1113
-            $end_date   = EEM_Change_Log::instance()->convert_datetime_for_query(
1114
-                'LOG_time',
1115
-                date('Y-m-d H:i:s', $end_date),
1116
-                'Y-m-d H:i:s'
1117
-            );
1118
-            $query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1119
-        }
1120
-        if ($count) {
1121
-            return EEM_Change_Log::instance()->count($query_params);
1122
-        }
1123
-        if (isset($this->_req_data['order'])) {
1124
-            $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1125
-                ? $this->_req_data['order']
1126
-                : 'DESC';
1127
-            $query_params['order_by'] = array('LOG_time' => $sort);
1128
-        } else {
1129
-            $query_params['order_by'] = array('LOG_time' => 'DESC');
1130
-        }
1131
-        $offset = ($current_page - 1) * $per_page;
1132
-        if (! isset($this->_req_data['download_results'])) {
1133
-            $query_params['limit'] = array($offset, $per_page);
1134
-        }
1135
-        // now they've requested to instead just download the file instead of viewing it.
1136
-        if (isset($this->_req_data['download_results'])) {
1137
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1138
-            header('Content-Disposition: attachment');
1139
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1140
-            echo '<h1> '
1141
-                . sprintf(
1142
-                    esc_html__('Payment Logs for %1$s', 'event_espresso'),
1143
-                    esc_url_raw(site_url())
1144
-                )
1145
-                . '</h1 >';
1146
-            echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1147
-            echo esc_html(var_export($query_params, true));
1148
-            echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1149
-            echo esc_html(var_export($wpdb_results, true));
1150
-            die;
1151
-        }
1152
-        return EEM_Change_Log::instance()->get_all($query_params);
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * Used by usort to RE-sort log query results, because we lose the ordering
1158
-     * because we're possibly combining the results from two queries
1159
-     *
1160
-     * @param EE_Change_Log $logA
1161
-     * @param EE_Change_Log $logB
1162
-     * @return int
1163
-     * @throws EE_Error
1164
-     * @throws ReflectionException
1165
-     */
1166
-    protected function _sort_logs_again($logA, $logB)
1167
-    {
1168
-        $timeA = $logA->get_raw('LOG_time');
1169
-        $timeB = $logB->get_raw('LOG_time');
1170
-        if ($timeA == $timeB) {
1171
-            return 0;
1172
-        }
1173
-        $comparison = $timeA < $timeB ? -1 : 1;
1174
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1175
-            return $comparison * -1;
1176
-        }
1177
-        return $comparison;
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * @throws EE_Error
1183
-     * @throws ReflectionException
1184
-     */
1185
-    protected function _payment_log_details()
1186
-    {
1187
-        EE_Registry::instance()->load_model('Change_Log');
1188
-        /** @var $payment_log EE_Change_Log */
1189
-        $payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1190
-        $payment_method = null;
1191
-        $transaction = null;
1192
-        if ($payment_log instanceof EE_Change_Log) {
1193
-            if ($payment_log->object() instanceof EE_Payment) {
1194
-                $payment_method = $payment_log->object()->payment_method();
1195
-                $transaction = $payment_log->object()->transaction();
1196
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1197
-                $payment_method = $payment_log->object();
1198
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1199
-                $transaction = $payment_log->object();
1200
-                $payment_method = $transaction->payment_method();
1201
-            }
1202
-        }
1203
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1204
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1205
-            array(
1206
-                'payment_log'    => $payment_log,
1207
-                'payment_method' => $payment_method,
1208
-                'transaction'    => $transaction,
1209
-            ),
1210
-            true
1211
-        );
1212
-        $this->display_admin_page_with_no_sidebar();
1213
-    }
19
+	/**
20
+	 * Variables used for when we're re-sorting the logs results,
21
+	 * in case we needed to do two queries, and we need to resort
22
+	 *
23
+	 * @var string
24
+	 */
25
+	private $_sort_logs_again_direction;
26
+
27
+
28
+	/**
29
+	 * @Constructor
30
+	 * @access public
31
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
+	 * @throws EE_Error
33
+	 * @throws InvalidArgumentException
34
+	 * @throws InvalidDataTypeException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws ReflectionException
37
+	 */
38
+	public function __construct($routing = true)
39
+	{
40
+		parent::__construct($routing);
41
+	}
42
+
43
+
44
+	protected function _init_page_props()
45
+	{
46
+		$this->page_slug = EE_PAYMENTS_PG_SLUG;
47
+		$this->page_label = esc_html__('Payment Methods', 'event_espresso');
48
+		$this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
+	}
51
+
52
+
53
+	protected function _ajax_hooks()
54
+	{
55
+		// todo: all hooks for ajax goes here.
56
+	}
57
+
58
+
59
+	protected function _define_page_props()
60
+	{
61
+		$this->_admin_page_title = $this->page_label;
62
+		$this->_labels = array(
63
+			'publishbox' => esc_html__('Update Settings', 'event_espresso'),
64
+		);
65
+	}
66
+
67
+
68
+	protected function _set_page_routes()
69
+	{
70
+		/**
71
+		 * note that with payment method capabilities, although we've implemented
72
+		 * capability mapping which will be used for accessing payment methods owned by
73
+		 * other users.  This is not fully implemented yet in the payment method ui.
74
+		 * Currently, only the "plural" caps are in active use.
75
+		 * When cap mapping is implemented, some routes will need to use the singular form of
76
+		 * capability method and also include the $id of the payment method for the route.
77
+		 **/
78
+		$this->_page_routes = array(
79
+			'default'                   => array(
80
+				'func'       => '_payment_methods_list',
81
+				'capability' => 'ee_edit_payment_methods',
82
+			),
83
+			'payment_settings'          => array(
84
+				'func'       => '_payment_settings',
85
+				'capability' => 'ee_manage_gateways',
86
+			),
87
+			'activate_payment_method'   => array(
88
+				'func'       => '_activate_payment_method',
89
+				'noheader'   => true,
90
+				'capability' => 'ee_edit_payment_methods',
91
+			),
92
+			'deactivate_payment_method' => array(
93
+				'func'       => '_deactivate_payment_method',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_delete_payment_methods',
96
+			),
97
+			'update_payment_method'     => array(
98
+				'func'               => '_update_payment_method',
99
+				'noheader'           => true,
100
+				'headers_sent_route' => 'default',
101
+				'capability'         => 'ee_edit_payment_methods',
102
+			),
103
+			'update_payment_settings'   => array(
104
+				'func'       => '_update_payment_settings',
105
+				'noheader'   => true,
106
+				'capability' => 'ee_manage_gateways',
107
+			),
108
+			'payment_log'               => array(
109
+				'func'       => '_payment_log_overview_list_table',
110
+				'capability' => 'ee_read_payment_methods',
111
+			),
112
+			'payment_log_details'       => array(
113
+				'func'       => '_payment_log_details',
114
+				'capability' => 'ee_read_payment_methods',
115
+			),
116
+		);
117
+	}
118
+
119
+
120
+	/**
121
+	 * @throws EE_Error
122
+	 * @throws ReflectionException
123
+	 */
124
+	protected function _set_page_config()
125
+	{
126
+		$payment_method_list_config = array(
127
+			'nav'           => array(
128
+				'label' => esc_html__('Payment Methods', 'event_espresso'),
129
+				'order' => 10,
130
+			),
131
+			'metaboxes'     => $this->_default_espresso_metaboxes,
132
+			'help_tabs'     => array_merge(
133
+				array(
134
+					'payment_methods_overview_help_tab' => array(
135
+						'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
136
+						'filename' => 'payment_methods_overview',
137
+					),
138
+				),
139
+				$this->_add_payment_method_help_tabs()
140
+			),
141
+			'require_nonce' => false,
142
+		);
143
+		$this->_page_config = array(
144
+			'default'          => $payment_method_list_config,
145
+			'payment_settings' => array(
146
+				'nav'           => array(
147
+					'label' => esc_html__('Settings', 'event_espresso'),
148
+					'order' => 20,
149
+				),
150
+				'help_tabs'     => array(
151
+					'payment_methods_settings_help_tab' => array(
152
+						'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
153
+						'filename' => 'payment_methods_settings',
154
+					),
155
+				),
156
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
157
+				'require_nonce' => false,
158
+			),
159
+			'payment_log'      => array(
160
+				'nav'           => array(
161
+					'label' => esc_html__("Logs", 'event_espresso'),
162
+					'order' => 30,
163
+				),
164
+				'list_table'    => 'Payment_Log_Admin_List_Table',
165
+				'metaboxes'     => $this->_default_espresso_metaboxes,
166
+				'require_nonce' => false,
167
+			),
168
+		);
169
+	}
170
+
171
+
172
+	/**
173
+	 * @return array
174
+	 * @throws DomainException
175
+	 * @throws EE_Error
176
+	 * @throws InvalidArgumentException
177
+	 * @throws InvalidDataTypeException
178
+	 * @throws InvalidInterfaceException
179
+	 * @throws ReflectionException
180
+	 */
181
+	protected function _add_payment_method_help_tabs()
182
+	{
183
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
184
+		$payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
185
+		$all_pmt_help_tabs_config = array();
186
+		foreach ($payment_method_types as $payment_method_type) {
187
+			if (
188
+				! EE_Registry::instance()->CAP->current_user_can(
189
+					$payment_method_type->cap_name(),
190
+					'specific_payment_method_type_access'
191
+				)
192
+			) {
193
+				continue;
194
+			}
195
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
196
+				$template_args = isset($config['template_args']) ? $config['template_args'] : array();
197
+				$template_args['admin_page_obj'] = $this;
198
+				$all_pmt_help_tabs_config[ $help_tab_name ] = array(
199
+					'title'   => $config['title'],
200
+					'content' => EEH_Template::display_template(
201
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
202
+						$template_args,
203
+						true
204
+					),
205
+				);
206
+			}
207
+		}
208
+		return $all_pmt_help_tabs_config;
209
+	}
210
+
211
+
212
+	// none of the below group are currently used for Gateway Settings
213
+	protected function _add_screen_options()
214
+	{
215
+	}
216
+
217
+
218
+	protected function _add_feature_pointers()
219
+	{
220
+	}
221
+
222
+
223
+	public function admin_init()
224
+	{
225
+	}
226
+
227
+
228
+	public function admin_notices()
229
+	{
230
+	}
231
+
232
+
233
+	public function admin_footer_scripts()
234
+	{
235
+	}
236
+
237
+
238
+	public function load_scripts_styles()
239
+	{
240
+		// styles
241
+		wp_enqueue_style('espresso-ui-theme');
242
+		wp_register_style(
243
+			'espresso_payments',
244
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
245
+			[],
246
+			EVENT_ESPRESSO_VERSION
247
+		);
248
+		// scripts
249
+		wp_enqueue_script('ee_admin_js');
250
+		wp_enqueue_script('ee-text-links');
251
+		wp_enqueue_script(
252
+			'espresso_payments',
253
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
254
+			['ee-datepicker'],
255
+			EVENT_ESPRESSO_VERSION,
256
+			true
257
+		);
258
+	}
259
+
260
+
261
+	public function load_scripts_styles_default()
262
+	{
263
+		wp_enqueue_style('espresso_payments');
264
+		wp_enqueue_style('ee-text-links');
265
+	}
266
+
267
+
268
+	public function load_scripts_styles_payment_log_details()
269
+	{
270
+		wp_enqueue_style('espresso_payments');
271
+	}
272
+
273
+
274
+	/**
275
+	 * @throws EE_Error
276
+	 * @throws ReflectionException
277
+	 */
278
+	protected function _payment_methods_list()
279
+	{
280
+		/**
281
+		 * first let's ensure payment methods have been set up.
282
+		 * We do this here because when people activate a payment method for the first time (as an addon),
283
+		 * it may not set up its capabilities or get registered correctly due to the loading process.
284
+		 * However, people MUST set up the details for the payment method,
285
+		 * so it's safe to do a recheck here.
286
+		 */
287
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
288
+		EEM_Payment_Method::instance()->verify_button_urls();
289
+		// set up tabs, one for each payment method type
290
+		$tabs = array();
291
+		$payment_methods = array();
292
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
293
+			// we don't want to show admin-only PMTs for now
294
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
295
+				continue;
296
+			}
297
+			// check access
298
+			if (
299
+				! EE_Registry::instance()->CAP->current_user_can(
300
+					$pmt_obj->cap_name(),
301
+					'specific_payment_method_type_access'
302
+				)
303
+			) {
304
+				continue;
305
+			}
306
+			// check for any active pms of that type
307
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
308
+			if (! $payment_method instanceof EE_Payment_Method) {
309
+				$payment_method = EE_Payment_Method::new_instance(
310
+					array(
311
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
312
+						'PMD_type'       => $pmt_obj->system_name(),
313
+						'PMD_name'       => $pmt_obj->pretty_name(),
314
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
315
+					)
316
+				);
317
+			}
318
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
319
+		}
320
+		$payment_methods = apply_filters(
321
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
322
+			$payment_methods
323
+		);
324
+		foreach ($payment_methods as $payment_method) {
325
+			if ($payment_method instanceof EE_Payment_Method) {
326
+				add_meta_box(
327
+					// html id
328
+					'espresso_' . $payment_method->slug() . '_payment_settings',
329
+					// title
330
+					sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
331
+					// callback
332
+					array($this, 'payment_method_settings_meta_box'),
333
+					// post type
334
+					null,
335
+					// context
336
+					'normal',
337
+					// priority
338
+					'default',
339
+					// callback args
340
+					array('payment_method' => $payment_method)
341
+				);
342
+				// setup for tabbed content
343
+				$tabs[ $payment_method->slug() ] = array(
344
+					'label' => $payment_method->admin_name(),
345
+					'class' => $payment_method->active() ? 'gateway-active' : '',
346
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
347
+					'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
348
+					'slug'  => $payment_method->slug(),
349
+				);
350
+			}
351
+		}
352
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
353
+			$tabs,
354
+			'payment_method_links',
355
+			'|',
356
+			$this->_get_active_payment_method_slug()
357
+		);
358
+		$this->display_admin_page_with_sidebar();
359
+	}
360
+
361
+
362
+	/**
363
+	 *   _get_active_payment_method_slug
364
+	 *
365
+	 * @return string
366
+	 * @throws EE_Error
367
+	 */
368
+	protected function _get_active_payment_method_slug()
369
+	{
370
+		$payment_method_slug = false;
371
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
372
+		if (isset($this->_req_data['payment_method'])) {
373
+			// if they provided the current payment method, use it
374
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
375
+		}
376
+		/** @var EE_Payment_Method $payment_method */
377
+		$payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
378
+		// if that didn't work or wasn't provided, find another way to select the current pm
379
+		if (! $this->_verify_payment_method($payment_method)) {
380
+			// like, looking for an active one
381
+			$payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
382
+			// test that one as well
383
+			if ($this->_verify_payment_method($payment_method)) {
384
+				$payment_method_slug = $payment_method->slug();
385
+			} else {
386
+				$payment_method_slug = 'paypal_standard';
387
+			}
388
+		}
389
+		return $payment_method_slug;
390
+	}
391
+
392
+
393
+	/**
394
+	 *    payment_method_settings_meta_box
395
+	 *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
396
+	 *    capabilities to access it
397
+	 *
398
+	 * @param EE_Payment_Method $payment_method
399
+	 * @return boolean
400
+	 * @throws EE_Error
401
+	 */
402
+	protected function _verify_payment_method($payment_method)
403
+	{
404
+		if (
405
+			$payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
406
+			&& EE_Registry::instance()->CAP->current_user_can(
407
+				$payment_method->type_obj()->cap_name(),
408
+				'specific_payment_method_type_access'
409
+			)
410
+		) {
411
+			return true;
412
+		}
413
+		return false;
414
+	}
415
+
416
+
417
+	/**
418
+	 *    payment_method_settings_meta_box
419
+	 *
420
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
421
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
422
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
423
+	 * @return void
424
+	 * @throws EE_Error
425
+	 * @throws ReflectionException
426
+	 */
427
+	public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
428
+	{
429
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
430
+			? $metabox['args']['payment_method'] : null;
431
+		if (! $payment_method instanceof EE_Payment_Method) {
432
+			throw new EE_Error(
433
+				esc_html__(
434
+					'Payment method metabox setup incorrectly. No Payment method object was supplied',
435
+					'event_espresso'
436
+				)
437
+			);
438
+		}
439
+		$payment_method_scopes = $payment_method->active();
440
+		// if the payment method really exists show its form, otherwise the activation template
441
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
442
+			$form = $this->_generate_payment_method_settings_form($payment_method);
443
+			if ($form->form_data_present_in($this->_req_data)) {
444
+				$form->receive_form_submission($this->_req_data);
445
+			}
446
+			echo $form->form_open() . $form->get_html_and_js() . $form->form_close(); // already escaped
447
+		} else {
448
+			echo $this->_activate_payment_method_button($payment_method)->get_html_and_js(); // already escaped
449
+		}
450
+	}
451
+
452
+
453
+	/**
454
+	 * Gets the form for all the settings related to this payment method type
455
+	 *
456
+	 * @access protected
457
+	 * @param EE_Payment_Method $payment_method
458
+	 * @return EE_Form_Section_Proper
459
+	 * @throws EE_Error
460
+	 */
461
+	protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method = null)
462
+	{
463
+		if (! $payment_method instanceof EE_Payment_Method) {
464
+			return new EE_Form_Section_Proper();
465
+		}
466
+		return new EE_Form_Section_Proper(
467
+			array(
468
+				'name'            => $payment_method->slug() . '_settings_form',
469
+				'html_id'         => $payment_method->slug() . '_settings_form',
470
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
471
+					array(
472
+						'action'         => 'update_payment_method',
473
+						'payment_method' => $payment_method->slug(),
474
+					),
475
+					EE_PAYMENTS_ADMIN_URL
476
+				),
477
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
478
+				'subsections'     => apply_filters(
479
+					'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
480
+					array(
481
+						'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
482
+						'currency_support'        => $this->_currency_support($payment_method),
483
+						'payment_method_settings' => $this->_payment_method_settings($payment_method),
484
+						'update'                  => $this->_update_payment_method_button($payment_method),
485
+						'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
486
+						'fine_print'              => $this->_fine_print(),
487
+					),
488
+					$payment_method
489
+				),
490
+			)
491
+		);
492
+	}
493
+
494
+
495
+	/**
496
+	 * _pci_dss_compliance
497
+	 *
498
+	 * @access protected
499
+	 * @param EE_Payment_Method $payment_method
500
+	 * @return EE_Form_Section_HTML
501
+	 * @throws EE_Error
502
+	 */
503
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
504
+	{
505
+		if ($payment_method->type_obj()->requires_https()) {
506
+			return new EE_Form_Section_HTML(
507
+				EEH_HTML::table(
508
+					EEH_HTML::tr(
509
+						EEH_HTML::th(
510
+							EEH_HTML::label(
511
+								EEH_HTML::strong(
512
+									esc_html__('IMPORTANT', 'event_espresso'),
513
+									'',
514
+									'important-notice'
515
+								)
516
+							)
517
+						) .
518
+						EEH_HTML::td(
519
+							EEH_HTML::strong(
520
+								esc_html__(
521
+									'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
522
+									'event_espresso'
523
+								)
524
+							)
525
+							.
526
+							EEH_HTML::br()
527
+							.
528
+							esc_html__('Learn more about ', 'event_espresso')
529
+							. EEH_HTML::link(
530
+								'https://www.pcisecuritystandards.org/merchants/index.php',
531
+								esc_html__('PCI DSS compliance', 'event_espresso')
532
+							)
533
+						)
534
+					)
535
+				)
536
+			);
537
+		}
538
+		return new EE_Form_Section_HTML('');
539
+	}
540
+
541
+
542
+	/**
543
+	 * _currency_support
544
+	 *
545
+	 * @access protected
546
+	 * @param EE_Payment_Method $payment_method
547
+	 * @return EE_Form_Section_HTML
548
+	 * @throws EE_Error
549
+	 */
550
+	protected function _currency_support(EE_Payment_Method $payment_method)
551
+	{
552
+		if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
553
+			return new EE_Form_Section_HTML(
554
+				EEH_HTML::table(
555
+					EEH_HTML::tr(
556
+						EEH_HTML::th(
557
+							EEH_HTML::label(
558
+								EEH_HTML::strong(
559
+									esc_html__('IMPORTANT', 'event_espresso'),
560
+									'',
561
+									'important-notice'
562
+								)
563
+							)
564
+						) .
565
+						EEH_HTML::td(
566
+							EEH_HTML::strong(
567
+								sprintf(
568
+									esc_html__(
569
+										'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
570
+										'event_espresso'
571
+									),
572
+									EE_Config::instance()->currency->code
573
+								)
574
+							)
575
+						)
576
+					)
577
+				)
578
+			);
579
+		}
580
+		return new EE_Form_Section_HTML('');
581
+	}
582
+
583
+
584
+	/**
585
+	 * _update_payment_method_button
586
+	 *
587
+	 * @access protected
588
+	 * @param EE_Payment_Method $payment_method
589
+	 * @return EE_Payment_Method_Form
590
+	 * @throws EE_Error
591
+	 */
592
+	protected function _payment_method_settings(EE_Payment_Method $payment_method)
593
+	{
594
+		// modify the form, so we only have/show fields that will be implemented for this version
595
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
596
+	}
597
+
598
+
599
+	/**
600
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
601
+	 *
602
+	 * @param EE_Form_Section_Proper $form_section
603
+	 * @param string                 $payment_method_name
604
+	 * @return EE_Payment_Method_Form
605
+	 * @throws EE_Error
606
+	 */
607
+	protected function _simplify_form($form_section, $payment_method_name = '')
608
+	{
609
+		if ($form_section instanceof EE_Payment_Method_Form) {
610
+			$form_section->exclude(
611
+				array(
612
+					'PMD_type', // don't want them changing the type
613
+					'PMD_slug', // or the slug (probably never)
614
+					'PMD_wp_user', // or the user's ID
615
+					'Currency' // or the currency, until the rest of EE supports simultaneous currencies
616
+				)
617
+			);
618
+			return $form_section;
619
+		} else {
620
+			throw new EE_Error(
621
+				sprintf(
622
+					esc_html__(
623
+						'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
624
+						'event_espresso'
625
+					),
626
+					$payment_method_name
627
+				)
628
+			);
629
+		}
630
+	}
631
+
632
+
633
+	/**
634
+	 * _update_payment_method_button
635
+	 *
636
+	 * @access protected
637
+	 * @param EE_Payment_Method $payment_method
638
+	 * @return EE_Form_Section_HTML
639
+	 * @throws EE_Error
640
+	 */
641
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method)
642
+	{
643
+		$update_button = new EE_Submit_Input(
644
+			array(
645
+				'name'       => 'submit',
646
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
647
+				'default'    => sprintf(
648
+					esc_html__('Update %s Payment Settings', 'event_espresso'),
649
+					$payment_method->admin_name()
650
+				),
651
+				'html_label' => EEH_HTML::nbsp(),
652
+			)
653
+		);
654
+		return new EE_Form_Section_HTML(
655
+			EEH_HTML::table(
656
+				EEH_HTML::no_row(EEH_HTML::br(2)) .
657
+				EEH_HTML::tr(
658
+					EEH_HTML::th(esc_html__('Update Settings', 'event_espresso')) .
659
+					EEH_HTML::td(
660
+						$update_button->get_html_for_input()
661
+					)
662
+				)
663
+			)
664
+		);
665
+	}
666
+
667
+
668
+	/**
669
+	 * _deactivate_payment_method_button
670
+	 *
671
+	 * @access protected
672
+	 * @param EE_Payment_Method $payment_method
673
+	 * @return EE_Form_Section_HTML
674
+	 */
675
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
676
+	{
677
+		$link_text_and_title = sprintf(
678
+			esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
679
+			$payment_method->admin_name()
680
+		);
681
+		return new EE_Form_Section_HTML(
682
+			EEH_HTML::table(
683
+				EEH_HTML::tr(
684
+					EEH_HTML::th(esc_html__('Deactivate Payment Method', 'event_espresso')) .
685
+					EEH_HTML::td(
686
+						EEH_HTML::link(
687
+							EE_Admin_Page::add_query_args_and_nonce(
688
+								array(
689
+									'action'         => 'deactivate_payment_method',
690
+									'payment_method' => $payment_method->slug(),
691
+								),
692
+								EE_PAYMENTS_ADMIN_URL
693
+							),
694
+							$link_text_and_title,
695
+							$link_text_and_title,
696
+							'deactivate_' . $payment_method->slug(),
697
+							'espresso-button button-secondary'
698
+						)
699
+					)
700
+				)
701
+			)
702
+		);
703
+	}
704
+
705
+
706
+	/**
707
+	 * _activate_payment_method_button
708
+	 *
709
+	 * @access protected
710
+	 * @param EE_Payment_Method $payment_method
711
+	 * @return EE_Form_Section_Proper
712
+	 * @throws EE_Error
713
+	 */
714
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
715
+	{
716
+		$link_text_and_title = sprintf(
717
+			esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
718
+			$payment_method->admin_name()
719
+		);
720
+		return new EE_Form_Section_Proper(
721
+			array(
722
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
723
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
724
+				'action'          => '#',
725
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
726
+				'subsections'     => apply_filters(
727
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
728
+					array(
729
+						new EE_Form_Section_HTML(
730
+							EEH_HTML::table(
731
+								EEH_HTML::tr(
732
+									EEH_HTML::td(
733
+										$payment_method->type_obj()->introductory_html(),
734
+										'',
735
+										'',
736
+										'',
737
+										'colspan="2"'
738
+									)
739
+								) .
740
+								EEH_HTML::tr(
741
+									EEH_HTML::th(
742
+										EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
743
+									) .
744
+									EEH_HTML::td(
745
+										EEH_HTML::link(
746
+											EE_Admin_Page::add_query_args_and_nonce(
747
+												array(
748
+													'action'              => 'activate_payment_method',
749
+													'payment_method_type' => $payment_method->type(),
750
+												),
751
+												EE_PAYMENTS_ADMIN_URL
752
+											),
753
+											$link_text_and_title,
754
+											$link_text_and_title,
755
+											'activate_' . $payment_method->slug(),
756
+											'espresso-button-green button-primary'
757
+										)
758
+									)
759
+								)
760
+							)
761
+						),
762
+					),
763
+					$payment_method
764
+				),
765
+			)
766
+		);
767
+	}
768
+
769
+
770
+	/**
771
+	 * _fine_print
772
+	 *
773
+	 * @access protected
774
+	 * @return EE_Form_Section_HTML
775
+	 */
776
+	protected function _fine_print()
777
+	{
778
+		return new EE_Form_Section_HTML(
779
+			EEH_HTML::table(
780
+				EEH_HTML::tr(
781
+					EEH_HTML::th() .
782
+					EEH_HTML::td(
783
+						EEH_HTML::p(esc_html__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
784
+					)
785
+				)
786
+			)
787
+		);
788
+	}
789
+
790
+
791
+	/**
792
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
793
+	 *
794
+	 * @throws EE_Error
795
+	 * @throws ReflectionException
796
+	 * @global WP_User $current_user
797
+	 */
798
+	protected function _activate_payment_method()
799
+	{
800
+		if (isset($this->_req_data['payment_method_type'])) {
801
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
802
+			// see if one exists
803
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
804
+			$payment_method = EE_Payment_Method_Manager::instance()
805
+													   ->activate_a_payment_method_of_type($payment_method_type);
806
+			$this->_redirect_after_action(
807
+				1,
808
+				'Payment Method',
809
+				'activated',
810
+				array('action' => 'default', 'payment_method' => $payment_method->slug())
811
+			);
812
+		} else {
813
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
814
+		}
815
+	}
816
+
817
+
818
+	/**
819
+	 * @throws EE_Error
820
+	 * @throws ReflectionException
821
+	 */
822
+	protected function _deactivate_payment_method()
823
+	{
824
+		if (isset($this->_req_data['payment_method'])) {
825
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
826
+			// deactivate it
827
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
828
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
829
+			$this->_redirect_after_action(
830
+				$count_updated,
831
+				'Payment Method',
832
+				'deactivated',
833
+				array('action' => 'default', 'payment_method' => $payment_method_slug)
834
+			);
835
+		} else {
836
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
837
+		}
838
+	}
839
+
840
+
841
+	/**
842
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
843
+	 * processing because we first need to identify WHICH form was processed and which payment method
844
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
845
+	 * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
846
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
847
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
848
+	 *
849
+	 * @return void
850
+	 * @throws EE_Error
851
+	 * @throws ReflectionException
852
+	 */
853
+	protected function _update_payment_method()
854
+	{
855
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
856
+			// ok let's find which gateway form to use based on the form input
857
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
858
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
859
+			$correct_pmt_form_to_use = null;
860
+			$payment_method = null;
861
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
862
+				if ($payment_method instanceof EE_Payment_Method) {
863
+					// get the form and simplify it, like what we do when we display it
864
+					$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
865
+					if ($pmt_form->form_data_present_in($this->_req_data)) {
866
+						$correct_pmt_form_to_use = $pmt_form;
867
+						break;
868
+					}
869
+				}
870
+			}
871
+			// if we couldn't find the correct payment method type...
872
+			if (! $correct_pmt_form_to_use) {
873
+				EE_Error::add_error(
874
+					esc_html__(
875
+						"We could not find which payment method type your form submission related to. Please contact support",
876
+						'event_espresso'
877
+					),
878
+					__FILE__,
879
+					__FUNCTION__,
880
+					__LINE__
881
+				);
882
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
883
+			}
884
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
885
+			if ($correct_pmt_form_to_use->is_valid()) {
886
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
887
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
888
+					throw new EE_Error(
889
+						sprintf(
890
+							esc_html__(
891
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
892
+								'event_espresso'
893
+							),
894
+							'payment_method_settings'
895
+						)
896
+					);
897
+				}
898
+				$payment_settings_subform->save();
899
+				/** @var $pm EE_Payment_Method */
900
+				$this->_redirect_after_action(
901
+					true,
902
+					'Payment Method',
903
+					'updated',
904
+					array('action' => 'default', 'payment_method' => $payment_method->slug())
905
+				);
906
+			} else {
907
+				EE_Error::add_error(
908
+					sprintf(
909
+						esc_html__(
910
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
911
+							'event_espresso'
912
+						),
913
+						$payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
914
+							: esc_html__('"(unknown)"', 'event_espresso')
915
+					),
916
+					__FILE__,
917
+					__FUNCTION__,
918
+					__LINE__
919
+				);
920
+			}
921
+		}
922
+	}
923
+
924
+
925
+	/**
926
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
927
+	 * @throws DomainException
928
+	 * @throws EE_Error
929
+	 * @throws InvalidArgumentException
930
+	 * @throws InvalidDataTypeException
931
+	 * @throws InvalidInterfaceException
932
+	 */
933
+	protected function _payment_settings()
934
+	{
935
+		$form = $this->getPaymentSettingsForm();
936
+		$this->_set_add_edit_form_tags('update_payment_settings');
937
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
938
+		$this->_template_args['admin_page_content'] =  $form->get_html_and_js();
939
+		$this->display_admin_page_with_sidebar();
940
+	}
941
+
942
+
943
+	/**
944
+	 *        _update_payment_settings
945
+	 *
946
+	 * @access protected
947
+	 * @return void
948
+	 * @throws EE_Error
949
+	 * @throws InvalidArgumentException
950
+	 * @throws InvalidDataTypeException
951
+	 * @throws InvalidInterfaceException
952
+	 */
953
+	protected function _update_payment_settings()
954
+	{
955
+		$form = $this->getPaymentSettingsForm();
956
+		if ($form->was_submitted($this->_req_data)) {
957
+			$form->receive_form_submission($this->_req_data);
958
+			if ($form->is_valid()) {
959
+				/**
960
+				 * @var $reg_config EE_Registration_Config
961
+				 */
962
+				$loader = LoaderFactory::getLoader();
963
+				$reg_config = $loader->getShared('EE_Registration_Config');
964
+				$valid_data = $form->valid_data();
965
+				$reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
966
+				$reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
967
+			}
968
+		}
969
+		EE_Registry::instance()->CFG = apply_filters(
970
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
971
+			EE_Registry::instance()->CFG
972
+		);
973
+
974
+		$what = esc_html__('Payment Settings', 'event_espresso');
975
+		$success = $this->_update_espresso_configuration(
976
+			$what,
977
+			EE_Registry::instance()->CFG,
978
+			__FILE__,
979
+			__FUNCTION__,
980
+			__LINE__
981
+		);
982
+		$this->_redirect_after_action(
983
+			$success,
984
+			$what,
985
+			esc_html__('updated', 'event_espresso'),
986
+			array('action' => 'payment_settings')
987
+		);
988
+	}
989
+
990
+
991
+	/**
992
+	 * Gets the form used for updating payment settings
993
+	 *
994
+	 * @return EE_Form_Section_Proper
995
+	 * @throws EE_Error
996
+	 * @throws InvalidArgumentException
997
+	 * @throws InvalidDataTypeException
998
+	 * @throws InvalidInterfaceException
999
+	 */
1000
+	protected function getPaymentSettingsForm()
1001
+	{
1002
+		/**
1003
+		 * @var $reg_config EE_Registration_Config
1004
+		 */
1005
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1006
+		return new EE_Form_Section_Proper(
1007
+			array(
1008
+				'name' => 'payment-settings',
1009
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1010
+				'subsections' => array(
1011
+					'show_pending_payment_options' => new EE_Yes_No_Input(
1012
+						array(
1013
+							'html_name' => 'show_pending_payment_options',
1014
+							'default' => $reg_config->show_pending_payment_options,
1015
+							'html_help_text' => esc_html__(
1016
+								"If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
1017
+								'event_espresso'
1018
+							)
1019
+						)
1020
+					),
1021
+					'gateway_log_lifespan' => new EE_Select_Input(
1022
+						$reg_config->gatewayLogLifespanOptions(),
1023
+						array(
1024
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1025
+							'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
1026
+							'default' => $reg_config->gateway_log_lifespan,
1027
+						)
1028
+					)
1029
+				)
1030
+			)
1031
+		);
1032
+	}
1033
+
1034
+
1035
+	/**
1036
+	 * @throws EE_Error
1037
+	 */
1038
+	protected function _payment_log_overview_list_table()
1039
+	{
1040
+		$this->display_admin_list_table_page_with_sidebar();
1041
+	}
1042
+
1043
+
1044
+	protected function _set_list_table_views_payment_log()
1045
+	{
1046
+		$this->_views = array(
1047
+			'all' => array(
1048
+				'slug'  => 'all',
1049
+				'label' => esc_html__('View All Logs', 'event_espresso'),
1050
+				'count' => 0,
1051
+			),
1052
+		);
1053
+	}
1054
+
1055
+
1056
+	/**
1057
+	 * @param int  $per_page
1058
+	 * @param int  $current_page
1059
+	 * @param bool $count
1060
+	 * @return array|int
1061
+	 * @throws EE_Error
1062
+	 * @throws ReflectionException
1063
+	 */
1064
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1065
+	{
1066
+		EE_Registry::instance()->load_model('Change_Log');
1067
+		// we may need to do multiple queries (joining differently), so we actually want an array of query params
1068
+		$query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1069
+		// check if they've selected a specific payment method
1070
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1071
+			$query_params[0]['OR*pm_or_pay_pm'] = array(
1072
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1073
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1074
+			);
1075
+		}
1076
+		// take into account search
1077
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1078
+			$similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1079
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1080
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1081
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1082
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1083
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1084
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1085
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1086
+			$query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1087
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1088
+			$query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1089
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1090
+		}
1091
+		if (
1092
+			isset($this->_req_data['payment-filter-start-date'])
1093
+			&& isset($this->_req_data['payment-filter-end-date'])
1094
+		) {
1095
+			// add date
1096
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1097
+			$end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1098
+			// make sure our timestamps start and end right at the boundaries for each day
1099
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1100
+			$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1101
+			// convert to timestamps
1102
+			$start_date = strtotime($start_date);
1103
+			$end_date = strtotime($end_date);
1104
+			// makes sure start date is the lowest value and vice versa
1105
+			$start_date = min($start_date, $end_date);
1106
+			$end_date = max($start_date, $end_date);
1107
+			// convert for query
1108
+			$start_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1109
+				'LOG_time',
1110
+				date('Y-m-d H:i:s', $start_date),
1111
+				'Y-m-d H:i:s'
1112
+			);
1113
+			$end_date   = EEM_Change_Log::instance()->convert_datetime_for_query(
1114
+				'LOG_time',
1115
+				date('Y-m-d H:i:s', $end_date),
1116
+				'Y-m-d H:i:s'
1117
+			);
1118
+			$query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1119
+		}
1120
+		if ($count) {
1121
+			return EEM_Change_Log::instance()->count($query_params);
1122
+		}
1123
+		if (isset($this->_req_data['order'])) {
1124
+			$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1125
+				? $this->_req_data['order']
1126
+				: 'DESC';
1127
+			$query_params['order_by'] = array('LOG_time' => $sort);
1128
+		} else {
1129
+			$query_params['order_by'] = array('LOG_time' => 'DESC');
1130
+		}
1131
+		$offset = ($current_page - 1) * $per_page;
1132
+		if (! isset($this->_req_data['download_results'])) {
1133
+			$query_params['limit'] = array($offset, $per_page);
1134
+		}
1135
+		// now they've requested to instead just download the file instead of viewing it.
1136
+		if (isset($this->_req_data['download_results'])) {
1137
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1138
+			header('Content-Disposition: attachment');
1139
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1140
+			echo '<h1> '
1141
+				. sprintf(
1142
+					esc_html__('Payment Logs for %1$s', 'event_espresso'),
1143
+					esc_url_raw(site_url())
1144
+				)
1145
+				. '</h1 >';
1146
+			echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1147
+			echo esc_html(var_export($query_params, true));
1148
+			echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1149
+			echo esc_html(var_export($wpdb_results, true));
1150
+			die;
1151
+		}
1152
+		return EEM_Change_Log::instance()->get_all($query_params);
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1158
+	 * because we're possibly combining the results from two queries
1159
+	 *
1160
+	 * @param EE_Change_Log $logA
1161
+	 * @param EE_Change_Log $logB
1162
+	 * @return int
1163
+	 * @throws EE_Error
1164
+	 * @throws ReflectionException
1165
+	 */
1166
+	protected function _sort_logs_again($logA, $logB)
1167
+	{
1168
+		$timeA = $logA->get_raw('LOG_time');
1169
+		$timeB = $logB->get_raw('LOG_time');
1170
+		if ($timeA == $timeB) {
1171
+			return 0;
1172
+		}
1173
+		$comparison = $timeA < $timeB ? -1 : 1;
1174
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1175
+			return $comparison * -1;
1176
+		}
1177
+		return $comparison;
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * @throws EE_Error
1183
+	 * @throws ReflectionException
1184
+	 */
1185
+	protected function _payment_log_details()
1186
+	{
1187
+		EE_Registry::instance()->load_model('Change_Log');
1188
+		/** @var $payment_log EE_Change_Log */
1189
+		$payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1190
+		$payment_method = null;
1191
+		$transaction = null;
1192
+		if ($payment_log instanceof EE_Change_Log) {
1193
+			if ($payment_log->object() instanceof EE_Payment) {
1194
+				$payment_method = $payment_log->object()->payment_method();
1195
+				$transaction = $payment_log->object()->transaction();
1196
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1197
+				$payment_method = $payment_log->object();
1198
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1199
+				$transaction = $payment_log->object();
1200
+				$payment_method = $transaction->payment_method();
1201
+			}
1202
+		}
1203
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1204
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1205
+			array(
1206
+				'payment_log'    => $payment_log,
1207
+				'payment_method' => $payment_method,
1208
+				'transaction'    => $transaction,
1209
+			),
1210
+			true
1211
+		);
1212
+		$this->display_admin_page_with_no_sidebar();
1213
+	}
1214 1214
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2893 added lines, -2893 removed lines patch added patch discarded remove patch
@@ -16,2900 +16,2900 @@
 block discarded – undo
16 16
 class Events_Admin_Page extends EE_Admin_Page_CPT
17 17
 {
18 18
 
19
-    /**
20
-     * This will hold the event object for event_details screen.
19
+	/**
20
+	 * This will hold the event object for event_details screen.
21
+	 *
22
+	 * @var EE_Event $_event
23
+	 */
24
+	protected $_event;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var stdClass $_category
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This will hold the event model instance
37
+	 *
38
+	 * @var EEM_Event $_event_model
39
+	 */
40
+	protected $_event_model;
41
+
42
+
43
+	/**
44
+	 * @var EE_Event
45
+	 */
46
+	protected $_cpt_model_obj = false;
47
+
48
+
49
+	/**
50
+	 * @var NodeGroupDao
51
+	 */
52
+	protected $model_obj_node_group_persister;
53
+
54
+
55
+	/**
56
+	 * Initialize page props for this admin page group.
57
+	 */
58
+	protected function _init_page_props()
59
+	{
60
+		$this->page_slug        = EVENTS_PG_SLUG;
61
+		$this->page_label       = EVENTS_LABEL;
62
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
63
+		$this->_admin_base_path = EVENTS_ADMIN;
64
+		$this->_cpt_model_names = [
65
+			'create_new' => 'EEM_Event',
66
+			'edit'       => 'EEM_Event',
67
+		];
68
+		$this->_cpt_edit_routes = [
69
+			'espresso_events' => 'edit',
70
+		];
71
+		add_action(
72
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
73
+			[$this, 'verify_event_edit'],
74
+			10,
75
+			2
76
+		);
77
+	}
78
+
79
+
80
+	/**
81
+	 * Sets the ajax hooks used for this admin page group.
82
+	 */
83
+	protected function _ajax_hooks()
84
+	{
85
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
86
+	}
87
+
88
+
89
+	/**
90
+	 * Sets the page properties for this admin page group.
91
+	 */
92
+	protected function _define_page_props()
93
+	{
94
+		$this->_admin_page_title = EVENTS_LABEL;
95
+		$this->_labels           = [
96
+			'buttons'      => [
97
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
98
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
99
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
100
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
101
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
102
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
103
+			],
104
+			'editor_title' => [
105
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
106
+			],
107
+			'publishbox'   => [
108
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
109
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
110
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
111
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
112
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
113
+			],
114
+		];
115
+	}
116
+
117
+
118
+	/**
119
+	 * Sets the page routes property for this admin page group.
120
+	 */
121
+	protected function _set_page_routes()
122
+	{
123
+		// load formatter helper
124
+		// load field generator helper
125
+		// is there a evt_id in the request?
126
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
127
+		$EVT_ID = $this->request->getRequestParam('post', $EVT_ID, 'int');
128
+
129
+		$this->_page_routes = [
130
+			'default'                       => [
131
+				'func'       => '_events_overview_list_table',
132
+				'capability' => 'ee_read_events',
133
+			],
134
+			'create_new'                    => [
135
+				'func'       => '_create_new_cpt_item',
136
+				'capability' => 'ee_edit_events',
137
+			],
138
+			'edit'                          => [
139
+				'func'       => '_edit_cpt_item',
140
+				'capability' => 'ee_edit_event',
141
+				'obj_id'     => $EVT_ID,
142
+			],
143
+			'copy_event'                    => [
144
+				'func'       => '_copy_events',
145
+				'capability' => 'ee_edit_event',
146
+				'obj_id'     => $EVT_ID,
147
+				'noheader'   => true,
148
+			],
149
+			'trash_event'                   => [
150
+				'func'       => '_trash_or_restore_event',
151
+				'args'       => ['event_status' => 'trash'],
152
+				'capability' => 'ee_delete_event',
153
+				'obj_id'     => $EVT_ID,
154
+				'noheader'   => true,
155
+			],
156
+			'trash_events'                  => [
157
+				'func'       => '_trash_or_restore_events',
158
+				'args'       => ['event_status' => 'trash'],
159
+				'capability' => 'ee_delete_events',
160
+				'noheader'   => true,
161
+			],
162
+			'restore_event'                 => [
163
+				'func'       => '_trash_or_restore_event',
164
+				'args'       => ['event_status' => 'draft'],
165
+				'capability' => 'ee_delete_event',
166
+				'obj_id'     => $EVT_ID,
167
+				'noheader'   => true,
168
+			],
169
+			'restore_events'                => [
170
+				'func'       => '_trash_or_restore_events',
171
+				'args'       => ['event_status' => 'draft'],
172
+				'capability' => 'ee_delete_events',
173
+				'noheader'   => true,
174
+			],
175
+			'delete_event'                  => [
176
+				'func'       => '_delete_event',
177
+				'capability' => 'ee_delete_event',
178
+				'obj_id'     => $EVT_ID,
179
+				'noheader'   => true,
180
+			],
181
+			'delete_events'                 => [
182
+				'func'       => '_delete_events',
183
+				'capability' => 'ee_delete_events',
184
+				'noheader'   => true,
185
+			],
186
+			'view_report'                   => [
187
+				'func'       => '_view_report',
188
+				'capability' => 'ee_edit_events',
189
+			],
190
+			'default_event_settings'        => [
191
+				'func'       => '_default_event_settings',
192
+				'capability' => 'manage_options',
193
+			],
194
+			'update_default_event_settings' => [
195
+				'func'       => '_update_default_event_settings',
196
+				'capability' => 'manage_options',
197
+				'noheader'   => true,
198
+			],
199
+			'template_settings'             => [
200
+				'func'       => '_template_settings',
201
+				'capability' => 'manage_options',
202
+			],
203
+			// event category tab related
204
+			'add_category'                  => [
205
+				'func'       => '_category_details',
206
+				'capability' => 'ee_edit_event_category',
207
+				'args'       => ['add'],
208
+			],
209
+			'edit_category'                 => [
210
+				'func'       => '_category_details',
211
+				'capability' => 'ee_edit_event_category',
212
+				'args'       => ['edit'],
213
+			],
214
+			'delete_categories'             => [
215
+				'func'       => '_delete_categories',
216
+				'capability' => 'ee_delete_event_category',
217
+				'noheader'   => true,
218
+			],
219
+			'delete_category'               => [
220
+				'func'       => '_delete_categories',
221
+				'capability' => 'ee_delete_event_category',
222
+				'noheader'   => true,
223
+			],
224
+			'insert_category'               => [
225
+				'func'       => '_insert_or_update_category',
226
+				'args'       => ['new_category' => true],
227
+				'capability' => 'ee_edit_event_category',
228
+				'noheader'   => true,
229
+			],
230
+			'update_category'               => [
231
+				'func'       => '_insert_or_update_category',
232
+				'args'       => ['new_category' => false],
233
+				'capability' => 'ee_edit_event_category',
234
+				'noheader'   => true,
235
+			],
236
+			'category_list'                 => [
237
+				'func'       => '_category_list_table',
238
+				'capability' => 'ee_manage_event_categories',
239
+			],
240
+			'preview_deletion'              => [
241
+				'func'       => 'previewDeletion',
242
+				'capability' => 'ee_delete_events',
243
+			],
244
+			'confirm_deletion'              => [
245
+				'func'       => 'confirmDeletion',
246
+				'capability' => 'ee_delete_events',
247
+				'noheader'   => true,
248
+			],
249
+		];
250
+	}
251
+
252
+
253
+	/**
254
+	 * Set the _page_config property for this admin page group.
255
+	 */
256
+	protected function _set_page_config()
257
+	{
258
+		$post_id            = $this->request->getRequestParam('post', 0, 'int');
259
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
260
+		$this->_page_config = [
261
+			'default'                => [
262
+				'nav'           => [
263
+					'label' => esc_html__('Overview', 'event_espresso'),
264
+					'order' => 10,
265
+				],
266
+				'list_table'    => 'Events_Admin_List_Table',
267
+				'help_tabs'     => [
268
+					'events_overview_help_tab'                       => [
269
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
270
+						'filename' => 'events_overview',
271
+					],
272
+					'events_overview_table_column_headings_help_tab' => [
273
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
274
+						'filename' => 'events_overview_table_column_headings',
275
+					],
276
+					'events_overview_filters_help_tab'               => [
277
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
278
+						'filename' => 'events_overview_filters',
279
+					],
280
+					'events_overview_view_help_tab'                  => [
281
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
282
+						'filename' => 'events_overview_views',
283
+					],
284
+					'events_overview_other_help_tab'                 => [
285
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
286
+						'filename' => 'events_overview_other',
287
+					],
288
+				],
289
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
290
+				// 'help_tour'     => [
291
+				//     'Event_Overview_Help_Tour',
292
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
293
+				// ],
294
+				'qtips'         => ['EE_Event_List_Table_Tips'],
295
+				'require_nonce' => false,
296
+			],
297
+			'create_new'             => [
298
+				'nav'           => [
299
+					'label'      => esc_html__('Add Event', 'event_espresso'),
300
+					'order'      => 5,
301
+					'persistent' => false,
302
+				],
303
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
304
+				'help_tabs'     => [
305
+					'event_editor_help_tab'                            => [
306
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
307
+						'filename' => 'event_editor',
308
+					],
309
+					'event_editor_title_richtexteditor_help_tab'       => [
310
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
311
+						'filename' => 'event_editor_title_richtexteditor',
312
+					],
313
+					'event_editor_venue_details_help_tab'              => [
314
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
315
+						'filename' => 'event_editor_venue_details',
316
+					],
317
+					'event_editor_event_datetimes_help_tab'            => [
318
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
319
+						'filename' => 'event_editor_event_datetimes',
320
+					],
321
+					'event_editor_event_tickets_help_tab'              => [
322
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
323
+						'filename' => 'event_editor_event_tickets',
324
+					],
325
+					'event_editor_event_registration_options_help_tab' => [
326
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
327
+						'filename' => 'event_editor_event_registration_options',
328
+					],
329
+					'event_editor_tags_categories_help_tab'            => [
330
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
331
+						'filename' => 'event_editor_tags_categories',
332
+					],
333
+					'event_editor_questions_registrants_help_tab'      => [
334
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
335
+						'filename' => 'event_editor_questions_registrants',
336
+					],
337
+					'event_editor_save_new_event_help_tab'             => [
338
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
339
+						'filename' => 'event_editor_save_new_event',
340
+					],
341
+					'event_editor_other_help_tab'                      => [
342
+						'title'    => esc_html__('Event Other', 'event_espresso'),
343
+						'filename' => 'event_editor_other',
344
+					],
345
+				],
346
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
347
+				// 'help_tour'     => [
348
+				//     'Event_Editor_Help_Tour',
349
+				// ],
350
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
351
+				'require_nonce' => false,
352
+			],
353
+			'edit'                   => [
354
+				'nav'           => [
355
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
356
+					'order'      => 5,
357
+					'persistent' => false,
358
+					'url'        => $post_id
359
+						? EE_Admin_Page::add_query_args_and_nonce(
360
+							['post' => $post_id, 'action' => 'edit'],
361
+							$this->_current_page_view_url
362
+						)
363
+						: $this->_admin_base_url,
364
+				],
365
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
366
+				'help_tabs'     => [
367
+					'event_editor_help_tab'                            => [
368
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
369
+						'filename' => 'event_editor',
370
+					],
371
+					'event_editor_title_richtexteditor_help_tab'       => [
372
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
373
+						'filename' => 'event_editor_title_richtexteditor',
374
+					],
375
+					'event_editor_venue_details_help_tab'              => [
376
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
377
+						'filename' => 'event_editor_venue_details',
378
+					],
379
+					'event_editor_event_datetimes_help_tab'            => [
380
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
381
+						'filename' => 'event_editor_event_datetimes',
382
+					],
383
+					'event_editor_event_tickets_help_tab'              => [
384
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
385
+						'filename' => 'event_editor_event_tickets',
386
+					],
387
+					'event_editor_event_registration_options_help_tab' => [
388
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
389
+						'filename' => 'event_editor_event_registration_options',
390
+					],
391
+					'event_editor_tags_categories_help_tab'            => [
392
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
393
+						'filename' => 'event_editor_tags_categories',
394
+					],
395
+					'event_editor_questions_registrants_help_tab'      => [
396
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
397
+						'filename' => 'event_editor_questions_registrants',
398
+					],
399
+					'event_editor_save_new_event_help_tab'             => [
400
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
401
+						'filename' => 'event_editor_save_new_event',
402
+					],
403
+					'event_editor_other_help_tab'                      => [
404
+						'title'    => esc_html__('Event Other', 'event_espresso'),
405
+						'filename' => 'event_editor_other',
406
+					],
407
+				],
408
+				'require_nonce' => false,
409
+			],
410
+			'default_event_settings' => [
411
+				'nav'           => [
412
+					'label' => esc_html__('Default Settings', 'event_espresso'),
413
+					'order' => 40,
414
+				],
415
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
416
+				'labels'        => [
417
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
418
+				],
419
+				'help_tabs'     => [
420
+					'default_settings_help_tab'        => [
421
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
422
+						'filename' => 'events_default_settings',
423
+					],
424
+					'default_settings_status_help_tab' => [
425
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
426
+						'filename' => 'events_default_settings_status',
427
+					],
428
+					'default_maximum_tickets_help_tab' => [
429
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
430
+						'filename' => 'events_default_settings_max_tickets',
431
+					],
432
+				],
433
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
434
+				// 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
435
+				'require_nonce' => false,
436
+			],
437
+			// template settings
438
+			'template_settings'      => [
439
+				'nav'           => [
440
+					'label' => esc_html__('Templates', 'event_espresso'),
441
+					'order' => 30,
442
+				],
443
+				'metaboxes'     => $this->_default_espresso_metaboxes,
444
+				'help_tabs'     => [
445
+					'general_settings_templates_help_tab' => [
446
+						'title'    => esc_html__('Templates', 'event_espresso'),
447
+						'filename' => 'general_settings_templates',
448
+					],
449
+				],
450
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
451
+				// 'help_tour'     => ['Templates_Help_Tour'],
452
+				'require_nonce' => false,
453
+			],
454
+			// event category stuff
455
+			'add_category'           => [
456
+				'nav'           => [
457
+					'label'      => esc_html__('Add Category', 'event_espresso'),
458
+					'order'      => 15,
459
+					'persistent' => false,
460
+				],
461
+				'help_tabs'     => [
462
+					'add_category_help_tab' => [
463
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
464
+						'filename' => 'events_add_category',
465
+					],
466
+				],
467
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
468
+				// 'help_tour'     => ['Event_Add_Category_Help_Tour'],
469
+				'metaboxes'     => ['_publish_post_box'],
470
+				'require_nonce' => false,
471
+			],
472
+			'edit_category'          => [
473
+				'nav'           => [
474
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
475
+					'order'      => 15,
476
+					'persistent' => false,
477
+					'url'        => $EVT_CAT_ID
478
+						? add_query_arg(
479
+							['EVT_CAT_ID' => $EVT_CAT_ID],
480
+							$this->_current_page_view_url
481
+						)
482
+						: $this->_admin_base_url,
483
+				],
484
+				'help_tabs'     => [
485
+					'edit_category_help_tab' => [
486
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
487
+						'filename' => 'events_edit_category',
488
+					],
489
+				],
490
+				/*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
491
+				'metaboxes'     => ['_publish_post_box'],
492
+				'require_nonce' => false,
493
+			],
494
+			'category_list'          => [
495
+				'nav'           => [
496
+					'label' => esc_html__('Categories', 'event_espresso'),
497
+					'order' => 20,
498
+				],
499
+				'list_table'    => 'Event_Categories_Admin_List_Table',
500
+				'help_tabs'     => [
501
+					'events_categories_help_tab'                       => [
502
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
503
+						'filename' => 'events_categories',
504
+					],
505
+					'events_categories_table_column_headings_help_tab' => [
506
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
507
+						'filename' => 'events_categories_table_column_headings',
508
+					],
509
+					'events_categories_view_help_tab'                  => [
510
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
511
+						'filename' => 'events_categories_views',
512
+					],
513
+					'events_categories_other_help_tab'                 => [
514
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
515
+						'filename' => 'events_categories_other',
516
+					],
517
+				],
518
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
519
+				// 'help_tour'     => [
520
+				//     'Event_Categories_Help_Tour',
521
+				// ],
522
+				'metaboxes'     => $this->_default_espresso_metaboxes,
523
+				'require_nonce' => false,
524
+			],
525
+			'preview_deletion'       => [
526
+				'nav'           => [
527
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
528
+					'order'      => 15,
529
+					'persistent' => false,
530
+					'url'        => '',
531
+				],
532
+				'require_nonce' => false,
533
+			],
534
+		];
535
+	}
536
+
537
+
538
+	/**
539
+	 * Used to register any global screen options if necessary for every route in this admin page group.
540
+	 */
541
+	protected function _add_screen_options()
542
+	{
543
+	}
544
+
545
+
546
+	/**
547
+	 * Implementing the screen options for the 'default' route.
548
+	 *
549
+	 * @throws InvalidArgumentException
550
+	 * @throws InvalidDataTypeException
551
+	 * @throws InvalidInterfaceException
552
+	 */
553
+	protected function _add_screen_options_default()
554
+	{
555
+		$this->_per_page_screen_option();
556
+	}
557
+
558
+
559
+	/**
560
+	 * Implementing screen options for the category list route.
561
+	 *
562
+	 * @throws InvalidArgumentException
563
+	 * @throws InvalidDataTypeException
564
+	 * @throws InvalidInterfaceException
565
+	 */
566
+	protected function _add_screen_options_category_list()
567
+	{
568
+		$page_title              = $this->_admin_page_title;
569
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
570
+		$this->_per_page_screen_option();
571
+		$this->_admin_page_title = $page_title;
572
+	}
573
+
574
+
575
+	/**
576
+	 * Used to register any global feature pointers for the admin page group.
577
+	 */
578
+	protected function _add_feature_pointers()
579
+	{
580
+	}
581
+
582
+
583
+	/**
584
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
585
+	 */
586
+	public function load_scripts_styles()
587
+	{
588
+		wp_register_style(
589
+			'events-admin-css',
590
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
591
+			[],
592
+			EVENT_ESPRESSO_VERSION
593
+		);
594
+		wp_register_style(
595
+			'ee-cat-admin',
596
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
597
+			[],
598
+			EVENT_ESPRESSO_VERSION
599
+		);
600
+		wp_enqueue_style('events-admin-css');
601
+		wp_enqueue_style('ee-cat-admin');
602
+		// scripts
603
+		wp_register_script(
604
+			'event_editor_js',
605
+			EVENTS_ASSETS_URL . 'event_editor.js',
606
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
607
+			EVENT_ESPRESSO_VERSION,
608
+			true
609
+		);
610
+	}
611
+
612
+
613
+	/**
614
+	 * Enqueuing scripts and styles specific to this view
615
+	 */
616
+	public function load_scripts_styles_create_new()
617
+	{
618
+		$this->load_scripts_styles_edit();
619
+	}
620
+
621
+
622
+	/**
623
+	 * Enqueuing scripts and styles specific to this view
624
+	 */
625
+	public function load_scripts_styles_edit()
626
+	{
627
+		// styles
628
+		wp_enqueue_style('espresso-ui-theme');
629
+		wp_register_style(
630
+			'event-editor-css',
631
+			EVENTS_ASSETS_URL . 'event-editor.css',
632
+			['ee-admin-css'],
633
+			EVENT_ESPRESSO_VERSION
634
+		);
635
+		wp_enqueue_style('event-editor-css');
636
+		// scripts
637
+		if (! $this->admin_config->useAdvancedEditor()) {
638
+			wp_register_script(
639
+				'event-datetime-metabox',
640
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
641
+				['event_editor_js', 'ee-datepicker'],
642
+				EVENT_ESPRESSO_VERSION
643
+			);
644
+			wp_enqueue_script('event-datetime-metabox');
645
+		}
646
+	}
647
+
648
+
649
+	/**
650
+	 * Populating the _views property for the category list table view.
651
+	 */
652
+	protected function _set_list_table_views_category_list()
653
+	{
654
+		$this->_views = [
655
+			'all' => [
656
+				'slug'        => 'all',
657
+				'label'       => esc_html__('All', 'event_espresso'),
658
+				'count'       => 0,
659
+				'bulk_action' => [
660
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
661
+				],
662
+			],
663
+		];
664
+	}
665
+
666
+
667
+	/**
668
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
669
+	 */
670
+	public function admin_init()
671
+	{
672
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
673
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
674
+			'event_espresso'
675
+		);
676
+	}
677
+
678
+
679
+	/**
680
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
681
+	 * group.
682
+	 */
683
+	public function admin_notices()
684
+	{
685
+	}
686
+
687
+
688
+	/**
689
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
690
+	 * this admin page group.
691
+	 */
692
+	public function admin_footer_scripts()
693
+	{
694
+	}
695
+
696
+
697
+	/**
698
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
699
+	 * warning (via EE_Error::add_error());
700
+	 *
701
+	 * @param EE_Event $event Event object
702
+	 * @param string   $req_type
703
+	 * @return void
704
+	 * @throws EE_Error
705
+	 * @throws ReflectionException
706
+	 */
707
+	public function verify_event_edit($event = null, $req_type = '')
708
+	{
709
+		// don't need to do this when processing
710
+		if (! empty($req_type)) {
711
+			return;
712
+		}
713
+		// no event?
714
+		if (! $event instanceof EE_Event) {
715
+			$event = $this->_cpt_model_obj;
716
+		}
717
+		// STILL no event?
718
+		if (! $event instanceof EE_Event) {
719
+			return;
720
+		}
721
+		$orig_status = $event->status();
722
+		// first check if event is active.
723
+		if (
724
+			$orig_status === EEM_Event::cancelled
725
+			|| $orig_status === EEM_Event::postponed
726
+			|| $event->is_expired()
727
+			|| $event->is_inactive()
728
+		) {
729
+			return;
730
+		}
731
+		// made it here so it IS active... next check that any of the tickets are sold.
732
+		if ($event->is_sold_out(true)) {
733
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
734
+				EE_Error::add_attention(
735
+					sprintf(
736
+						esc_html__(
737
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
738
+							'event_espresso'
739
+						),
740
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
741
+					)
742
+				);
743
+			}
744
+			return;
745
+		}
746
+		if ($orig_status === EEM_Event::sold_out) {
747
+			EE_Error::add_attention(
748
+				sprintf(
749
+					esc_html__(
750
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
751
+						'event_espresso'
752
+					),
753
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
754
+				)
755
+			);
756
+		}
757
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
+		if (! $event->tickets_on_sale()) {
759
+			return;
760
+		}
761
+		// made it here so show warning
762
+		$this->_edit_event_warning();
763
+	}
764
+
765
+
766
+	/**
767
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
768
+	 * When needed, hook this into a EE_Error::add_error() notice.
769
+	 *
770
+	 * @access protected
771
+	 * @return void
772
+	 */
773
+	protected function _edit_event_warning()
774
+	{
775
+		// we don't want to add warnings during these requests
776
+		if ($this->request->getRequestParam('action') === 'editpost') {
777
+			return;
778
+		}
779
+		EE_Error::add_attention(
780
+			sprintf(
781
+				esc_html__(
782
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
783
+					'event_espresso'
784
+				),
785
+				'<a class="espresso-help-tab-lnk">',
786
+				'</a>'
787
+			)
788
+		);
789
+	}
790
+
791
+
792
+	/**
793
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
794
+	 * Otherwise, do the normal logic
795
+	 *
796
+	 * @return void
797
+	 * @throws EE_Error
798
+	 * @throws InvalidArgumentException
799
+	 * @throws InvalidDataTypeException
800
+	 * @throws InvalidInterfaceException
801
+	 */
802
+	protected function _create_new_cpt_item()
803
+	{
804
+		$has_timezone_string = get_option('timezone_string');
805
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
806
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
+			EE_Error::add_attention(
808
+				sprintf(
809
+					esc_html__(
810
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
811
+						'event_espresso'
812
+					),
813
+					'<br>',
814
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
+					. '</select>',
817
+					'<button class="button button-secondary timezone-submit">',
818
+					'</button><span class="spinner"></span>'
819
+				),
820
+				__FILE__,
821
+				__FUNCTION__,
822
+				__LINE__
823
+			);
824
+		}
825
+		parent::_create_new_cpt_item();
826
+	}
827
+
828
+
829
+	/**
830
+	 * Sets the _views property for the default route in this admin page group.
831
+	 */
832
+	protected function _set_list_table_views_default()
833
+	{
834
+		$this->_views = [
835
+			'all'   => [
836
+				'slug'        => 'all',
837
+				'label'       => esc_html__('View All Events', 'event_espresso'),
838
+				'count'       => 0,
839
+				'bulk_action' => [
840
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
+				],
842
+			],
843
+			'draft' => [
844
+				'slug'        => 'draft',
845
+				'label'       => esc_html__('Draft', 'event_espresso'),
846
+				'count'       => 0,
847
+				'bulk_action' => [
848
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
+				],
850
+			],
851
+		];
852
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
+			$this->_views['trash'] = [
854
+				'slug'        => 'trash',
855
+				'label'       => esc_html__('Trash', 'event_espresso'),
856
+				'count'       => 0,
857
+				'bulk_action' => [
858
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
+				],
861
+			];
862
+		}
863
+	}
864
+
865
+
866
+	/**
867
+	 * Provides the legend item array for the default list table view.
868
+	 *
869
+	 * @return array
870
+	 * @throws EE_Error
871
+	 * @throws EE_Error
872
+	 */
873
+	protected function _event_legend_items()
874
+	{
875
+		$items    = [
876
+			'view_details'   => [
877
+				'class' => 'dashicons dashicons-search',
878
+				'desc'  => esc_html__('View Event', 'event_espresso'),
879
+			],
880
+			'edit_event'     => [
881
+				'class' => 'ee-icon ee-icon-calendar-edit',
882
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
+			],
884
+			'view_attendees' => [
885
+				'class' => 'dashicons dashicons-groups',
886
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
+			],
888
+		];
889
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
+		$statuses = [
891
+			'sold_out_status'  => [
892
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
893
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
+			],
895
+			'active_status'    => [
896
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
897
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
+			],
899
+			'upcoming_status'  => [
900
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
901
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
+			],
903
+			'postponed_status' => [
904
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
905
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
+			],
907
+			'cancelled_status' => [
908
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
909
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
+			],
911
+			'expired_status'   => [
912
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
913
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
+			],
915
+			'inactive_status'  => [
916
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
917
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
+			],
919
+		];
920
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
+		return array_merge($items, $statuses);
922
+	}
923
+
924
+
925
+	/**
926
+	 * @return EEM_Event
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @throws ReflectionException
932
+	 */
933
+	private function _event_model()
934
+	{
935
+		if (! $this->_event_model instanceof EEM_Event) {
936
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
937
+		}
938
+		return $this->_event_model;
939
+	}
940
+
941
+
942
+	/**
943
+	 * Adds extra buttons to the WP CPT permalink field row.
944
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
+	 *
946
+	 * @param string $return    the current html
947
+	 * @param int    $id        the post id for the page
948
+	 * @param string $new_title What the title is
949
+	 * @param string $new_slug  what the slug is
950
+	 * @return string            The new html string for the permalink area
951
+	 */
952
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
953
+	{
954
+		// make sure this is only when editing
955
+		if (! empty($id)) {
956
+			$post   = get_post($id);
957
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
958
+					   . esc_html__('Shortcode', 'event_espresso')
959
+					   . '</a> ';
960
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
961
+					   . $post->ID
962
+					   . ']">';
963
+		}
964
+		return $return;
965
+	}
966
+
967
+
968
+	/**
969
+	 * _events_overview_list_table
970
+	 * This contains the logic for showing the events_overview list
971
+	 *
972
+	 * @access protected
973
+	 * @return void
974
+	 * @throws DomainException
975
+	 * @throws EE_Error
976
+	 * @throws InvalidArgumentException
977
+	 * @throws InvalidDataTypeException
978
+	 * @throws InvalidInterfaceException
979
+	 */
980
+	protected function _events_overview_list_table()
981
+	{
982
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
983
+		$after_list_table                           = [];
984
+		$after_list_table['view_event_list_button'] = EEH_HTML::br();
985
+		$after_list_table['view_event_list_button'] .= EEH_Template::get_button_or_link(
986
+			get_post_type_archive_link('espresso_events'),
987
+			esc_html__('View Event Archive Page', 'event_espresso'),
988
+			'button'
989
+		);
990
+		$after_list_table['legend']                 = $this->_display_legend($this->_event_legend_items());
991
+		$this->_admin_page_title                    .= ' ' . $this->get_action_link_or_button(
992
+			'create_new',
993
+			'add',
994
+			[],
995
+			'add-new-h2'
996
+		);
997
+		$this->_template_args['after_list_table']   = array_merge(
998
+			(array) $this->_template_args['after_list_table'],
999
+			$after_list_table
1000
+		);
1001
+		$this->display_admin_list_table_page_with_no_sidebar();
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * this allows for extra misc actions in the default WP publish box
1007
+	 *
1008
+	 * @return void
1009
+	 * @throws DomainException
1010
+	 * @throws EE_Error
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 * @throws ReflectionException
1015
+	 */
1016
+	public function extra_misc_actions_publish_box()
1017
+	{
1018
+		$this->_generate_publish_box_extra_content();
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1024
+	 * saved.
1025
+	 * Typically you would use this to save any additional data.
1026
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1027
+	 * ALSO very important.  When a post transitions from scheduled to published,
1028
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1029
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1030
+	 *
1031
+	 * @access protected
1032
+	 * @abstract
1033
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1034
+	 * @param object $post    The post object of the cpt that was saved.
1035
+	 * @return void
1036
+	 * @throws EE_Error
1037
+	 * @throws InvalidArgumentException
1038
+	 * @throws InvalidDataTypeException
1039
+	 * @throws InvalidInterfaceException
1040
+	 * @throws ReflectionException
1041
+	 */
1042
+	protected function _insert_update_cpt_item($post_id, $post)
1043
+	{
1044
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1045
+			// get out we're not processing an event save.
1046
+			return;
1047
+		}
1048
+		$event_values = [
1049
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, 'bool'),
1050
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, 'bool'),
1051
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1052
+		];
1053
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1054
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1055
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1056
+				'display_ticket_selector',
1057
+				false,
1058
+				'bool'
1059
+			);
1060
+			$event_values['EVT_additional_limit']            = min(
1061
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1062
+				$this->request->getRequestParam('additional_limit', null, 'int')
1063
+			);
1064
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1065
+				'EVT_default_registration_status',
1066
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1067
+			);
1068
+
1069
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1070
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1071
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, 'bool');
1072
+		}
1073
+		// update event
1074
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1075
+		// get event_object for other metaboxes...
1076
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1077
+		// i have to setup where conditions to override the filters in the model
1078
+		// that filter out autodraft and inherit statuses so we GET the inherit id!
1079
+		$event = $this->_event_model()->get_one(
1080
+			[
1081
+				[
1082
+					$this->_event_model()->primary_key_name() => $post_id,
1083
+					'OR'                                      => [
1084
+						'status'   => $post->post_status,
1085
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1086
+						// but the returned object here has a status of "publish", so use the original post status as well
1087
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1088
+					],
1089
+				],
1090
+			]
1091
+		);
1092
+
1093
+		// the following are default callbacks for event attachment updates
1094
+		// that can be overridden by caffeinated functionality and/or addons.
1095
+		$event_update_callbacks = [];
1096
+		if (! $this->admin_config->useAdvancedEditor()) {
1097
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1098
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1099
+		}
1100
+		$event_update_callbacks = apply_filters(
1101
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1102
+			$event_update_callbacks
1103
+		);
1104
+
1105
+		$att_success = true;
1106
+		foreach ($event_update_callbacks as $e_callback) {
1107
+			$_success = is_callable($e_callback)
1108
+				? $e_callback($event, $this->request->requestParams())
1109
+				: false;
1110
+			// if ANY of these updates fail then we want the appropriate global error message
1111
+			$att_success = $_success !== false ? $att_success : false;
1112
+		}
1113
+		// any errors?
1114
+		if ($success && $att_success === false) {
1115
+			EE_Error::add_error(
1116
+				esc_html__(
1117
+					'Event Details saved successfully but something went wrong with saving attachments.',
1118
+					'event_espresso'
1119
+				),
1120
+				__FILE__,
1121
+				__FUNCTION__,
1122
+				__LINE__
1123
+			);
1124
+		} elseif ($success === false) {
1125
+			EE_Error::add_error(
1126
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1127
+				__FILE__,
1128
+				__FUNCTION__,
1129
+				__LINE__
1130
+			);
1131
+		}
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * @param int $post_id
1137
+	 * @param int $revision_id
1138
+	 * @throws EE_Error
1139
+	 * @throws EE_Error
1140
+	 * @throws ReflectionException
1141
+	 * @see parent::restore_item()
1142
+	 */
1143
+	protected function _restore_cpt_item($post_id, $revision_id)
1144
+	{
1145
+		// copy existing event meta to new post
1146
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1147
+		if ($post_evt instanceof EE_Event) {
1148
+			// meta revision restore
1149
+			$post_evt->restore_revision($revision_id);
1150
+			// related objs restore
1151
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1152
+		}
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * Attach the venue to the Event
1158
+	 *
1159
+	 * @param EE_Event $event Event Object to add the venue to
1160
+	 * @param array    $data  The request data from the form
1161
+	 * @return bool           Success or fail.
1162
+	 * @throws EE_Error
1163
+	 * @throws ReflectionException
1164
+	 */
1165
+	protected function _default_venue_update(EE_Event $event, $data)
1166
+	{
1167
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1168
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1169
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1170
+		// very important.  If we don't have a venue name...
1171
+		// then we'll get out because not necessary to create empty venue
1172
+		if (empty($data['venue_title'])) {
1173
+			return false;
1174
+		}
1175
+		$venue_array = [
1176
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1177
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1178
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1179
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1180
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1181
+				? $data['venue_short_description']
1182
+				: null,
1183
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1184
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1185
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1186
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1187
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1188
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1189
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1190
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1191
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1192
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1193
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1194
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1195
+			'status'              => 'publish',
1196
+		];
1197
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1198
+		if (! empty($venue_id)) {
1199
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1200
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1201
+			// we've gotta make sure that the venue is always attached to a revision..
1202
+			// add_relation_to should take care of making sure that the relation is already present.
1203
+			$event->_add_relation_to($venue_id, 'Venue');
1204
+			return $rows_affected > 0;
1205
+		}
1206
+		// we insert the venue
1207
+		$venue_id = $venue_model->insert($venue_array);
1208
+		$event->_add_relation_to($venue_id, 'Venue');
1209
+		return ! empty($venue_id);
1210
+		// when we have the ancestor come in it's already been handled by the revision save.
1211
+	}
1212
+
1213
+
1214
+	/**
1215
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1216
+	 *
1217
+	 * @param EE_Event $event The Event object we're attaching data to
1218
+	 * @param array    $data  The request data from the form
1219
+	 * @return array
1220
+	 * @throws EE_Error
1221
+	 * @throws ReflectionException
1222
+	 * @throws Exception
1223
+	 */
1224
+	protected function _default_tickets_update(EE_Event $event, $data)
1225
+	{
1226
+		if ($this->admin_config->useAdvancedEditor()) {
1227
+			return [];
1228
+		}
1229
+		$datetime       = null;
1230
+		$saved_tickets  = [];
1231
+		$event_timezone = $event->get_timezone();
1232
+		$date_formats   = ['Y-m-d', 'h:i a'];
1233
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1234
+			// trim all values to ensure any excess whitespace is removed.
1235
+			$datetime_data                = array_map('trim', $datetime_data);
1236
+			$datetime_data['DTT_EVT_end'] =
1237
+				isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1238
+					? $datetime_data['DTT_EVT_end']
1239
+					: $datetime_data['DTT_EVT_start'];
1240
+			$datetime_values              = [
1241
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1242
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1243
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1244
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1245
+				'DTT_order'     => $row,
1246
+			];
1247
+			// if we have an id then let's get existing object first and then set the new values.
1248
+			//  Otherwise we instantiate a new object for save.
1249
+			if (! empty($datetime_data['DTT_ID'])) {
1250
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1251
+				if (! $datetime instanceof EE_Datetime) {
1252
+					throw new RuntimeException(
1253
+						sprintf(
1254
+							esc_html__(
1255
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1256
+								'event_espresso'
1257
+							),
1258
+							$datetime_data['DTT_ID']
1259
+						)
1260
+					);
1261
+				}
1262
+				$datetime->set_date_format($date_formats[0]);
1263
+				$datetime->set_time_format($date_formats[1]);
1264
+				foreach ($datetime_values as $field => $value) {
1265
+					$datetime->set($field, $value);
1266
+				}
1267
+			} else {
1268
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1269
+			}
1270
+			if (! $datetime instanceof EE_Datetime) {
1271
+				throw new RuntimeException(
1272
+					sprintf(
1273
+						esc_html__(
1274
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1275
+							'event_espresso'
1276
+						),
1277
+						print_r($datetime_values, true)
1278
+					)
1279
+				);
1280
+			}
1281
+			// before going any further make sure our dates are setup correctly
1282
+			// so that the end date is always equal or greater than the start date.
1283
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1284
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1285
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1286
+			}
1287
+			$datetime->save();
1288
+			$event->_add_relation_to($datetime, 'Datetime');
1289
+		}
1290
+		// no datetimes get deleted so we don't do any of that logic here.
1291
+		// update tickets next
1292
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1293
+
1294
+		// set up some default start and end dates in case those are not present in the incoming data
1295
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1296
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1297
+		// use the start date of the first datetime for the end date
1298
+		$first_datetime   = $event->first_datetime();
1299
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1300
+
1301
+		// now process the incoming data
1302
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1303
+			$update_prices = false;
1304
+			$ticket_price  = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1305
+				? $data['edit_prices'][ $row ][1]['PRC_amount']
1306
+				: 0;
1307
+			// trim inputs to ensure any excess whitespace is removed.
1308
+			$ticket_data   = array_map('trim', $ticket_data);
1309
+			$ticket_values = [
1310
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1311
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1312
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1313
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1314
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1315
+					? $ticket_data['TKT_start_date']
1316
+					: $default_start_date,
1317
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1318
+					? $ticket_data['TKT_end_date']
1319
+					: $default_end_date,
1320
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1321
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1322
+					? $ticket_data['TKT_qty']
1323
+					: EE_INF,
1324
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1325
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1326
+					? $ticket_data['TKT_uses']
1327
+					: EE_INF,
1328
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1329
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1330
+				'TKT_order'       => isset($ticket_data['TKT_order']) ? $ticket_data['TKT_order'] : $row,
1331
+				'TKT_price'       => $ticket_price,
1332
+				'TKT_row'         => $row,
1333
+			];
1334
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1335
+			// which means in turn that the prices will become new prices as well.
1336
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1337
+				$ticket_values['TKT_ID']         = 0;
1338
+				$ticket_values['TKT_is_default'] = 0;
1339
+				$update_prices                   = true;
1340
+			}
1341
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1342
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1343
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1344
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1345
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1346
+			if (! empty($ticket_data['TKT_ID'])) {
1347
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1348
+				if (! $existing_ticket instanceof EE_Ticket) {
1349
+					throw new RuntimeException(
1350
+						sprintf(
1351
+							esc_html__(
1352
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1353
+								'event_espresso'
1354
+							),
1355
+							$ticket_data['TKT_ID']
1356
+						)
1357
+					);
1358
+				}
1359
+				$ticket_sold = $existing_ticket->count_related(
1360
+					'Registration',
1361
+					[
1362
+							[
1363
+								'STS_ID' => [
1364
+									'NOT IN',
1365
+									[EEM_Registration::status_id_incomplete],
1366
+								],
1367
+							],
1368
+						]
1369
+				) > 0;
1370
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1371
+				// if they are different then we create a new ticket (if $ticket_sold)
1372
+				// if they aren't different then we go ahead and modify existing ticket.
1373
+				$create_new_ticket = $ticket_sold
1374
+									 && $ticket_price !== $existing_ticket->price()
1375
+									 && ! $existing_ticket->deleted();
1376
+				$existing_ticket->set_date_format($date_formats[0]);
1377
+				$existing_ticket->set_time_format($date_formats[1]);
1378
+				// set new values
1379
+				foreach ($ticket_values as $field => $value) {
1380
+					if ($field == 'TKT_qty') {
1381
+						$existing_ticket->set_qty($value);
1382
+					} elseif ($field == 'TKT_price') {
1383
+						$existing_ticket->set('TKT_price', $ticket_price);
1384
+					} else {
1385
+						$existing_ticket->set($field, $value);
1386
+					}
1387
+				}
1388
+				$ticket = $existing_ticket;
1389
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1390
+				//  Otherwise we have to create a new ticket.
1391
+				if ($create_new_ticket) {
1392
+					// archive the old ticket first
1393
+					$existing_ticket->set('TKT_deleted', 1);
1394
+					$existing_ticket->save();
1395
+					// make sure this ticket is still recorded in our $saved_tickets
1396
+					// so we don't run it through the regular trash routine.
1397
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1398
+					// create new ticket that's a copy of the existing except,
1399
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1400
+					$new_ticket = clone $existing_ticket;
1401
+					$new_ticket->set('TKT_ID', 0);
1402
+					$new_ticket->set('TKT_deleted', 0);
1403
+					$new_ticket->set('TKT_sold', 0);
1404
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1405
+					$update_prices = true;
1406
+					$ticket        = $new_ticket;
1407
+				}
1408
+			} else {
1409
+				// no TKT_id so a new ticket
1410
+				$ticket_values['TKT_price'] = $ticket_price;
1411
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1412
+				$update_prices              = true;
1413
+			}
1414
+			if (! $ticket instanceof EE_Ticket) {
1415
+				throw new RuntimeException(
1416
+					sprintf(
1417
+						esc_html__(
1418
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1419
+							'event_espresso'
1420
+						),
1421
+						print_r($ticket_values, true)
1422
+					)
1423
+				);
1424
+			}
1425
+			// cap ticket qty by datetime reg limits
1426
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1427
+			// update ticket.
1428
+			$ticket->save();
1429
+			// before going any further make sure our dates are setup correctly
1430
+			// so that the end date is always equal or greater than the start date.
1431
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1432
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1433
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1434
+				$ticket->save();
1435
+			}
1436
+			// initially let's add the ticket to the datetime
1437
+			$datetime->_add_relation_to($ticket, 'Ticket');
1438
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1439
+			// add prices to ticket
1440
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $ticket, $update_prices);
1441
+		}
1442
+		// however now we need to handle permanently deleting tickets via the ui.
1443
+		//  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1444
+		//  However, it does allow for deleting tickets that have no tickets sold,
1445
+		// in which case we want to get rid of permanently because there is no need to save in db.
1446
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1447
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1448
+		foreach ($tickets_removed as $id) {
1449
+			$id = absint($id);
1450
+			// get the ticket for this id
1451
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1452
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1453
+				continue;
1454
+			}
1455
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1456
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1457
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1458
+			foreach ($related_datetimes as $related_datetime) {
1459
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1460
+			}
1461
+			// need to do the same for prices (except these prices can also be deleted because again,
1462
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1463
+			$ticket_to_remove->delete_related_permanently('Price');
1464
+			// finally let's delete this ticket
1465
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1466
+			$ticket_to_remove->delete_permanently();
1467
+		}
1468
+		return [$datetime, $saved_tickets];
1469
+	}
1470
+
1471
+
1472
+	/**
1473
+	 * This attaches a list of given prices to a ticket.
1474
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1475
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1476
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1477
+	 *
1478
+	 * @access  private
1479
+	 * @param array     $prices_data Array of prices from the form.
1480
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1481
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1482
+	 * @return  void
1483
+	 * @throws EE_Error
1484
+	 * @throws ReflectionException
1485
+	 */
1486
+	private function _add_prices_to_ticket($prices_data, EE_Ticket $ticket, $new_prices = false)
1487
+	{
1488
+		$timezone = $ticket->get_timezone();
1489
+		foreach ($prices_data as $row => $price_data) {
1490
+			$price_values = [
1491
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1492
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1493
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1494
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1495
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1496
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1497
+				'PRC_order'      => $row,
1498
+			];
1499
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1500
+				$price_values['PRC_ID'] = 0;
1501
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1502
+			} else {
1503
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1504
+				// update this price with new values
1505
+				foreach ($price_values as $field => $new_price) {
1506
+					$price->set($field, $new_price);
1507
+				}
1508
+			}
1509
+			if (! $price instanceof EE_Price) {
1510
+				throw new RuntimeException(
1511
+					sprintf(
1512
+						esc_html__(
1513
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1514
+							'event_espresso'
1515
+						),
1516
+						print_r($price_values, true)
1517
+					)
1518
+				);
1519
+			}
1520
+			$price->save();
1521
+			$ticket->_add_relation_to($price, 'Price');
1522
+		}
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * Add in our autosave ajax handlers
1528
+	 *
1529
+	 */
1530
+	protected function _ee_autosave_create_new()
1531
+	{
1532
+	}
1533
+
1534
+
1535
+	/**
1536
+	 * More autosave handlers.
1537
+	 */
1538
+	protected function _ee_autosave_edit()
1539
+	{
1540
+	}
1541
+
1542
+
1543
+	/**
1544
+	 * @throws EE_Error
1545
+	 * @throws ReflectionException
1546
+	 */
1547
+	private function _generate_publish_box_extra_content()
1548
+	{
1549
+		// load formatter helper
1550
+		// args for getting related registrations
1551
+		$approved_query_args        = [
1552
+			[
1553
+				'REG_deleted' => 0,
1554
+				'STS_ID'      => EEM_Registration::status_id_approved,
1555
+			],
1556
+		];
1557
+		$not_approved_query_args    = [
1558
+			[
1559
+				'REG_deleted' => 0,
1560
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1561
+			],
1562
+		];
1563
+		$pending_payment_query_args = [
1564
+			[
1565
+				'REG_deleted' => 0,
1566
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1567
+			],
1568
+		];
1569
+		// publish box
1570
+		$publish_box_extra_args = [
1571
+			'view_approved_reg_url'        => add_query_arg(
1572
+				[
1573
+					'action'      => 'default',
1574
+					'event_id'    => $this->_cpt_model_obj->ID(),
1575
+					'_reg_status' => EEM_Registration::status_id_approved,
1576
+				],
1577
+				REG_ADMIN_URL
1578
+			),
1579
+			'view_not_approved_reg_url'    => add_query_arg(
1580
+				[
1581
+					'action'      => 'default',
1582
+					'event_id'    => $this->_cpt_model_obj->ID(),
1583
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1584
+				],
1585
+				REG_ADMIN_URL
1586
+			),
1587
+			'view_pending_payment_reg_url' => add_query_arg(
1588
+				[
1589
+					'action'      => 'default',
1590
+					'event_id'    => $this->_cpt_model_obj->ID(),
1591
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1592
+				],
1593
+				REG_ADMIN_URL
1594
+			),
1595
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1596
+				'Registration',
1597
+				$approved_query_args
1598
+			),
1599
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1600
+				'Registration',
1601
+				$not_approved_query_args
1602
+			),
1603
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1604
+				'Registration',
1605
+				$pending_payment_query_args
1606
+			),
1607
+			'misc_pub_section_class'       => apply_filters(
1608
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1609
+				'misc-pub-section'
1610
+			),
1611
+		];
1612
+		ob_start();
1613
+		do_action(
1614
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1615
+			$this->_cpt_model_obj
1616
+		);
1617
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1618
+		// load template
1619
+		EEH_Template::display_template(
1620
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1621
+			$publish_box_extra_args
1622
+		);
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * @return EE_Event
1628
+	 */
1629
+	public function get_event_object()
1630
+	{
1631
+		return $this->_cpt_model_obj;
1632
+	}
1633
+
1634
+
1635
+
1636
+
1637
+	/** METABOXES * */
1638
+	/**
1639
+	 * _register_event_editor_meta_boxes
1640
+	 * add all metaboxes related to the event_editor
1641
+	 *
1642
+	 * @return void
1643
+	 * @throws EE_Error
1644
+	 * @throws ReflectionException
1645
+	 */
1646
+	protected function _register_event_editor_meta_boxes()
1647
+	{
1648
+		$this->verify_cpt_object();
1649
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1650
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1651
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1652
+			add_meta_box(
1653
+				'espresso_event_editor_event_options',
1654
+				esc_html__('Event Registration Options', 'event_espresso'),
1655
+				[$this, 'registration_options_meta_box'],
1656
+				$this->page_slug,
1657
+				'side'
1658
+			);
1659
+		}
1660
+		if (! $use_advanced_editor) {
1661
+			add_meta_box(
1662
+				'espresso_event_editor_tickets',
1663
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1664
+				[$this, 'ticket_metabox'],
1665
+				$this->page_slug,
1666
+				'normal',
1667
+				'high'
1668
+			);
1669
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1670
+			add_action(
1671
+				'add_meta_boxes_espresso_events',
1672
+				function () {
1673
+					global $current_screen;
1674
+					remove_meta_box('authordiv', $current_screen, 'normal');
1675
+				},
1676
+				99
1677
+			);
1678
+		}
1679
+		// NOTE: if you're looking for other metaboxes in here,
1680
+		// where a metabox has a related management page in the admin
1681
+		// you will find it setup in the related management page's "_Hooks" file.
1682
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1683
+	}
1684
+
1685
+
1686
+	/**
1687
+	 * @throws DomainException
1688
+	 * @throws EE_Error
1689
+	 * @throws ReflectionException
1690
+	 */
1691
+	public function ticket_metabox()
1692
+	{
1693
+		$existing_datetime_ids = $existing_ticket_ids = [];
1694
+		// defaults for template args
1695
+		$template_args = [
1696
+			'existing_datetime_ids'    => '',
1697
+			'event_datetime_help_link' => '',
1698
+			'ticket_options_help_link' => '',
1699
+			'time'                     => null,
1700
+			'ticket_rows'              => '',
1701
+			'existing_ticket_ids'      => '',
1702
+			'total_ticket_rows'        => 1,
1703
+			'ticket_js_structure'      => '',
1704
+			'trash_icon'               => 'ee-lock-icon',
1705
+			'disabled'                 => '',
1706
+		];
1707
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1708
+		/**
1709
+		 * 1. Start with retrieving Datetimes
1710
+		 * 2. Fore each datetime get related tickets
1711
+		 * 3. For each ticket get related prices
1712
+		 */
1713
+		/** @var EEM_Datetime $datetime_model */
1714
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1715
+		/** @var EEM_Ticket $datetime_model */
1716
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1717
+		$times        = $datetime_model->get_all_event_dates($event_id);
1718
+		/** @type EE_Datetime $first_datetime */
1719
+		$first_datetime = reset($times);
1720
+		// do we get related tickets?
1721
+		if (
1722
+			$first_datetime instanceof EE_Datetime
1723
+			&& $first_datetime->ID() !== 0
1724
+		) {
1725
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1726
+			$template_args['time']   = $first_datetime;
1727
+			$related_tickets         = $first_datetime->tickets(
1728
+				[
1729
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1730
+					'default_where_conditions' => 'none',
1731
+				]
1732
+			);
1733
+			if (! empty($related_tickets)) {
1734
+				$template_args['total_ticket_rows'] = count($related_tickets);
1735
+				$row                                = 0;
1736
+				foreach ($related_tickets as $ticket) {
1737
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1738
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1739
+					$row++;
1740
+				}
1741
+			} else {
1742
+				$template_args['total_ticket_rows'] = 1;
1743
+				/** @type EE_Ticket $ticket */
1744
+				$ticket                       = $ticket_model->create_default_object();
1745
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1746
+			}
1747
+		} else {
1748
+			$template_args['time'] = $times[0];
1749
+			/** @type EE_Ticket[] $tickets */
1750
+			$tickets                      = $ticket_model->get_all_default_tickets();
1751
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1752
+			// NOTE: we're just sending the first default row
1753
+			// (decaf can't manage default tickets so this should be sufficient);
1754
+		}
1755
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1756
+			'event_editor_event_datetimes_help_tab'
1757
+		);
1758
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1759
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1760
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1761
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1762
+			$ticket_model->create_default_object(),
1763
+			true
1764
+		);
1765
+		$template                                  = apply_filters(
1766
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1767
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1768
+		);
1769
+		EEH_Template::display_template($template, $template_args);
1770
+	}
1771
+
1772
+
1773
+	/**
1774
+	 * Setup an individual ticket form for the decaf event editor page
1775
+	 *
1776
+	 * @access private
1777
+	 * @param EE_Ticket $ticket   the ticket object
1778
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1779
+	 * @param int       $row
1780
+	 * @return string generated html for the ticket row.
1781
+	 * @throws EE_Error
1782
+	 * @throws ReflectionException
1783
+	 */
1784
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1785
+	{
1786
+		$template_args = [
1787
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1788
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1789
+				: '',
1790
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1791
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1792
+			'TKT_name'            => $ticket->get('TKT_name'),
1793
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1794
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1795
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1796
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1797
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1798
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1799
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1800
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1801
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1802
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1803
+				: ' disabled=disabled',
1804
+		];
1805
+		$price         = $ticket->ID() !== 0
1806
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1807
+			: null;
1808
+		$price         = $price instanceof EE_Price
1809
+			? $price
1810
+			: EEM_Price::instance()->create_default_object();
1811
+		$price_args    = [
1812
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1813
+			'PRC_amount'            => $price->get('PRC_amount'),
1814
+			'PRT_ID'                => $price->get('PRT_ID'),
1815
+			'PRC_ID'                => $price->get('PRC_ID'),
1816
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1817
+		];
1818
+		// make sure we have default start and end dates if skeleton
1819
+		// handle rows that should NOT be empty
1820
+		if (empty($template_args['TKT_start_date'])) {
1821
+			// if empty then the start date will be now.
1822
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1823
+		}
1824
+		if (empty($template_args['TKT_end_date'])) {
1825
+			// get the earliest datetime (if present);
1826
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1827
+				? $this->_cpt_model_obj->get_first_related(
1828
+					'Datetime',
1829
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1830
+				)
1831
+				: null;
1832
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1833
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1834
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1835
+		}
1836
+		$template_args = array_merge($template_args, $price_args);
1837
+		$template      = apply_filters(
1838
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1839
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1840
+			$ticket
1841
+		);
1842
+		return EEH_Template::display_template($template, $template_args, true);
1843
+	}
1844
+
1845
+
1846
+	/**
1847
+	 * @throws EE_Error
1848
+	 * @throws ReflectionException
1849
+	 */
1850
+	public function registration_options_meta_box()
1851
+	{
1852
+		$yes_no_values             = [
1853
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1854
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1855
+		];
1856
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1857
+			[
1858
+				EEM_Registration::status_id_cancelled,
1859
+				EEM_Registration::status_id_declined,
1860
+				EEM_Registration::status_id_incomplete,
1861
+			],
1862
+			true
1863
+		);
1864
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1865
+		$template_args['_event']                          = $this->_cpt_model_obj;
1866
+		$template_args['event']                           = $this->_cpt_model_obj;
1867
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1868
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1869
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1870
+			'default_reg_status',
1871
+			$default_reg_status_values,
1872
+			$this->_cpt_model_obj->default_registration_status()
1873
+		);
1874
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1875
+			'display_desc',
1876
+			$yes_no_values,
1877
+			$this->_cpt_model_obj->display_description()
1878
+		);
1879
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1880
+			'display_ticket_selector',
1881
+			$yes_no_values,
1882
+			$this->_cpt_model_obj->display_ticket_selector(),
1883
+			'',
1884
+			'',
1885
+			false
1886
+		);
1887
+		$template_args['additional_registration_options'] = apply_filters(
1888
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1889
+			'',
1890
+			$template_args,
1891
+			$yes_no_values,
1892
+			$default_reg_status_values
1893
+		);
1894
+		EEH_Template::display_template(
1895
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1896
+			$template_args
1897
+		);
1898
+	}
1899
+
1900
+
1901
+	/**
1902
+	 * _get_events()
1903
+	 * This method simply returns all the events (for the given _view and paging)
1904
+	 *
1905
+	 * @access public
1906
+	 * @param int  $per_page     count of items per page (20 default);
1907
+	 * @param int  $current_page what is the current page being viewed.
1908
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1909
+	 *                           If FALSE then we return an array of event objects
1910
+	 *                           that match the given _view and paging parameters.
1911
+	 * @return array|int         an array of event objects or a count of them.
1912
+	 * @throws Exception
1913
+	 */
1914
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1915
+	{
1916
+		$EEM_Event   = $this->_event_model();
1917
+		$offset      = ($current_page - 1) * $per_page;
1918
+		$limit       = $count ? null : $offset . ',' . $per_page;
1919
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1920
+		$order       = $this->request->getRequestParam('order', 'DESC');
1921
+		$month_range = $this->request->getRequestParam('month_range');
1922
+		if ($month_range) {
1923
+			$pieces = explode(' ', $month_range, 3);
1924
+			// simulate the FIRST day of the month, that fixes issues for months like February
1925
+			// where PHP doesn't know what to assume for date.
1926
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1927
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1928
+			$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1929
+		}
1930
+		$where  = [];
1931
+		$status = $this->request->getRequestParam('status');
1932
+		// determine what post_status our condition will have for the query.
1933
+		switch ($status) {
1934
+			case 'month':
1935
+			case 'today':
1936
+			case null:
1937
+			case 'all':
1938
+				break;
1939
+			case 'draft':
1940
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1941
+				break;
1942
+			default:
1943
+				$where['status'] = $status;
1944
+		}
1945
+		// categories? The default for all categories is -1
1946
+		$category = $this->request->getRequestParam('EVT_CAT', -1, 'int');
1947
+		if ($category !== -1) {
1948
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1949
+			$where['Term_Taxonomy.term_id']  = $category;
1950
+		}
1951
+		// date where conditions
1952
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1953
+		if ($month_range) {
1954
+			$DateTime = new DateTime(
1955
+				$year_r . '-' . $month_r . '-01 00:00:00',
1956
+				new DateTimeZone('UTC')
1957
+			);
1958
+			$start    = $DateTime->getTimestamp();
1959
+			// set the datetime to be the end of the month
1960
+			$DateTime->setDate(
1961
+				$year_r,
1962
+				$month_r,
1963
+				$DateTime->format('t')
1964
+			)->setTime(23, 59, 59);
1965
+			$end                             = $DateTime->getTimestamp();
1966
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1967
+		} elseif ($status === 'today') {
1968
+			$DateTime                        =
1969
+				new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1970
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1971
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1972
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1973
+		} elseif ($status === 'month') {
1974
+			$now                             = date('Y-m-01');
1975
+			$DateTime                        =
1976
+				new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1977
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1978
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1979
+														->setTime(23, 59, 59)
1980
+														->format(implode(' ', $start_formats));
1981
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1982
+		}
1983
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1984
+			$where['EVT_wp_user'] = get_current_user_id();
1985
+		} else {
1986
+			if (! isset($where['status'])) {
1987
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1988
+					$where['OR'] = [
1989
+						'status*restrict_private' => ['!=', 'private'],
1990
+						'AND'                     => [
1991
+							'status*inclusive' => ['=', 'private'],
1992
+							'EVT_wp_user'      => get_current_user_id(),
1993
+						],
1994
+					];
1995
+				}
1996
+			}
1997
+		}
1998
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, 'int');
1999
+		if (
2000
+			$wp_user
2001
+			&& $wp_user !== get_current_user_id()
2002
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2003
+		) {
2004
+			$where['EVT_wp_user'] = $wp_user;
2005
+		}
2006
+		// search query handling
2007
+		$search_term = $this->request->getRequestParam('s');
2008
+		if ($search_term) {
2009
+			$search_term = '%' . $search_term . '%';
2010
+			$where['OR'] = [
2011
+				'EVT_name'       => ['LIKE', $search_term],
2012
+				'EVT_desc'       => ['LIKE', $search_term],
2013
+				'EVT_short_desc' => ['LIKE', $search_term],
2014
+			];
2015
+		}
2016
+		// filter events by venue.
2017
+		$venue = $this->request->getRequestParam('venue', 0, 'int');
2018
+		if ($venue) {
2019
+			$where['Venue.VNU_ID'] = $venue;
2020
+		}
2021
+		$request_params = $this->request->requestParams();
2022
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2023
+		$query_params   = apply_filters(
2024
+			'FHEE__Events_Admin_Page__get_events__query_params',
2025
+			[
2026
+				$where,
2027
+				'limit'    => $limit,
2028
+				'order_by' => $orderby,
2029
+				'order'    => $order,
2030
+				'group_by' => 'EVT_ID',
2031
+			],
2032
+			$request_params
2033
+		);
2034
+
2035
+		// let's first check if we have special requests coming in.
2036
+		$active_status = $this->request->getRequestParam('active_status');
2037
+		if ($active_status) {
2038
+			switch ($active_status) {
2039
+				case 'upcoming':
2040
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2041
+				case 'expired':
2042
+					return $EEM_Event->get_expired_events($query_params, $count);
2043
+				case 'active':
2044
+					return $EEM_Event->get_active_events($query_params, $count);
2045
+				case 'inactive':
2046
+					return $EEM_Event->get_inactive_events($query_params, $count);
2047
+			}
2048
+		}
2049
+
2050
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2051
+	}
2052
+
2053
+
2054
+	/**
2055
+	 * handling for WordPress CPT actions (trash, restore, delete)
2056
+	 *
2057
+	 * @param string $post_id
2058
+	 * @throws EE_Error
2059
+	 * @throws ReflectionException
2060
+	 */
2061
+	public function trash_cpt_item($post_id)
2062
+	{
2063
+		$this->request->setRequestParam('EVT_ID', $post_id);
2064
+		$this->_trash_or_restore_event('trash', false);
2065
+	}
2066
+
2067
+
2068
+	/**
2069
+	 * @param string $post_id
2070
+	 * @throws EE_Error
2071
+	 * @throws ReflectionException
2072
+	 */
2073
+	public function restore_cpt_item($post_id)
2074
+	{
2075
+		$this->request->setRequestParam('EVT_ID', $post_id);
2076
+		$this->_trash_or_restore_event('draft', false);
2077
+	}
2078
+
2079
+
2080
+	/**
2081
+	 * @param string $post_id
2082
+	 * @throws EE_Error
2083
+	 * @throws EE_Error
2084
+	 */
2085
+	public function delete_cpt_item($post_id)
2086
+	{
2087
+		throw new EE_Error(
2088
+			esc_html__(
2089
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2090
+				'event_espresso'
2091
+			)
2092
+		);
2093
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2094
+		// $this->_delete_event();
2095
+	}
2096
+
2097
+
2098
+	/**
2099
+	 * _trash_or_restore_event
2100
+	 *
2101
+	 * @access protected
2102
+	 * @param string $event_status
2103
+	 * @param bool   $redirect_after
2104
+	 * @throws EE_Error
2105
+	 * @throws EE_Error
2106
+	 * @throws ReflectionException
2107
+	 */
2108
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2109
+	{
2110
+		// determine the event id and set to array.
2111
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2112
+		// loop thru events
2113
+		if ($EVT_ID) {
2114
+			// clean status
2115
+			$event_status = sanitize_key($event_status);
2116
+			// grab status
2117
+			if (! empty($event_status)) {
2118
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2119
+			} else {
2120
+				$success = false;
2121
+				$msg     = esc_html__(
2122
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2123
+					'event_espresso'
2124
+				);
2125
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2126
+			}
2127
+		} else {
2128
+			$success = false;
2129
+			$msg     = esc_html__(
2130
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2131
+				'event_espresso'
2132
+			);
2133
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2134
+		}
2135
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2136
+		if ($redirect_after) {
2137
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2138
+		}
2139
+	}
2140
+
2141
+
2142
+	/**
2143
+	 * _trash_or_restore_events
2144
+	 *
2145
+	 * @access protected
2146
+	 * @param string $event_status
2147
+	 * @return void
2148
+	 * @throws EE_Error
2149
+	 * @throws EE_Error
2150
+	 * @throws ReflectionException
2151
+	 */
2152
+	protected function _trash_or_restore_events($event_status = 'trash')
2153
+	{
2154
+		// clean status
2155
+		$event_status = sanitize_key($event_status);
2156
+		// grab status
2157
+		if (! empty($event_status)) {
2158
+			$success = true;
2159
+			// determine the event id and set to array.
2160
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2161
+			// loop thru events
2162
+			foreach ($EVT_IDs as $EVT_ID) {
2163
+				if ($EVT_ID = absint($EVT_ID)) {
2164
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2165
+					$success = $results !== false ? $success : false;
2166
+				} else {
2167
+					$msg = sprintf(
2168
+						esc_html__(
2169
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2170
+							'event_espresso'
2171
+						),
2172
+						$EVT_ID
2173
+					);
2174
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2175
+					$success = false;
2176
+				}
2177
+			}
2178
+		} else {
2179
+			$success = false;
2180
+			$msg     = esc_html__(
2181
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2182
+				'event_espresso'
2183
+			);
2184
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2185
+		}
2186
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2187
+		$success = $success ? 2 : false;
2188
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2189
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2190
+	}
2191
+
2192
+
2193
+	/**
2194
+	 * @param int    $EVT_ID
2195
+	 * @param string $event_status
2196
+	 * @return bool
2197
+	 * @throws EE_Error
2198
+	 * @throws ReflectionException
2199
+	 */
2200
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2201
+	{
2202
+		// grab event id
2203
+		if (! $EVT_ID) {
2204
+			$msg = esc_html__(
2205
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2206
+				'event_espresso'
2207
+			);
2208
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2209
+			return false;
2210
+		}
2211
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2212
+		// clean status
2213
+		$event_status = sanitize_key($event_status);
2214
+		// grab status
2215
+		if (empty($event_status)) {
2216
+			$msg = esc_html__(
2217
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2218
+				'event_espresso'
2219
+			);
2220
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
+			return false;
2222
+		}
2223
+		// was event trashed or restored ?
2224
+		switch ($event_status) {
2225
+			case 'draft':
2226
+				$action = 'restored from the trash';
2227
+				$hook   = 'AHEE_event_restored_from_trash';
2228
+				break;
2229
+			case 'trash':
2230
+				$action = 'moved to the trash';
2231
+				$hook   = 'AHEE_event_moved_to_trash';
2232
+				break;
2233
+			default:
2234
+				$action = 'updated';
2235
+				$hook   = false;
2236
+		}
2237
+		// use class to change status
2238
+		$this->_cpt_model_obj->set_status($event_status);
2239
+		$success = $this->_cpt_model_obj->save();
2240
+		if (! $success) {
2241
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2242
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2243
+			return false;
2244
+		}
2245
+		if ($hook) {
2246
+			do_action($hook);
2247
+		}
2248
+		return true;
2249
+	}
2250
+
2251
+
2252
+	/**
2253
+	 * @param array $event_ids
2254
+	 * @return array
2255
+	 * @since   4.10.23.p
2256
+	 */
2257
+	private function cleanEventIds(array $event_ids)
2258
+	{
2259
+		return array_map('absint', $event_ids);
2260
+	}
2261
+
2262
+
2263
+	/**
2264
+	 * @return array
2265
+	 * @since   4.10.23.p
2266
+	 */
2267
+	private function getEventIdsFromRequest()
2268
+	{
2269
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2270
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2271
+		} else {
2272
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2273
+		}
2274
+	}
2275
+
2276
+
2277
+	/**
2278
+	 * @param bool $preview_delete
2279
+	 * @throws EE_Error
2280
+	 */
2281
+	protected function _delete_event($preview_delete = true)
2282
+	{
2283
+		$this->_delete_events($preview_delete);
2284
+	}
2285
+
2286
+
2287
+	/**
2288
+	 * Gets the tree traversal batch persister.
2289
+	 *
2290
+	 * @return NodeGroupDao
2291
+	 * @throws InvalidArgumentException
2292
+	 * @throws InvalidDataTypeException
2293
+	 * @throws InvalidInterfaceException
2294
+	 * @since 4.10.12.p
2295
+	 */
2296
+	protected function getModelObjNodeGroupPersister()
2297
+	{
2298
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2299
+			$this->model_obj_node_group_persister =
2300
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2301
+		}
2302
+		return $this->model_obj_node_group_persister;
2303
+	}
2304
+
2305
+
2306
+	/**
2307
+	 * @param bool $preview_delete
2308
+	 * @return void
2309
+	 * @throws EE_Error
2310
+	 */
2311
+	protected function _delete_events($preview_delete = true)
2312
+	{
2313
+		$event_ids = $this->getEventIdsFromRequest();
2314
+		if ($preview_delete) {
2315
+			$this->generateDeletionPreview($event_ids);
2316
+		} else {
2317
+			EEM_Event::instance()->delete_permanently([['EVT_ID' => ['IN', $event_ids]]]);
2318
+		}
2319
+	}
2320
+
2321
+
2322
+	/**
2323
+	 * @param array $event_ids
2324
+	 */
2325
+	protected function generateDeletionPreview(array $event_ids)
2326
+	{
2327
+		$event_ids = $this->cleanEventIds($event_ids);
2328
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2329
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2330
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2331
+			[
2332
+				'action'            => 'preview_deletion',
2333
+				'deletion_job_code' => $deletion_job_code,
2334
+			],
2335
+			$this->_admin_base_url
2336
+		);
2337
+		EEH_URL::safeRedirectAndExit(
2338
+			EE_Admin_Page::add_query_args_and_nonce(
2339
+				[
2340
+					'page'              => 'espresso_batch',
2341
+					'batch'             => EED_Batch::batch_job,
2342
+					'EVT_IDs'           => $event_ids,
2343
+					'deletion_job_code' => $deletion_job_code,
2344
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2345
+					'return_url'        => urlencode($return_url),
2346
+				],
2347
+				admin_url()
2348
+			)
2349
+		);
2350
+	}
2351
+
2352
+
2353
+	/**
2354
+	 * Checks for a POST submission
2355
+	 *
2356
+	 * @since 4.10.12.p
2357
+	 */
2358
+	protected function confirmDeletion()
2359
+	{
2360
+		$deletion_redirect_logic =
2361
+			$this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2362
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2363
+	}
2364
+
2365
+
2366
+	/**
2367
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2368
+	 *
2369
+	 * @throws EE_Error
2370
+	 * @since 4.10.12.p
2371
+	 */
2372
+	protected function previewDeletion()
2373
+	{
2374
+		$preview_deletion_logic =
2375
+			$this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2376
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2377
+		$this->display_admin_page_with_no_sidebar();
2378
+	}
2379
+
2380
+
2381
+	/**
2382
+	 * get total number of events
2383
+	 *
2384
+	 * @access public
2385
+	 * @return int
2386
+	 * @throws EE_Error
2387
+	 * @throws EE_Error
2388
+	 */
2389
+	public function total_events()
2390
+	{
2391
+		return EEM_Event::instance()->count(
2392
+			['caps' => 'read_admin'],
2393
+			'EVT_ID',
2394
+			true
2395
+		);
2396
+	}
2397
+
2398
+
2399
+	/**
2400
+	 * get total number of draft events
2401
+	 *
2402
+	 * @access public
2403
+	 * @return int
2404
+	 * @throws EE_Error
2405
+	 * @throws EE_Error
2406
+	 */
2407
+	public function total_events_draft()
2408
+	{
2409
+		return EEM_Event::instance()->count(
2410
+			[
2411
+				['status' => ['IN', ['draft', 'auto-draft']]],
2412
+				'caps' => 'read_admin',
2413
+			],
2414
+			'EVT_ID',
2415
+			true
2416
+		);
2417
+	}
2418
+
2419
+
2420
+	/**
2421
+	 * get total number of trashed events
2422
+	 *
2423
+	 * @access public
2424
+	 * @return int
2425
+	 * @throws EE_Error
2426
+	 * @throws EE_Error
2427
+	 */
2428
+	public function total_trashed_events()
2429
+	{
2430
+		return EEM_Event::instance()->count(
2431
+			[
2432
+				['status' => 'trash'],
2433
+				'caps' => 'read_admin',
2434
+			],
2435
+			'EVT_ID',
2436
+			true
2437
+		);
2438
+	}
2439
+
2440
+
2441
+	/**
2442
+	 *    _default_event_settings
2443
+	 *    This generates the Default Settings Tab
2444
+	 *
2445
+	 * @return void
2446
+	 * @throws DomainException
2447
+	 * @throws EE_Error
2448
+	 * @throws InvalidArgumentException
2449
+	 * @throws InvalidDataTypeException
2450
+	 * @throws InvalidInterfaceException
2451
+	 */
2452
+	protected function _default_event_settings()
2453
+	{
2454
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2455
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2456
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2457
+		$this->display_admin_page_with_sidebar();
2458
+	}
2459
+
2460
+
2461
+	/**
2462
+	 * Return the form for event settings.
2463
+	 *
2464
+	 * @return EE_Form_Section_Proper
2465
+	 * @throws EE_Error
2466
+	 */
2467
+	protected function _default_event_settings_form()
2468
+	{
2469
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2470
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2471
+		// exclude
2472
+			[
2473
+				EEM_Registration::status_id_cancelled,
2474
+				EEM_Registration::status_id_declined,
2475
+				EEM_Registration::status_id_incomplete,
2476
+				EEM_Registration::status_id_wait_list,
2477
+			],
2478
+			true
2479
+		);
2480
+		return new EE_Form_Section_Proper(
2481
+			[
2482
+				'name'            => 'update_default_event_settings',
2483
+				'html_id'         => 'update_default_event_settings',
2484
+				'html_class'      => 'form-table',
2485
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2486
+				'subsections'     => apply_filters(
2487
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2488
+					[
2489
+						'default_reg_status'  => new EE_Select_Input(
2490
+							$registration_stati_for_selection,
2491
+							[
2492
+								'default'         => isset($registration_config->default_STS_ID)
2493
+													 && array_key_exists(
2494
+														 $registration_config->default_STS_ID,
2495
+														 $registration_stati_for_selection
2496
+													 )
2497
+									? sanitize_text_field($registration_config->default_STS_ID)
2498
+									: EEM_Registration::status_id_pending_payment,
2499
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2500
+													 . EEH_Template::get_help_tab_link(
2501
+														 'default_settings_status_help_tab'
2502
+													 ),
2503
+								'html_help_text'  => esc_html__(
2504
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2505
+									'event_espresso'
2506
+								),
2507
+							]
2508
+						),
2509
+						'default_max_tickets' => new EE_Integer_Input(
2510
+							[
2511
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2512
+									? $registration_config->default_maximum_number_of_tickets
2513
+									: EEM_Event::get_default_additional_limit(),
2514
+								'html_label_text' => esc_html__(
2515
+									'Default Maximum Tickets Allowed Per Order:',
2516
+									'event_espresso'
2517
+								)
2518
+													 . EEH_Template::get_help_tab_link(
2519
+														 'default_maximum_tickets_help_tab"'
2520
+													 ),
2521
+								'html_help_text'  => esc_html__(
2522
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2523
+									'event_espresso'
2524
+								),
2525
+							]
2526
+						),
2527
+					]
2528
+				),
2529
+			]
2530
+		);
2531
+	}
2532
+
2533
+
2534
+	/**
2535
+	 * @return void
2536
+	 * @throws EE_Error
2537
+	 * @throws InvalidArgumentException
2538
+	 * @throws InvalidDataTypeException
2539
+	 * @throws InvalidInterfaceException
2540
+	 */
2541
+	protected function _update_default_event_settings()
2542
+	{
2543
+		$form = $this->_default_event_settings_form();
2544
+		if ($form->was_submitted()) {
2545
+			$form->receive_form_submission();
2546
+			if ($form->is_valid()) {
2547
+				$registration_config = EE_Registry::instance()->CFG->registration;
2548
+				$valid_data          = $form->valid_data();
2549
+				if (isset($valid_data['default_reg_status'])) {
2550
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2551
+				}
2552
+				if (isset($valid_data['default_max_tickets'])) {
2553
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2554
+				}
2555
+				do_action(
2556
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2557
+					$valid_data,
2558
+					EE_Registry::instance()->CFG,
2559
+					$this
2560
+				);
2561
+				// update because data was valid!
2562
+				EE_Registry::instance()->CFG->update_espresso_config();
2563
+				EE_Error::overwrite_success();
2564
+				EE_Error::add_success(
2565
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2566
+				);
2567
+			}
2568
+		}
2569
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2570
+	}
2571
+
2572
+
2573
+	/*************        Templates        *************
21 2574
      *
22
-     * @var EE_Event $_event
23
-     */
24
-    protected $_event;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var stdClass $_category
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This will hold the event model instance
37
-     *
38
-     * @var EEM_Event $_event_model
39
-     */
40
-    protected $_event_model;
41
-
42
-
43
-    /**
44
-     * @var EE_Event
45
-     */
46
-    protected $_cpt_model_obj = false;
47
-
48
-
49
-    /**
50
-     * @var NodeGroupDao
51
-     */
52
-    protected $model_obj_node_group_persister;
53
-
54
-
55
-    /**
56
-     * Initialize page props for this admin page group.
57
-     */
58
-    protected function _init_page_props()
59
-    {
60
-        $this->page_slug        = EVENTS_PG_SLUG;
61
-        $this->page_label       = EVENTS_LABEL;
62
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
63
-        $this->_admin_base_path = EVENTS_ADMIN;
64
-        $this->_cpt_model_names = [
65
-            'create_new' => 'EEM_Event',
66
-            'edit'       => 'EEM_Event',
67
-        ];
68
-        $this->_cpt_edit_routes = [
69
-            'espresso_events' => 'edit',
70
-        ];
71
-        add_action(
72
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
73
-            [$this, 'verify_event_edit'],
74
-            10,
75
-            2
76
-        );
77
-    }
78
-
79
-
80
-    /**
81
-     * Sets the ajax hooks used for this admin page group.
82
-     */
83
-    protected function _ajax_hooks()
84
-    {
85
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
86
-    }
87
-
88
-
89
-    /**
90
-     * Sets the page properties for this admin page group.
91
-     */
92
-    protected function _define_page_props()
93
-    {
94
-        $this->_admin_page_title = EVENTS_LABEL;
95
-        $this->_labels           = [
96
-            'buttons'      => [
97
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
98
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
99
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
100
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
101
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
102
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
103
-            ],
104
-            'editor_title' => [
105
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
106
-            ],
107
-            'publishbox'   => [
108
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
109
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
110
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
111
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
112
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
113
-            ],
114
-        ];
115
-    }
116
-
117
-
118
-    /**
119
-     * Sets the page routes property for this admin page group.
120
-     */
121
-    protected function _set_page_routes()
122
-    {
123
-        // load formatter helper
124
-        // load field generator helper
125
-        // is there a evt_id in the request?
126
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
127
-        $EVT_ID = $this->request->getRequestParam('post', $EVT_ID, 'int');
128
-
129
-        $this->_page_routes = [
130
-            'default'                       => [
131
-                'func'       => '_events_overview_list_table',
132
-                'capability' => 'ee_read_events',
133
-            ],
134
-            'create_new'                    => [
135
-                'func'       => '_create_new_cpt_item',
136
-                'capability' => 'ee_edit_events',
137
-            ],
138
-            'edit'                          => [
139
-                'func'       => '_edit_cpt_item',
140
-                'capability' => 'ee_edit_event',
141
-                'obj_id'     => $EVT_ID,
142
-            ],
143
-            'copy_event'                    => [
144
-                'func'       => '_copy_events',
145
-                'capability' => 'ee_edit_event',
146
-                'obj_id'     => $EVT_ID,
147
-                'noheader'   => true,
148
-            ],
149
-            'trash_event'                   => [
150
-                'func'       => '_trash_or_restore_event',
151
-                'args'       => ['event_status' => 'trash'],
152
-                'capability' => 'ee_delete_event',
153
-                'obj_id'     => $EVT_ID,
154
-                'noheader'   => true,
155
-            ],
156
-            'trash_events'                  => [
157
-                'func'       => '_trash_or_restore_events',
158
-                'args'       => ['event_status' => 'trash'],
159
-                'capability' => 'ee_delete_events',
160
-                'noheader'   => true,
161
-            ],
162
-            'restore_event'                 => [
163
-                'func'       => '_trash_or_restore_event',
164
-                'args'       => ['event_status' => 'draft'],
165
-                'capability' => 'ee_delete_event',
166
-                'obj_id'     => $EVT_ID,
167
-                'noheader'   => true,
168
-            ],
169
-            'restore_events'                => [
170
-                'func'       => '_trash_or_restore_events',
171
-                'args'       => ['event_status' => 'draft'],
172
-                'capability' => 'ee_delete_events',
173
-                'noheader'   => true,
174
-            ],
175
-            'delete_event'                  => [
176
-                'func'       => '_delete_event',
177
-                'capability' => 'ee_delete_event',
178
-                'obj_id'     => $EVT_ID,
179
-                'noheader'   => true,
180
-            ],
181
-            'delete_events'                 => [
182
-                'func'       => '_delete_events',
183
-                'capability' => 'ee_delete_events',
184
-                'noheader'   => true,
185
-            ],
186
-            'view_report'                   => [
187
-                'func'       => '_view_report',
188
-                'capability' => 'ee_edit_events',
189
-            ],
190
-            'default_event_settings'        => [
191
-                'func'       => '_default_event_settings',
192
-                'capability' => 'manage_options',
193
-            ],
194
-            'update_default_event_settings' => [
195
-                'func'       => '_update_default_event_settings',
196
-                'capability' => 'manage_options',
197
-                'noheader'   => true,
198
-            ],
199
-            'template_settings'             => [
200
-                'func'       => '_template_settings',
201
-                'capability' => 'manage_options',
202
-            ],
203
-            // event category tab related
204
-            'add_category'                  => [
205
-                'func'       => '_category_details',
206
-                'capability' => 'ee_edit_event_category',
207
-                'args'       => ['add'],
208
-            ],
209
-            'edit_category'                 => [
210
-                'func'       => '_category_details',
211
-                'capability' => 'ee_edit_event_category',
212
-                'args'       => ['edit'],
213
-            ],
214
-            'delete_categories'             => [
215
-                'func'       => '_delete_categories',
216
-                'capability' => 'ee_delete_event_category',
217
-                'noheader'   => true,
218
-            ],
219
-            'delete_category'               => [
220
-                'func'       => '_delete_categories',
221
-                'capability' => 'ee_delete_event_category',
222
-                'noheader'   => true,
223
-            ],
224
-            'insert_category'               => [
225
-                'func'       => '_insert_or_update_category',
226
-                'args'       => ['new_category' => true],
227
-                'capability' => 'ee_edit_event_category',
228
-                'noheader'   => true,
229
-            ],
230
-            'update_category'               => [
231
-                'func'       => '_insert_or_update_category',
232
-                'args'       => ['new_category' => false],
233
-                'capability' => 'ee_edit_event_category',
234
-                'noheader'   => true,
235
-            ],
236
-            'category_list'                 => [
237
-                'func'       => '_category_list_table',
238
-                'capability' => 'ee_manage_event_categories',
239
-            ],
240
-            'preview_deletion'              => [
241
-                'func'       => 'previewDeletion',
242
-                'capability' => 'ee_delete_events',
243
-            ],
244
-            'confirm_deletion'              => [
245
-                'func'       => 'confirmDeletion',
246
-                'capability' => 'ee_delete_events',
247
-                'noheader'   => true,
248
-            ],
249
-        ];
250
-    }
251
-
252
-
253
-    /**
254
-     * Set the _page_config property for this admin page group.
255
-     */
256
-    protected function _set_page_config()
257
-    {
258
-        $post_id            = $this->request->getRequestParam('post', 0, 'int');
259
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
260
-        $this->_page_config = [
261
-            'default'                => [
262
-                'nav'           => [
263
-                    'label' => esc_html__('Overview', 'event_espresso'),
264
-                    'order' => 10,
265
-                ],
266
-                'list_table'    => 'Events_Admin_List_Table',
267
-                'help_tabs'     => [
268
-                    'events_overview_help_tab'                       => [
269
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
270
-                        'filename' => 'events_overview',
271
-                    ],
272
-                    'events_overview_table_column_headings_help_tab' => [
273
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
274
-                        'filename' => 'events_overview_table_column_headings',
275
-                    ],
276
-                    'events_overview_filters_help_tab'               => [
277
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
278
-                        'filename' => 'events_overview_filters',
279
-                    ],
280
-                    'events_overview_view_help_tab'                  => [
281
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
282
-                        'filename' => 'events_overview_views',
283
-                    ],
284
-                    'events_overview_other_help_tab'                 => [
285
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
286
-                        'filename' => 'events_overview_other',
287
-                    ],
288
-                ],
289
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
290
-                // 'help_tour'     => [
291
-                //     'Event_Overview_Help_Tour',
292
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
293
-                // ],
294
-                'qtips'         => ['EE_Event_List_Table_Tips'],
295
-                'require_nonce' => false,
296
-            ],
297
-            'create_new'             => [
298
-                'nav'           => [
299
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
300
-                    'order'      => 5,
301
-                    'persistent' => false,
302
-                ],
303
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
304
-                'help_tabs'     => [
305
-                    'event_editor_help_tab'                            => [
306
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
307
-                        'filename' => 'event_editor',
308
-                    ],
309
-                    'event_editor_title_richtexteditor_help_tab'       => [
310
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
311
-                        'filename' => 'event_editor_title_richtexteditor',
312
-                    ],
313
-                    'event_editor_venue_details_help_tab'              => [
314
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
315
-                        'filename' => 'event_editor_venue_details',
316
-                    ],
317
-                    'event_editor_event_datetimes_help_tab'            => [
318
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
319
-                        'filename' => 'event_editor_event_datetimes',
320
-                    ],
321
-                    'event_editor_event_tickets_help_tab'              => [
322
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
323
-                        'filename' => 'event_editor_event_tickets',
324
-                    ],
325
-                    'event_editor_event_registration_options_help_tab' => [
326
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
327
-                        'filename' => 'event_editor_event_registration_options',
328
-                    ],
329
-                    'event_editor_tags_categories_help_tab'            => [
330
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
331
-                        'filename' => 'event_editor_tags_categories',
332
-                    ],
333
-                    'event_editor_questions_registrants_help_tab'      => [
334
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
335
-                        'filename' => 'event_editor_questions_registrants',
336
-                    ],
337
-                    'event_editor_save_new_event_help_tab'             => [
338
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
339
-                        'filename' => 'event_editor_save_new_event',
340
-                    ],
341
-                    'event_editor_other_help_tab'                      => [
342
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
343
-                        'filename' => 'event_editor_other',
344
-                    ],
345
-                ],
346
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
347
-                // 'help_tour'     => [
348
-                //     'Event_Editor_Help_Tour',
349
-                // ],
350
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
351
-                'require_nonce' => false,
352
-            ],
353
-            'edit'                   => [
354
-                'nav'           => [
355
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
356
-                    'order'      => 5,
357
-                    'persistent' => false,
358
-                    'url'        => $post_id
359
-                        ? EE_Admin_Page::add_query_args_and_nonce(
360
-                            ['post' => $post_id, 'action' => 'edit'],
361
-                            $this->_current_page_view_url
362
-                        )
363
-                        : $this->_admin_base_url,
364
-                ],
365
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
366
-                'help_tabs'     => [
367
-                    'event_editor_help_tab'                            => [
368
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
369
-                        'filename' => 'event_editor',
370
-                    ],
371
-                    'event_editor_title_richtexteditor_help_tab'       => [
372
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
373
-                        'filename' => 'event_editor_title_richtexteditor',
374
-                    ],
375
-                    'event_editor_venue_details_help_tab'              => [
376
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
377
-                        'filename' => 'event_editor_venue_details',
378
-                    ],
379
-                    'event_editor_event_datetimes_help_tab'            => [
380
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
381
-                        'filename' => 'event_editor_event_datetimes',
382
-                    ],
383
-                    'event_editor_event_tickets_help_tab'              => [
384
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
385
-                        'filename' => 'event_editor_event_tickets',
386
-                    ],
387
-                    'event_editor_event_registration_options_help_tab' => [
388
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
389
-                        'filename' => 'event_editor_event_registration_options',
390
-                    ],
391
-                    'event_editor_tags_categories_help_tab'            => [
392
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
393
-                        'filename' => 'event_editor_tags_categories',
394
-                    ],
395
-                    'event_editor_questions_registrants_help_tab'      => [
396
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
397
-                        'filename' => 'event_editor_questions_registrants',
398
-                    ],
399
-                    'event_editor_save_new_event_help_tab'             => [
400
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
401
-                        'filename' => 'event_editor_save_new_event',
402
-                    ],
403
-                    'event_editor_other_help_tab'                      => [
404
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
405
-                        'filename' => 'event_editor_other',
406
-                    ],
407
-                ],
408
-                'require_nonce' => false,
409
-            ],
410
-            'default_event_settings' => [
411
-                'nav'           => [
412
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
413
-                    'order' => 40,
414
-                ],
415
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
416
-                'labels'        => [
417
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
418
-                ],
419
-                'help_tabs'     => [
420
-                    'default_settings_help_tab'        => [
421
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
422
-                        'filename' => 'events_default_settings',
423
-                    ],
424
-                    'default_settings_status_help_tab' => [
425
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
426
-                        'filename' => 'events_default_settings_status',
427
-                    ],
428
-                    'default_maximum_tickets_help_tab' => [
429
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
430
-                        'filename' => 'events_default_settings_max_tickets',
431
-                    ],
432
-                ],
433
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
434
-                // 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
435
-                'require_nonce' => false,
436
-            ],
437
-            // template settings
438
-            'template_settings'      => [
439
-                'nav'           => [
440
-                    'label' => esc_html__('Templates', 'event_espresso'),
441
-                    'order' => 30,
442
-                ],
443
-                'metaboxes'     => $this->_default_espresso_metaboxes,
444
-                'help_tabs'     => [
445
-                    'general_settings_templates_help_tab' => [
446
-                        'title'    => esc_html__('Templates', 'event_espresso'),
447
-                        'filename' => 'general_settings_templates',
448
-                    ],
449
-                ],
450
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
451
-                // 'help_tour'     => ['Templates_Help_Tour'],
452
-                'require_nonce' => false,
453
-            ],
454
-            // event category stuff
455
-            'add_category'           => [
456
-                'nav'           => [
457
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
458
-                    'order'      => 15,
459
-                    'persistent' => false,
460
-                ],
461
-                'help_tabs'     => [
462
-                    'add_category_help_tab' => [
463
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
464
-                        'filename' => 'events_add_category',
465
-                    ],
466
-                ],
467
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
468
-                // 'help_tour'     => ['Event_Add_Category_Help_Tour'],
469
-                'metaboxes'     => ['_publish_post_box'],
470
-                'require_nonce' => false,
471
-            ],
472
-            'edit_category'          => [
473
-                'nav'           => [
474
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
475
-                    'order'      => 15,
476
-                    'persistent' => false,
477
-                    'url'        => $EVT_CAT_ID
478
-                        ? add_query_arg(
479
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
480
-                            $this->_current_page_view_url
481
-                        )
482
-                        : $this->_admin_base_url,
483
-                ],
484
-                'help_tabs'     => [
485
-                    'edit_category_help_tab' => [
486
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
487
-                        'filename' => 'events_edit_category',
488
-                    ],
489
-                ],
490
-                /*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
491
-                'metaboxes'     => ['_publish_post_box'],
492
-                'require_nonce' => false,
493
-            ],
494
-            'category_list'          => [
495
-                'nav'           => [
496
-                    'label' => esc_html__('Categories', 'event_espresso'),
497
-                    'order' => 20,
498
-                ],
499
-                'list_table'    => 'Event_Categories_Admin_List_Table',
500
-                'help_tabs'     => [
501
-                    'events_categories_help_tab'                       => [
502
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
503
-                        'filename' => 'events_categories',
504
-                    ],
505
-                    'events_categories_table_column_headings_help_tab' => [
506
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
507
-                        'filename' => 'events_categories_table_column_headings',
508
-                    ],
509
-                    'events_categories_view_help_tab'                  => [
510
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
511
-                        'filename' => 'events_categories_views',
512
-                    ],
513
-                    'events_categories_other_help_tab'                 => [
514
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
515
-                        'filename' => 'events_categories_other',
516
-                    ],
517
-                ],
518
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
519
-                // 'help_tour'     => [
520
-                //     'Event_Categories_Help_Tour',
521
-                // ],
522
-                'metaboxes'     => $this->_default_espresso_metaboxes,
523
-                'require_nonce' => false,
524
-            ],
525
-            'preview_deletion'       => [
526
-                'nav'           => [
527
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
528
-                    'order'      => 15,
529
-                    'persistent' => false,
530
-                    'url'        => '',
531
-                ],
532
-                'require_nonce' => false,
533
-            ],
534
-        ];
535
-    }
536
-
537
-
538
-    /**
539
-     * Used to register any global screen options if necessary for every route in this admin page group.
540
-     */
541
-    protected function _add_screen_options()
542
-    {
543
-    }
544
-
545
-
546
-    /**
547
-     * Implementing the screen options for the 'default' route.
548
-     *
549
-     * @throws InvalidArgumentException
550
-     * @throws InvalidDataTypeException
551
-     * @throws InvalidInterfaceException
552
-     */
553
-    protected function _add_screen_options_default()
554
-    {
555
-        $this->_per_page_screen_option();
556
-    }
557
-
558
-
559
-    /**
560
-     * Implementing screen options for the category list route.
561
-     *
562
-     * @throws InvalidArgumentException
563
-     * @throws InvalidDataTypeException
564
-     * @throws InvalidInterfaceException
565
-     */
566
-    protected function _add_screen_options_category_list()
567
-    {
568
-        $page_title              = $this->_admin_page_title;
569
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
570
-        $this->_per_page_screen_option();
571
-        $this->_admin_page_title = $page_title;
572
-    }
573
-
574
-
575
-    /**
576
-     * Used to register any global feature pointers for the admin page group.
577
-     */
578
-    protected function _add_feature_pointers()
579
-    {
580
-    }
581
-
582
-
583
-    /**
584
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
585
-     */
586
-    public function load_scripts_styles()
587
-    {
588
-        wp_register_style(
589
-            'events-admin-css',
590
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
591
-            [],
592
-            EVENT_ESPRESSO_VERSION
593
-        );
594
-        wp_register_style(
595
-            'ee-cat-admin',
596
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
597
-            [],
598
-            EVENT_ESPRESSO_VERSION
599
-        );
600
-        wp_enqueue_style('events-admin-css');
601
-        wp_enqueue_style('ee-cat-admin');
602
-        // scripts
603
-        wp_register_script(
604
-            'event_editor_js',
605
-            EVENTS_ASSETS_URL . 'event_editor.js',
606
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
607
-            EVENT_ESPRESSO_VERSION,
608
-            true
609
-        );
610
-    }
611
-
612
-
613
-    /**
614
-     * Enqueuing scripts and styles specific to this view
615
-     */
616
-    public function load_scripts_styles_create_new()
617
-    {
618
-        $this->load_scripts_styles_edit();
619
-    }
620
-
621
-
622
-    /**
623
-     * Enqueuing scripts and styles specific to this view
624
-     */
625
-    public function load_scripts_styles_edit()
626
-    {
627
-        // styles
628
-        wp_enqueue_style('espresso-ui-theme');
629
-        wp_register_style(
630
-            'event-editor-css',
631
-            EVENTS_ASSETS_URL . 'event-editor.css',
632
-            ['ee-admin-css'],
633
-            EVENT_ESPRESSO_VERSION
634
-        );
635
-        wp_enqueue_style('event-editor-css');
636
-        // scripts
637
-        if (! $this->admin_config->useAdvancedEditor()) {
638
-            wp_register_script(
639
-                'event-datetime-metabox',
640
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
641
-                ['event_editor_js', 'ee-datepicker'],
642
-                EVENT_ESPRESSO_VERSION
643
-            );
644
-            wp_enqueue_script('event-datetime-metabox');
645
-        }
646
-    }
647
-
648
-
649
-    /**
650
-     * Populating the _views property for the category list table view.
651
-     */
652
-    protected function _set_list_table_views_category_list()
653
-    {
654
-        $this->_views = [
655
-            'all' => [
656
-                'slug'        => 'all',
657
-                'label'       => esc_html__('All', 'event_espresso'),
658
-                'count'       => 0,
659
-                'bulk_action' => [
660
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
661
-                ],
662
-            ],
663
-        ];
664
-    }
665
-
666
-
667
-    /**
668
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
669
-     */
670
-    public function admin_init()
671
-    {
672
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
673
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
674
-            'event_espresso'
675
-        );
676
-    }
677
-
678
-
679
-    /**
680
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
681
-     * group.
682
-     */
683
-    public function admin_notices()
684
-    {
685
-    }
686
-
687
-
688
-    /**
689
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
690
-     * this admin page group.
691
-     */
692
-    public function admin_footer_scripts()
693
-    {
694
-    }
695
-
696
-
697
-    /**
698
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
699
-     * warning (via EE_Error::add_error());
700
-     *
701
-     * @param EE_Event $event Event object
702
-     * @param string   $req_type
703
-     * @return void
704
-     * @throws EE_Error
705
-     * @throws ReflectionException
706
-     */
707
-    public function verify_event_edit($event = null, $req_type = '')
708
-    {
709
-        // don't need to do this when processing
710
-        if (! empty($req_type)) {
711
-            return;
712
-        }
713
-        // no event?
714
-        if (! $event instanceof EE_Event) {
715
-            $event = $this->_cpt_model_obj;
716
-        }
717
-        // STILL no event?
718
-        if (! $event instanceof EE_Event) {
719
-            return;
720
-        }
721
-        $orig_status = $event->status();
722
-        // first check if event is active.
723
-        if (
724
-            $orig_status === EEM_Event::cancelled
725
-            || $orig_status === EEM_Event::postponed
726
-            || $event->is_expired()
727
-            || $event->is_inactive()
728
-        ) {
729
-            return;
730
-        }
731
-        // made it here so it IS active... next check that any of the tickets are sold.
732
-        if ($event->is_sold_out(true)) {
733
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
734
-                EE_Error::add_attention(
735
-                    sprintf(
736
-                        esc_html__(
737
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
738
-                            'event_espresso'
739
-                        ),
740
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
741
-                    )
742
-                );
743
-            }
744
-            return;
745
-        }
746
-        if ($orig_status === EEM_Event::sold_out) {
747
-            EE_Error::add_attention(
748
-                sprintf(
749
-                    esc_html__(
750
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
751
-                        'event_espresso'
752
-                    ),
753
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
754
-                )
755
-            );
756
-        }
757
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
-        if (! $event->tickets_on_sale()) {
759
-            return;
760
-        }
761
-        // made it here so show warning
762
-        $this->_edit_event_warning();
763
-    }
764
-
765
-
766
-    /**
767
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
768
-     * When needed, hook this into a EE_Error::add_error() notice.
769
-     *
770
-     * @access protected
771
-     * @return void
772
-     */
773
-    protected function _edit_event_warning()
774
-    {
775
-        // we don't want to add warnings during these requests
776
-        if ($this->request->getRequestParam('action') === 'editpost') {
777
-            return;
778
-        }
779
-        EE_Error::add_attention(
780
-            sprintf(
781
-                esc_html__(
782
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
783
-                    'event_espresso'
784
-                ),
785
-                '<a class="espresso-help-tab-lnk">',
786
-                '</a>'
787
-            )
788
-        );
789
-    }
790
-
791
-
792
-    /**
793
-     * When a user is creating a new event, notify them if they haven't set their timezone.
794
-     * Otherwise, do the normal logic
795
-     *
796
-     * @return void
797
-     * @throws EE_Error
798
-     * @throws InvalidArgumentException
799
-     * @throws InvalidDataTypeException
800
-     * @throws InvalidInterfaceException
801
-     */
802
-    protected function _create_new_cpt_item()
803
-    {
804
-        $has_timezone_string = get_option('timezone_string');
805
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
806
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
-            EE_Error::add_attention(
808
-                sprintf(
809
-                    esc_html__(
810
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
811
-                        'event_espresso'
812
-                    ),
813
-                    '<br>',
814
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
-                    . '</select>',
817
-                    '<button class="button button-secondary timezone-submit">',
818
-                    '</button><span class="spinner"></span>'
819
-                ),
820
-                __FILE__,
821
-                __FUNCTION__,
822
-                __LINE__
823
-            );
824
-        }
825
-        parent::_create_new_cpt_item();
826
-    }
827
-
828
-
829
-    /**
830
-     * Sets the _views property for the default route in this admin page group.
831
-     */
832
-    protected function _set_list_table_views_default()
833
-    {
834
-        $this->_views = [
835
-            'all'   => [
836
-                'slug'        => 'all',
837
-                'label'       => esc_html__('View All Events', 'event_espresso'),
838
-                'count'       => 0,
839
-                'bulk_action' => [
840
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
-                ],
842
-            ],
843
-            'draft' => [
844
-                'slug'        => 'draft',
845
-                'label'       => esc_html__('Draft', 'event_espresso'),
846
-                'count'       => 0,
847
-                'bulk_action' => [
848
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
-                ],
850
-            ],
851
-        ];
852
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
-            $this->_views['trash'] = [
854
-                'slug'        => 'trash',
855
-                'label'       => esc_html__('Trash', 'event_espresso'),
856
-                'count'       => 0,
857
-                'bulk_action' => [
858
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
-                ],
861
-            ];
862
-        }
863
-    }
864
-
865
-
866
-    /**
867
-     * Provides the legend item array for the default list table view.
868
-     *
869
-     * @return array
870
-     * @throws EE_Error
871
-     * @throws EE_Error
872
-     */
873
-    protected function _event_legend_items()
874
-    {
875
-        $items    = [
876
-            'view_details'   => [
877
-                'class' => 'dashicons dashicons-search',
878
-                'desc'  => esc_html__('View Event', 'event_espresso'),
879
-            ],
880
-            'edit_event'     => [
881
-                'class' => 'ee-icon ee-icon-calendar-edit',
882
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
-            ],
884
-            'view_attendees' => [
885
-                'class' => 'dashicons dashicons-groups',
886
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
-            ],
888
-        ];
889
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
-        $statuses = [
891
-            'sold_out_status'  => [
892
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
893
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
-            ],
895
-            'active_status'    => [
896
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
897
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
-            ],
899
-            'upcoming_status'  => [
900
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
901
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
-            ],
903
-            'postponed_status' => [
904
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
905
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
-            ],
907
-            'cancelled_status' => [
908
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
909
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
-            ],
911
-            'expired_status'   => [
912
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
913
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
-            ],
915
-            'inactive_status'  => [
916
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
917
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
-            ],
919
-        ];
920
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
-        return array_merge($items, $statuses);
922
-    }
923
-
924
-
925
-    /**
926
-     * @return EEM_Event
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @throws ReflectionException
932
-     */
933
-    private function _event_model()
934
-    {
935
-        if (! $this->_event_model instanceof EEM_Event) {
936
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
937
-        }
938
-        return $this->_event_model;
939
-    }
940
-
941
-
942
-    /**
943
-     * Adds extra buttons to the WP CPT permalink field row.
944
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
-     *
946
-     * @param string $return    the current html
947
-     * @param int    $id        the post id for the page
948
-     * @param string $new_title What the title is
949
-     * @param string $new_slug  what the slug is
950
-     * @return string            The new html string for the permalink area
951
-     */
952
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
953
-    {
954
-        // make sure this is only when editing
955
-        if (! empty($id)) {
956
-            $post   = get_post($id);
957
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
958
-                       . esc_html__('Shortcode', 'event_espresso')
959
-                       . '</a> ';
960
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
961
-                       . $post->ID
962
-                       . ']">';
963
-        }
964
-        return $return;
965
-    }
966
-
967
-
968
-    /**
969
-     * _events_overview_list_table
970
-     * This contains the logic for showing the events_overview list
971
-     *
972
-     * @access protected
973
-     * @return void
974
-     * @throws DomainException
975
-     * @throws EE_Error
976
-     * @throws InvalidArgumentException
977
-     * @throws InvalidDataTypeException
978
-     * @throws InvalidInterfaceException
979
-     */
980
-    protected function _events_overview_list_table()
981
-    {
982
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
983
-        $after_list_table                           = [];
984
-        $after_list_table['view_event_list_button'] = EEH_HTML::br();
985
-        $after_list_table['view_event_list_button'] .= EEH_Template::get_button_or_link(
986
-            get_post_type_archive_link('espresso_events'),
987
-            esc_html__('View Event Archive Page', 'event_espresso'),
988
-            'button'
989
-        );
990
-        $after_list_table['legend']                 = $this->_display_legend($this->_event_legend_items());
991
-        $this->_admin_page_title                    .= ' ' . $this->get_action_link_or_button(
992
-            'create_new',
993
-            'add',
994
-            [],
995
-            'add-new-h2'
996
-        );
997
-        $this->_template_args['after_list_table']   = array_merge(
998
-            (array) $this->_template_args['after_list_table'],
999
-            $after_list_table
1000
-        );
1001
-        $this->display_admin_list_table_page_with_no_sidebar();
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * this allows for extra misc actions in the default WP publish box
1007
-     *
1008
-     * @return void
1009
-     * @throws DomainException
1010
-     * @throws EE_Error
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     * @throws ReflectionException
1015
-     */
1016
-    public function extra_misc_actions_publish_box()
1017
-    {
1018
-        $this->_generate_publish_box_extra_content();
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1024
-     * saved.
1025
-     * Typically you would use this to save any additional data.
1026
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1027
-     * ALSO very important.  When a post transitions from scheduled to published,
1028
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1029
-     * other meta saves. So MAKE sure that you handle this accordingly.
1030
-     *
1031
-     * @access protected
1032
-     * @abstract
1033
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1034
-     * @param object $post    The post object of the cpt that was saved.
1035
-     * @return void
1036
-     * @throws EE_Error
1037
-     * @throws InvalidArgumentException
1038
-     * @throws InvalidDataTypeException
1039
-     * @throws InvalidInterfaceException
1040
-     * @throws ReflectionException
1041
-     */
1042
-    protected function _insert_update_cpt_item($post_id, $post)
1043
-    {
1044
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1045
-            // get out we're not processing an event save.
1046
-            return;
1047
-        }
1048
-        $event_values = [
1049
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, 'bool'),
1050
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, 'bool'),
1051
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1052
-        ];
1053
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1054
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1055
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1056
-                'display_ticket_selector',
1057
-                false,
1058
-                'bool'
1059
-            );
1060
-            $event_values['EVT_additional_limit']            = min(
1061
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1062
-                $this->request->getRequestParam('additional_limit', null, 'int')
1063
-            );
1064
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1065
-                'EVT_default_registration_status',
1066
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1067
-            );
1068
-
1069
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1070
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1071
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, 'bool');
1072
-        }
1073
-        // update event
1074
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1075
-        // get event_object for other metaboxes...
1076
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1077
-        // i have to setup where conditions to override the filters in the model
1078
-        // that filter out autodraft and inherit statuses so we GET the inherit id!
1079
-        $event = $this->_event_model()->get_one(
1080
-            [
1081
-                [
1082
-                    $this->_event_model()->primary_key_name() => $post_id,
1083
-                    'OR'                                      => [
1084
-                        'status'   => $post->post_status,
1085
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1086
-                        // but the returned object here has a status of "publish", so use the original post status as well
1087
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1088
-                    ],
1089
-                ],
1090
-            ]
1091
-        );
1092
-
1093
-        // the following are default callbacks for event attachment updates
1094
-        // that can be overridden by caffeinated functionality and/or addons.
1095
-        $event_update_callbacks = [];
1096
-        if (! $this->admin_config->useAdvancedEditor()) {
1097
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1098
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1099
-        }
1100
-        $event_update_callbacks = apply_filters(
1101
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1102
-            $event_update_callbacks
1103
-        );
1104
-
1105
-        $att_success = true;
1106
-        foreach ($event_update_callbacks as $e_callback) {
1107
-            $_success = is_callable($e_callback)
1108
-                ? $e_callback($event, $this->request->requestParams())
1109
-                : false;
1110
-            // if ANY of these updates fail then we want the appropriate global error message
1111
-            $att_success = $_success !== false ? $att_success : false;
1112
-        }
1113
-        // any errors?
1114
-        if ($success && $att_success === false) {
1115
-            EE_Error::add_error(
1116
-                esc_html__(
1117
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1118
-                    'event_espresso'
1119
-                ),
1120
-                __FILE__,
1121
-                __FUNCTION__,
1122
-                __LINE__
1123
-            );
1124
-        } elseif ($success === false) {
1125
-            EE_Error::add_error(
1126
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1127
-                __FILE__,
1128
-                __FUNCTION__,
1129
-                __LINE__
1130
-            );
1131
-        }
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * @param int $post_id
1137
-     * @param int $revision_id
1138
-     * @throws EE_Error
1139
-     * @throws EE_Error
1140
-     * @throws ReflectionException
1141
-     * @see parent::restore_item()
1142
-     */
1143
-    protected function _restore_cpt_item($post_id, $revision_id)
1144
-    {
1145
-        // copy existing event meta to new post
1146
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1147
-        if ($post_evt instanceof EE_Event) {
1148
-            // meta revision restore
1149
-            $post_evt->restore_revision($revision_id);
1150
-            // related objs restore
1151
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1152
-        }
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * Attach the venue to the Event
1158
-     *
1159
-     * @param EE_Event $event Event Object to add the venue to
1160
-     * @param array    $data  The request data from the form
1161
-     * @return bool           Success or fail.
1162
-     * @throws EE_Error
1163
-     * @throws ReflectionException
1164
-     */
1165
-    protected function _default_venue_update(EE_Event $event, $data)
1166
-    {
1167
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1168
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1169
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1170
-        // very important.  If we don't have a venue name...
1171
-        // then we'll get out because not necessary to create empty venue
1172
-        if (empty($data['venue_title'])) {
1173
-            return false;
1174
-        }
1175
-        $venue_array = [
1176
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1177
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1178
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1179
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1180
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1181
-                ? $data['venue_short_description']
1182
-                : null,
1183
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1184
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1185
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1186
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1187
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1188
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1189
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1190
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1191
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1192
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1193
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1194
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1195
-            'status'              => 'publish',
1196
-        ];
1197
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1198
-        if (! empty($venue_id)) {
1199
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1200
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1201
-            // we've gotta make sure that the venue is always attached to a revision..
1202
-            // add_relation_to should take care of making sure that the relation is already present.
1203
-            $event->_add_relation_to($venue_id, 'Venue');
1204
-            return $rows_affected > 0;
1205
-        }
1206
-        // we insert the venue
1207
-        $venue_id = $venue_model->insert($venue_array);
1208
-        $event->_add_relation_to($venue_id, 'Venue');
1209
-        return ! empty($venue_id);
1210
-        // when we have the ancestor come in it's already been handled by the revision save.
1211
-    }
1212
-
1213
-
1214
-    /**
1215
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1216
-     *
1217
-     * @param EE_Event $event The Event object we're attaching data to
1218
-     * @param array    $data  The request data from the form
1219
-     * @return array
1220
-     * @throws EE_Error
1221
-     * @throws ReflectionException
1222
-     * @throws Exception
1223
-     */
1224
-    protected function _default_tickets_update(EE_Event $event, $data)
1225
-    {
1226
-        if ($this->admin_config->useAdvancedEditor()) {
1227
-            return [];
1228
-        }
1229
-        $datetime       = null;
1230
-        $saved_tickets  = [];
1231
-        $event_timezone = $event->get_timezone();
1232
-        $date_formats   = ['Y-m-d', 'h:i a'];
1233
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1234
-            // trim all values to ensure any excess whitespace is removed.
1235
-            $datetime_data                = array_map('trim', $datetime_data);
1236
-            $datetime_data['DTT_EVT_end'] =
1237
-                isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1238
-                    ? $datetime_data['DTT_EVT_end']
1239
-                    : $datetime_data['DTT_EVT_start'];
1240
-            $datetime_values              = [
1241
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1242
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1243
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1244
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1245
-                'DTT_order'     => $row,
1246
-            ];
1247
-            // if we have an id then let's get existing object first and then set the new values.
1248
-            //  Otherwise we instantiate a new object for save.
1249
-            if (! empty($datetime_data['DTT_ID'])) {
1250
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1251
-                if (! $datetime instanceof EE_Datetime) {
1252
-                    throw new RuntimeException(
1253
-                        sprintf(
1254
-                            esc_html__(
1255
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1256
-                                'event_espresso'
1257
-                            ),
1258
-                            $datetime_data['DTT_ID']
1259
-                        )
1260
-                    );
1261
-                }
1262
-                $datetime->set_date_format($date_formats[0]);
1263
-                $datetime->set_time_format($date_formats[1]);
1264
-                foreach ($datetime_values as $field => $value) {
1265
-                    $datetime->set($field, $value);
1266
-                }
1267
-            } else {
1268
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1269
-            }
1270
-            if (! $datetime instanceof EE_Datetime) {
1271
-                throw new RuntimeException(
1272
-                    sprintf(
1273
-                        esc_html__(
1274
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1275
-                            'event_espresso'
1276
-                        ),
1277
-                        print_r($datetime_values, true)
1278
-                    )
1279
-                );
1280
-            }
1281
-            // before going any further make sure our dates are setup correctly
1282
-            // so that the end date is always equal or greater than the start date.
1283
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1284
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1285
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1286
-            }
1287
-            $datetime->save();
1288
-            $event->_add_relation_to($datetime, 'Datetime');
1289
-        }
1290
-        // no datetimes get deleted so we don't do any of that logic here.
1291
-        // update tickets next
1292
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1293
-
1294
-        // set up some default start and end dates in case those are not present in the incoming data
1295
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1296
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1297
-        // use the start date of the first datetime for the end date
1298
-        $first_datetime   = $event->first_datetime();
1299
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1300
-
1301
-        // now process the incoming data
1302
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1303
-            $update_prices = false;
1304
-            $ticket_price  = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1305
-                ? $data['edit_prices'][ $row ][1]['PRC_amount']
1306
-                : 0;
1307
-            // trim inputs to ensure any excess whitespace is removed.
1308
-            $ticket_data   = array_map('trim', $ticket_data);
1309
-            $ticket_values = [
1310
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1311
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1312
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1313
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1314
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1315
-                    ? $ticket_data['TKT_start_date']
1316
-                    : $default_start_date,
1317
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1318
-                    ? $ticket_data['TKT_end_date']
1319
-                    : $default_end_date,
1320
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1321
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1322
-                    ? $ticket_data['TKT_qty']
1323
-                    : EE_INF,
1324
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1325
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1326
-                    ? $ticket_data['TKT_uses']
1327
-                    : EE_INF,
1328
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1329
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1330
-                'TKT_order'       => isset($ticket_data['TKT_order']) ? $ticket_data['TKT_order'] : $row,
1331
-                'TKT_price'       => $ticket_price,
1332
-                'TKT_row'         => $row,
1333
-            ];
1334
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1335
-            // which means in turn that the prices will become new prices as well.
1336
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1337
-                $ticket_values['TKT_ID']         = 0;
1338
-                $ticket_values['TKT_is_default'] = 0;
1339
-                $update_prices                   = true;
1340
-            }
1341
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1342
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1343
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1344
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1345
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1346
-            if (! empty($ticket_data['TKT_ID'])) {
1347
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1348
-                if (! $existing_ticket instanceof EE_Ticket) {
1349
-                    throw new RuntimeException(
1350
-                        sprintf(
1351
-                            esc_html__(
1352
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1353
-                                'event_espresso'
1354
-                            ),
1355
-                            $ticket_data['TKT_ID']
1356
-                        )
1357
-                    );
1358
-                }
1359
-                $ticket_sold = $existing_ticket->count_related(
1360
-                    'Registration',
1361
-                    [
1362
-                            [
1363
-                                'STS_ID' => [
1364
-                                    'NOT IN',
1365
-                                    [EEM_Registration::status_id_incomplete],
1366
-                                ],
1367
-                            ],
1368
-                        ]
1369
-                ) > 0;
1370
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1371
-                // if they are different then we create a new ticket (if $ticket_sold)
1372
-                // if they aren't different then we go ahead and modify existing ticket.
1373
-                $create_new_ticket = $ticket_sold
1374
-                                     && $ticket_price !== $existing_ticket->price()
1375
-                                     && ! $existing_ticket->deleted();
1376
-                $existing_ticket->set_date_format($date_formats[0]);
1377
-                $existing_ticket->set_time_format($date_formats[1]);
1378
-                // set new values
1379
-                foreach ($ticket_values as $field => $value) {
1380
-                    if ($field == 'TKT_qty') {
1381
-                        $existing_ticket->set_qty($value);
1382
-                    } elseif ($field == 'TKT_price') {
1383
-                        $existing_ticket->set('TKT_price', $ticket_price);
1384
-                    } else {
1385
-                        $existing_ticket->set($field, $value);
1386
-                    }
1387
-                }
1388
-                $ticket = $existing_ticket;
1389
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1390
-                //  Otherwise we have to create a new ticket.
1391
-                if ($create_new_ticket) {
1392
-                    // archive the old ticket first
1393
-                    $existing_ticket->set('TKT_deleted', 1);
1394
-                    $existing_ticket->save();
1395
-                    // make sure this ticket is still recorded in our $saved_tickets
1396
-                    // so we don't run it through the regular trash routine.
1397
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1398
-                    // create new ticket that's a copy of the existing except,
1399
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1400
-                    $new_ticket = clone $existing_ticket;
1401
-                    $new_ticket->set('TKT_ID', 0);
1402
-                    $new_ticket->set('TKT_deleted', 0);
1403
-                    $new_ticket->set('TKT_sold', 0);
1404
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1405
-                    $update_prices = true;
1406
-                    $ticket        = $new_ticket;
1407
-                }
1408
-            } else {
1409
-                // no TKT_id so a new ticket
1410
-                $ticket_values['TKT_price'] = $ticket_price;
1411
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1412
-                $update_prices              = true;
1413
-            }
1414
-            if (! $ticket instanceof EE_Ticket) {
1415
-                throw new RuntimeException(
1416
-                    sprintf(
1417
-                        esc_html__(
1418
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1419
-                            'event_espresso'
1420
-                        ),
1421
-                        print_r($ticket_values, true)
1422
-                    )
1423
-                );
1424
-            }
1425
-            // cap ticket qty by datetime reg limits
1426
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1427
-            // update ticket.
1428
-            $ticket->save();
1429
-            // before going any further make sure our dates are setup correctly
1430
-            // so that the end date is always equal or greater than the start date.
1431
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1432
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1433
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1434
-                $ticket->save();
1435
-            }
1436
-            // initially let's add the ticket to the datetime
1437
-            $datetime->_add_relation_to($ticket, 'Ticket');
1438
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1439
-            // add prices to ticket
1440
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $ticket, $update_prices);
1441
-        }
1442
-        // however now we need to handle permanently deleting tickets via the ui.
1443
-        //  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1444
-        //  However, it does allow for deleting tickets that have no tickets sold,
1445
-        // in which case we want to get rid of permanently because there is no need to save in db.
1446
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1447
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1448
-        foreach ($tickets_removed as $id) {
1449
-            $id = absint($id);
1450
-            // get the ticket for this id
1451
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1452
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1453
-                continue;
1454
-            }
1455
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1456
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1457
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1458
-            foreach ($related_datetimes as $related_datetime) {
1459
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1460
-            }
1461
-            // need to do the same for prices (except these prices can also be deleted because again,
1462
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1463
-            $ticket_to_remove->delete_related_permanently('Price');
1464
-            // finally let's delete this ticket
1465
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1466
-            $ticket_to_remove->delete_permanently();
1467
-        }
1468
-        return [$datetime, $saved_tickets];
1469
-    }
1470
-
1471
-
1472
-    /**
1473
-     * This attaches a list of given prices to a ticket.
1474
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1475
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1476
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1477
-     *
1478
-     * @access  private
1479
-     * @param array     $prices_data Array of prices from the form.
1480
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1481
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1482
-     * @return  void
1483
-     * @throws EE_Error
1484
-     * @throws ReflectionException
1485
-     */
1486
-    private function _add_prices_to_ticket($prices_data, EE_Ticket $ticket, $new_prices = false)
1487
-    {
1488
-        $timezone = $ticket->get_timezone();
1489
-        foreach ($prices_data as $row => $price_data) {
1490
-            $price_values = [
1491
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1492
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1493
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1494
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1495
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1496
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1497
-                'PRC_order'      => $row,
1498
-            ];
1499
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1500
-                $price_values['PRC_ID'] = 0;
1501
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1502
-            } else {
1503
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1504
-                // update this price with new values
1505
-                foreach ($price_values as $field => $new_price) {
1506
-                    $price->set($field, $new_price);
1507
-                }
1508
-            }
1509
-            if (! $price instanceof EE_Price) {
1510
-                throw new RuntimeException(
1511
-                    sprintf(
1512
-                        esc_html__(
1513
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1514
-                            'event_espresso'
1515
-                        ),
1516
-                        print_r($price_values, true)
1517
-                    )
1518
-                );
1519
-            }
1520
-            $price->save();
1521
-            $ticket->_add_relation_to($price, 'Price');
1522
-        }
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * Add in our autosave ajax handlers
1528
-     *
1529
-     */
1530
-    protected function _ee_autosave_create_new()
1531
-    {
1532
-    }
1533
-
1534
-
1535
-    /**
1536
-     * More autosave handlers.
1537
-     */
1538
-    protected function _ee_autosave_edit()
1539
-    {
1540
-    }
1541
-
1542
-
1543
-    /**
1544
-     * @throws EE_Error
1545
-     * @throws ReflectionException
1546
-     */
1547
-    private function _generate_publish_box_extra_content()
1548
-    {
1549
-        // load formatter helper
1550
-        // args for getting related registrations
1551
-        $approved_query_args        = [
1552
-            [
1553
-                'REG_deleted' => 0,
1554
-                'STS_ID'      => EEM_Registration::status_id_approved,
1555
-            ],
1556
-        ];
1557
-        $not_approved_query_args    = [
1558
-            [
1559
-                'REG_deleted' => 0,
1560
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1561
-            ],
1562
-        ];
1563
-        $pending_payment_query_args = [
1564
-            [
1565
-                'REG_deleted' => 0,
1566
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1567
-            ],
1568
-        ];
1569
-        // publish box
1570
-        $publish_box_extra_args = [
1571
-            'view_approved_reg_url'        => add_query_arg(
1572
-                [
1573
-                    'action'      => 'default',
1574
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1575
-                    '_reg_status' => EEM_Registration::status_id_approved,
1576
-                ],
1577
-                REG_ADMIN_URL
1578
-            ),
1579
-            'view_not_approved_reg_url'    => add_query_arg(
1580
-                [
1581
-                    'action'      => 'default',
1582
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1583
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1584
-                ],
1585
-                REG_ADMIN_URL
1586
-            ),
1587
-            'view_pending_payment_reg_url' => add_query_arg(
1588
-                [
1589
-                    'action'      => 'default',
1590
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1591
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1592
-                ],
1593
-                REG_ADMIN_URL
1594
-            ),
1595
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1596
-                'Registration',
1597
-                $approved_query_args
1598
-            ),
1599
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1600
-                'Registration',
1601
-                $not_approved_query_args
1602
-            ),
1603
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1604
-                'Registration',
1605
-                $pending_payment_query_args
1606
-            ),
1607
-            'misc_pub_section_class'       => apply_filters(
1608
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1609
-                'misc-pub-section'
1610
-            ),
1611
-        ];
1612
-        ob_start();
1613
-        do_action(
1614
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1615
-            $this->_cpt_model_obj
1616
-        );
1617
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1618
-        // load template
1619
-        EEH_Template::display_template(
1620
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1621
-            $publish_box_extra_args
1622
-        );
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * @return EE_Event
1628
-     */
1629
-    public function get_event_object()
1630
-    {
1631
-        return $this->_cpt_model_obj;
1632
-    }
1633
-
1634
-
1635
-
1636
-
1637
-    /** METABOXES * */
1638
-    /**
1639
-     * _register_event_editor_meta_boxes
1640
-     * add all metaboxes related to the event_editor
1641
-     *
1642
-     * @return void
1643
-     * @throws EE_Error
1644
-     * @throws ReflectionException
1645
-     */
1646
-    protected function _register_event_editor_meta_boxes()
1647
-    {
1648
-        $this->verify_cpt_object();
1649
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1650
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1651
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1652
-            add_meta_box(
1653
-                'espresso_event_editor_event_options',
1654
-                esc_html__('Event Registration Options', 'event_espresso'),
1655
-                [$this, 'registration_options_meta_box'],
1656
-                $this->page_slug,
1657
-                'side'
1658
-            );
1659
-        }
1660
-        if (! $use_advanced_editor) {
1661
-            add_meta_box(
1662
-                'espresso_event_editor_tickets',
1663
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1664
-                [$this, 'ticket_metabox'],
1665
-                $this->page_slug,
1666
-                'normal',
1667
-                'high'
1668
-            );
1669
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1670
-            add_action(
1671
-                'add_meta_boxes_espresso_events',
1672
-                function () {
1673
-                    global $current_screen;
1674
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1675
-                },
1676
-                99
1677
-            );
1678
-        }
1679
-        // NOTE: if you're looking for other metaboxes in here,
1680
-        // where a metabox has a related management page in the admin
1681
-        // you will find it setup in the related management page's "_Hooks" file.
1682
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1683
-    }
1684
-
1685
-
1686
-    /**
1687
-     * @throws DomainException
1688
-     * @throws EE_Error
1689
-     * @throws ReflectionException
1690
-     */
1691
-    public function ticket_metabox()
1692
-    {
1693
-        $existing_datetime_ids = $existing_ticket_ids = [];
1694
-        // defaults for template args
1695
-        $template_args = [
1696
-            'existing_datetime_ids'    => '',
1697
-            'event_datetime_help_link' => '',
1698
-            'ticket_options_help_link' => '',
1699
-            'time'                     => null,
1700
-            'ticket_rows'              => '',
1701
-            'existing_ticket_ids'      => '',
1702
-            'total_ticket_rows'        => 1,
1703
-            'ticket_js_structure'      => '',
1704
-            'trash_icon'               => 'ee-lock-icon',
1705
-            'disabled'                 => '',
1706
-        ];
1707
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1708
-        /**
1709
-         * 1. Start with retrieving Datetimes
1710
-         * 2. Fore each datetime get related tickets
1711
-         * 3. For each ticket get related prices
1712
-         */
1713
-        /** @var EEM_Datetime $datetime_model */
1714
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1715
-        /** @var EEM_Ticket $datetime_model */
1716
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1717
-        $times        = $datetime_model->get_all_event_dates($event_id);
1718
-        /** @type EE_Datetime $first_datetime */
1719
-        $first_datetime = reset($times);
1720
-        // do we get related tickets?
1721
-        if (
1722
-            $first_datetime instanceof EE_Datetime
1723
-            && $first_datetime->ID() !== 0
1724
-        ) {
1725
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1726
-            $template_args['time']   = $first_datetime;
1727
-            $related_tickets         = $first_datetime->tickets(
1728
-                [
1729
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1730
-                    'default_where_conditions' => 'none',
1731
-                ]
1732
-            );
1733
-            if (! empty($related_tickets)) {
1734
-                $template_args['total_ticket_rows'] = count($related_tickets);
1735
-                $row                                = 0;
1736
-                foreach ($related_tickets as $ticket) {
1737
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1738
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1739
-                    $row++;
1740
-                }
1741
-            } else {
1742
-                $template_args['total_ticket_rows'] = 1;
1743
-                /** @type EE_Ticket $ticket */
1744
-                $ticket                       = $ticket_model->create_default_object();
1745
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1746
-            }
1747
-        } else {
1748
-            $template_args['time'] = $times[0];
1749
-            /** @type EE_Ticket[] $tickets */
1750
-            $tickets                      = $ticket_model->get_all_default_tickets();
1751
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1752
-            // NOTE: we're just sending the first default row
1753
-            // (decaf can't manage default tickets so this should be sufficient);
1754
-        }
1755
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1756
-            'event_editor_event_datetimes_help_tab'
1757
-        );
1758
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1759
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1760
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1761
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1762
-            $ticket_model->create_default_object(),
1763
-            true
1764
-        );
1765
-        $template                                  = apply_filters(
1766
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1767
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1768
-        );
1769
-        EEH_Template::display_template($template, $template_args);
1770
-    }
1771
-
1772
-
1773
-    /**
1774
-     * Setup an individual ticket form for the decaf event editor page
1775
-     *
1776
-     * @access private
1777
-     * @param EE_Ticket $ticket   the ticket object
1778
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1779
-     * @param int       $row
1780
-     * @return string generated html for the ticket row.
1781
-     * @throws EE_Error
1782
-     * @throws ReflectionException
1783
-     */
1784
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1785
-    {
1786
-        $template_args = [
1787
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1788
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1789
-                : '',
1790
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1791
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1792
-            'TKT_name'            => $ticket->get('TKT_name'),
1793
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1794
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1795
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1796
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1797
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1798
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1799
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1800
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1801
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1802
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1803
-                : ' disabled=disabled',
1804
-        ];
1805
-        $price         = $ticket->ID() !== 0
1806
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1807
-            : null;
1808
-        $price         = $price instanceof EE_Price
1809
-            ? $price
1810
-            : EEM_Price::instance()->create_default_object();
1811
-        $price_args    = [
1812
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1813
-            'PRC_amount'            => $price->get('PRC_amount'),
1814
-            'PRT_ID'                => $price->get('PRT_ID'),
1815
-            'PRC_ID'                => $price->get('PRC_ID'),
1816
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1817
-        ];
1818
-        // make sure we have default start and end dates if skeleton
1819
-        // handle rows that should NOT be empty
1820
-        if (empty($template_args['TKT_start_date'])) {
1821
-            // if empty then the start date will be now.
1822
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1823
-        }
1824
-        if (empty($template_args['TKT_end_date'])) {
1825
-            // get the earliest datetime (if present);
1826
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1827
-                ? $this->_cpt_model_obj->get_first_related(
1828
-                    'Datetime',
1829
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1830
-                )
1831
-                : null;
1832
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1833
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1834
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1835
-        }
1836
-        $template_args = array_merge($template_args, $price_args);
1837
-        $template      = apply_filters(
1838
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1839
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1840
-            $ticket
1841
-        );
1842
-        return EEH_Template::display_template($template, $template_args, true);
1843
-    }
1844
-
1845
-
1846
-    /**
1847
-     * @throws EE_Error
1848
-     * @throws ReflectionException
1849
-     */
1850
-    public function registration_options_meta_box()
1851
-    {
1852
-        $yes_no_values             = [
1853
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1854
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1855
-        ];
1856
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1857
-            [
1858
-                EEM_Registration::status_id_cancelled,
1859
-                EEM_Registration::status_id_declined,
1860
-                EEM_Registration::status_id_incomplete,
1861
-            ],
1862
-            true
1863
-        );
1864
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1865
-        $template_args['_event']                          = $this->_cpt_model_obj;
1866
-        $template_args['event']                           = $this->_cpt_model_obj;
1867
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1868
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1869
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1870
-            'default_reg_status',
1871
-            $default_reg_status_values,
1872
-            $this->_cpt_model_obj->default_registration_status()
1873
-        );
1874
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1875
-            'display_desc',
1876
-            $yes_no_values,
1877
-            $this->_cpt_model_obj->display_description()
1878
-        );
1879
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1880
-            'display_ticket_selector',
1881
-            $yes_no_values,
1882
-            $this->_cpt_model_obj->display_ticket_selector(),
1883
-            '',
1884
-            '',
1885
-            false
1886
-        );
1887
-        $template_args['additional_registration_options'] = apply_filters(
1888
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1889
-            '',
1890
-            $template_args,
1891
-            $yes_no_values,
1892
-            $default_reg_status_values
1893
-        );
1894
-        EEH_Template::display_template(
1895
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1896
-            $template_args
1897
-        );
1898
-    }
1899
-
1900
-
1901
-    /**
1902
-     * _get_events()
1903
-     * This method simply returns all the events (for the given _view and paging)
1904
-     *
1905
-     * @access public
1906
-     * @param int  $per_page     count of items per page (20 default);
1907
-     * @param int  $current_page what is the current page being viewed.
1908
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1909
-     *                           If FALSE then we return an array of event objects
1910
-     *                           that match the given _view and paging parameters.
1911
-     * @return array|int         an array of event objects or a count of them.
1912
-     * @throws Exception
1913
-     */
1914
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1915
-    {
1916
-        $EEM_Event   = $this->_event_model();
1917
-        $offset      = ($current_page - 1) * $per_page;
1918
-        $limit       = $count ? null : $offset . ',' . $per_page;
1919
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1920
-        $order       = $this->request->getRequestParam('order', 'DESC');
1921
-        $month_range = $this->request->getRequestParam('month_range');
1922
-        if ($month_range) {
1923
-            $pieces = explode(' ', $month_range, 3);
1924
-            // simulate the FIRST day of the month, that fixes issues for months like February
1925
-            // where PHP doesn't know what to assume for date.
1926
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1927
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1928
-            $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1929
-        }
1930
-        $where  = [];
1931
-        $status = $this->request->getRequestParam('status');
1932
-        // determine what post_status our condition will have for the query.
1933
-        switch ($status) {
1934
-            case 'month':
1935
-            case 'today':
1936
-            case null:
1937
-            case 'all':
1938
-                break;
1939
-            case 'draft':
1940
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1941
-                break;
1942
-            default:
1943
-                $where['status'] = $status;
1944
-        }
1945
-        // categories? The default for all categories is -1
1946
-        $category = $this->request->getRequestParam('EVT_CAT', -1, 'int');
1947
-        if ($category !== -1) {
1948
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1949
-            $where['Term_Taxonomy.term_id']  = $category;
1950
-        }
1951
-        // date where conditions
1952
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1953
-        if ($month_range) {
1954
-            $DateTime = new DateTime(
1955
-                $year_r . '-' . $month_r . '-01 00:00:00',
1956
-                new DateTimeZone('UTC')
1957
-            );
1958
-            $start    = $DateTime->getTimestamp();
1959
-            // set the datetime to be the end of the month
1960
-            $DateTime->setDate(
1961
-                $year_r,
1962
-                $month_r,
1963
-                $DateTime->format('t')
1964
-            )->setTime(23, 59, 59);
1965
-            $end                             = $DateTime->getTimestamp();
1966
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1967
-        } elseif ($status === 'today') {
1968
-            $DateTime                        =
1969
-                new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1970
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1971
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1972
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1973
-        } elseif ($status === 'month') {
1974
-            $now                             = date('Y-m-01');
1975
-            $DateTime                        =
1976
-                new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1977
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1978
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1979
-                                                        ->setTime(23, 59, 59)
1980
-                                                        ->format(implode(' ', $start_formats));
1981
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1982
-        }
1983
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1984
-            $where['EVT_wp_user'] = get_current_user_id();
1985
-        } else {
1986
-            if (! isset($where['status'])) {
1987
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1988
-                    $where['OR'] = [
1989
-                        'status*restrict_private' => ['!=', 'private'],
1990
-                        'AND'                     => [
1991
-                            'status*inclusive' => ['=', 'private'],
1992
-                            'EVT_wp_user'      => get_current_user_id(),
1993
-                        ],
1994
-                    ];
1995
-                }
1996
-            }
1997
-        }
1998
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, 'int');
1999
-        if (
2000
-            $wp_user
2001
-            && $wp_user !== get_current_user_id()
2002
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2003
-        ) {
2004
-            $where['EVT_wp_user'] = $wp_user;
2005
-        }
2006
-        // search query handling
2007
-        $search_term = $this->request->getRequestParam('s');
2008
-        if ($search_term) {
2009
-            $search_term = '%' . $search_term . '%';
2010
-            $where['OR'] = [
2011
-                'EVT_name'       => ['LIKE', $search_term],
2012
-                'EVT_desc'       => ['LIKE', $search_term],
2013
-                'EVT_short_desc' => ['LIKE', $search_term],
2014
-            ];
2015
-        }
2016
-        // filter events by venue.
2017
-        $venue = $this->request->getRequestParam('venue', 0, 'int');
2018
-        if ($venue) {
2019
-            $where['Venue.VNU_ID'] = $venue;
2020
-        }
2021
-        $request_params = $this->request->requestParams();
2022
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2023
-        $query_params   = apply_filters(
2024
-            'FHEE__Events_Admin_Page__get_events__query_params',
2025
-            [
2026
-                $where,
2027
-                'limit'    => $limit,
2028
-                'order_by' => $orderby,
2029
-                'order'    => $order,
2030
-                'group_by' => 'EVT_ID',
2031
-            ],
2032
-            $request_params
2033
-        );
2034
-
2035
-        // let's first check if we have special requests coming in.
2036
-        $active_status = $this->request->getRequestParam('active_status');
2037
-        if ($active_status) {
2038
-            switch ($active_status) {
2039
-                case 'upcoming':
2040
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2041
-                case 'expired':
2042
-                    return $EEM_Event->get_expired_events($query_params, $count);
2043
-                case 'active':
2044
-                    return $EEM_Event->get_active_events($query_params, $count);
2045
-                case 'inactive':
2046
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2047
-            }
2048
-        }
2049
-
2050
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2051
-    }
2052
-
2053
-
2054
-    /**
2055
-     * handling for WordPress CPT actions (trash, restore, delete)
2056
-     *
2057
-     * @param string $post_id
2058
-     * @throws EE_Error
2059
-     * @throws ReflectionException
2060
-     */
2061
-    public function trash_cpt_item($post_id)
2062
-    {
2063
-        $this->request->setRequestParam('EVT_ID', $post_id);
2064
-        $this->_trash_or_restore_event('trash', false);
2065
-    }
2066
-
2067
-
2068
-    /**
2069
-     * @param string $post_id
2070
-     * @throws EE_Error
2071
-     * @throws ReflectionException
2072
-     */
2073
-    public function restore_cpt_item($post_id)
2074
-    {
2075
-        $this->request->setRequestParam('EVT_ID', $post_id);
2076
-        $this->_trash_or_restore_event('draft', false);
2077
-    }
2078
-
2079
-
2080
-    /**
2081
-     * @param string $post_id
2082
-     * @throws EE_Error
2083
-     * @throws EE_Error
2084
-     */
2085
-    public function delete_cpt_item($post_id)
2086
-    {
2087
-        throw new EE_Error(
2088
-            esc_html__(
2089
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2090
-                'event_espresso'
2091
-            )
2092
-        );
2093
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2094
-        // $this->_delete_event();
2095
-    }
2096
-
2097
-
2098
-    /**
2099
-     * _trash_or_restore_event
2100
-     *
2101
-     * @access protected
2102
-     * @param string $event_status
2103
-     * @param bool   $redirect_after
2104
-     * @throws EE_Error
2105
-     * @throws EE_Error
2106
-     * @throws ReflectionException
2107
-     */
2108
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2109
-    {
2110
-        // determine the event id and set to array.
2111
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2112
-        // loop thru events
2113
-        if ($EVT_ID) {
2114
-            // clean status
2115
-            $event_status = sanitize_key($event_status);
2116
-            // grab status
2117
-            if (! empty($event_status)) {
2118
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2119
-            } else {
2120
-                $success = false;
2121
-                $msg     = esc_html__(
2122
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2123
-                    'event_espresso'
2124
-                );
2125
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2126
-            }
2127
-        } else {
2128
-            $success = false;
2129
-            $msg     = esc_html__(
2130
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2131
-                'event_espresso'
2132
-            );
2133
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2134
-        }
2135
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2136
-        if ($redirect_after) {
2137
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2138
-        }
2139
-    }
2140
-
2141
-
2142
-    /**
2143
-     * _trash_or_restore_events
2144
-     *
2145
-     * @access protected
2146
-     * @param string $event_status
2147
-     * @return void
2148
-     * @throws EE_Error
2149
-     * @throws EE_Error
2150
-     * @throws ReflectionException
2151
-     */
2152
-    protected function _trash_or_restore_events($event_status = 'trash')
2153
-    {
2154
-        // clean status
2155
-        $event_status = sanitize_key($event_status);
2156
-        // grab status
2157
-        if (! empty($event_status)) {
2158
-            $success = true;
2159
-            // determine the event id and set to array.
2160
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2161
-            // loop thru events
2162
-            foreach ($EVT_IDs as $EVT_ID) {
2163
-                if ($EVT_ID = absint($EVT_ID)) {
2164
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2165
-                    $success = $results !== false ? $success : false;
2166
-                } else {
2167
-                    $msg = sprintf(
2168
-                        esc_html__(
2169
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2170
-                            'event_espresso'
2171
-                        ),
2172
-                        $EVT_ID
2173
-                    );
2174
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2175
-                    $success = false;
2176
-                }
2177
-            }
2178
-        } else {
2179
-            $success = false;
2180
-            $msg     = esc_html__(
2181
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2182
-                'event_espresso'
2183
-            );
2184
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2185
-        }
2186
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2187
-        $success = $success ? 2 : false;
2188
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2189
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2190
-    }
2191
-
2192
-
2193
-    /**
2194
-     * @param int    $EVT_ID
2195
-     * @param string $event_status
2196
-     * @return bool
2197
-     * @throws EE_Error
2198
-     * @throws ReflectionException
2199
-     */
2200
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2201
-    {
2202
-        // grab event id
2203
-        if (! $EVT_ID) {
2204
-            $msg = esc_html__(
2205
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2206
-                'event_espresso'
2207
-            );
2208
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2209
-            return false;
2210
-        }
2211
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2212
-        // clean status
2213
-        $event_status = sanitize_key($event_status);
2214
-        // grab status
2215
-        if (empty($event_status)) {
2216
-            $msg = esc_html__(
2217
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2218
-                'event_espresso'
2219
-            );
2220
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
-            return false;
2222
-        }
2223
-        // was event trashed or restored ?
2224
-        switch ($event_status) {
2225
-            case 'draft':
2226
-                $action = 'restored from the trash';
2227
-                $hook   = 'AHEE_event_restored_from_trash';
2228
-                break;
2229
-            case 'trash':
2230
-                $action = 'moved to the trash';
2231
-                $hook   = 'AHEE_event_moved_to_trash';
2232
-                break;
2233
-            default:
2234
-                $action = 'updated';
2235
-                $hook   = false;
2236
-        }
2237
-        // use class to change status
2238
-        $this->_cpt_model_obj->set_status($event_status);
2239
-        $success = $this->_cpt_model_obj->save();
2240
-        if (! $success) {
2241
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2242
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2243
-            return false;
2244
-        }
2245
-        if ($hook) {
2246
-            do_action($hook);
2247
-        }
2248
-        return true;
2249
-    }
2250
-
2251
-
2252
-    /**
2253
-     * @param array $event_ids
2254
-     * @return array
2255
-     * @since   4.10.23.p
2256
-     */
2257
-    private function cleanEventIds(array $event_ids)
2258
-    {
2259
-        return array_map('absint', $event_ids);
2260
-    }
2261
-
2262
-
2263
-    /**
2264
-     * @return array
2265
-     * @since   4.10.23.p
2266
-     */
2267
-    private function getEventIdsFromRequest()
2268
-    {
2269
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2270
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2271
-        } else {
2272
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2273
-        }
2274
-    }
2275
-
2276
-
2277
-    /**
2278
-     * @param bool $preview_delete
2279
-     * @throws EE_Error
2280
-     */
2281
-    protected function _delete_event($preview_delete = true)
2282
-    {
2283
-        $this->_delete_events($preview_delete);
2284
-    }
2285
-
2286
-
2287
-    /**
2288
-     * Gets the tree traversal batch persister.
2289
-     *
2290
-     * @return NodeGroupDao
2291
-     * @throws InvalidArgumentException
2292
-     * @throws InvalidDataTypeException
2293
-     * @throws InvalidInterfaceException
2294
-     * @since 4.10.12.p
2295
-     */
2296
-    protected function getModelObjNodeGroupPersister()
2297
-    {
2298
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2299
-            $this->model_obj_node_group_persister =
2300
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2301
-        }
2302
-        return $this->model_obj_node_group_persister;
2303
-    }
2304
-
2305
-
2306
-    /**
2307
-     * @param bool $preview_delete
2308
-     * @return void
2309
-     * @throws EE_Error
2310
-     */
2311
-    protected function _delete_events($preview_delete = true)
2312
-    {
2313
-        $event_ids = $this->getEventIdsFromRequest();
2314
-        if ($preview_delete) {
2315
-            $this->generateDeletionPreview($event_ids);
2316
-        } else {
2317
-            EEM_Event::instance()->delete_permanently([['EVT_ID' => ['IN', $event_ids]]]);
2318
-        }
2319
-    }
2320
-
2321
-
2322
-    /**
2323
-     * @param array $event_ids
2324
-     */
2325
-    protected function generateDeletionPreview(array $event_ids)
2326
-    {
2327
-        $event_ids = $this->cleanEventIds($event_ids);
2328
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2329
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2330
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2331
-            [
2332
-                'action'            => 'preview_deletion',
2333
-                'deletion_job_code' => $deletion_job_code,
2334
-            ],
2335
-            $this->_admin_base_url
2336
-        );
2337
-        EEH_URL::safeRedirectAndExit(
2338
-            EE_Admin_Page::add_query_args_and_nonce(
2339
-                [
2340
-                    'page'              => 'espresso_batch',
2341
-                    'batch'             => EED_Batch::batch_job,
2342
-                    'EVT_IDs'           => $event_ids,
2343
-                    'deletion_job_code' => $deletion_job_code,
2344
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2345
-                    'return_url'        => urlencode($return_url),
2346
-                ],
2347
-                admin_url()
2348
-            )
2349
-        );
2350
-    }
2351
-
2352
-
2353
-    /**
2354
-     * Checks for a POST submission
2355
-     *
2356
-     * @since 4.10.12.p
2357
-     */
2358
-    protected function confirmDeletion()
2359
-    {
2360
-        $deletion_redirect_logic =
2361
-            $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2362
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2363
-    }
2364
-
2365
-
2366
-    /**
2367
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2368
-     *
2369
-     * @throws EE_Error
2370
-     * @since 4.10.12.p
2371
-     */
2372
-    protected function previewDeletion()
2373
-    {
2374
-        $preview_deletion_logic =
2375
-            $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2376
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2377
-        $this->display_admin_page_with_no_sidebar();
2378
-    }
2379
-
2380
-
2381
-    /**
2382
-     * get total number of events
2383
-     *
2384
-     * @access public
2385
-     * @return int
2386
-     * @throws EE_Error
2387
-     * @throws EE_Error
2388
-     */
2389
-    public function total_events()
2390
-    {
2391
-        return EEM_Event::instance()->count(
2392
-            ['caps' => 'read_admin'],
2393
-            'EVT_ID',
2394
-            true
2395
-        );
2396
-    }
2397
-
2398
-
2399
-    /**
2400
-     * get total number of draft events
2401
-     *
2402
-     * @access public
2403
-     * @return int
2404
-     * @throws EE_Error
2405
-     * @throws EE_Error
2406
-     */
2407
-    public function total_events_draft()
2408
-    {
2409
-        return EEM_Event::instance()->count(
2410
-            [
2411
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2412
-                'caps' => 'read_admin',
2413
-            ],
2414
-            'EVT_ID',
2415
-            true
2416
-        );
2417
-    }
2418
-
2419
-
2420
-    /**
2421
-     * get total number of trashed events
2422
-     *
2423
-     * @access public
2424
-     * @return int
2425
-     * @throws EE_Error
2426
-     * @throws EE_Error
2427
-     */
2428
-    public function total_trashed_events()
2429
-    {
2430
-        return EEM_Event::instance()->count(
2431
-            [
2432
-                ['status' => 'trash'],
2433
-                'caps' => 'read_admin',
2434
-            ],
2435
-            'EVT_ID',
2436
-            true
2437
-        );
2438
-    }
2439
-
2440
-
2441
-    /**
2442
-     *    _default_event_settings
2443
-     *    This generates the Default Settings Tab
2444
-     *
2445
-     * @return void
2446
-     * @throws DomainException
2447
-     * @throws EE_Error
2448
-     * @throws InvalidArgumentException
2449
-     * @throws InvalidDataTypeException
2450
-     * @throws InvalidInterfaceException
2451
-     */
2452
-    protected function _default_event_settings()
2453
-    {
2454
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2455
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2456
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2457
-        $this->display_admin_page_with_sidebar();
2458
-    }
2459
-
2460
-
2461
-    /**
2462
-     * Return the form for event settings.
2463
-     *
2464
-     * @return EE_Form_Section_Proper
2465
-     * @throws EE_Error
2466
-     */
2467
-    protected function _default_event_settings_form()
2468
-    {
2469
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2470
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2471
-        // exclude
2472
-            [
2473
-                EEM_Registration::status_id_cancelled,
2474
-                EEM_Registration::status_id_declined,
2475
-                EEM_Registration::status_id_incomplete,
2476
-                EEM_Registration::status_id_wait_list,
2477
-            ],
2478
-            true
2479
-        );
2480
-        return new EE_Form_Section_Proper(
2481
-            [
2482
-                'name'            => 'update_default_event_settings',
2483
-                'html_id'         => 'update_default_event_settings',
2484
-                'html_class'      => 'form-table',
2485
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2486
-                'subsections'     => apply_filters(
2487
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2488
-                    [
2489
-                        'default_reg_status'  => new EE_Select_Input(
2490
-                            $registration_stati_for_selection,
2491
-                            [
2492
-                                'default'         => isset($registration_config->default_STS_ID)
2493
-                                                     && array_key_exists(
2494
-                                                         $registration_config->default_STS_ID,
2495
-                                                         $registration_stati_for_selection
2496
-                                                     )
2497
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2498
-                                    : EEM_Registration::status_id_pending_payment,
2499
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2500
-                                                     . EEH_Template::get_help_tab_link(
2501
-                                                         'default_settings_status_help_tab'
2502
-                                                     ),
2503
-                                'html_help_text'  => esc_html__(
2504
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2505
-                                    'event_espresso'
2506
-                                ),
2507
-                            ]
2508
-                        ),
2509
-                        'default_max_tickets' => new EE_Integer_Input(
2510
-                            [
2511
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2512
-                                    ? $registration_config->default_maximum_number_of_tickets
2513
-                                    : EEM_Event::get_default_additional_limit(),
2514
-                                'html_label_text' => esc_html__(
2515
-                                    'Default Maximum Tickets Allowed Per Order:',
2516
-                                    'event_espresso'
2517
-                                )
2518
-                                                     . EEH_Template::get_help_tab_link(
2519
-                                                         'default_maximum_tickets_help_tab"'
2520
-                                                     ),
2521
-                                'html_help_text'  => esc_html__(
2522
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2523
-                                    'event_espresso'
2524
-                                ),
2525
-                            ]
2526
-                        ),
2527
-                    ]
2528
-                ),
2529
-            ]
2530
-        );
2531
-    }
2532
-
2533
-
2534
-    /**
2535
-     * @return void
2536
-     * @throws EE_Error
2537
-     * @throws InvalidArgumentException
2538
-     * @throws InvalidDataTypeException
2539
-     * @throws InvalidInterfaceException
2540
-     */
2541
-    protected function _update_default_event_settings()
2542
-    {
2543
-        $form = $this->_default_event_settings_form();
2544
-        if ($form->was_submitted()) {
2545
-            $form->receive_form_submission();
2546
-            if ($form->is_valid()) {
2547
-                $registration_config = EE_Registry::instance()->CFG->registration;
2548
-                $valid_data          = $form->valid_data();
2549
-                if (isset($valid_data['default_reg_status'])) {
2550
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2551
-                }
2552
-                if (isset($valid_data['default_max_tickets'])) {
2553
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2554
-                }
2555
-                do_action(
2556
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2557
-                    $valid_data,
2558
-                    EE_Registry::instance()->CFG,
2559
-                    $this
2560
-                );
2561
-                // update because data was valid!
2562
-                EE_Registry::instance()->CFG->update_espresso_config();
2563
-                EE_Error::overwrite_success();
2564
-                EE_Error::add_success(
2565
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2566
-                );
2567
-            }
2568
-        }
2569
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2570
-    }
2571
-
2572
-
2573
-    /*************        Templates        *************
2574
-     *
2575
-     * @throws EE_Error
2576
-     */
2577
-    protected function _template_settings()
2578
-    {
2579
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2580
-        $this->_template_args['preview_img']  = '<img src="'
2581
-                                                . EVENTS_ASSETS_URL
2582
-                                                . '/images/'
2583
-                                                . 'caffeinated_template_features.jpg" alt="'
2584
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2585
-                                                . '" />';
2586
-        $this->_template_args['preview_text'] = '<strong>'
2587
-                                                . esc_html__(
2588
-                                                    'Template Settings 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. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2589
-                                                    'event_espresso'
2590
-                                                ) . '</strong>';
2591
-        $this->display_admin_caf_preview_page('template_settings_tab');
2592
-    }
2593
-
2594
-
2595
-    /** Event Category Stuff **/
2596
-    /**
2597
-     * set the _category property with the category object for the loaded page.
2598
-     *
2599
-     * @access private
2600
-     * @return void
2601
-     */
2602
-    private function _set_category_object()
2603
-    {
2604
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2605
-            return;
2606
-        } //already have the category object so get out.
2607
-        // set default category object
2608
-        $this->_set_empty_category_object();
2609
-        // only set if we've got an id
2610
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
2611
-        if (! $category_ID) {
2612
-            return;
2613
-        }
2614
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2615
-        if (! empty($term)) {
2616
-            $this->_category->category_name       = $term->name;
2617
-            $this->_category->category_identifier = $term->slug;
2618
-            $this->_category->category_desc       = $term->description;
2619
-            $this->_category->id                  = $term->term_id;
2620
-            $this->_category->parent              = $term->parent;
2621
-        }
2622
-    }
2623
-
2624
-
2625
-    /**
2626
-     * Clears out category properties.
2627
-     */
2628
-    private function _set_empty_category_object()
2629
-    {
2630
-        $this->_category                = new stdClass();
2631
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2632
-        $this->_category->id            = $this->_category->parent = 0;
2633
-    }
2634
-
2635
-
2636
-    /**
2637
-     * @throws DomainException
2638
-     * @throws EE_Error
2639
-     * @throws InvalidArgumentException
2640
-     * @throws InvalidDataTypeException
2641
-     * @throws InvalidInterfaceException
2642
-     */
2643
-    protected function _category_list_table()
2644
-    {
2645
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2646
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2647
-        $this->_admin_page_title .= ' ';
2648
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2649
-            'add_category',
2650
-            'add_category',
2651
-            [],
2652
-            'add-new-h2'
2653
-        );
2654
-        $this->display_admin_list_table_page_with_sidebar();
2655
-    }
2656
-
2657
-
2658
-    /**
2659
-     * Output category details view.
2660
-     *
2661
-     * @throws EE_Error
2662
-     * @throws EE_Error
2663
-     */
2664
-    protected function _category_details($view)
2665
-    {
2666
-        // load formatter helper
2667
-        // load field generator helper
2668
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2669
-        $this->_set_add_edit_form_tags($route);
2670
-        $this->_set_category_object();
2671
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2672
-        $delete_action = 'delete_category';
2673
-        // custom redirect
2674
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2675
-            ['action' => 'category_list'],
2676
-            $this->_admin_base_url
2677
-        );
2678
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2679
-        // take care of contents
2680
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2681
-        $this->display_admin_page_with_sidebar();
2682
-    }
2683
-
2684
-
2685
-    /**
2686
-     * Output category details content.
2687
-     *
2688
-     * @throws DomainException
2689
-     */
2690
-    protected function _category_details_content()
2691
-    {
2692
-        $editor_args['category_desc'] = [
2693
-            'type'          => 'wp_editor',
2694
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2695
-            'class'         => 'my_editor_custom',
2696
-            'wpeditor_args' => ['media_buttons' => false],
2697
-        ];
2698
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2699
-        $all_terms                    = get_terms(
2700
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2701
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2702
-        );
2703
-        // setup category select for term parents.
2704
-        $category_select_values[] = [
2705
-            'text' => esc_html__('No Parent', 'event_espresso'),
2706
-            'id'   => 0,
2707
-        ];
2708
-        foreach ($all_terms as $term) {
2709
-            $category_select_values[] = [
2710
-                'text' => $term->name,
2711
-                'id'   => $term->term_id,
2712
-            ];
2713
-        }
2714
-        $category_select = EEH_Form_Fields::select_input(
2715
-            'category_parent',
2716
-            $category_select_values,
2717
-            $this->_category->parent
2718
-        );
2719
-        $template_args   = [
2720
-            'category'                 => $this->_category,
2721
-            'category_select'          => $category_select,
2722
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2723
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2724
-            'disable'                  => '',
2725
-            'disabled_message'         => false,
2726
-        ];
2727
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2728
-        return EEH_Template::display_template($template, $template_args, true);
2729
-    }
2730
-
2731
-
2732
-    /**
2733
-     * Handles deleting categories.
2734
-     *
2735
-     * @throws EE_Error
2736
-     */
2737
-    protected function _delete_categories()
2738
-    {
2739
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2740
-        foreach ($category_IDs as $category_ID) {
2741
-            $this->_delete_category($category_ID);
2742
-        }
2743
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2744
-        $query_args = [
2745
-            'action' => 'category_list',
2746
-        ];
2747
-        $this->_redirect_after_action(0, '', '', $query_args);
2748
-    }
2749
-
2750
-
2751
-    /**
2752
-     * Handles deleting specific category.
2753
-     *
2754
-     * @param int $cat_id
2755
-     */
2756
-    protected function _delete_category($cat_id)
2757
-    {
2758
-        $cat_id = absint($cat_id);
2759
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2760
-    }
2761
-
2762
-
2763
-    /**
2764
-     * Handles triggering the update or insertion of a new category.
2765
-     *
2766
-     * @param bool $new_category true means we're triggering the insert of a new category.
2767
-     * @throws EE_Error
2768
-     * @throws EE_Error
2769
-     */
2770
-    protected function _insert_or_update_category($new_category)
2771
-    {
2772
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2773
-        $success = 0; // we already have a success message so lets not send another.
2774
-        if ($cat_id) {
2775
-            $query_args = [
2776
-                'action'     => 'edit_category',
2777
-                'EVT_CAT_ID' => $cat_id,
2778
-            ];
2779
-        } else {
2780
-            $query_args = ['action' => 'add_category'];
2781
-        }
2782
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2783
-    }
2784
-
2785
-
2786
-    /**
2787
-     * Inserts or updates category
2788
-     *
2789
-     * @param bool $update (true indicates we're updating a category).
2790
-     * @return bool|mixed|string
2791
-     */
2792
-    private function _insert_category($update = false)
2793
-    {
2794
-        $category_ID         = $update ? $this->request->getRequestParam('EVT_CAT_ID', 0, 'int') : 0;
2795
-        $category_name       = $this->request->getRequestParam('category_name', '');
2796
-        $category_desc       = $this->request->getRequestParam('category_desc', '');
2797
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, 'int');
2798
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2799
-
2800
-        if (empty($category_name)) {
2801
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2802
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2803
-            return false;
2804
-        }
2805
-        $term_args = [
2806
-            'name'        => $category_name,
2807
-            'description' => $category_desc,
2808
-            'parent'      => $category_parent,
2809
-        ];
2810
-        // was the category_identifier input disabled?
2811
-        if ($category_identifier) {
2812
-            $term_args['slug'] = $category_identifier;
2813
-        }
2814
-        $insert_ids = $update
2815
-            ? wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2816
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2817
-        if (! is_array($insert_ids)) {
2818
-            $msg = esc_html__(
2819
-                'An error occurred and the category has not been saved to the database.',
2820
-                'event_espresso'
2821
-            );
2822
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2823
-        } else {
2824
-            $category_ID = $insert_ids['term_id'];
2825
-            $msg         = sprintf(
2826
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2827
-                $category_name
2828
-            );
2829
-            EE_Error::add_success($msg);
2830
-        }
2831
-        return $category_ID;
2832
-    }
2833
-
2834
-
2835
-    /**
2836
-     * Gets categories or count of categories matching the arguments in the request.
2837
-     *
2838
-     * @param int  $per_page
2839
-     * @param int  $current_page
2840
-     * @param bool $count
2841
-     * @return EE_Term_Taxonomy[]|int
2842
-     * @throws EE_Error
2843
-     */
2844
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2845
-    {
2846
-        // testing term stuff
2847
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2848
-        $order       = $this->request->getRequestParam('order', 'DESC');
2849
-        $limit       = ($current_page - 1) * $per_page;
2850
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2851
-        $search_term = $this->request->getRequestParam('s');
2852
-        if ($search_term) {
2853
-            $search_term = '%' . $search_term . '%';
2854
-            $where['OR'] = [
2855
-                'Term.name'   => ['LIKE', $search_term],
2856
-                'description' => ['LIKE', $search_term],
2857
-            ];
2858
-        }
2859
-        $query_params = [
2860
-            $where,
2861
-            'order_by'   => [$orderby => $order],
2862
-            'limit'      => $limit . ',' . $per_page,
2863
-            'force_join' => ['Term'],
2864
-        ];
2865
-        return $count
2866
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2867
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2868
-    }
2869
-
2870
-    /* end category stuff */
2871
-
2872
-
2873
-    /**************/
2874
-
2875
-
2876
-    /**
2877
-     * Callback for the `ee_save_timezone_setting` ajax action.
2878
-     *
2879
-     * @throws EE_Error
2880
-     * @throws InvalidArgumentException
2881
-     * @throws InvalidDataTypeException
2882
-     * @throws InvalidInterfaceException
2883
-     */
2884
-    public function saveTimezoneString()
2885
-    {
2886
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2887
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2888
-            EE_Error::add_error(
2889
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2890
-                __FILE__,
2891
-                __FUNCTION__,
2892
-                __LINE__
2893
-            );
2894
-            $this->_template_args['error'] = true;
2895
-            $this->_return_json();
2896
-        }
2897
-
2898
-        update_option('timezone_string', $timezone_string);
2899
-        EE_Error::add_success(
2900
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2901
-        );
2902
-        $this->_template_args['success'] = true;
2903
-        $this->_return_json(true, ['action' => 'create_new']);
2904
-    }
2905
-
2906
-
2907
-    /**
2908 2575
      * @throws EE_Error
2909
-     * @deprecated 4.10.25.p
2910 2576
      */
2911
-    public function save_timezonestring_setting()
2912
-    {
2913
-        $this->saveTimezoneString();
2914
-    }
2577
+	protected function _template_settings()
2578
+	{
2579
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2580
+		$this->_template_args['preview_img']  = '<img src="'
2581
+												. EVENTS_ASSETS_URL
2582
+												. '/images/'
2583
+												. 'caffeinated_template_features.jpg" alt="'
2584
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2585
+												. '" />';
2586
+		$this->_template_args['preview_text'] = '<strong>'
2587
+												. esc_html__(
2588
+													'Template Settings 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. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2589
+													'event_espresso'
2590
+												) . '</strong>';
2591
+		$this->display_admin_caf_preview_page('template_settings_tab');
2592
+	}
2593
+
2594
+
2595
+	/** Event Category Stuff **/
2596
+	/**
2597
+	 * set the _category property with the category object for the loaded page.
2598
+	 *
2599
+	 * @access private
2600
+	 * @return void
2601
+	 */
2602
+	private function _set_category_object()
2603
+	{
2604
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2605
+			return;
2606
+		} //already have the category object so get out.
2607
+		// set default category object
2608
+		$this->_set_empty_category_object();
2609
+		// only set if we've got an id
2610
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
2611
+		if (! $category_ID) {
2612
+			return;
2613
+		}
2614
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2615
+		if (! empty($term)) {
2616
+			$this->_category->category_name       = $term->name;
2617
+			$this->_category->category_identifier = $term->slug;
2618
+			$this->_category->category_desc       = $term->description;
2619
+			$this->_category->id                  = $term->term_id;
2620
+			$this->_category->parent              = $term->parent;
2621
+		}
2622
+	}
2623
+
2624
+
2625
+	/**
2626
+	 * Clears out category properties.
2627
+	 */
2628
+	private function _set_empty_category_object()
2629
+	{
2630
+		$this->_category                = new stdClass();
2631
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2632
+		$this->_category->id            = $this->_category->parent = 0;
2633
+	}
2634
+
2635
+
2636
+	/**
2637
+	 * @throws DomainException
2638
+	 * @throws EE_Error
2639
+	 * @throws InvalidArgumentException
2640
+	 * @throws InvalidDataTypeException
2641
+	 * @throws InvalidInterfaceException
2642
+	 */
2643
+	protected function _category_list_table()
2644
+	{
2645
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2646
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2647
+		$this->_admin_page_title .= ' ';
2648
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2649
+			'add_category',
2650
+			'add_category',
2651
+			[],
2652
+			'add-new-h2'
2653
+		);
2654
+		$this->display_admin_list_table_page_with_sidebar();
2655
+	}
2656
+
2657
+
2658
+	/**
2659
+	 * Output category details view.
2660
+	 *
2661
+	 * @throws EE_Error
2662
+	 * @throws EE_Error
2663
+	 */
2664
+	protected function _category_details($view)
2665
+	{
2666
+		// load formatter helper
2667
+		// load field generator helper
2668
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2669
+		$this->_set_add_edit_form_tags($route);
2670
+		$this->_set_category_object();
2671
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2672
+		$delete_action = 'delete_category';
2673
+		// custom redirect
2674
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2675
+			['action' => 'category_list'],
2676
+			$this->_admin_base_url
2677
+		);
2678
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2679
+		// take care of contents
2680
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2681
+		$this->display_admin_page_with_sidebar();
2682
+	}
2683
+
2684
+
2685
+	/**
2686
+	 * Output category details content.
2687
+	 *
2688
+	 * @throws DomainException
2689
+	 */
2690
+	protected function _category_details_content()
2691
+	{
2692
+		$editor_args['category_desc'] = [
2693
+			'type'          => 'wp_editor',
2694
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2695
+			'class'         => 'my_editor_custom',
2696
+			'wpeditor_args' => ['media_buttons' => false],
2697
+		];
2698
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2699
+		$all_terms                    = get_terms(
2700
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2701
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2702
+		);
2703
+		// setup category select for term parents.
2704
+		$category_select_values[] = [
2705
+			'text' => esc_html__('No Parent', 'event_espresso'),
2706
+			'id'   => 0,
2707
+		];
2708
+		foreach ($all_terms as $term) {
2709
+			$category_select_values[] = [
2710
+				'text' => $term->name,
2711
+				'id'   => $term->term_id,
2712
+			];
2713
+		}
2714
+		$category_select = EEH_Form_Fields::select_input(
2715
+			'category_parent',
2716
+			$category_select_values,
2717
+			$this->_category->parent
2718
+		);
2719
+		$template_args   = [
2720
+			'category'                 => $this->_category,
2721
+			'category_select'          => $category_select,
2722
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2723
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2724
+			'disable'                  => '',
2725
+			'disabled_message'         => false,
2726
+		];
2727
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2728
+		return EEH_Template::display_template($template, $template_args, true);
2729
+	}
2730
+
2731
+
2732
+	/**
2733
+	 * Handles deleting categories.
2734
+	 *
2735
+	 * @throws EE_Error
2736
+	 */
2737
+	protected function _delete_categories()
2738
+	{
2739
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2740
+		foreach ($category_IDs as $category_ID) {
2741
+			$this->_delete_category($category_ID);
2742
+		}
2743
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2744
+		$query_args = [
2745
+			'action' => 'category_list',
2746
+		];
2747
+		$this->_redirect_after_action(0, '', '', $query_args);
2748
+	}
2749
+
2750
+
2751
+	/**
2752
+	 * Handles deleting specific category.
2753
+	 *
2754
+	 * @param int $cat_id
2755
+	 */
2756
+	protected function _delete_category($cat_id)
2757
+	{
2758
+		$cat_id = absint($cat_id);
2759
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2760
+	}
2761
+
2762
+
2763
+	/**
2764
+	 * Handles triggering the update or insertion of a new category.
2765
+	 *
2766
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2767
+	 * @throws EE_Error
2768
+	 * @throws EE_Error
2769
+	 */
2770
+	protected function _insert_or_update_category($new_category)
2771
+	{
2772
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2773
+		$success = 0; // we already have a success message so lets not send another.
2774
+		if ($cat_id) {
2775
+			$query_args = [
2776
+				'action'     => 'edit_category',
2777
+				'EVT_CAT_ID' => $cat_id,
2778
+			];
2779
+		} else {
2780
+			$query_args = ['action' => 'add_category'];
2781
+		}
2782
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2783
+	}
2784
+
2785
+
2786
+	/**
2787
+	 * Inserts or updates category
2788
+	 *
2789
+	 * @param bool $update (true indicates we're updating a category).
2790
+	 * @return bool|mixed|string
2791
+	 */
2792
+	private function _insert_category($update = false)
2793
+	{
2794
+		$category_ID         = $update ? $this->request->getRequestParam('EVT_CAT_ID', 0, 'int') : 0;
2795
+		$category_name       = $this->request->getRequestParam('category_name', '');
2796
+		$category_desc       = $this->request->getRequestParam('category_desc', '');
2797
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, 'int');
2798
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2799
+
2800
+		if (empty($category_name)) {
2801
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2802
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2803
+			return false;
2804
+		}
2805
+		$term_args = [
2806
+			'name'        => $category_name,
2807
+			'description' => $category_desc,
2808
+			'parent'      => $category_parent,
2809
+		];
2810
+		// was the category_identifier input disabled?
2811
+		if ($category_identifier) {
2812
+			$term_args['slug'] = $category_identifier;
2813
+		}
2814
+		$insert_ids = $update
2815
+			? wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2816
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2817
+		if (! is_array($insert_ids)) {
2818
+			$msg = esc_html__(
2819
+				'An error occurred and the category has not been saved to the database.',
2820
+				'event_espresso'
2821
+			);
2822
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2823
+		} else {
2824
+			$category_ID = $insert_ids['term_id'];
2825
+			$msg         = sprintf(
2826
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2827
+				$category_name
2828
+			);
2829
+			EE_Error::add_success($msg);
2830
+		}
2831
+		return $category_ID;
2832
+	}
2833
+
2834
+
2835
+	/**
2836
+	 * Gets categories or count of categories matching the arguments in the request.
2837
+	 *
2838
+	 * @param int  $per_page
2839
+	 * @param int  $current_page
2840
+	 * @param bool $count
2841
+	 * @return EE_Term_Taxonomy[]|int
2842
+	 * @throws EE_Error
2843
+	 */
2844
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2845
+	{
2846
+		// testing term stuff
2847
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2848
+		$order       = $this->request->getRequestParam('order', 'DESC');
2849
+		$limit       = ($current_page - 1) * $per_page;
2850
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2851
+		$search_term = $this->request->getRequestParam('s');
2852
+		if ($search_term) {
2853
+			$search_term = '%' . $search_term . '%';
2854
+			$where['OR'] = [
2855
+				'Term.name'   => ['LIKE', $search_term],
2856
+				'description' => ['LIKE', $search_term],
2857
+			];
2858
+		}
2859
+		$query_params = [
2860
+			$where,
2861
+			'order_by'   => [$orderby => $order],
2862
+			'limit'      => $limit . ',' . $per_page,
2863
+			'force_join' => ['Term'],
2864
+		];
2865
+		return $count
2866
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2867
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2868
+	}
2869
+
2870
+	/* end category stuff */
2871
+
2872
+
2873
+	/**************/
2874
+
2875
+
2876
+	/**
2877
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2878
+	 *
2879
+	 * @throws EE_Error
2880
+	 * @throws InvalidArgumentException
2881
+	 * @throws InvalidDataTypeException
2882
+	 * @throws InvalidInterfaceException
2883
+	 */
2884
+	public function saveTimezoneString()
2885
+	{
2886
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2887
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2888
+			EE_Error::add_error(
2889
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2890
+				__FILE__,
2891
+				__FUNCTION__,
2892
+				__LINE__
2893
+			);
2894
+			$this->_template_args['error'] = true;
2895
+			$this->_return_json();
2896
+		}
2897
+
2898
+		update_option('timezone_string', $timezone_string);
2899
+		EE_Error::add_success(
2900
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2901
+		);
2902
+		$this->_template_args['success'] = true;
2903
+		$this->_return_json(true, ['action' => 'create_new']);
2904
+	}
2905
+
2906
+
2907
+	/**
2908
+	 * @throws EE_Error
2909
+	 * @deprecated 4.10.25.p
2910
+	 */
2911
+	public function save_timezonestring_setting()
2912
+	{
2913
+		$this->saveTimezoneString();
2914
+	}
2915 2915
 }
Please login to merge, or discard this patch.
Spacing   +89 added lines, -89 removed lines patch added patch discarded remove patch
@@ -587,13 +587,13 @@  discard block
 block discarded – undo
587 587
     {
588 588
         wp_register_style(
589 589
             'events-admin-css',
590
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
590
+            EVENTS_ASSETS_URL.'events-admin-page.css',
591 591
             [],
592 592
             EVENT_ESPRESSO_VERSION
593 593
         );
594 594
         wp_register_style(
595 595
             'ee-cat-admin',
596
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
596
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
597 597
             [],
598 598
             EVENT_ESPRESSO_VERSION
599 599
         );
@@ -602,7 +602,7 @@  discard block
 block discarded – undo
602 602
         // scripts
603 603
         wp_register_script(
604 604
             'event_editor_js',
605
-            EVENTS_ASSETS_URL . 'event_editor.js',
605
+            EVENTS_ASSETS_URL.'event_editor.js',
606 606
             ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
607 607
             EVENT_ESPRESSO_VERSION,
608 608
             true
@@ -628,16 +628,16 @@  discard block
 block discarded – undo
628 628
         wp_enqueue_style('espresso-ui-theme');
629 629
         wp_register_style(
630 630
             'event-editor-css',
631
-            EVENTS_ASSETS_URL . 'event-editor.css',
631
+            EVENTS_ASSETS_URL.'event-editor.css',
632 632
             ['ee-admin-css'],
633 633
             EVENT_ESPRESSO_VERSION
634 634
         );
635 635
         wp_enqueue_style('event-editor-css');
636 636
         // scripts
637
-        if (! $this->admin_config->useAdvancedEditor()) {
637
+        if ( ! $this->admin_config->useAdvancedEditor()) {
638 638
             wp_register_script(
639 639
                 'event-datetime-metabox',
640
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
640
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
641 641
                 ['event_editor_js', 'ee-datepicker'],
642 642
                 EVENT_ESPRESSO_VERSION
643 643
             );
@@ -707,15 +707,15 @@  discard block
 block discarded – undo
707 707
     public function verify_event_edit($event = null, $req_type = '')
708 708
     {
709 709
         // don't need to do this when processing
710
-        if (! empty($req_type)) {
710
+        if ( ! empty($req_type)) {
711 711
             return;
712 712
         }
713 713
         // no event?
714
-        if (! $event instanceof EE_Event) {
714
+        if ( ! $event instanceof EE_Event) {
715 715
             $event = $this->_cpt_model_obj;
716 716
         }
717 717
         // STILL no event?
718
-        if (! $event instanceof EE_Event) {
718
+        if ( ! $event instanceof EE_Event) {
719 719
             return;
720 720
         }
721 721
         $orig_status = $event->status();
@@ -755,7 +755,7 @@  discard block
 block discarded – undo
755 755
             );
756 756
         }
757 757
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
758
-        if (! $event->tickets_on_sale()) {
758
+        if ( ! $event->tickets_on_sale()) {
759 759
             return;
760 760
         }
761 761
         // made it here so show warning
@@ -803,7 +803,7 @@  discard block
 block discarded – undo
803 803
     {
804 804
         $has_timezone_string = get_option('timezone_string');
805 805
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
806
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
806
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807 807
             EE_Error::add_attention(
808 808
                 sprintf(
809 809
                     esc_html__(
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
      */
873 873
     protected function _event_legend_items()
874 874
     {
875
-        $items    = [
875
+        $items = [
876 876
             'view_details'   => [
877 877
                 'class' => 'dashicons dashicons-search',
878 878
                 'desc'  => esc_html__('View Event', 'event_espresso'),
@@ -889,31 +889,31 @@  discard block
 block discarded – undo
889 889
         $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890 890
         $statuses = [
891 891
             'sold_out_status'  => [
892
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
892
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
893 893
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894 894
             ],
895 895
             'active_status'    => [
896
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
896
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
897 897
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898 898
             ],
899 899
             'upcoming_status'  => [
900
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
900
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
901 901
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902 902
             ],
903 903
             'postponed_status' => [
904
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
904
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
905 905
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906 906
             ],
907 907
             'cancelled_status' => [
908
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
908
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
909 909
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910 910
             ],
911 911
             'expired_status'   => [
912
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
912
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
913 913
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914 914
             ],
915 915
             'inactive_status'  => [
916
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
916
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
917 917
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918 918
             ],
919 919
         ];
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
      */
933 933
     private function _event_model()
934 934
     {
935
-        if (! $this->_event_model instanceof EEM_Event) {
935
+        if ( ! $this->_event_model instanceof EEM_Event) {
936 936
             $this->_event_model = EE_Registry::instance()->load_model('Event');
937 937
         }
938 938
         return $this->_event_model;
@@ -952,8 +952,8 @@  discard block
 block discarded – undo
952 952
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
953 953
     {
954 954
         // make sure this is only when editing
955
-        if (! empty($id)) {
956
-            $post   = get_post($id);
955
+        if ( ! empty($id)) {
956
+            $post = get_post($id);
957 957
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
958 958
                        . esc_html__('Shortcode', 'event_espresso')
959 959
                        . '</a> ';
@@ -987,14 +987,14 @@  discard block
 block discarded – undo
987 987
             esc_html__('View Event Archive Page', 'event_espresso'),
988 988
             'button'
989 989
         );
990
-        $after_list_table['legend']                 = $this->_display_legend($this->_event_legend_items());
991
-        $this->_admin_page_title                    .= ' ' . $this->get_action_link_or_button(
990
+        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
991
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
992 992
             'create_new',
993 993
             'add',
994 994
             [],
995 995
             'add-new-h2'
996 996
         );
997
-        $this->_template_args['after_list_table']   = array_merge(
997
+        $this->_template_args['after_list_table'] = array_merge(
998 998
             (array) $this->_template_args['after_list_table'],
999 999
             $after_list_table
1000 1000
         );
@@ -1051,13 +1051,13 @@  discard block
 block discarded – undo
1051 1051
             'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1052 1052
         ];
1053 1053
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1054
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1055
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1054
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1055
+            $event_values['EVT_display_ticket_selector'] = $this->request->getRequestParam(
1056 1056
                 'display_ticket_selector',
1057 1057
                 false,
1058 1058
                 'bool'
1059 1059
             );
1060
-            $event_values['EVT_additional_limit']            = min(
1060
+            $event_values['EVT_additional_limit'] = min(
1061 1061
                 apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1062 1062
                 $this->request->getRequestParam('additional_limit', null, 'int')
1063 1063
             );
@@ -1093,7 +1093,7 @@  discard block
 block discarded – undo
1093 1093
         // the following are default callbacks for event attachment updates
1094 1094
         // that can be overridden by caffeinated functionality and/or addons.
1095 1095
         $event_update_callbacks = [];
1096
-        if (! $this->admin_config->useAdvancedEditor()) {
1096
+        if ( ! $this->admin_config->useAdvancedEditor()) {
1097 1097
             $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1098 1098
             $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1099 1099
         }
@@ -1164,7 +1164,7 @@  discard block
 block discarded – undo
1164 1164
      */
1165 1165
     protected function _default_venue_update(EE_Event $event, $data)
1166 1166
     {
1167
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1167
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1168 1168
         $venue_model = EE_Registry::instance()->load_model('Venue');
1169 1169
         $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1170 1170
         // very important.  If we don't have a venue name...
@@ -1195,7 +1195,7 @@  discard block
 block discarded – undo
1195 1195
             'status'              => 'publish',
1196 1196
         ];
1197 1197
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1198
-        if (! empty($venue_id)) {
1198
+        if ( ! empty($venue_id)) {
1199 1199
             $update_where  = [$venue_model->primary_key_name() => $venue_id];
1200 1200
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1201 1201
             // we've gotta make sure that the venue is always attached to a revision..
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
                 isset($datetime_data['DTT_EVT_end']) && ! empty($datetime_data['DTT_EVT_end'])
1238 1238
                     ? $datetime_data['DTT_EVT_end']
1239 1239
                     : $datetime_data['DTT_EVT_start'];
1240
-            $datetime_values              = [
1240
+            $datetime_values = [
1241 1241
                 'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1242 1242
                 'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1243 1243
                 'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
@@ -1246,9 +1246,9 @@  discard block
 block discarded – undo
1246 1246
             ];
1247 1247
             // if we have an id then let's get existing object first and then set the new values.
1248 1248
             //  Otherwise we instantiate a new object for save.
1249
-            if (! empty($datetime_data['DTT_ID'])) {
1249
+            if ( ! empty($datetime_data['DTT_ID'])) {
1250 1250
                 $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1251
-                if (! $datetime instanceof EE_Datetime) {
1251
+                if ( ! $datetime instanceof EE_Datetime) {
1252 1252
                     throw new RuntimeException(
1253 1253
                         sprintf(
1254 1254
                             esc_html__(
@@ -1267,7 +1267,7 @@  discard block
 block discarded – undo
1267 1267
             } else {
1268 1268
                 $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1269 1269
             }
1270
-            if (! $datetime instanceof EE_Datetime) {
1270
+            if ( ! $datetime instanceof EE_Datetime) {
1271 1271
                 throw new RuntimeException(
1272 1272
                     sprintf(
1273 1273
                         esc_html__(
@@ -1293,7 +1293,7 @@  discard block
 block discarded – undo
1293 1293
 
1294 1294
         // set up some default start and end dates in case those are not present in the incoming data
1295 1295
         $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1296
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1296
+        $default_start_date = $default_start_date->format($date_formats[0].' '.$date_formats[1]);
1297 1297
         // use the start date of the first datetime for the end date
1298 1298
         $first_datetime   = $event->first_datetime();
1299 1299
         $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
@@ -1301,8 +1301,8 @@  discard block
 block discarded – undo
1301 1301
         // now process the incoming data
1302 1302
         foreach ($data['edit_tickets'] as $row => $ticket_data) {
1303 1303
             $update_prices = false;
1304
-            $ticket_price  = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1305
-                ? $data['edit_prices'][ $row ][1]['PRC_amount']
1304
+            $ticket_price  = isset($data['edit_prices'][$row][1]['PRC_amount'])
1305
+                ? $data['edit_prices'][$row][1]['PRC_amount']
1306 1306
                 : 0;
1307 1307
             // trim inputs to ensure any excess whitespace is removed.
1308 1308
             $ticket_data   = array_map('trim', $ticket_data);
@@ -1343,9 +1343,9 @@  discard block
 block discarded – undo
1343 1343
             // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1344 1344
             // keep in mind that if the ticket has been sold (and we have changed pricing information),
1345 1345
             // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1346
-            if (! empty($ticket_data['TKT_ID'])) {
1346
+            if ( ! empty($ticket_data['TKT_ID'])) {
1347 1347
                 $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1348
-                if (! $existing_ticket instanceof EE_Ticket) {
1348
+                if ( ! $existing_ticket instanceof EE_Ticket) {
1349 1349
                     throw new RuntimeException(
1350 1350
                         sprintf(
1351 1351
                             esc_html__(
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
                     $existing_ticket->save();
1395 1395
                     // make sure this ticket is still recorded in our $saved_tickets
1396 1396
                     // so we don't run it through the regular trash routine.
1397
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1397
+                    $saved_tickets[$existing_ticket->ID()] = $existing_ticket;
1398 1398
                     // create new ticket that's a copy of the existing except,
1399 1399
                     // (a new id of course and not archived) AND has the new TKT_price associated with it.
1400 1400
                     $new_ticket = clone $existing_ticket;
@@ -1411,7 +1411,7 @@  discard block
 block discarded – undo
1411 1411
                 $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1412 1412
                 $update_prices              = true;
1413 1413
             }
1414
-            if (! $ticket instanceof EE_Ticket) {
1414
+            if ( ! $ticket instanceof EE_Ticket) {
1415 1415
                 throw new RuntimeException(
1416 1416
                     sprintf(
1417 1417
                         esc_html__(
@@ -1435,9 +1435,9 @@  discard block
 block discarded – undo
1435 1435
             }
1436 1436
             // initially let's add the ticket to the datetime
1437 1437
             $datetime->_add_relation_to($ticket, 'Ticket');
1438
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1438
+            $saved_tickets[$ticket->ID()] = $ticket;
1439 1439
             // add prices to ticket
1440
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $ticket, $update_prices);
1440
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $ticket, $update_prices);
1441 1441
         }
1442 1442
         // however now we need to handle permanently deleting tickets via the ui.
1443 1443
         //  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
@@ -1449,7 +1449,7 @@  discard block
 block discarded – undo
1449 1449
             $id = absint($id);
1450 1450
             // get the ticket for this id
1451 1451
             $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1452
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1452
+            if ( ! $ticket_to_remove instanceof EE_Ticket) {
1453 1453
                 continue;
1454 1454
             }
1455 1455
             // need to get all the related datetimes on this ticket and remove from every single one of them
@@ -1506,7 +1506,7 @@  discard block
 block discarded – undo
1506 1506
                     $price->set($field, $new_price);
1507 1507
                 }
1508 1508
             }
1509
-            if (! $price instanceof EE_Price) {
1509
+            if ( ! $price instanceof EE_Price) {
1510 1510
                 throw new RuntimeException(
1511 1511
                     sprintf(
1512 1512
                         esc_html__(
@@ -1548,13 +1548,13 @@  discard block
 block discarded – undo
1548 1548
     {
1549 1549
         // load formatter helper
1550 1550
         // args for getting related registrations
1551
-        $approved_query_args        = [
1551
+        $approved_query_args = [
1552 1552
             [
1553 1553
                 'REG_deleted' => 0,
1554 1554
                 'STS_ID'      => EEM_Registration::status_id_approved,
1555 1555
             ],
1556 1556
         ];
1557
-        $not_approved_query_args    = [
1557
+        $not_approved_query_args = [
1558 1558
             [
1559 1559
                 'REG_deleted' => 0,
1560 1560
                 'STS_ID'      => EEM_Registration::status_id_not_approved,
@@ -1617,7 +1617,7 @@  discard block
 block discarded – undo
1617 1617
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1618 1618
         // load template
1619 1619
         EEH_Template::display_template(
1620
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1620
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1621 1621
             $publish_box_extra_args
1622 1622
         );
1623 1623
     }
@@ -1648,7 +1648,7 @@  discard block
 block discarded – undo
1648 1648
         $this->verify_cpt_object();
1649 1649
         $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1650 1650
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1651
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1651
+        if ( ! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1652 1652
             add_meta_box(
1653 1653
                 'espresso_event_editor_event_options',
1654 1654
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1657,7 +1657,7 @@  discard block
 block discarded – undo
1657 1657
                 'side'
1658 1658
             );
1659 1659
         }
1660
-        if (! $use_advanced_editor) {
1660
+        if ( ! $use_advanced_editor) {
1661 1661
             add_meta_box(
1662 1662
                 'espresso_event_editor_tickets',
1663 1663
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1669,7 +1669,7 @@  discard block
 block discarded – undo
1669 1669
         } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1670 1670
             add_action(
1671 1671
                 'add_meta_boxes_espresso_events',
1672
-                function () {
1672
+                function() {
1673 1673
                     global $current_screen;
1674 1674
                     remove_meta_box('authordiv', $current_screen, 'normal');
1675 1675
                 },
@@ -1704,7 +1704,7 @@  discard block
 block discarded – undo
1704 1704
             'trash_icon'               => 'ee-lock-icon',
1705 1705
             'disabled'                 => '',
1706 1706
         ];
1707
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1707
+        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1708 1708
         /**
1709 1709
          * 1. Start with retrieving Datetimes
1710 1710
          * 2. Fore each datetime get related tickets
@@ -1730,24 +1730,24 @@  discard block
 block discarded – undo
1730 1730
                     'default_where_conditions' => 'none',
1731 1731
                 ]
1732 1732
             );
1733
-            if (! empty($related_tickets)) {
1733
+            if ( ! empty($related_tickets)) {
1734 1734
                 $template_args['total_ticket_rows'] = count($related_tickets);
1735 1735
                 $row                                = 0;
1736 1736
                 foreach ($related_tickets as $ticket) {
1737
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1737
+                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1738 1738
                     $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1739 1739
                     $row++;
1740 1740
                 }
1741 1741
             } else {
1742 1742
                 $template_args['total_ticket_rows'] = 1;
1743 1743
                 /** @type EE_Ticket $ticket */
1744
-                $ticket                       = $ticket_model->create_default_object();
1744
+                $ticket = $ticket_model->create_default_object();
1745 1745
                 $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1746 1746
             }
1747 1747
         } else {
1748 1748
             $template_args['time'] = $times[0];
1749 1749
             /** @type EE_Ticket[] $tickets */
1750
-            $tickets                      = $ticket_model->get_all_default_tickets();
1750
+            $tickets = $ticket_model->get_all_default_tickets();
1751 1751
             $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1752 1752
             // NOTE: we're just sending the first default row
1753 1753
             // (decaf can't manage default tickets so this should be sufficient);
@@ -1762,9 +1762,9 @@  discard block
 block discarded – undo
1762 1762
             $ticket_model->create_default_object(),
1763 1763
             true
1764 1764
         );
1765
-        $template                                  = apply_filters(
1765
+        $template = apply_filters(
1766 1766
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1767
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1767
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1768 1768
         );
1769 1769
         EEH_Template::display_template($template, $template_args);
1770 1770
     }
@@ -1784,7 +1784,7 @@  discard block
 block discarded – undo
1784 1784
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1785 1785
     {
1786 1786
         $template_args = [
1787
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1787
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1788 1788
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1789 1789
                 : '',
1790 1790
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1796,10 +1796,10 @@  discard block
 block discarded – undo
1796 1796
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1797 1797
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1798 1798
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1799
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1800
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1799
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1800
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1801 1801
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1802
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1802
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1803 1803
                 : ' disabled=disabled',
1804 1804
         ];
1805 1805
         $price         = $ticket->ID() !== 0
@@ -1823,7 +1823,7 @@  discard block
 block discarded – undo
1823 1823
         }
1824 1824
         if (empty($template_args['TKT_end_date'])) {
1825 1825
             // get the earliest datetime (if present);
1826
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1826
+            $earliest_datetime = $this->_cpt_model_obj->ID() > 0
1827 1827
                 ? $this->_cpt_model_obj->get_first_related(
1828 1828
                     'Datetime',
1829 1829
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
@@ -1836,7 +1836,7 @@  discard block
 block discarded – undo
1836 1836
         $template_args = array_merge($template_args, $price_args);
1837 1837
         $template      = apply_filters(
1838 1838
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1839
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1839
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1840 1840
             $ticket
1841 1841
         );
1842 1842
         return EEH_Template::display_template($template, $template_args, true);
@@ -1849,7 +1849,7 @@  discard block
 block discarded – undo
1849 1849
      */
1850 1850
     public function registration_options_meta_box()
1851 1851
     {
1852
-        $yes_no_values             = [
1852
+        $yes_no_values = [
1853 1853
             ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1854 1854
             ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1855 1855
         ];
@@ -1871,12 +1871,12 @@  discard block
 block discarded – undo
1871 1871
             $default_reg_status_values,
1872 1872
             $this->_cpt_model_obj->default_registration_status()
1873 1873
         );
1874
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1874
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
1875 1875
             'display_desc',
1876 1876
             $yes_no_values,
1877 1877
             $this->_cpt_model_obj->display_description()
1878 1878
         );
1879
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1879
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1880 1880
             'display_ticket_selector',
1881 1881
             $yes_no_values,
1882 1882
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -1892,7 +1892,7 @@  discard block
 block discarded – undo
1892 1892
             $default_reg_status_values
1893 1893
         );
1894 1894
         EEH_Template::display_template(
1895
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1895
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1896 1896
             $template_args
1897 1897
         );
1898 1898
     }
@@ -1915,7 +1915,7 @@  discard block
 block discarded – undo
1915 1915
     {
1916 1916
         $EEM_Event   = $this->_event_model();
1917 1917
         $offset      = ($current_page - 1) * $per_page;
1918
-        $limit       = $count ? null : $offset . ',' . $per_page;
1918
+        $limit       = $count ? null : $offset.','.$per_page;
1919 1919
         $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1920 1920
         $order       = $this->request->getRequestParam('order', 'DESC');
1921 1921
         $month_range = $this->request->getRequestParam('month_range');
@@ -1952,10 +1952,10 @@  discard block
 block discarded – undo
1952 1952
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1953 1953
         if ($month_range) {
1954 1954
             $DateTime = new DateTime(
1955
-                $year_r . '-' . $month_r . '-01 00:00:00',
1955
+                $year_r.'-'.$month_r.'-01 00:00:00',
1956 1956
                 new DateTimeZone('UTC')
1957 1957
             );
1958
-            $start    = $DateTime->getTimestamp();
1958
+            $start = $DateTime->getTimestamp();
1959 1959
             // set the datetime to be the end of the month
1960 1960
             $DateTime->setDate(
1961 1961
                 $year_r,
@@ -1980,11 +1980,11 @@  discard block
 block discarded – undo
1980 1980
                                                         ->format(implode(' ', $start_formats));
1981 1981
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1982 1982
         }
1983
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1983
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1984 1984
             $where['EVT_wp_user'] = get_current_user_id();
1985 1985
         } else {
1986
-            if (! isset($where['status'])) {
1987
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1986
+            if ( ! isset($where['status'])) {
1987
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1988 1988
                     $where['OR'] = [
1989 1989
                         'status*restrict_private' => ['!=', 'private'],
1990 1990
                         'AND'                     => [
@@ -2006,7 +2006,7 @@  discard block
 block discarded – undo
2006 2006
         // search query handling
2007 2007
         $search_term = $this->request->getRequestParam('s');
2008 2008
         if ($search_term) {
2009
-            $search_term = '%' . $search_term . '%';
2009
+            $search_term = '%'.$search_term.'%';
2010 2010
             $where['OR'] = [
2011 2011
                 'EVT_name'       => ['LIKE', $search_term],
2012 2012
                 'EVT_desc'       => ['LIKE', $search_term],
@@ -2114,7 +2114,7 @@  discard block
 block discarded – undo
2114 2114
             // clean status
2115 2115
             $event_status = sanitize_key($event_status);
2116 2116
             // grab status
2117
-            if (! empty($event_status)) {
2117
+            if ( ! empty($event_status)) {
2118 2118
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2119 2119
             } else {
2120 2120
                 $success = false;
@@ -2154,7 +2154,7 @@  discard block
 block discarded – undo
2154 2154
         // clean status
2155 2155
         $event_status = sanitize_key($event_status);
2156 2156
         // grab status
2157
-        if (! empty($event_status)) {
2157
+        if ( ! empty($event_status)) {
2158 2158
             $success = true;
2159 2159
             // determine the event id and set to array.
2160 2160
             $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
@@ -2200,7 +2200,7 @@  discard block
 block discarded – undo
2200 2200
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2201 2201
     {
2202 2202
         // grab event id
2203
-        if (! $EVT_ID) {
2203
+        if ( ! $EVT_ID) {
2204 2204
             $msg = esc_html__(
2205 2205
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2206 2206
                 'event_espresso'
@@ -2237,7 +2237,7 @@  discard block
 block discarded – undo
2237 2237
         // use class to change status
2238 2238
         $this->_cpt_model_obj->set_status($event_status);
2239 2239
         $success = $this->_cpt_model_obj->save();
2240
-        if (! $success) {
2240
+        if ( ! $success) {
2241 2241
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2242 2242
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2243 2243
             return false;
@@ -2295,7 +2295,7 @@  discard block
 block discarded – undo
2295 2295
      */
2296 2296
     protected function getModelObjNodeGroupPersister()
2297 2297
     {
2298
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2298
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2299 2299
             $this->model_obj_node_group_persister =
2300 2300
                 $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2301 2301
         }
@@ -2587,7 +2587,7 @@  discard block
 block discarded – undo
2587 2587
                                                 . esc_html__(
2588 2588
                                                     'Template Settings 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. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2589 2589
                                                     'event_espresso'
2590
-                                                ) . '</strong>';
2590
+                                                ).'</strong>';
2591 2591
         $this->display_admin_caf_preview_page('template_settings_tab');
2592 2592
     }
2593 2593
 
@@ -2608,11 +2608,11 @@  discard block
 block discarded – undo
2608 2608
         $this->_set_empty_category_object();
2609 2609
         // only set if we've got an id
2610 2610
         $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
2611
-        if (! $category_ID) {
2611
+        if ( ! $category_ID) {
2612 2612
             return;
2613 2613
         }
2614 2614
         $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2615
-        if (! empty($term)) {
2615
+        if ( ! empty($term)) {
2616 2616
             $this->_category->category_name       = $term->name;
2617 2617
             $this->_category->category_identifier = $term->slug;
2618 2618
             $this->_category->category_desc       = $term->description;
@@ -2716,7 +2716,7 @@  discard block
 block discarded – undo
2716 2716
             $category_select_values,
2717 2717
             $this->_category->parent
2718 2718
         );
2719
-        $template_args   = [
2719
+        $template_args = [
2720 2720
             'category'                 => $this->_category,
2721 2721
             'category_select'          => $category_select,
2722 2722
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -2724,7 +2724,7 @@  discard block
 block discarded – undo
2724 2724
             'disable'                  => '',
2725 2725
             'disabled_message'         => false,
2726 2726
         ];
2727
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2727
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2728 2728
         return EEH_Template::display_template($template, $template_args, true);
2729 2729
     }
2730 2730
 
@@ -2814,7 +2814,7 @@  discard block
 block discarded – undo
2814 2814
         $insert_ids = $update
2815 2815
             ? wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2816 2816
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2817
-        if (! is_array($insert_ids)) {
2817
+        if ( ! is_array($insert_ids)) {
2818 2818
             $msg = esc_html__(
2819 2819
                 'An error occurred and the category has not been saved to the database.',
2820 2820
                 'event_espresso'
@@ -2850,7 +2850,7 @@  discard block
 block discarded – undo
2850 2850
         $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2851 2851
         $search_term = $this->request->getRequestParam('s');
2852 2852
         if ($search_term) {
2853
-            $search_term = '%' . $search_term . '%';
2853
+            $search_term = '%'.$search_term.'%';
2854 2854
             $where['OR'] = [
2855 2855
                 'Term.name'   => ['LIKE', $search_term],
2856 2856
                 'description' => ['LIKE', $search_term],
@@ -2859,7 +2859,7 @@  discard block
 block discarded – undo
2859 2859
         $query_params = [
2860 2860
             $where,
2861 2861
             'order_by'   => [$orderby => $order],
2862
-            'limit'      => $limit . ',' . $per_page,
2862
+            'limit'      => $limit.','.$per_page,
2863 2863
             'force_join' => ['Term'],
2864 2864
         ];
2865 2865
         return $count
Please login to merge, or discard this patch.