Completed
Branch master (76375f)
by
unknown
10:42 queued 05:22
created
registration_form/Registration_Form_Questions_Admin_List_Table.class.php 1 patch
Indentation   +212 added lines, -212 removed lines patch added patch discarded remove patch
@@ -15,223 +15,223 @@
 block discarded – undo
15 15
  */
16 16
 class Registration_Form_Questions_Admin_List_Table extends EE_Admin_List_Table
17 17
 {
18
-    /**
19
-     * @var Registration_Form_Admin_Page $_admin_page
20
-     */
21
-    protected EE_Admin_Page $_admin_page;
22
-
23
-    /**
24
-     * @var RegFormListTableUserCapabilities
25
-     */
26
-    protected $caps_handler;
27
-
28
-
29
-    public function __construct($admin_page)
30
-    {
31
-        $this->caps_handler = new RegFormListTableUserCapabilities(EE_Registry::instance()->CAP);
32
-        parent::__construct($admin_page);
33
-
34
-        if (! defined('REG_ADMIN_URL')) {
35
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
36
-        }
37
-    }
38
-
39
-
40
-    /**
41
-     * @throws EE_Error
42
-     */
43
-    protected function _setup_data()
44
-    {
45
-        if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'trash') {
46
-            $this->_data = $this->_admin_page->get_trashed_questions($this->_per_page, $this->_current_page);
47
-        } else {
48
-            $this->_data = $this->_admin_page->get_questions($this->_per_page, $this->_current_page);
49
-        }
50
-        $this->_all_data_count = $this->_admin_page->get_questions($this->_per_page, $this->_current_page, true);
51
-    }
52
-
53
-
54
-    protected function _set_properties()
55
-    {
56
-        $this->_wp_list_args = [
57
-            'singular' => esc_html__('question', 'event_espresso'),
58
-            'plural'   => esc_html__('questions', 'event_espresso'),
59
-            'ajax'     => true, // for now,
60
-            'screen'   => $this->_admin_page->get_current_screen()->id,
61
-        ];
62
-
63
-        $this->_columns = [
64
-            'cb'           => '<input type="checkbox" />',
65
-            'id'           => esc_html__('ID', 'event_espresso'),
66
-            'display_text' => esc_html__('Question', 'event_espresso'),
67
-            'admin_label'  => esc_html__('Admin Label', 'event_espresso'),
68
-            'type'         => esc_html__('Type', 'event_espresso'),
69
-            'values'       => esc_html__('Values', 'event_espresso'),
70
-            'required'     => esc_html__('Req', 'event_espresso'),
71
-        ];
72
-
73
-        $this->_primary_column = 'id';
74
-
75
-        $this->_sortable_columns = [
76
-            'id'           => ['QST_ID' => false],
77
-            'display_text' => ['QST_display_text' => false],
78
-        ];
79
-
80
-        $this->_hidden_columns = [];
81
-    }
82
-
83
-
84
-    // not needed
85
-    protected function _get_table_filters()
86
-    {
87
-        return [];
88
-    }
89
-
90
-
91
-    /**
92
-     * @throws EE_Error
93
-     */
94
-    protected function _add_view_counts()
95
-    {
96
-        $this->_views['all']['count'] = $this->_admin_page->get_questions($this->_per_page, $this->_current_page, true);
97
-        if ($this->caps_handler->userCanTrashQuestions()) {
98
-            $this->_views['trash']['count'] = $this->_admin_page->get_trashed_questions(-1, $this->_current_page, true);
99
-        }
100
-    }
101
-
102
-
103
-    /**
104
-     * @param EE_Question $item
105
-     * @return string
106
-     * @throws EE_Error
107
-     * @throws ReflectionException
108
-     */
109
-    public function column_cb($item): string
110
-    {
111
-        $system_question      = $item->is_system_question();
112
-        $related_answer_count = $item->count_related('Answer');
113
-        $has_answers          = ! $system_question && $related_answer_count > 0 && $this->_view == 'trash';
114
-        $notice               = $has_answers
115
-            ? esc_html__(
116
-                'This question has answers attached to it from registrations that have the question.  It cannot be permanently deleted.',
117
-                'event_espresso'
118
-            )
119
-            : esc_html__('This question is a system question and cannot be trashed', 'event_espresso');
120
-
121
-        return $system_question || $has_answers
122
-            ? '
18
+	/**
19
+	 * @var Registration_Form_Admin_Page $_admin_page
20
+	 */
21
+	protected EE_Admin_Page $_admin_page;
22
+
23
+	/**
24
+	 * @var RegFormListTableUserCapabilities
25
+	 */
26
+	protected $caps_handler;
27
+
28
+
29
+	public function __construct($admin_page)
30
+	{
31
+		$this->caps_handler = new RegFormListTableUserCapabilities(EE_Registry::instance()->CAP);
32
+		parent::__construct($admin_page);
33
+
34
+		if (! defined('REG_ADMIN_URL')) {
35
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
36
+		}
37
+	}
38
+
39
+
40
+	/**
41
+	 * @throws EE_Error
42
+	 */
43
+	protected function _setup_data()
44
+	{
45
+		if (isset($this->_req_data['status']) && $this->_req_data['status'] == 'trash') {
46
+			$this->_data = $this->_admin_page->get_trashed_questions($this->_per_page, $this->_current_page);
47
+		} else {
48
+			$this->_data = $this->_admin_page->get_questions($this->_per_page, $this->_current_page);
49
+		}
50
+		$this->_all_data_count = $this->_admin_page->get_questions($this->_per_page, $this->_current_page, true);
51
+	}
52
+
53
+
54
+	protected function _set_properties()
55
+	{
56
+		$this->_wp_list_args = [
57
+			'singular' => esc_html__('question', 'event_espresso'),
58
+			'plural'   => esc_html__('questions', 'event_espresso'),
59
+			'ajax'     => true, // for now,
60
+			'screen'   => $this->_admin_page->get_current_screen()->id,
61
+		];
62
+
63
+		$this->_columns = [
64
+			'cb'           => '<input type="checkbox" />',
65
+			'id'           => esc_html__('ID', 'event_espresso'),
66
+			'display_text' => esc_html__('Question', 'event_espresso'),
67
+			'admin_label'  => esc_html__('Admin Label', 'event_espresso'),
68
+			'type'         => esc_html__('Type', 'event_espresso'),
69
+			'values'       => esc_html__('Values', 'event_espresso'),
70
+			'required'     => esc_html__('Req', 'event_espresso'),
71
+		];
72
+
73
+		$this->_primary_column = 'id';
74
+
75
+		$this->_sortable_columns = [
76
+			'id'           => ['QST_ID' => false],
77
+			'display_text' => ['QST_display_text' => false],
78
+		];
79
+
80
+		$this->_hidden_columns = [];
81
+	}
82
+
83
+
84
+	// not needed
85
+	protected function _get_table_filters()
86
+	{
87
+		return [];
88
+	}
89
+
90
+
91
+	/**
92
+	 * @throws EE_Error
93
+	 */
94
+	protected function _add_view_counts()
95
+	{
96
+		$this->_views['all']['count'] = $this->_admin_page->get_questions($this->_per_page, $this->_current_page, true);
97
+		if ($this->caps_handler->userCanTrashQuestions()) {
98
+			$this->_views['trash']['count'] = $this->_admin_page->get_trashed_questions(-1, $this->_current_page, true);
99
+		}
100
+	}
101
+
102
+
103
+	/**
104
+	 * @param EE_Question $item
105
+	 * @return string
106
+	 * @throws EE_Error
107
+	 * @throws ReflectionException
108
+	 */
109
+	public function column_cb($item): string
110
+	{
111
+		$system_question      = $item->is_system_question();
112
+		$related_answer_count = $item->count_related('Answer');
113
+		$has_answers          = ! $system_question && $related_answer_count > 0 && $this->_view == 'trash';
114
+		$notice               = $has_answers
115
+			? esc_html__(
116
+				'This question has answers attached to it from registrations that have the question.  It cannot be permanently deleted.',
117
+				'event_espresso'
118
+			)
119
+			: esc_html__('This question is a system question and cannot be trashed', 'event_espresso');
120
+
121
+		return $system_question || $has_answers
122
+			? '
123 123
             <span class="dashicons dashicons-lock ee-locked-entity ee-aria-tooltip"
124 124
                     aria-label="' . $notice . '"></span>
125 125
             ' . sprintf('<input type="hidden" name="hdnchk[%1$d]" value="%1$d" />', $item->ID())
126
-            : sprintf('<input type="checkbox" class="QST_ID" name="checkbox[%1$d]" value="%1$d" />', $item->ID());
127
-    }
128
-
129
-
130
-    /**
131
-     * @param EE_Question $item
132
-     * @return string
133
-     * @throws EE_Error
134
-     * @throws ReflectionException
135
-     */
136
-    public function column_id(EE_Question $item): string
137
-    {
138
-        $content = '
126
+			: sprintf('<input type="checkbox" class="QST_ID" name="checkbox[%1$d]" value="%1$d" />', $item->ID());
127
+	}
128
+
129
+
130
+	/**
131
+	 * @param EE_Question $item
132
+	 * @return string
133
+	 * @throws EE_Error
134
+	 * @throws ReflectionException
135
+	 */
136
+	public function column_id(EE_Question $item): string
137
+	{
138
+		$content = '
139 139
             <span class="ee-entity-id">' . $item->ID() . '</span>
140 140
             <span class="show-on-mobile-view-only">
141 141
                 ' . $this->column_display_text($item, false) . '
142 142
             </span>';
143
-        return $this->columnContent('id', $content, 'end');
144
-    }
145
-
146
-
147
-    /**
148
-     * @param EE_Question $question
149
-     * @param bool        $prep_content
150
-     * @return string
151
-     * @throws EE_Error
152
-     * @throws ReflectionException
153
-     */
154
-    public function column_display_text(EE_Question $question, bool $prep_content = true): string
155
-    {
156
-        if ($this->caps_handler->userCanEditQuestion($question)) {
157
-            $content = $this->getActionLink(
158
-                $this->getActionUrl($question, self::ACTION_EDIT),
159
-                $prep_content ? $question->display_text() : $question->admin_label(),
160
-                esc_attr__('Edit Question', 'event_espresso'),
161
-                'row-title'
162
-            );
163
-            $content .= $this->row_actions(
164
-                [
165
-                    'edit' => $this->getActionLink(
166
-                        $this->getActionUrl($question, self::ACTION_EDIT),
167
-                        esc_html__('Edit', 'event_espresso'),
168
-                        esc_attr__('Edit Question', 'event_espresso')
169
-                    ),
170
-                ]
171
-            );
172
-        } else {
173
-            $content = $question->display_text();
174
-        }
175
-
176
-        return $prep_content ? $this->columnContent('display_text', $content) : $content;
177
-    }
178
-
179
-
180
-    /**
181
-     * @param EE_Question $question
182
-     * @param string      $action
183
-     * @return string
184
-     * @throws EE_Error
185
-     * @throws ReflectionException
186
-     * @since 5.0.0.p
187
-     */
188
-    protected function getActionUrl(EE_Question $question, string $action): string
189
-    {
190
-        if (! in_array($action, self::$actions)) {
191
-            throw new DomainException(esc_html__('Invalid Action', 'event_espresso'));
192
-        }
193
-        return EE_Admin_Page::add_query_args_and_nonce(
194
-            [
195
-                'action'   => $action === self::ACTION_DELETE ? "{$action}_questions" : "{$action}_question",
196
-                'QST_ID'   => $question->ID(),
197
-                'noheader' => $action !== self::ACTION_EDIT,
198
-            ],
199
-            EE_FORMS_ADMIN_URL
200
-        );
201
-    }
202
-
203
-
204
-    public function column_admin_label(EE_Question $item): string
205
-    {
206
-        return $this->columnContent('admin_label', $item->admin_label());
207
-    }
208
-
209
-
210
-    public function column_values(EE_Question $item): string
211
-    {
212
-        $optionNames = [];
213
-        $options     = $item->options();
214
-        if (empty($options)) {
215
-            $content = "N/A";
216
-        } else {
217
-            foreach ($options as $option) {
218
-                $optionNames[] = $option->value();
219
-            }
220
-            $content = implode(', ', $optionNames);
221
-        }
222
-        return $this->columnContent('values', $content);
223
-    }
224
-
225
-
226
-    public function column_type(EE_Question $item): string
227
-    {
228
-        return $this->columnContent('type', $item->type());
229
-    }
230
-
231
-
232
-    public function column_required(EE_Question $item): string
233
-    {
234
-        $content = $item->required() ? 'Yes' : '';
235
-        return $this->columnContent('required', $content);
236
-    }
143
+		return $this->columnContent('id', $content, 'end');
144
+	}
145
+
146
+
147
+	/**
148
+	 * @param EE_Question $question
149
+	 * @param bool        $prep_content
150
+	 * @return string
151
+	 * @throws EE_Error
152
+	 * @throws ReflectionException
153
+	 */
154
+	public function column_display_text(EE_Question $question, bool $prep_content = true): string
155
+	{
156
+		if ($this->caps_handler->userCanEditQuestion($question)) {
157
+			$content = $this->getActionLink(
158
+				$this->getActionUrl($question, self::ACTION_EDIT),
159
+				$prep_content ? $question->display_text() : $question->admin_label(),
160
+				esc_attr__('Edit Question', 'event_espresso'),
161
+				'row-title'
162
+			);
163
+			$content .= $this->row_actions(
164
+				[
165
+					'edit' => $this->getActionLink(
166
+						$this->getActionUrl($question, self::ACTION_EDIT),
167
+						esc_html__('Edit', 'event_espresso'),
168
+						esc_attr__('Edit Question', 'event_espresso')
169
+					),
170
+				]
171
+			);
172
+		} else {
173
+			$content = $question->display_text();
174
+		}
175
+
176
+		return $prep_content ? $this->columnContent('display_text', $content) : $content;
177
+	}
178
+
179
+
180
+	/**
181
+	 * @param EE_Question $question
182
+	 * @param string      $action
183
+	 * @return string
184
+	 * @throws EE_Error
185
+	 * @throws ReflectionException
186
+	 * @since 5.0.0.p
187
+	 */
188
+	protected function getActionUrl(EE_Question $question, string $action): string
189
+	{
190
+		if (! in_array($action, self::$actions)) {
191
+			throw new DomainException(esc_html__('Invalid Action', 'event_espresso'));
192
+		}
193
+		return EE_Admin_Page::add_query_args_and_nonce(
194
+			[
195
+				'action'   => $action === self::ACTION_DELETE ? "{$action}_questions" : "{$action}_question",
196
+				'QST_ID'   => $question->ID(),
197
+				'noheader' => $action !== self::ACTION_EDIT,
198
+			],
199
+			EE_FORMS_ADMIN_URL
200
+		);
201
+	}
202
+
203
+
204
+	public function column_admin_label(EE_Question $item): string
205
+	{
206
+		return $this->columnContent('admin_label', $item->admin_label());
207
+	}
208
+
209
+
210
+	public function column_values(EE_Question $item): string
211
+	{
212
+		$optionNames = [];
213
+		$options     = $item->options();
214
+		if (empty($options)) {
215
+			$content = "N/A";
216
+		} else {
217
+			foreach ($options as $option) {
218
+				$optionNames[] = $option->value();
219
+			}
220
+			$content = implode(', ', $optionNames);
221
+		}
222
+		return $this->columnContent('values', $content);
223
+	}
224
+
225
+
226
+	public function column_type(EE_Question $item): string
227
+	{
228
+		return $this->columnContent('type', $item->type());
229
+	}
230
+
231
+
232
+	public function column_required(EE_Question $item): string
233
+	{
234
+		$content = $item->required() ? 'Yes' : '';
235
+		return $this->columnContent('required', $content);
236
+	}
237 237
 }
Please login to merge, or discard this patch.
registration_form/espresso_events_Registration_Form_Hooks.class.php 2 patches
Indentation   +210 added lines, -210 removed lines patch added patch discarded remove patch
@@ -15,99 +15,99 @@  discard block
 block discarded – undo
15 15
  */
16 16
 class espresso_events_Registration_Form_Hooks extends EE_Admin_Hooks
17 17
 {
18
-    protected ?EE_Event $_event = null;
19
-
20
-
21
-    protected function _set_hooks_properties()
22
-    {
23
-        $this->_name = 'registration_form';
24
-        if (
25
-            $this->_adminpage_obj->adminConfig()->useAdvancedEditor()
26
-            && $this->_adminpage_obj->feature()->allowed('use_reg_form_builder')
27
-        ) {
28
-            $this->_metaboxes      = [];
29
-            $this->_scripts_styles = [];
30
-            return;
31
-        }
32
-        $this->_metaboxes = [
33
-            0 => [
34
-                'page_route' => ['edit', 'create_new'],
35
-                'func'       => [$this, 'primary_questions'],
36
-                'label'      => esc_html__('Questions for Primary Registrant', 'event_espresso'),
37
-                'priority'   => 'default',
38
-                'context'    => 'side',
39
-            ],
40
-        ];
41
-
42
-        // hook into the handler for saving question groups
43
-        add_filter(
44
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
45
-            [$this, 'modify_callbacks']
46
-        );
47
-
48
-        // hook into revision restores (we're hooking into the global action because EE_Admin_Hooks classes are already
49
-        // restricted by page)
50
-        add_action('AHEE_EE_Admin_Page_CPT__restore_revision', [$this, 'restore_revision'], 10, 2);
51
-    }
52
-
53
-
54
-    /**
55
-     * Callback for FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks hook
56
-     *
57
-     * @param array $callbacks
58
-     * @return array
59
-     */
60
-    public function modify_callbacks(array $callbacks): array
61
-    {
62
-        // now let's add the question group callback
63
-        $callbacks['primary_question_group_update'] = [$this, 'primary_question_group_update'];
64
-        return $callbacks;
65
-    }
66
-
67
-
68
-    /**
69
-     * Hooked into revision restores.
70
-     *
71
-     * @param $post_id
72
-     * @param $revision_id
73
-     * @return EE_Base_Class
74
-     * @throws EE_Error
75
-     * @throws InvalidArgumentException
76
-     * @throws InvalidDataTypeException
77
-     * @throws InvalidInterfaceException
78
-     * @throws ReflectionException
79
-     */
80
-    public function restore_revision($post_id, $revision_id)
81
-    {
82
-        $post_evt = EEM_Event::instance()->get_one_by_ID($post_id);
83
-        // restore revision for primary questions
84
-        if ($post_evt instanceof EE_Event) {
85
-            $post_evt->restore_revision(
86
-                $revision_id,
87
-                ['Question_Group'],
88
-                ['Question_Group' => ['Event_Question_Group.EQG_primary' => true]]
89
-            );
90
-        }
91
-        return $post_evt;
92
-    }
93
-
94
-
95
-    /**
96
-     * Content of metabox.
97
-     *
98
-     * @param $post_id
99
-     * @param $post
100
-     * @throws EE_Error
101
-     * @throws InvalidArgumentException
102
-     * @throws InvalidDataTypeException
103
-     * @throws InvalidInterfaceException
104
-     * @throws ReflectionException
105
-     */
106
-    public function primary_questions($post_id, $post)
107
-    {
108
-        $this->_event = $this->_adminpage_obj->get_event_object();
109
-        $event_id     = $this->_event->ID();
110
-        ?>
18
+	protected ?EE_Event $_event = null;
19
+
20
+
21
+	protected function _set_hooks_properties()
22
+	{
23
+		$this->_name = 'registration_form';
24
+		if (
25
+			$this->_adminpage_obj->adminConfig()->useAdvancedEditor()
26
+			&& $this->_adminpage_obj->feature()->allowed('use_reg_form_builder')
27
+		) {
28
+			$this->_metaboxes      = [];
29
+			$this->_scripts_styles = [];
30
+			return;
31
+		}
32
+		$this->_metaboxes = [
33
+			0 => [
34
+				'page_route' => ['edit', 'create_new'],
35
+				'func'       => [$this, 'primary_questions'],
36
+				'label'      => esc_html__('Questions for Primary Registrant', 'event_espresso'),
37
+				'priority'   => 'default',
38
+				'context'    => 'side',
39
+			],
40
+		];
41
+
42
+		// hook into the handler for saving question groups
43
+		add_filter(
44
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
45
+			[$this, 'modify_callbacks']
46
+		);
47
+
48
+		// hook into revision restores (we're hooking into the global action because EE_Admin_Hooks classes are already
49
+		// restricted by page)
50
+		add_action('AHEE_EE_Admin_Page_CPT__restore_revision', [$this, 'restore_revision'], 10, 2);
51
+	}
52
+
53
+
54
+	/**
55
+	 * Callback for FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks hook
56
+	 *
57
+	 * @param array $callbacks
58
+	 * @return array
59
+	 */
60
+	public function modify_callbacks(array $callbacks): array
61
+	{
62
+		// now let's add the question group callback
63
+		$callbacks['primary_question_group_update'] = [$this, 'primary_question_group_update'];
64
+		return $callbacks;
65
+	}
66
+
67
+
68
+	/**
69
+	 * Hooked into revision restores.
70
+	 *
71
+	 * @param $post_id
72
+	 * @param $revision_id
73
+	 * @return EE_Base_Class
74
+	 * @throws EE_Error
75
+	 * @throws InvalidArgumentException
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws InvalidInterfaceException
78
+	 * @throws ReflectionException
79
+	 */
80
+	public function restore_revision($post_id, $revision_id)
81
+	{
82
+		$post_evt = EEM_Event::instance()->get_one_by_ID($post_id);
83
+		// restore revision for primary questions
84
+		if ($post_evt instanceof EE_Event) {
85
+			$post_evt->restore_revision(
86
+				$revision_id,
87
+				['Question_Group'],
88
+				['Question_Group' => ['Event_Question_Group.EQG_primary' => true]]
89
+			);
90
+		}
91
+		return $post_evt;
92
+	}
93
+
94
+
95
+	/**
96
+	 * Content of metabox.
97
+	 *
98
+	 * @param $post_id
99
+	 * @param $post
100
+	 * @throws EE_Error
101
+	 * @throws InvalidArgumentException
102
+	 * @throws InvalidDataTypeException
103
+	 * @throws InvalidInterfaceException
104
+	 * @throws ReflectionException
105
+	 */
106
+	public function primary_questions($post_id, $post)
107
+	{
108
+		$this->_event = $this->_adminpage_obj->get_event_object();
109
+		$event_id     = $this->_event->ID();
110
+		?>
111 111
         <div class="inside">
112 112
             <p>
113 113
                 <strong>
@@ -115,75 +115,75 @@  discard block
 block discarded – undo
115 115
                 </strong>
116 116
                 <br/>
117 117
                 <?php
118
-                printf(
119
-                    esc_html__(
120
-                        'Add a pre-populated %1$sgroup of questions%2$s to your event. The personal information group is required for all events',
121
-                        'event_espresso'
122
-                    ),
123
-                    '<a href="admin.php?page=espresso_registration_form" target="_blank">',
124
-                    '</a>'
125
-                )
126
-                ?>
118
+				printf(
119
+					esc_html__(
120
+						'Add a pre-populated %1$sgroup of questions%2$s to your event. The personal information group is required for all events',
121
+						'event_espresso'
122
+					),
123
+					'<a href="admin.php?page=espresso_registration_form" target="_blank">',
124
+					'</a>'
125
+				)
126
+				?>
127 127
             </p>
128 128
             <?php
129 129
 
130
-            $qsg_where = [ 'QSG_deleted' => false ];
131
-            if (
132
-                (defined('EE_DECAF') && EE_DECAF)
133
-                || ! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin')
134
-            ) {
135
-                $qsg_where['QSG_system'] = ['!=', 0];
136
-            }
137
-            $query_params             = apply_filters(
138
-                'FHEE__espresso_events_Registration_Form_Hooks__primary_questions__question_group_query_parameters',
139
-                [$qsg_where, 'order_by' => ['QSG_order' => 'ASC']]
140
-            );
141
-            $QSGs                     = EEM_Question_Group::instance()->get_all($query_params);
142
-            $EQGs                     = ! empty($event_id)
143
-                ? $this->_event->get_many_related(
144
-                    'Question_Group',
145
-                    [['Event_Question_Group.EQG_primary' => true]]
146
-                )
147
-                : [];
148
-            $EQGids                   = array_keys($EQGs);
149
-
150
-            if (! empty($QSGs)) {
151
-                $html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
152
-                foreach ($QSGs as $QSG) {
153
-                    $QSG_ID             = absint($QSG->ID());
154
-                    $is_system_question = $QSG->get('QSG_system') === 1;
155
-                    $checked            = $is_system_question || in_array($QSG_ID, $EQGids, true)
156
-                        ? ' checked'
157
-                        : '';
158
-
159
-                    $visibility = $is_system_question ? ' style="visibility:hidden"' : '';
160
-                    $readonly   = $is_system_question ? ' readonly' : '';
161
-
162
-                    $edit_query_args    = $this->_adminpage_obj->is_caf()
163
-                        ? [
164
-                            'action' => 'edit_question_group',
165
-                            'QSG_ID' => $QSG_ID,
166
-                        ]
167
-                        : ['action' => 'question_groups'];
168
-                    $edit_link          = EE_Admin_Page::add_query_args_and_nonce(
169
-                        $edit_query_args,
170
-                        EE_FORMS_ADMIN_URL
171
-                    );
172
-                    $edit_link_title    = sprintf(
173
-                        esc_attr__('Edit %s Group', 'event_espresso'),
174
-                        $QSG->get('QSG_name')
175
-                    );
176
-
177
-                    $html .= '
130
+			$qsg_where = [ 'QSG_deleted' => false ];
131
+			if (
132
+				(defined('EE_DECAF') && EE_DECAF)
133
+				|| ! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin')
134
+			) {
135
+				$qsg_where['QSG_system'] = ['!=', 0];
136
+			}
137
+			$query_params             = apply_filters(
138
+				'FHEE__espresso_events_Registration_Form_Hooks__primary_questions__question_group_query_parameters',
139
+				[$qsg_where, 'order_by' => ['QSG_order' => 'ASC']]
140
+			);
141
+			$QSGs                     = EEM_Question_Group::instance()->get_all($query_params);
142
+			$EQGs                     = ! empty($event_id)
143
+				? $this->_event->get_many_related(
144
+					'Question_Group',
145
+					[['Event_Question_Group.EQG_primary' => true]]
146
+				)
147
+				: [];
148
+			$EQGids                   = array_keys($EQGs);
149
+
150
+			if (! empty($QSGs)) {
151
+				$html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
152
+				foreach ($QSGs as $QSG) {
153
+					$QSG_ID             = absint($QSG->ID());
154
+					$is_system_question = $QSG->get('QSG_system') === 1;
155
+					$checked            = $is_system_question || in_array($QSG_ID, $EQGids, true)
156
+						? ' checked'
157
+						: '';
158
+
159
+					$visibility = $is_system_question ? ' style="visibility:hidden"' : '';
160
+					$readonly   = $is_system_question ? ' readonly' : '';
161
+
162
+					$edit_query_args    = $this->_adminpage_obj->is_caf()
163
+						? [
164
+							'action' => 'edit_question_group',
165
+							'QSG_ID' => $QSG_ID,
166
+						]
167
+						: ['action' => 'question_groups'];
168
+					$edit_link          = EE_Admin_Page::add_query_args_and_nonce(
169
+						$edit_query_args,
170
+						EE_FORMS_ADMIN_URL
171
+					);
172
+					$edit_link_title    = sprintf(
173
+						esc_attr__('Edit %s Group', 'event_espresso'),
174
+						$QSG->get('QSG_name')
175
+					);
176
+
177
+					$html .= '
178 178
 					<p id="event-question-group-' . $QSG_ID . '">
179 179
 						<input value="' . $QSG_ID . '"
180 180
 						    type="checkbox"
181 181
 						    name="question_groups[' . $QSG_ID . ']"
182 182
                             aria-label="' . sprintf(esc_attr__('primary registrant %s questions'), $QSG->get('QSG_name')) . '" '
183
-                            . $visibility
184
-                            . $checked
185
-                            . $readonly
186
-                            . '
183
+							. $visibility
184
+							. $checked
185
+							. $readonly
186
+							. '
187 187
                         />
188 188
 						<a href="' . esc_url_raw($edit_link) . '"
189 189
 						    aria-label="' . esc_attr($edit_link_title) . '"
@@ -192,62 +192,62 @@  discard block
 block discarded – undo
192 192
 						    ' . $QSG->get('QSG_name') . '
193 193
                         </a>
194 194
 					</p>';
195
-                }
196
-                $html .= count($QSGs) > 10 ? '</div>' : '';
197
-                echo wp_kses($html, AllowedTags::getWithFormTags());
198
-            } else {
199
-                esc_html_e(
200
-                    'There seems to be a problem with your questions. Please contact [email protected]',
201
-                    'event_espresso'
202
-                );
203
-            }
204
-            do_action('AHEE_event_editor_questions_notice');
205
-            ?>
195
+				}
196
+				$html .= count($QSGs) > 10 ? '</div>' : '';
197
+				echo wp_kses($html, AllowedTags::getWithFormTags());
198
+			} else {
199
+				esc_html_e(
200
+					'There seems to be a problem with your questions. Please contact [email protected]',
201
+					'event_espresso'
202
+				);
203
+			}
204
+			do_action('AHEE_event_editor_questions_notice');
205
+			?>
206 206
         </div>
207 207
         <?php
208
-    }
209
-
210
-
211
-    /**
212
-     * @param EE_Event $event
213
-     * @param array    $data
214
-     * @return bool
215
-     * @throws EE_Error
216
-     * @throws ReflectionException
217
-     */
218
-    public function primary_question_group_update(EE_Event $event, array $data): bool
219
-    {
220
-        $question_groups = ! empty($data['question_groups']) ? (array) $data['question_groups'] : [];
221
-        $added_qgs       = array_keys($question_groups);
222
-        $success         = true;
223
-
224
-        // let's get all current question groups associated with this event.
225
-        $current_qgs = $event->get_many_related(
226
-            'Question_Group',
227
-            [['Event_Question_Group.EQG_primary' => true]]
228
-        );
229
-        $current_qgs = array_keys($current_qgs); // we just want the ids
230
-
231
-        // now let's get the groups selected in the editor and update (IF we have data)
232
-        if (! empty($question_groups)) {
233
-            foreach ($question_groups as $QSG_ID => $val) {
234
-                // add to event
235
-                if ($val) {
236
-                    $qg = $event->_add_relation_to($QSG_ID, 'Question_Group', ['EQG_primary' => true]);
237
-                }
238
-                // trip success to false if result is empty
239
-                $success = ! empty($qg) ? $success : false;
240
-            }
241
-        }
242
-
243
-        // wait a minute... are there question groups missing in the saved groups that ARE with the current event?
244
-        $removed_qgs = array_diff($current_qgs, $added_qgs);
245
-
246
-        foreach ($removed_qgs as $QSG_ID) {
247
-            $qg = $event->_remove_relation_to($QSG_ID, 'Question_Group', ['EQG_primary' => true]);
248
-            // trip success to false if result is empty
249
-            $success = ! empty($qg) ? $success : false;
250
-        }
251
-        return $success;
252
-    }
208
+	}
209
+
210
+
211
+	/**
212
+	 * @param EE_Event $event
213
+	 * @param array    $data
214
+	 * @return bool
215
+	 * @throws EE_Error
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function primary_question_group_update(EE_Event $event, array $data): bool
219
+	{
220
+		$question_groups = ! empty($data['question_groups']) ? (array) $data['question_groups'] : [];
221
+		$added_qgs       = array_keys($question_groups);
222
+		$success         = true;
223
+
224
+		// let's get all current question groups associated with this event.
225
+		$current_qgs = $event->get_many_related(
226
+			'Question_Group',
227
+			[['Event_Question_Group.EQG_primary' => true]]
228
+		);
229
+		$current_qgs = array_keys($current_qgs); // we just want the ids
230
+
231
+		// now let's get the groups selected in the editor and update (IF we have data)
232
+		if (! empty($question_groups)) {
233
+			foreach ($question_groups as $QSG_ID => $val) {
234
+				// add to event
235
+				if ($val) {
236
+					$qg = $event->_add_relation_to($QSG_ID, 'Question_Group', ['EQG_primary' => true]);
237
+				}
238
+				// trip success to false if result is empty
239
+				$success = ! empty($qg) ? $success : false;
240
+			}
241
+		}
242
+
243
+		// wait a minute... are there question groups missing in the saved groups that ARE with the current event?
244
+		$removed_qgs = array_diff($current_qgs, $added_qgs);
245
+
246
+		foreach ($removed_qgs as $QSG_ID) {
247
+			$qg = $event->_remove_relation_to($QSG_ID, 'Question_Group', ['EQG_primary' => true]);
248
+			// trip success to false if result is empty
249
+			$success = ! empty($qg) ? $success : false;
250
+		}
251
+		return $success;
252
+	}
253 253
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -127,14 +127,14 @@  discard block
 block discarded – undo
127 127
             </p>
128 128
             <?php
129 129
 
130
-            $qsg_where = [ 'QSG_deleted' => false ];
130
+            $qsg_where = ['QSG_deleted' => false];
131 131
             if (
132 132
                 (defined('EE_DECAF') && EE_DECAF)
133
-                || ! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated/admin')
133
+                || ! is_dir(EE_PLUGIN_DIR_PATH.'caffeinated/admin')
134 134
             ) {
135 135
                 $qsg_where['QSG_system'] = ['!=', 0];
136 136
             }
137
-            $query_params             = apply_filters(
137
+            $query_params = apply_filters(
138 138
                 'FHEE__espresso_events_Registration_Form_Hooks__primary_questions__question_group_query_parameters',
139 139
                 [$qsg_where, 'order_by' => ['QSG_order' => 'ASC']]
140 140
             );
@@ -145,9 +145,9 @@  discard block
 block discarded – undo
145 145
                     [['Event_Question_Group.EQG_primary' => true]]
146 146
                 )
147 147
                 : [];
148
-            $EQGids                   = array_keys($EQGs);
148
+            $EQGids = array_keys($EQGs);
149 149
 
150
-            if (! empty($QSGs)) {
150
+            if ( ! empty($QSGs)) {
151 151
                 $html = count($QSGs) > 10 ? '<div style="height:250px;overflow:auto;">' : '';
152 152
                 foreach ($QSGs as $QSG) {
153 153
                     $QSG_ID             = absint($QSG->ID());
@@ -159,37 +159,37 @@  discard block
 block discarded – undo
159 159
                     $visibility = $is_system_question ? ' style="visibility:hidden"' : '';
160 160
                     $readonly   = $is_system_question ? ' readonly' : '';
161 161
 
162
-                    $edit_query_args    = $this->_adminpage_obj->is_caf()
162
+                    $edit_query_args = $this->_adminpage_obj->is_caf()
163 163
                         ? [
164 164
                             'action' => 'edit_question_group',
165 165
                             'QSG_ID' => $QSG_ID,
166 166
                         ]
167 167
                         : ['action' => 'question_groups'];
168
-                    $edit_link          = EE_Admin_Page::add_query_args_and_nonce(
168
+                    $edit_link = EE_Admin_Page::add_query_args_and_nonce(
169 169
                         $edit_query_args,
170 170
                         EE_FORMS_ADMIN_URL
171 171
                     );
172
-                    $edit_link_title    = sprintf(
172
+                    $edit_link_title = sprintf(
173 173
                         esc_attr__('Edit %s Group', 'event_espresso'),
174 174
                         $QSG->get('QSG_name')
175 175
                     );
176 176
 
177 177
                     $html .= '
178
-					<p id="event-question-group-' . $QSG_ID . '">
179
-						<input value="' . $QSG_ID . '"
178
+					<p id="event-question-group-' . $QSG_ID.'">
179
+						<input value="' . $QSG_ID.'"
180 180
 						    type="checkbox"
181
-						    name="question_groups[' . $QSG_ID . ']"
182
-                            aria-label="' . sprintf(esc_attr__('primary registrant %s questions'), $QSG->get('QSG_name')) . '" '
181
+						    name="question_groups[' . $QSG_ID.']"
182
+                            aria-label="' . sprintf(esc_attr__('primary registrant %s questions'), $QSG->get('QSG_name')).'" '
183 183
                             . $visibility
184 184
                             . $checked
185 185
                             . $readonly
186 186
                             . '
187 187
                         />
188
-						<a href="' . esc_url_raw($edit_link) . '"
189
-						    aria-label="' . esc_attr($edit_link_title) . '"
188
+						<a href="' . esc_url_raw($edit_link).'"
189
+						    aria-label="' . esc_attr($edit_link_title).'"
190 190
 						    target="_blank"
191 191
 						    >
192
-						    ' . $QSG->get('QSG_name') . '
192
+						    ' . $QSG->get('QSG_name').'
193 193
                         </a>
194 194
 					</p>';
195 195
                 }
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
         $current_qgs = array_keys($current_qgs); // we just want the ids
230 230
 
231 231
         // now let's get the groups selected in the editor and update (IF we have data)
232
-        if (! empty($question_groups)) {
232
+        if ( ! empty($question_groups)) {
233 233
             foreach ($question_groups as $QSG_ID => $val) {
234 234
                 // add to event
235 235
                 if ($val) {
Please login to merge, or discard this patch.
templates/txn_admin_details_side_meta_box_billing_info.template.php 2 patches
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -8,24 +8,24 @@
 block discarded – undo
8 8
 ?>
9 9
 <div id="admin-side-mbox-billing-info-dv" class="admin-side-mbox-dv">
10 10
     <?php if ($billing_form instanceof EE_Form_Section_Proper) :
11
-        $found_cc_data = BillingInfoSanitizer::displaySanitizedBillingInfo($billing_form);
12
-        if (
13
-            apply_filters(
14
-                'FHEE__txn_admin_details_side_meta_box_billing_info__show_default_note',
15
-                $found_cc_data,
16
-                $billing_form
17
-            )
18
-        ) { ?>
11
+		$found_cc_data = BillingInfoSanitizer::displaySanitizedBillingInfo($billing_form);
12
+		if (
13
+			apply_filters(
14
+				'FHEE__txn_admin_details_side_meta_box_billing_info__show_default_note',
15
+				$found_cc_data,
16
+				$billing_form
17
+			)
18
+		) { ?>
19 19
             <p class="help">
20 20
                 <?php esc_html_e(
21
-                    'Note: Card expiry dates and CCV are not stored. Only the last 4 digits of card numbers are stored.',
22
-                    'event_espresso'
23
-                ); ?>
21
+					'Note: Card expiry dates and CCV are not stored. Only the last 4 digits of card numbers are stored.',
22
+					'event_espresso'
23
+				); ?>
24 24
             </p>
25 25
             <?php
26
-        }
27
-        do_action('AHEE__txn_admin_details_side_meta_box_billing_info__billing_form_footer', $billing_form);
28
-    else : // invalid billing form ?>
26
+		}
27
+		do_action('AHEE__txn_admin_details_side_meta_box_billing_info__billing_form_footer', $billing_form);
28
+	else : // invalid billing form ?>
29 29
         <div class="clearfix">
30 30
             <?php esc_html_e('There is no billing info for this transaction.', 'event_espresso'); ?><br/>
31 31
         </div>
Please login to merge, or discard this patch.
Braces   +5 added lines, -2 removed lines patch added patch discarded remove patch
@@ -25,9 +25,12 @@
 block discarded – undo
25 25
             <?php
26 26
         }
27 27
         do_action('AHEE__txn_admin_details_side_meta_box_billing_info__billing_form_footer', $billing_form);
28
-    else : // invalid billing form ?>
28
+    else {
29
+    	: // invalid billing form ?>
29 30
         <div class="clearfix">
30
-            <?php esc_html_e('There is no billing info for this transaction.', 'event_espresso'); ?><br/>
31
+            <?php esc_html_e('There is no billing info for this transaction.', 'event_espresso');
32
+    }
33
+    ?><br/>
31 34
         </div>
32 35
     <?php endif; ?>
33 36
 </div>
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 2 patches
Indentation   +2552 added lines, -2552 removed lines patch added patch discarded remove patch
@@ -16,2556 +16,2556 @@
 block discarded – undo
16 16
  */
17 17
 class Transactions_Admin_Page extends EE_Admin_Page
18 18
 {
19
-    /**
20
-     * @var EE_Transaction
21
-     */
22
-    private $_transaction;
23
-
24
-    /**
25
-     * @var EE_Session
26
-     */
27
-    private $_session;
28
-
29
-    /**
30
-     * @var array $_txn_status
31
-     */
32
-    private static $_txn_status;
33
-
34
-    /**
35
-     * @var array $_pay_status
36
-     */
37
-    private static $_pay_status;
38
-
39
-    /**
40
-     * @var array $_existing_reg_payment_REG_IDs
41
-     */
42
-    protected $_existing_reg_payment_REG_IDs;
43
-
44
-
45
-    /**
46
-     *    _init_page_props
47
-     *
48
-     * @return void
49
-     */
50
-    protected function _init_page_props()
51
-    {
52
-        $this->page_slug        = TXN_PG_SLUG;
53
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
54
-        $this->_admin_base_url  = TXN_ADMIN_URL;
55
-        $this->_admin_base_path = TXN_ADMIN;
56
-    }
57
-
58
-
59
-    /**
60
-     *    _ajax_hooks
61
-     *
62
-     * @return void
63
-     */
64
-    protected function _ajax_hooks()
65
-    {
66
-        // add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
67
-        // add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
68
-        // add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
69
-    }
70
-
71
-
72
-    /**
73
-     *    _define_page_props
74
-     *
75
-     * @return void
76
-     */
77
-    protected function _define_page_props()
78
-    {
79
-        $this->_admin_page_title = $this->page_label;
80
-        $this->_labels           = [
81
-            'buttons' => [
82
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
83
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
84
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
85
-            ],
86
-        ];
87
-    }
88
-
89
-
90
-    /**
91
-     *        grab url requests and route them
92
-     *
93
-     * @access private
94
-     * @return void
95
-     * @throws EE_Error
96
-     * @throws InvalidArgumentException
97
-     * @throws InvalidDataTypeException
98
-     * @throws InvalidInterfaceException
99
-     * @throws ReflectionException
100
-     */
101
-    public function _set_page_routes()
102
-    {
103
-        $this->_set_transaction_status_array();
104
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
105
-
106
-        $this->_page_routes = [
107
-
108
-            'default' => [
109
-                'func'       => '_transactions_overview_list_table',
110
-                'capability' => 'ee_read_transactions',
111
-            ],
112
-
113
-            'view_transaction' => [
114
-                'func'       => '_transaction_details',
115
-                'capability' => 'ee_read_transaction',
116
-                'obj_id'     => $TXN_ID,
117
-            ],
118
-
119
-            'send_payment_reminder' => [
120
-                'func'       => '_send_payment_reminder',
121
-                'noheader'   => true,
122
-                'capability' => 'ee_send_message',
123
-            ],
124
-
125
-            'espresso_apply_payment' => [
126
-                'func'       => [$this, 'apply_payments_or_refunds'],
127
-                'noheader'   => true,
128
-                'capability' => 'ee_edit_payments',
129
-            ],
130
-
131
-            'espresso_apply_refund' => [
132
-                'func'       => [$this, 'apply_payments_or_refunds'],
133
-                'noheader'   => true,
134
-                'capability' => 'ee_edit_payments',
135
-            ],
136
-
137
-            'espresso_delete_payment' => [
138
-                'func'       => [$this, 'delete_payment'],
139
-                'noheader'   => true,
140
-                'capability' => 'ee_delete_payments',
141
-            ],
142
-
143
-            'espresso_recalculate_line_items' => [
144
-                'func'       => 'recalculateLineItems',
145
-                'noheader'   => true,
146
-                'capability' => 'ee_edit_payments',
147
-            ],
148
-
149
-        ];
150
-    }
151
-
152
-
153
-    protected function _set_page_config()
154
-    {
155
-        $TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
156
-        $this->_page_config = [
157
-            'default'          => [
158
-                'nav'           => [
159
-                    'label' => esc_html__('Overview', 'event_espresso'),
160
-                    'icon'  => 'dashicons-list-view',
161
-                    'order' => 10,
162
-                ],
163
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
164
-                'help_tabs'     => [
165
-                    'transactions_overview_help_tab'                       => [
166
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
167
-                        'filename' => 'transactions_overview',
168
-                    ],
169
-                    'transactions_overview_table_column_headings_help_tab' => [
170
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
171
-                        'filename' => 'transactions_overview_table_column_headings',
172
-                    ],
173
-                    'transactions_overview_views_filters_help_tab'         => [
174
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
175
-                        'filename' => 'transactions_overview_views_filters_search',
176
-                    ],
177
-                ],
178
-                'require_nonce' => false,
179
-            ],
180
-            'view_transaction' => [
181
-                'nav'       => [
182
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
183
-                    'icon'       => 'dashicons-cart',
184
-                    'order'      => 5,
185
-                    'url'        => $TXN_ID
186
-                        ? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
187
-                        : $this->_admin_base_url,
188
-                    'persistent' => false,
189
-                ],
190
-                'help_tabs' => [
191
-                    'transactions_view_transaction_help_tab'                                              => [
192
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
193
-                        'filename' => 'transactions_view_transaction',
194
-                    ],
195
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => [
196
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
197
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
198
-                    ],
199
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => [
200
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
201
-                        'filename' => 'transactions_view_transaction_attendees_registered',
202
-                    ],
203
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
204
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
205
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
206
-                    ],
207
-                ],
208
-                'qtips'     => ['Transaction_Details_Tips'],
209
-                'metaboxes' => ['_transaction_details_metaboxes'],
210
-
211
-                'require_nonce' => false,
212
-            ],
213
-        ];
214
-    }
215
-
216
-
217
-    /**
218
-     * The below methods aren't used by this class currently
219
-     */
220
-    protected function _add_screen_options()
221
-    {
222
-        // noop
223
-    }
224
-
225
-
226
-    protected function _add_feature_pointers()
227
-    {
228
-        // noop
229
-    }
230
-
231
-
232
-    public function admin_init()
233
-    {
234
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
235
-        $event_name    = $this->request->getRequestParam('event_name');
236
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
237
-        // IF a registration was JUST added via the admin...
238
-        if ($EVT_ID && $event_name && $redirect_from) {
239
-            // then set a cookie so that we can block any attempts to use
240
-            // the back button as a way to enter another registration.
241
-            setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
242
-            // and update the global
243
-            $_COOKIE['ee_registration_added'] = $EVT_ID;
244
-        }
245
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
246
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
247
-            'event_espresso'
248
-        );
249
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
250
-            'An error occurred! Please refresh the page and try again.',
251
-            'event_espresso'
252
-        );
253
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
254
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
255
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
256
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
257
-            'This transaction has been overpaid ! Payments Total',
258
-            'event_espresso'
259
-        );
260
-    }
261
-
262
-
263
-    public function admin_notices()
264
-    {
265
-        // noop
266
-    }
267
-
268
-
269
-    public function admin_footer_scripts()
270
-    {
271
-        // noop
272
-    }
273
-
274
-
275
-    /**
276
-     * _set_transaction_status_array
277
-     * sets list of transaction statuses
278
-     *
279
-     * @access private
280
-     * @return void
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    private function _set_transaction_status_array()
288
-    {
289
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
-    }
291
-
292
-
293
-    /**
294
-     * get_transaction_status_array
295
-     * return the transaction status array for wp_list_table
296
-     *
297
-     * @access public
298
-     * @return array
299
-     */
300
-    public function get_transaction_status_array()
301
-    {
302
-        return self::$_txn_status;
303
-    }
304
-
305
-
306
-    /**
307
-     *    get list of payment statuses
308
-     *
309
-     * @access private
310
-     * @return void
311
-     * @throws EE_Error
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     */
317
-    private function _get_payment_status_array()
318
-    {
319
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
320
-        $this->_template_args['payment_status'] = self::$_pay_status;
321
-    }
322
-
323
-
324
-    /**
325
-     *    _add_screen_options_default
326
-     *
327
-     * @access protected
328
-     * @return void
329
-     * @throws InvalidArgumentException
330
-     * @throws InvalidDataTypeException
331
-     * @throws InvalidInterfaceException
332
-     */
333
-    protected function _add_screen_options_default()
334
-    {
335
-        $this->_per_page_screen_option();
336
-    }
337
-
338
-
339
-    /**
340
-     * load_scripts_styles
341
-     *
342
-     * @access public
343
-     * @return void
344
-     */
345
-    public function load_scripts_styles()
346
-    {
347
-        // enqueue style
348
-        wp_register_style(
349
-            'espresso_txn',
350
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
351
-            [],
352
-            EVENT_ESPRESSO_VERSION
353
-        );
354
-        wp_enqueue_style('espresso_txn');
355
-        // scripts
356
-        wp_register_script(
357
-            'espresso_txn',
358
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
359
-            [
360
-                'ee_admin_js',
361
-                'ee-datepicker',
362
-                'jquery-ui-datepicker',
363
-                'jquery-ui-draggable',
364
-                'ee-dialog',
365
-                'ee-accounting',
366
-                'ee-serialize-full-array',
367
-            ],
368
-            EVENT_ESPRESSO_VERSION,
369
-            true
370
-        );
371
-        wp_enqueue_script('espresso_txn');
372
-    }
373
-
374
-
375
-    /**
376
-     *    load_scripts_styles_view_transaction
377
-     *
378
-     * @access public
379
-     * @return void
380
-     */
381
-    public function load_scripts_styles_view_transaction()
382
-    {
383
-        // styles
384
-        wp_enqueue_style('espresso-ui-theme');
385
-    }
386
-
387
-
388
-    /**
389
-     *    load_scripts_styles_default
390
-     *
391
-     * @access public
392
-     * @return void
393
-     */
394
-    public function load_scripts_styles_default()
395
-    {
396
-        // styles
397
-        wp_enqueue_style('espresso-ui-theme');
398
-    }
399
-
400
-
401
-    /**
402
-     *    _set_list_table_views_default
403
-     *
404
-     * @access protected
405
-     * @return void
406
-     */
407
-    protected function _set_list_table_views_default()
408
-    {
409
-        $this->_views = [
410
-            'all'        => [
411
-                'slug'  => 'all',
412
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
413
-                'count' => 0,
414
-            ],
415
-            'abandoned'  => [
416
-                'slug'  => 'abandoned',
417
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
418
-                'count' => 0,
419
-            ],
420
-            'incomplete' => [
421
-                'slug'  => 'incomplete',
422
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
423
-                'count' => 0,
424
-            ],
425
-        ];
426
-        if (
427
-            /**
428
-             * Filters whether a link to the "Failed Transactions" list table
429
-             * appears on the Transactions Admin Page list table.
430
-             * List display can be turned back on via the following:
431
-             * add_filter(
432
-             *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
433
-             *     '__return_true'
434
-             * );
435
-             *
436
-             * @param boolean                 $display_failed_txns_list
437
-             * @param Transactions_Admin_Page $this
438
-             * @since 4.9.70.p
439
-             */
440
-        apply_filters(
441
-            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
442
-            false,
443
-            $this
444
-        )
445
-        ) {
446
-            $this->_views['failed'] = [
447
-                'slug'  => 'failed',
448
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
449
-                'count' => 0,
450
-            ];
451
-        }
452
-    }
453
-
454
-
455
-    /**
456
-     * _set_transaction_object
457
-     * This sets the _transaction property for the transaction details screen
458
-     *
459
-     * @access private
460
-     * @return void
461
-     * @throws EE_Error
462
-     * @throws InvalidArgumentException
463
-     * @throws RuntimeException
464
-     * @throws InvalidDataTypeException
465
-     * @throws InvalidInterfaceException
466
-     * @throws ReflectionException
467
-     */
468
-    private function _set_transaction_object()
469
-    {
470
-        if ($this->_transaction instanceof EE_Transaction) {
471
-            return;
472
-        } //get out we've already set the object
473
-
474
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
475
-
476
-        // get transaction object
477
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
478
-        $this->_session     = $this->_transaction instanceof EE_Transaction
479
-            ? $this->_transaction->session_data()
480
-            : null;
481
-        if ($this->_transaction instanceof EE_Transaction) {
482
-            $this->_transaction->verify_abandoned_transaction_status();
483
-        }
484
-
485
-        if (! $this->_transaction instanceof EE_Transaction) {
486
-            $error_msg = sprintf(
487
-                esc_html__(
488
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
489
-                    'event_espresso'
490
-                ),
491
-                $TXN_ID
492
-            );
493
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
494
-        }
495
-    }
496
-
497
-
498
-    /**
499
-     *    _transaction_legend_items
500
-     *
501
-     * @access protected
502
-     * @return array
503
-     * @throws EE_Error
504
-     * @throws InvalidArgumentException
505
-     * @throws ReflectionException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidInterfaceException
508
-     */
509
-    protected function _transaction_legend_items()
510
-    {
511
-        EE_Registry::instance()->load_helper('MSG_Template');
512
-        $items = [];
513
-
514
-        if (
515
-            $this->capabilities->current_user_can(
516
-                'ee_read_global_messages',
517
-                'view_filtered_messages'
518
-            )
519
-        ) {
520
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
521
-            if (
522
-                is_array($related_for_icon)
523
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
524
-            ) {
525
-                $items['view_related_messages'] = [
526
-                    'class' => $related_for_icon['css_class'],
527
-                    'desc'  => $related_for_icon['label'],
528
-                ];
529
-            }
530
-        }
531
-
532
-        $items = apply_filters(
533
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
534
-            array_merge(
535
-                $items,
536
-                [
537
-                    'view_details'          => [
538
-                        'class' => 'dashicons dashicons-cart',
539
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
540
-                    ],
541
-                    'view_invoice'          => [
542
-                        'class' => 'dashicons dashicons-media-spreadsheet',
543
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
544
-                    ],
545
-                    'view_receipt'          => [
546
-                        'class' => 'dashicons dashicons-text-page',
547
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
548
-                    ],
549
-                    'view_registration'     => [
550
-                        'class' => 'dashicons dashicons-clipboard',
551
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
552
-                    ],
553
-                    'payment_overview_link' => [
554
-                        'class' => 'dashicons dashicons-money',
555
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
556
-                    ],
557
-                ]
558
-            )
559
-        );
560
-
561
-        if (
562
-            EEH_MSG_Template::is_mt_active('payment_reminder')
563
-            && $this->capabilities->current_user_can(
564
-                'ee_send_message',
565
-                'espresso_transactions_send_payment_reminder'
566
-            )
567
-        ) {
568
-            $items['send_payment_reminder'] = [
569
-                'class' => 'dashicons dashicons-email-alt',
570
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
571
-            ];
572
-        } else {
573
-            $items['blank*'] = [
574
-                'class' => '',
575
-                'desc'  => '',
576
-            ];
577
-        }
578
-        $more_items = apply_filters(
579
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
580
-            [
581
-                'overpaid'   => [
582
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
583
-                    'desc'  => EEH_Template::pretty_status(
584
-                        EEM_Transaction::overpaid_status_code,
585
-                        false,
586
-                        'sentence'
587
-                    ),
588
-                ],
589
-                'complete'   => [
590
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
591
-                    'desc'  => EEH_Template::pretty_status(
592
-                        EEM_Transaction::complete_status_code,
593
-                        false,
594
-                        'sentence'
595
-                    ),
596
-                ],
597
-                'incomplete' => [
598
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
599
-                    'desc'  => EEH_Template::pretty_status(
600
-                        EEM_Transaction::incomplete_status_code,
601
-                        false,
602
-                        'sentence'
603
-                    ),
604
-                ],
605
-                'abandoned'  => [
606
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
607
-                    'desc'  => EEH_Template::pretty_status(
608
-                        EEM_Transaction::abandoned_status_code,
609
-                        false,
610
-                        'sentence'
611
-                    ),
612
-                ],
613
-                'failed'     => [
614
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
615
-                    'desc'  => EEH_Template::pretty_status(
616
-                        EEM_Transaction::failed_status_code,
617
-                        false,
618
-                        'sentence'
619
-                    ),
620
-                ],
621
-            ]
622
-        );
623
-
624
-        return array_merge($items, $more_items);
625
-    }
626
-
627
-
628
-    /**
629
-     *    _transactions_overview_list_table
630
-     *
631
-     * @access protected
632
-     * @return void
633
-     * @throws DomainException
634
-     * @throws EE_Error
635
-     * @throws InvalidArgumentException
636
-     * @throws InvalidDataTypeException
637
-     * @throws InvalidInterfaceException
638
-     * @throws ReflectionException
639
-     */
640
-    protected function _transactions_overview_list_table()
641
-    {
642
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
643
-
644
-        $EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
645
-        $event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
646
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
647
-            ? sprintf(
648
-                esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
649
-                '<h3>',
650
-                '<a href="'
651
-                . EE_Admin_Page::add_query_args_and_nonce(
652
-                    ['action' => 'edit', 'post' => $event->ID()],
653
-                    EVENTS_ADMIN_URL
654
-                )
655
-                . '" aria-label="'
656
-                . esc_attr__('Click to Edit event', 'event_espresso')
657
-                . '">' . $event->name() . '</a>',
658
-                '</h3>'
659
-            )
660
-            : '';
661
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
662
-        $this->display_admin_list_table_page_with_no_sidebar();
663
-    }
664
-
665
-
666
-    /**
667
-     *    _transaction_details
668
-     * generates HTML for the View Transaction Details Admin page
669
-     *
670
-     * @access protected
671
-     * @return void
672
-     * @throws DomainException
673
-     * @throws EE_Error
674
-     * @throws InvalidArgumentException
675
-     * @throws InvalidDataTypeException
676
-     * @throws InvalidInterfaceException
677
-     * @throws RuntimeException
678
-     * @throws ReflectionException
679
-     */
680
-    protected function _transaction_details()
681
-    {
682
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
683
-
684
-        $this->_set_transaction_status_array();
685
-
686
-        $this->_template_args                      = [];
687
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
688
-
689
-        $this->_set_transaction_object();
690
-
691
-        if (! $this->_transaction instanceof EE_Transaction) {
692
-            return;
693
-        }
694
-
695
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
696
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
697
-
698
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
699
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
700
-
701
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
702
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
703
-        $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
704
-
705
-        $txn_total  = $this->_transaction->total();
706
-        $total_paid = $this->_transaction->paid();
707
-        $amount_due = $txn_total - $total_paid;
708
-
709
-        $this->_template_args['grand_total'] = $txn_total;
710
-        $this->_template_args['total_paid']  = $total_paid;
711
-
712
-        $this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
713
-        $this->_template_args['amount_due_raw'] = $amount_due;
714
-
715
-        $this->_template_args['amount_due_class'] = '';
716
-
717
-        if ($txn_total === (float) 0) {
718
-            // free event
719
-            $this->_template_args['amount_due'] = false;
720
-        } elseif ($amount_due < (float) 0) {
721
-            // overpaid
722
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
723
-        } elseif ($amount_due > (float) 0) {
724
-            // monies owing
725
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
726
-        } elseif ($total_paid === (float) 0) {
727
-            // no payments made yet
728
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
729
-        }
730
-
731
-        $payment_method = $this->_transaction->payment_method();
732
-
733
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
734
-            ? $payment_method->admin_name()
735
-            : esc_html__('Unknown', 'event_espresso');
736
-
737
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
738
-        // link back to overview
739
-        $this->_template_args['txn_overview_url'] = $this->request->getServerParam(
740
-            'HTTP_REFERER',
741
-            TXN_ADMIN_URL
742
-        );
743
-
744
-
745
-        // next link
746
-        $next_txn                                 = $this->_transaction->next(
747
-            null,
748
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
749
-            'TXN_ID'
750
-        );
751
-        $this->_template_args['next_transaction'] = $next_txn
752
-            ? $this->_next_link(
753
-                EE_Admin_Page::add_query_args_and_nonce(
754
-                    ['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
755
-                    TXN_ADMIN_URL
756
-                ),
757
-                'dashicons dashicons-arrow-right ee-icon-size-22'
758
-            )
759
-            : '';
760
-        // previous link
761
-        $previous_txn                                 = $this->_transaction->previous(
762
-            null,
763
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
764
-            'TXN_ID'
765
-        );
766
-        $this->_template_args['previous_transaction'] = $previous_txn
767
-            ? $this->_previous_link(
768
-                EE_Admin_Page::add_query_args_and_nonce(
769
-                    ['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
770
-                    TXN_ADMIN_URL
771
-                ),
772
-                'dashicons dashicons-arrow-left ee-icon-size-22'
773
-            )
774
-            : '';
775
-
776
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
777
-        $event_name    = $this->request->getRequestParam('event_name');
778
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
779
-
780
-        // were we just redirected here after adding a new registration ???
781
-        if ($EVT_ID && $event_name && $redirect_from) {
782
-            if (
783
-                $this->capabilities->current_user_can(
784
-                    'ee_edit_registrations',
785
-                    'espresso_registrations_new_registration',
786
-                    $EVT_ID
787
-                )
788
-            ) {
789
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
790
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
791
-                    [
792
-                        'page'     => 'espresso_registrations',
793
-                        'action'   => 'new_registration',
794
-                        'return'   => 'default',
795
-                        'TXN_ID'   => $this->_transaction->ID(),
796
-                        'event_id' => $EVT_ID,
797
-                    ],
798
-                    REG_ADMIN_URL
799
-                );
800
-                $this->_admin_page_title .= '">';
801
-
802
-                $this->_admin_page_title .= sprintf(
803
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
804
-                    htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
805
-                );
806
-                $this->_admin_page_title .= '</a>';
807
-            }
808
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
809
-        }
810
-        // grab messages at the last second
811
-        $this->_template_args['notices'] = EE_Error::get_notices();
812
-        // path to template
813
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
814
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
815
-            $template_path,
816
-            $this->_template_args,
817
-            true
818
-        );
819
-
820
-        // the details template wrapper
821
-        $this->display_admin_page_with_sidebar();
822
-    }
823
-
824
-
825
-    /**
826
-     *        _transaction_details_metaboxes
827
-     *
828
-     * @access protected
829
-     * @return void
830
-     * @throws EE_Error
831
-     * @throws InvalidArgumentException
832
-     * @throws InvalidDataTypeException
833
-     * @throws InvalidInterfaceException
834
-     * @throws RuntimeException
835
-     * @throws ReflectionException
836
-     */
837
-    protected function _transaction_details_metaboxes()
838
-    {
839
-        $this->_set_transaction_object();
840
-
841
-        if (! $this->_transaction instanceof EE_Transaction) {
842
-            return;
843
-        }
844
-        $this->addMetaBox(
845
-            'edit-txn-details-mbox',
846
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
847
-            . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
848
-            [$this, 'txn_details_meta_box'],
849
-            $this->_wp_page_slug
850
-        );
851
-        $this->addMetaBox(
852
-            'edit-txn-attendees-mbox',
853
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
854
-            . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
855
-            [$this, 'txn_attendees_meta_box'],
856
-            $this->_wp_page_slug,
857
-            'normal',
858
-            'high',
859
-            ['TXN_ID' => $this->_transaction->ID()]
860
-        );
861
-        $this->addMetaBox(
862
-            'edit-txn-registrant-mbox',
863
-            esc_html__('Primary Contact', 'event_espresso'),
864
-            [$this, 'txn_registrant_side_meta_box'],
865
-            $this->_wp_page_slug,
866
-            'side'
867
-        );
868
-        $this->addMetaBox(
869
-            'edit-txn-billing-info-mbox',
870
-            esc_html__('Billing Information', 'event_espresso'),
871
-            [$this, 'txn_billing_info_side_meta_box'],
872
-            $this->_wp_page_slug,
873
-            'side'
874
-        );
875
-    }
876
-
877
-
878
-    /**
879
-     * Callback for transaction actions metabox.
880
-     *
881
-     * @param EE_Transaction|null $transaction
882
-     * @return string
883
-     * @throws DomainException
884
-     * @throws EE_Error
885
-     * @throws InvalidArgumentException
886
-     * @throws InvalidDataTypeException
887
-     * @throws InvalidInterfaceException
888
-     * @throws ReflectionException
889
-     * @throws RuntimeException
890
-     */
891
-    public function getActionButtons(EE_Transaction $transaction = null)
892
-    {
893
-        $content = '';
894
-        $actions = [];
895
-        if (! $transaction instanceof EE_Transaction) {
896
-            return $content;
897
-        }
898
-        /** @var EE_Registration $primary_registration */
899
-        $primary_registration = $transaction->primary_registration();
900
-        $attendee             = $primary_registration instanceof EE_Registration
901
-            ? $primary_registration->attendee()
902
-            : null;
903
-
904
-        if (
905
-            $attendee instanceof EE_Attendee
906
-            && $this->capabilities->current_user_can(
907
-                'ee_send_message',
908
-                'espresso_transactions_send_payment_reminder'
909
-            )
910
-        ) {
911
-            $actions['payment_reminder'] =
912
-                EEH_MSG_Template::is_mt_active('payment_reminder')
913
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
914
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
915
-                    ? EEH_Template::get_button_or_link(
916
-                    EE_Admin_Page::add_query_args_and_nonce(
917
-                        [
918
-                            'action'      => 'send_payment_reminder',
919
-                            'TXN_ID'      => $this->_transaction->ID(),
920
-                            'redirect_to' => 'view_transaction',
921
-                        ],
922
-                        TXN_ADMIN_URL
923
-                    ),
924
-                    esc_html__(' Send Payment Reminder', 'event_espresso'),
925
-                    'button button--secondary',
926
-                    'dashicons dashicons-email-alt'
927
-                )
928
-                    : '';
929
-        }
930
-
931
-        if (
932
-            $this->capabilities->current_user_can(
933
-                'ee_edit_payments',
934
-                'espresso_transactions_recalculate_line_items'
935
-            )
936
-        ) {
937
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
938
-                EE_Admin_Page::add_query_args_and_nonce(
939
-                    [
940
-                        'action'      => 'espresso_recalculate_line_items',
941
-                        'TXN_ID'      => $this->_transaction->ID(),
942
-                        'redirect_to' => 'view_transaction',
943
-                    ],
944
-                    TXN_ADMIN_URL
945
-                ),
946
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
947
-                'button button--secondary',
948
-                'dashicons dashicons-update'
949
-            );
950
-        }
951
-
952
-        if (
953
-            $primary_registration instanceof EE_Registration
954
-            && EEH_MSG_Template::is_mt_active('receipt')
955
-        ) {
956
-            $actions['receipt'] = EEH_Template::get_button_or_link(
957
-                $primary_registration->receipt_url(),
958
-                esc_html__('View Receipt', 'event_espresso'),
959
-                'button button--secondary',
960
-                'dashicons dashicons-text-page'
961
-            );
962
-        }
963
-
964
-        if (
965
-            $primary_registration instanceof EE_Registration
966
-            && EEH_MSG_Template::is_mt_active('invoice')
967
-        ) {
968
-            $actions['invoice'] = EEH_Template::get_button_or_link(
969
-                $primary_registration->invoice_url(),
970
-                esc_html__('View Invoice', 'event_espresso'),
971
-                'button button--secondary',
972
-                'dashicons dashicons-media-spreadsheet'
973
-            );
974
-        }
975
-        $actions = array_filter(
976
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
977
-        );
978
-        if ($actions) {
979
-            $content .= implode('', $actions);
980
-        }
981
-        return $content;
982
-    }
983
-
984
-
985
-    /**
986
-     * txn_details_meta_box
987
-     * generates HTML for the Transaction main meta box
988
-     *
989
-     * @return void
990
-     * @throws DomainException
991
-     * @throws EE_Error
992
-     * @throws InvalidArgumentException
993
-     * @throws InvalidDataTypeException
994
-     * @throws InvalidInterfaceException
995
-     * @throws RuntimeException
996
-     * @throws ReflectionException
997
-     */
998
-    public function txn_details_meta_box()
999
-    {
1000
-        $this->_set_transaction_object();
1001
-        $this->_template_args['TXN_ID']              = $this->_transaction->ID();
1002
-        $this->_template_args['attendee']            =
1003
-            $this->_transaction->primary_registration() instanceof EE_Registration
1004
-                ? $this->_transaction->primary_registration()->attendee()
1005
-                : null;
1006
-        $this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1007
-            'ee_edit_payments',
1008
-            'apply_payment_or_refund_from_registration_details'
1009
-        );
1010
-        $this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1011
-            'ee_delete_payments',
1012
-            'delete_payment_from_registration_details'
1013
-        );
1014
-
1015
-        // get line table
1016
-        EEH_Autoloader::register_line_item_display_autoloaders();
1017
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1018
-            'admin_table',
1019
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1020
-        );
1021
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1022
-            $this->_transaction->total_line_item()
1023
-        );
1024
-        $this->_template_args['REG_code']        =
1025
-            $this->_transaction->primary_registration() instanceof EE_Registration
1026
-                ? $this->_transaction->primary_registration()->reg_code()
1027
-                : null;
1028
-        // process taxes
1029
-        $taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1030
-        $this->_template_args['taxes'] = ! empty($taxes)
1031
-            ? $taxes
1032
-            : false;
1033
-
1034
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1035
-            $this->_transaction->total(),
1036
-            false,
1037
-            false
1038
-        );
1039
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1040
-        $this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1041
-
1042
-        // process payment details
1043
-        $payments = $this->_transaction->payments();
1044
-        if (! empty($payments)) {
1045
-            $this->_template_args['payments']              = $payments;
1046
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1047
-        } else {
1048
-            $this->_template_args['payments']              = false;
1049
-            $this->_template_args['existing_reg_payments'] = [];
1050
-        }
1051
-
1052
-        $this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1053
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1054
-            ['action' => 'espresso_delete_payment'],
1055
-            TXN_ADMIN_URL
1056
-        );
1057
-
1058
-        if (isset($txn_details['invoice_number'])) {
1059
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1060
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1061
-                'Invoice Number',
1062
-                'event_espresso'
1063
-            );
1064
-        }
1065
-
1066
-        $this->_template_args['txn_details']['registration_session']['value'] =
1067
-            $this->_transaction->primary_registration() instanceof EE_Registration
1068
-                ? $this->_transaction->primary_registration()->session_ID()
1069
-                : null;
1070
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1071
-            'Registration Session',
1072
-            'event_espresso'
1073
-        );
1074
-
1075
-        $this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1076
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1077
-            'Transaction placed from IP',
1078
-            'event_espresso'
1079
-        );
1080
-
1081
-        $this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1082
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1083
-            'Registrant User Agent',
1084
-            'event_espresso'
1085
-        );
1086
-
1087
-        $reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1088
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1089
-            if ($reg_step_status === true) {
1090
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1091
-                              . sprintf(
1092
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1093
-                                  ucwords(str_replace('_', ' ', $reg_step))
1094
-                              )
1095
-                              . '</div>';
1096
-            } elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1097
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1098
-                              . sprintf(
1099
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1100
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1101
-                                  date(
1102
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1103
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1104
-                                  )
1105
-                              )
1106
-                              . '</div>';
1107
-            } else {
1108
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1109
-                              . sprintf(
1110
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1111
-                                  ucwords(str_replace('_', ' ', $reg_step))
1112
-                              )
1113
-                              . '</div>';
1114
-            }
1115
-        }
1116
-        $reg_steps                                                 .= '</ul>';
1117
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1118
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1119
-            'Registration Step Progress',
1120
-            'event_espresso'
1121
-        );
1122
-
1123
-
1124
-        $this->_get_registrations_to_apply_payment_to();
1125
-        $this->_get_payment_methods($payments);
1126
-        $this->_get_payment_status_array();
1127
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1128
-
1129
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1130
-            [
1131
-                'action'  => 'edit_transaction',
1132
-                'process' => 'transaction',
1133
-            ],
1134
-            TXN_ADMIN_URL
1135
-        );
1136
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1137
-            [
1138
-                'page'   => 'espresso_transactions',
1139
-                'action' => 'espresso_apply_payment',
1140
-            ],
1141
-            TXN_ADMIN_URL
1142
-        );
1143
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1144
-            [
1145
-                'page'   => 'espresso_transactions',
1146
-                'action' => 'espresso_delete_payment',
1147
-            ],
1148
-            TXN_ADMIN_URL
1149
-        );
1150
-
1151
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1152
-
1153
-        // 'espresso_delete_payment_nonce'
1154
-
1155
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1156
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1157
-    }
1158
-
1159
-
1160
-    /**
1161
-     * _get_registration_payment_IDs
1162
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1163
-     *
1164
-     * @access protected
1165
-     * @param EE_Payment[] $payments
1166
-     * @return array
1167
-     * @throws EE_Error
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws InvalidInterfaceException
1171
-     * @throws ReflectionException
1172
-     */
1173
-    protected function _get_registration_payment_IDs($payments = [])
1174
-    {
1175
-        $existing_reg_payments = [];
1176
-        // get all reg payments for these payments
1177
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1178
-            [
1179
-                [
1180
-                    'PAY_ID' => [
1181
-                        'IN',
1182
-                        array_keys($payments),
1183
-                    ],
1184
-                ],
1185
-            ]
1186
-        );
1187
-        if (! empty($reg_payments)) {
1188
-            foreach ($payments as $payment) {
1189
-                if (! $payment instanceof EE_Payment) {
1190
-                    continue;
1191
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1192
-                    $existing_reg_payments[ $payment->ID() ] = [];
1193
-                }
1194
-                foreach ($reg_payments as $reg_payment) {
1195
-                    if (
1196
-                        $reg_payment instanceof EE_Registration_Payment
1197
-                        && $reg_payment->payment_ID() === $payment->ID()
1198
-                    ) {
1199
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1200
-                    }
1201
-                }
1202
-            }
1203
-        }
1204
-
1205
-        return $existing_reg_payments;
1206
-    }
1207
-
1208
-
1209
-    /**
1210
-     * _get_registrations_to_apply_payment_to
1211
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1212
-     * which allows the admin to only apply the payment to the specific registrations
1213
-     *
1214
-     * @access protected
1215
-     * @return void
1216
-     * @throws EE_Error
1217
-     * @throws InvalidArgumentException
1218
-     * @throws InvalidDataTypeException
1219
-     * @throws InvalidInterfaceException
1220
-     * @throws ReflectionException
1221
-     */
1222
-    protected function _get_registrations_to_apply_payment_to()
1223
-    {
1224
-        // we want any registration with an active status (ie: not deleted or cancelled)
1225
-        $query_params                      = [
1226
-            [
1227
-                'STS_ID' => [
1228
-                    'IN',
1229
-                    [
1230
-                        RegStatus::APPROVED,
1231
-                        RegStatus::PENDING_PAYMENT,
1232
-                        RegStatus::AWAITING_REVIEW,
1233
-                    ],
1234
-                ],
1235
-            ],
1236
-        ];
1237
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1238
-                '',
1239
-                'txn-admin-apply-payment-to-registrations-dv',
1240
-                '',
1241
-                'clear: both; margin: 1.5em 0 0; display: none;'
1242
-            );
1243
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1244
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1245
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1246
-            EEH_HTML::tr(
1247
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1248
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1249
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1250
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1251
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1252
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1253
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1254
-            )
1255
-        );
1256
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1257
-        // get registrations for TXN
1258
-        $registrations         = $this->_transaction->registrations($query_params);
1259
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1260
-        foreach ($registrations as $registration) {
1261
-            if ($registration instanceof EE_Registration) {
1262
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1263
-                    ? $registration->attendee()->full_name()
1264
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1265
-                $owing                             = $registration->final_price() - $registration->paid();
1266
-                $taxable                           = $registration->ticket()->taxable()
1267
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1268
-                    : '';
1269
-                $checked                           = empty($existing_reg_payments)
1270
-                                                     || in_array($registration->ID(), $existing_reg_payments, true)
1271
-                    ? ' checked'
1272
-                    : '';
1273
-                $disabled                          = $registration->final_price() > 0
1274
-                    ? ''
1275
-                    : ' disabled';
1276
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1277
-                    EEH_HTML::td($registration->ID()) .
1278
-                    EEH_HTML::td($attendee_name) .
1279
-                    EEH_HTML::td(
1280
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1281
-                    ) .
1282
-                    EEH_HTML::td($registration->event_name()) .
1283
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1284
-                    EEH_HTML::td(
1285
-                        EEH_Template::format_currency($owing),
1286
-                        '',
1287
-                        'txn-admin-payment-owing-td jst-cntr'
1288
-                    ) .
1289
-                    EEH_HTML::td(
1290
-                        '<input type="checkbox" value="' . $registration->ID()
1291
-                        . '" name="txn_admin_payment[registrations]"'
1292
-                        . $checked . $disabled . '>',
1293
-                        '',
1294
-                        'jst-cntr'
1295
-                    ),
1296
-                    'apply-payment-registration-row-' . $registration->ID()
1297
-                );
1298
-            }
1299
-        }
1300
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1301
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1302
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1303
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1304
-            esc_html__(
1305
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1306
-                'event_espresso'
1307
-            ),
1308
-            '',
1309
-            'clear description'
1310
-        );
1311
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1312
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1313
-    }
1314
-
1315
-
1316
-    /**
1317
-     * _get_reg_status_selection
1318
-     *
1319
-     * @return void
1320
-     * @throws EE_Error
1321
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1322
-     *         instead of events.
1323
-     * @access protected
1324
-     */
1325
-    protected function _get_reg_status_selection()
1326
-    {
1327
-        // first get all possible statuses
1328
-        $statuses = EEM_Registration::reg_status_array([], true);
1329
-        // let's add a "don't change" option.
1330
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1331
-        $status_array                                        = array_merge($status_array, $statuses);
1332
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1333
-            'txn_reg_status_change[reg_status]',
1334
-            $status_array,
1335
-            'NAN',
1336
-            'id="txn-admin-payment-reg-status-inp"',
1337
-            'txn-reg-status-change-reg-status'
1338
-        );
1339
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1340
-            'delete_txn_reg_status_change[reg_status]',
1341
-            $status_array,
1342
-            'NAN',
1343
-            'delete-txn-admin-payment-reg-status-inp',
1344
-            'delete-txn-reg-status-change-reg-status'
1345
-        );
1346
-    }
1347
-
1348
-
1349
-    /**
1350
-     *    _get_payment_methods
1351
-     * Gets all the payment methods available generally, or the ones that are already
1352
-     * selected on these payments (in case their payment methods are no longer active).
1353
-     * Has the side-effect of updating the template args' payment_methods item
1354
-     *
1355
-     * @access private
1356
-     * @param EE_Payment[] to show on this page
1357
-     * @return void
1358
-     * @throws EE_Error
1359
-     * @throws InvalidArgumentException
1360
-     * @throws InvalidDataTypeException
1361
-     * @throws InvalidInterfaceException
1362
-     * @throws ReflectionException
1363
-     */
1364
-    private function _get_payment_methods($payments = [])
1365
-    {
1366
-        $payment_methods_of_payments = [];
1367
-        foreach ($payments as $payment) {
1368
-            if ($payment instanceof EE_Payment) {
1369
-                $payment_methods_of_payments[] = $payment->ID();
1370
-            }
1371
-        }
1372
-        if ($payment_methods_of_payments) {
1373
-            $query_args = [
1374
-                [
1375
-                    'OR*payment_method_for_payment' => [
1376
-                        'PMD_ID'    => ['IN', $payment_methods_of_payments],
1377
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1378
-                    ],
1379
-                ],
1380
-            ];
1381
-        } else {
1382
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1383
-        }
1384
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1385
-    }
1386
-
1387
-
1388
-    /**
1389
-     * txn_attendees_meta_box
1390
-     *    generates HTML for the Attendees Transaction main meta box
1391
-     *
1392
-     * @access public
1393
-     * @param WP_Post $post
1394
-     * @param array   $metabox
1395
-     * @return void
1396
-     * @throws DomainException
1397
-     * @throws EE_Error
1398
-     * @throws InvalidArgumentException
1399
-     * @throws InvalidDataTypeException
1400
-     * @throws InvalidInterfaceException
1401
-     * @throws ReflectionException
1402
-     */
1403
-    public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1404
-    {
1405
-        /** @noinspection NonSecureExtractUsageInspection */
1406
-        extract($metabox['args']);
1407
-        $this->_template_args['post']            = $post;
1408
-        $this->_template_args['event_attendees'] = [];
1409
-        // process items in cart
1410
-        $line_items = $this->_transaction->get_many_related(
1411
-            'Line_Item',
1412
-            [['LIN_type' => 'line-item']]
1413
-        );
1414
-        if (! empty($line_items)) {
1415
-            foreach ($line_items as $item) {
1416
-                if ($item instanceof EE_Line_Item) {
1417
-                    switch ($item->OBJ_type()) {
1418
-                        case 'Event':
1419
-                            break;
1420
-                        case 'Ticket':
1421
-                            $ticket = $item->ticket();
1422
-                            // right now we're only handling tickets here.
1423
-                            // Cause its expected that only tickets will have attendees right?
1424
-                            if (! $ticket instanceof EE_Ticket) {
1425
-                                break;
1426
-                            }
1427
-                            try {
1428
-                                $event_name = $ticket->get_event_name();
1429
-                            } catch (Exception $e) {
1430
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1431
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1432
-                            }
1433
-                            $event_name   .= ' - ' . $item->name();
1434
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1435
-                            // now get all of the registrations for this transaction that use this ticket
1436
-                            $registrations = $ticket->registrations(
1437
-                                [['TXN_ID' => $this->_transaction->ID()]]
1438
-                            );
1439
-                            foreach ($registrations as $registration) {
1440
-                                if (! $registration instanceof EE_Registration) {
1441
-                                    break;
1442
-                                }
1443
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1444
-                                    = $registration->status_ID();
1445
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1446
-                                    = $registration->count();
1447
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1448
-                                    = $event_name;
1449
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1450
-                                    = $ticket_price;
1451
-                                // attendee info
1452
-                                $attendee = $registration->get_first_related('Attendee');
1453
-                                if ($attendee instanceof EE_Attendee) {
1454
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1455
-                                        = $attendee->ID();
1456
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1457
-                                        = $attendee->full_name();
1458
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1459
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1460
-                                          . esc_html__(
1461
-                                              ' Event',
1462
-                                              'event_espresso'
1463
-                                          )
1464
-                                          . '">' . $attendee->email() . '</a>';
1465
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1466
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1467
-                                } else {
1468
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1469
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1470
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1471
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1472
-                                }
1473
-                            }
1474
-                            break;
1475
-                    }
1476
-                }
1477
-            }
1478
-
1479
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1480
-                [
1481
-                    'action'  => 'edit_transaction',
1482
-                    'process' => 'attendees',
1483
-                ],
1484
-                TXN_ADMIN_URL
1485
-            );
1486
-            echo EEH_Template::display_template(
1487
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1488
-                $this->_template_args,
1489
-                true
1490
-            );
1491
-        } else {
1492
-            printf(
1493
-                esc_html__(
1494
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1495
-                    'event_espresso'
1496
-                ),
1497
-                '<p class="important-notice">',
1498
-                '</p>'
1499
-            );
1500
-        }
1501
-    }
1502
-
1503
-
1504
-    /**
1505
-     * txn_registrant_side_meta_box
1506
-     * generates HTML for the Edit Transaction side meta box
1507
-     *
1508
-     * @access public
1509
-     * @return void
1510
-     * @throws DomainException
1511
-     * @throws EE_Error
1512
-     * @throws InvalidArgumentException
1513
-     * @throws InvalidDataTypeException
1514
-     * @throws InvalidInterfaceException
1515
-     * @throws ReflectionException
1516
-     */
1517
-    public function txn_registrant_side_meta_box()
1518
-    {
1519
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1520
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1521
-            : null;
1522
-        if (! $primary_att instanceof EE_Attendee) {
1523
-            $this->_template_args['no_attendee_message'] = esc_html__(
1524
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1525
-                'event_espresso'
1526
-            );
1527
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1528
-        }
1529
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1530
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1531
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1532
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1533
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1534
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1535
-            [
1536
-                'action' => 'edit_attendee',
1537
-                'post'   => $primary_att->ID(),
1538
-            ],
1539
-            REG_ADMIN_URL
1540
-        );
1541
-        // get formatted address for registrant
1542
-        $formatted_address                         = EEH_Address::format($primary_att);
1543
-        $formatted_address                         =
1544
-            $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1545
-                ? $formatted_address
1546
-                : '';
1547
-        $this->_template_args['formatted_address'] = $formatted_address;
1548
-        echo EEH_Template::display_template(
1549
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1550
-            $this->_template_args,
1551
-            true
1552
-        );
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * txn_billing_info_side_meta_box
1558
-     *    generates HTML for the Edit Transaction side meta box
1559
-     *
1560
-     * @access public
1561
-     * @return void
1562
-     * @throws DomainException
1563
-     */
1564
-    public function txn_billing_info_side_meta_box()
1565
-    {
1566
-        try {
1567
-            $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1568
-            $this->_template_args['billing_form_url'] = add_query_arg(
1569
-                ['action' => 'edit_transaction', 'process' => 'billing'],
1570
-                TXN_ADMIN_URL
1571
-            );
1572
-        } catch (Exception $e) {
1573
-            $this->_template_args['billing_form'] = [];
1574
-            $this->_template_args['billing_form_url'] = '';
1575
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1576
-        }
1577
-
1578
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1579
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1580
-    }
1581
-
1582
-
1583
-    /**
1584
-     * apply_payments_or_refunds
1585
-     *    registers a payment or refund made towards a transaction
1586
-     *
1587
-     * @access public
1588
-     * @return void
1589
-     * @throws EE_Error
1590
-     * @throws InvalidArgumentException
1591
-     * @throws ReflectionException
1592
-     * @throws RuntimeException
1593
-     * @throws InvalidDataTypeException
1594
-     * @throws InvalidInterfaceException
1595
-     */
1596
-    public function apply_payments_or_refunds()
1597
-    {
1598
-        $valid_data = $this->_validate_payment_request_data();
1599
-        $has_access = $this->capabilities->current_user_can(
1600
-            'ee_edit_payments',
1601
-            'apply_payment_or_refund_from_registration_details'
1602
-        );
1603
-        $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1604
-        $amount     = 0;
1605
-        if (! empty($valid_data) && $has_access) {
1606
-            $PAY_ID = $valid_data['PAY_ID'];
1607
-            // save  the new payment
1608
-            $payment = $this->_create_payment_from_request_data($valid_data);
1609
-            $amount  = $payment->amount();
1610
-            // get the TXN for this payment
1611
-            $transaction = $payment->transaction();
1612
-            // verify transaction
1613
-            if ($transaction instanceof EE_Transaction) {
1614
-                // calculate_total_payments_and_update_status
1615
-                $this->_process_transaction_payments($transaction);
1616
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1617
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1618
-                // apply payment to registrations (if applicable)
1619
-                if (! empty($REG_IDs)) {
1620
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1621
-                    $this->_maybe_send_notifications();
1622
-                    // now process status changes for the same registrations
1623
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1624
-                }
1625
-                $this->_maybe_send_notifications($payment);
1626
-                // prepare to render page
1627
-                do_action(
1628
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1629
-                    $transaction,
1630
-                    $payment
1631
-                );
1632
-            } else {
1633
-                EE_Error::add_error(
1634
-                    esc_html__(
1635
-                        'A valid Transaction for this payment could not be retrieved.',
1636
-                        'event_espresso'
1637
-                    ),
1638
-                    __FILE__,
1639
-                    __FUNCTION__,
1640
-                    __LINE__
1641
-                );
1642
-            }
1643
-        } elseif ($has_access) {
1644
-            EE_Error::add_error(
1645
-                esc_html__(
1646
-                    'The payment form data could not be processed. Please try again.',
1647
-                    'event_espresso'
1648
-                ),
1649
-                __FILE__,
1650
-                __FUNCTION__,
1651
-                __LINE__
1652
-            );
1653
-        } else {
1654
-            EE_Error::add_error(
1655
-                esc_html__(
1656
-                    'You do not have access to apply payments or refunds to a registration.',
1657
-                    'event_espresso'
1658
-                ),
1659
-                __FILE__,
1660
-                __FUNCTION__,
1661
-                __LINE__
1662
-            );
1663
-        }
1664
-        $query_args = [
1665
-            'page'   => 'espresso_transactions',
1666
-            'action' => 'view_transaction',
1667
-            'TXN_ID' => $TXD_ID,
1668
-        ];
1669
-
1670
-        $this->_redirect_after_action(
1671
-            ! EE_Error::has_error(),
1672
-            $amount > 0
1673
-                ? esc_html__('payment', 'event_espresso')
1674
-                : esc_html__('refund', 'event_espresso'),
1675
-            esc_html__('processed', 'event_espresso'),
1676
-            $query_args
1677
-        );
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     * _validate_payment_request_data
1683
-     *
1684
-     * @return array
1685
-     * @throws EE_Error
1686
-     * @throws InvalidArgumentException
1687
-     * @throws InvalidDataTypeException
1688
-     * @throws InvalidInterfaceException
1689
-     */
1690
-    protected function _validate_payment_request_data()
1691
-    {
1692
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1693
-            return [];
1694
-        }
1695
-        $payment_form = $this->_generate_payment_form_section();
1696
-        try {
1697
-            if ($payment_form->was_submitted()) {
1698
-                $payment_form->receive_form_submission();
1699
-                if (! $payment_form->is_valid()) {
1700
-                    $submission_error_messages = [];
1701
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1702
-                        if ($validation_error instanceof EE_Validation_Error) {
1703
-                            $form_input                  = $validation_error->get_form_section();
1704
-                            $submission_error_messages[] = sprintf(
1705
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1706
-                                $form_input instanceof EE_Form_Input_Base
1707
-                                    ? $form_input->html_label_text()
1708
-                                    : '',
1709
-                                $validation_error->getMessage()
1710
-                            );
1711
-                        }
1712
-                    }
1713
-                    EE_Error::add_error(
1714
-                        implode('<br />', $submission_error_messages),
1715
-                        __FILE__,
1716
-                        __FUNCTION__,
1717
-                        __LINE__
1718
-                    );
1719
-                    return [];
1720
-                }
1721
-            }
1722
-        } catch (EE_Error $e) {
1723
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1724
-            return [];
1725
-        }
1726
-
1727
-        return $payment_form->valid_data();
1728
-    }
1729
-
1730
-
1731
-    /**
1732
-     * _generate_payment_form_section
1733
-     *
1734
-     * @return EE_Form_Section_Proper
1735
-     * @throws EE_Error
1736
-     */
1737
-    protected function _generate_payment_form_section()
1738
-    {
1739
-        return new EE_Form_Section_Proper(
1740
-            [
1741
-                'name'        => 'txn_admin_payment',
1742
-                'subsections' => [
1743
-                    'PAY_ID'          => new EE_Text_Input(
1744
-                        [
1745
-                            'default'               => 0,
1746
-                            'required'              => false,
1747
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1748
-                            'validation_strategies' => [new EE_Int_Normalization()],
1749
-                        ]
1750
-                    ),
1751
-                    'TXN_ID'          => new EE_Text_Input(
1752
-                        [
1753
-                            'default'               => 0,
1754
-                            'required'              => true,
1755
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1756
-                            'validation_strategies' => [new EE_Int_Normalization()],
1757
-                        ]
1758
-                    ),
1759
-                    'type'            => new EE_Text_Input(
1760
-                        [
1761
-                            'default'               => 1,
1762
-                            'required'              => true,
1763
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1764
-                            'validation_strategies' => [new EE_Int_Normalization()],
1765
-                        ]
1766
-                    ),
1767
-                    'amount'          => new EE_Text_Input(
1768
-                        [
1769
-                            'default'               => 0,
1770
-                            'required'              => true,
1771
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1772
-                            'validation_strategies' => [new EE_Float_Normalization()],
1773
-                        ]
1774
-                    ),
1775
-                    'status'          => new EE_Text_Input(
1776
-                        [
1777
-                            'default'         => EEM_Payment::status_id_approved,
1778
-                            'required'        => true,
1779
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1780
-                        ]
1781
-                    ),
1782
-                    'PMD_ID'          => new EE_Text_Input(
1783
-                        [
1784
-                            'default'               => 2,
1785
-                            'required'              => true,
1786
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1787
-                            'validation_strategies' => [new EE_Int_Normalization()],
1788
-                        ]
1789
-                    ),
1790
-                    'date'            => new EE_Text_Input(
1791
-                        [
1792
-                            'default'         => time(),
1793
-                            'required'        => true,
1794
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1795
-                        ]
1796
-                    ),
1797
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1798
-                        [
1799
-                            'default'               => '',
1800
-                            'required'              => false,
1801
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1802
-                            'validation_strategies' => [
1803
-                                new EE_Max_Length_Validation_Strategy(
1804
-                                    esc_html__('Input too long', 'event_espresso'),
1805
-                                    100
1806
-                                ),
1807
-                            ],
1808
-                        ]
1809
-                    ),
1810
-                    'po_number'       => new EE_Text_Input(
1811
-                        [
1812
-                            'default'               => '',
1813
-                            'required'              => false,
1814
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1815
-                            'validation_strategies' => [
1816
-                                new EE_Max_Length_Validation_Strategy(
1817
-                                    esc_html__('Input too long', 'event_espresso'),
1818
-                                    100
1819
-                                ),
1820
-                            ],
1821
-                        ]
1822
-                    ),
1823
-                    'accounting'      => new EE_Text_Input(
1824
-                        [
1825
-                            'default'               => '',
1826
-                            'required'              => false,
1827
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1828
-                            'validation_strategies' => [
1829
-                                new EE_Max_Length_Validation_Strategy(
1830
-                                    esc_html__('Input too long', 'event_espresso'),
1831
-                                    100
1832
-                                ),
1833
-                            ],
1834
-                        ]
1835
-                    ),
1836
-                ],
1837
-            ]
1838
-        );
1839
-    }
1840
-
1841
-
1842
-    /**
1843
-     * _create_payment_from_request_data
1844
-     *
1845
-     * @param array $valid_data
1846
-     * @return EE_Payment
1847
-     * @throws EE_Error
1848
-     * @throws InvalidArgumentException
1849
-     * @throws InvalidDataTypeException
1850
-     * @throws InvalidInterfaceException
1851
-     * @throws ReflectionException
1852
-     */
1853
-    protected function _create_payment_from_request_data($valid_data)
1854
-    {
1855
-        $PAY_ID = $valid_data['PAY_ID'];
1856
-        // get payment amount
1857
-        $amount = $valid_data['amount']
1858
-            ? EEH_Money::strip_localized_money_formatting($valid_data['amount'])
1859
-            : 0;
1860
-        // payments have a type value of 1 and refunds have a type value of -1
1861
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1862
-        $amount = $valid_data['type'] < 0
1863
-            ? $amount * -1
1864
-            : $amount;
1865
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1866
-        $date    = $valid_data['date']
1867
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1868
-            : date('Y-m-d g:i a', current_time('timestamp'));
1869
-        $payment = EE_Payment::new_instance(
1870
-            [
1871
-                'TXN_ID'              => $valid_data['TXN_ID'],
1872
-                'STS_ID'              => $valid_data['status'],
1873
-                'PAY_timestamp'       => $date,
1874
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1875
-                'PMD_ID'              => $valid_data['PMD_ID'],
1876
-                'PAY_amount'          => $amount,
1877
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1878
-                'PAY_po_number'       => $valid_data['po_number'],
1879
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1880
-                'PAY_details'         => $valid_data,
1881
-                'PAY_ID'              => $PAY_ID,
1882
-            ],
1883
-            '',
1884
-            ['Y-m-d', 'g:i a']
1885
-        );
1886
-
1887
-        if (! $payment->save()) {
1888
-            EE_Error::add_error(
1889
-                sprintf(
1890
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1891
-                    $payment->ID()
1892
-                ),
1893
-                __FILE__,
1894
-                __FUNCTION__,
1895
-                __LINE__
1896
-            );
1897
-        }
1898
-
1899
-        return $payment;
1900
-    }
1901
-
1902
-
1903
-    /**
1904
-     * _process_transaction_payments
1905
-     *
1906
-     * @param EE_Transaction $transaction
1907
-     * @return void
1908
-     * @throws EE_Error
1909
-     * @throws InvalidArgumentException
1910
-     * @throws ReflectionException
1911
-     * @throws InvalidDataTypeException
1912
-     * @throws InvalidInterfaceException
1913
-     */
1914
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1915
-    {
1916
-        /** @type EE_Transaction_Payments $transaction_payments */
1917
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1918
-        // update the transaction with this payment
1919
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1920
-            EE_Error::add_success(
1921
-                esc_html__(
1922
-                    'The payment has been processed successfully.',
1923
-                    'event_espresso'
1924
-                ),
1925
-                __FILE__,
1926
-                __FUNCTION__,
1927
-                __LINE__
1928
-            );
1929
-        } else {
1930
-            EE_Error::add_error(
1931
-                esc_html__(
1932
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1933
-                    'event_espresso'
1934
-                ),
1935
-                __FILE__,
1936
-                __FUNCTION__,
1937
-                __LINE__
1938
-            );
1939
-        }
1940
-    }
1941
-
1942
-
1943
-    /**
1944
-     * _get_REG_IDs_to_apply_payment_to
1945
-     * returns a list of registration IDs that the payment will apply to
1946
-     *
1947
-     * @param EE_Payment $payment
1948
-     * @return array
1949
-     * @throws EE_Error
1950
-     * @throws InvalidArgumentException
1951
-     * @throws InvalidDataTypeException
1952
-     * @throws InvalidInterfaceException
1953
-     * @throws ReflectionException
1954
-     */
1955
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1956
-    {
1957
-        // grab array of IDs for specific registrations to apply changes to
1958
-        $apply_to_all = $this->request->getRequestParam(
1959
-            'txn_admin_payment[apply_to_all_registrations]',
1960
-            false,
1961
-            DataType::BOOL
1962
-        );
1963
-        $REG_IDs      = ! $apply_to_all
1964
-            ? $this->request->getRequestParam(
1965
-                'txn_admin_payment[registrations]',
1966
-                [],
1967
-                DataType::INT,
1968
-                true
1969
-            )
1970
-            : [];
1971
-        // nothing specified ? then get all reg IDs
1972
-        if ($apply_to_all || empty($REG_IDs)) {
1973
-            $registrations = $payment->transaction()->registrations(
1974
-                [
1975
-                    [
1976
-                        'STS_ID' => [
1977
-                            'NOT_IN', [ RegStatus::CANCELLED ]
1978
-                        ]
1979
-                    ]
1980
-                ]
1981
-            );
1982
-            $REG_IDs       = ! empty($registrations)
1983
-                ? array_keys($registrations)
1984
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1985
-        }
1986
-        // ensure that REG_IDs are integers and NOT strings
1987
-        return array_map('absint', $REG_IDs);
1988
-    }
1989
-
1990
-
1991
-    /**
1992
-     * @return array
1993
-     */
1994
-    public function existing_reg_payment_REG_IDs()
1995
-    {
1996
-        return $this->_existing_reg_payment_REG_IDs;
1997
-    }
1998
-
1999
-
2000
-    /**
2001
-     * @param array $existing_reg_payment_REG_IDs
2002
-     */
2003
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2004
-    {
2005
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2006
-    }
2007
-
2008
-
2009
-    /**
2010
-     * _get_existing_reg_payment_REG_IDs
2011
-     * returns a list of registration IDs that the payment is currently related to
2012
-     * as recorded in the database
2013
-     *
2014
-     * @param EE_Payment $payment
2015
-     * @return array
2016
-     * @throws EE_Error
2017
-     * @throws InvalidArgumentException
2018
-     * @throws InvalidDataTypeException
2019
-     * @throws InvalidInterfaceException
2020
-     * @throws ReflectionException
2021
-     */
2022
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2023
-    {
2024
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2025
-            // let's get any existing reg payment records for this payment
2026
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2027
-            // but we only want the REG IDs, so grab the array keys
2028
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2029
-                ? array_keys($existing_reg_payment_REG_IDs)
2030
-                : [];
2031
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2032
-        }
2033
-
2034
-        return $this->existing_reg_payment_REG_IDs();
2035
-    }
2036
-
2037
-
2038
-    /**
2039
-     * _remove_existing_registration_payments
2040
-     * this calculates the difference between existing relations
2041
-     * to the supplied payment and the new list registration IDs,
2042
-     * removes any related registrations that no longer apply,
2043
-     * and then updates the registration paid fields
2044
-     *
2045
-     * @param EE_Payment $payment
2046
-     * @param int        $PAY_ID
2047
-     * @return bool;
2048
-     * @throws EE_Error
2049
-     * @throws InvalidArgumentException
2050
-     * @throws ReflectionException
2051
-     * @throws InvalidDataTypeException
2052
-     * @throws InvalidInterfaceException
2053
-     */
2054
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2055
-    {
2056
-        // newly created payments will have nothing recorded for $PAY_ID
2057
-        if (absint($PAY_ID) === 0) {
2058
-            return false;
2059
-        }
2060
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2061
-        if (empty($existing_reg_payment_REG_IDs)) {
2062
-            return false;
2063
-        }
2064
-        /** @type EE_Transaction_Payments $transaction_payments */
2065
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2066
-
2067
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2068
-            $payment,
2069
-            [
2070
-                [
2071
-                    'PAY_ID' => $payment->ID(),
2072
-                    'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2073
-                ],
2074
-            ]
2075
-        );
2076
-    }
2077
-
2078
-
2079
-    /**
2080
-     * _update_registration_payments
2081
-     * this applies the payments to the selected registrations
2082
-     * but only if they have not already been paid for
2083
-     *
2084
-     * @param EE_Transaction $transaction
2085
-     * @param EE_Payment     $payment
2086
-     * @param array          $REG_IDs
2087
-     * @return void
2088
-     * @throws EE_Error
2089
-     * @throws InvalidArgumentException
2090
-     * @throws ReflectionException
2091
-     * @throws RuntimeException
2092
-     * @throws InvalidDataTypeException
2093
-     * @throws InvalidInterfaceException
2094
-     */
2095
-    protected function _update_registration_payments(
2096
-        EE_Transaction $transaction,
2097
-        EE_Payment $payment,
2098
-        $REG_IDs = []
2099
-    ) {
2100
-        // we can pass our own custom set of registrations to RegistrationPayments::processRegistrationPayments()
2101
-        // so let's do that using our set of REG_IDs from the form
2102
-        $registration_query_where_params = [
2103
-            'REG_ID' => ['IN', $REG_IDs],
2104
-        ];
2105
-        // but add in some conditions regarding payment,
2106
-        // so that we don't apply payments to registrations that are free or have already been paid for
2107
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2108
-        if (! $payment->is_a_refund()) {
2109
-            $registration_query_where_params['REG_final_price']  = ['!=', 0];
2110
-            $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2111
-        }
2112
-        $registrations = $transaction->registrations([$registration_query_where_params]);
2113
-        if (! empty($registrations)) {
2114
-            /** @var RegistrationPayments $payment_processor */
2115
-            $payment_processor = LoaderFactory::getShared(RegistrationPayments::class);
2116
-            $payment_processor->processRegistrationPayments($transaction, $payment, $registrations);
2117
-        }
2118
-    }
2119
-
2120
-
2121
-    /**
2122
-     * _process_registration_status_change
2123
-     * This processes requested registration status changes for all the registrations
2124
-     * on a given transaction and (optionally) sends out notifications for the changes.
2125
-     *
2126
-     * @param EE_Transaction $transaction
2127
-     * @param array          $REG_IDs
2128
-     * @return bool
2129
-     * @throws EE_Error
2130
-     * @throws InvalidArgumentException
2131
-     * @throws ReflectionException
2132
-     * @throws InvalidDataTypeException
2133
-     * @throws InvalidInterfaceException
2134
-     */
2135
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2136
-    {
2137
-        // first if there is no change in status then we get out.
2138
-        $reg_status = $reg_status
2139
-            ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2140
-        if ($reg_status === 'NAN') {
2141
-            // no error message, no change requested, just nothing to do man.
2142
-            return false;
2143
-        }
2144
-        /** @type EE_Transaction_Processor $transaction_processor */
2145
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2146
-
2147
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2148
-        return $transaction_processor->manually_update_registration_statuses(
2149
-            $transaction,
2150
-            $reg_status,
2151
-            [['REG_ID' => ['IN', $REG_IDs]]]
2152
-        );
2153
-    }
2154
-
2155
-
2156
-    /**
2157
-     * _build_payment_json_response
2158
-     *
2159
-     * @access public
2160
-     * @param EE_Payment  $payment
2161
-     * @param array       $REG_IDs
2162
-     * @param bool | null $delete_txn_reg_status_change
2163
-     * @return array
2164
-     * @throws EE_Error
2165
-     * @throws InvalidArgumentException
2166
-     * @throws InvalidDataTypeException
2167
-     * @throws InvalidInterfaceException
2168
-     * @throws ReflectionException
2169
-     */
2170
-    protected function _build_payment_json_response(
2171
-        EE_Payment $payment,
2172
-        $REG_IDs = [],
2173
-        $delete_txn_reg_status_change = null
2174
-    ) {
2175
-        // was the payment deleted ?
2176
-        if (is_bool($delete_txn_reg_status_change)) {
2177
-            return [
2178
-                'PAY_ID'                       => $payment->ID(),
2179
-                'amount'                       => $payment->amount(),
2180
-                'total_paid'                   => $payment->transaction()->paid(),
2181
-                'txn_status'                   => $payment->transaction()->status_ID(),
2182
-                'pay_status'                   => $payment->STS_ID(),
2183
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2184
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2185
-            ];
2186
-        }
2187
-
2188
-        $this->_get_payment_status_array();
2189
-        $payment_method = $payment->payment_method();
2190
-        return [
2191
-            'amount'           => $payment->amount(),
2192
-            'total_paid'       => $payment->transaction()->paid(),
2193
-            'txn_status'       => $payment->transaction()->status_ID(),
2194
-            'pay_status'       => $payment->STS_ID(),
2195
-            'PAY_ID'           => $payment->ID(),
2196
-            'STS_ID'           => $payment->STS_ID(),
2197
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2198
-            'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2199
-            'method'           => strtoupper($payment->source()),
2200
-            'PM_ID'            => $payment_method instanceof EE_Payment_Method
2201
-                ? $payment_method->ID()
2202
-                : 1,
2203
-            'gateway'          => $payment_method instanceof EE_Payment_Method
2204
-                ? $payment_method->admin_name()
2205
-                : esc_html__('Unknown', 'event_espresso'),
2206
-            'gateway_response' => $payment->gateway_response(),
2207
-            'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2208
-            'po_number'        => $payment->po_number(),
2209
-            'extra_accntng'    => $payment->extra_accntng(),
2210
-            'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2211
-        ];
2212
-    }
2213
-
2214
-
2215
-    /**
2216
-     * delete_payment
2217
-     *    delete a payment or refund made towards a transaction
2218
-     *
2219
-     * @access public
2220
-     * @return void
2221
-     * @throws EE_Error
2222
-     * @throws InvalidArgumentException
2223
-     * @throws ReflectionException
2224
-     * @throws InvalidDataTypeException
2225
-     * @throws InvalidInterfaceException
2226
-     */
2227
-    public function delete_payment()
2228
-    {
2229
-        $TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2230
-        // $json_response_data = ['return_data' => false];
2231
-        $PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2232
-        $amount     = 0;
2233
-        $can_delete = $this->capabilities->current_user_can(
2234
-            'ee_delete_payments',
2235
-            'delete_payment_from_registration_details'
2236
-        );
2237
-        if ($PAY_ID && $can_delete) {
2238
-            $delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2239
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2240
-            if ($payment instanceof EE_Payment) {
2241
-                $amount  = $payment->amount();
2242
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2243
-                /** @type EE_Transaction_Payments $transaction_payments */
2244
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2245
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2246
-                    if ($delete_txn_reg_status_change) {
2247
-                        $this->_maybe_send_notifications();
2248
-                        $this->_process_registration_status_change(
2249
-                            $payment->transaction(),
2250
-                            $REG_IDs,
2251
-                            $delete_txn_reg_status_change
2252
-                        );
2253
-                    }
2254
-                }
2255
-            } else {
2256
-                EE_Error::add_error(
2257
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2258
-                    __FILE__,
2259
-                    __FUNCTION__,
2260
-                    __LINE__
2261
-                );
2262
-            }
2263
-        } elseif ($can_delete) {
2264
-            EE_Error::add_error(
2265
-                esc_html__(
2266
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2267
-                    'event_espresso'
2268
-                ),
2269
-                __FILE__,
2270
-                __FUNCTION__,
2271
-                __LINE__
2272
-            );
2273
-        } else {
2274
-            EE_Error::add_error(
2275
-                esc_html__(
2276
-                    'You do not have access to delete a payment.',
2277
-                    'event_espresso'
2278
-                ),
2279
-                __FILE__,
2280
-                __FUNCTION__,
2281
-                __LINE__
2282
-            );
2283
-        }
2284
-        $query_args = [
2285
-            'page'   => 'espresso_transactions',
2286
-            'action' => 'view_transaction',
2287
-            'TXN_ID' => $TXD_ID,
2288
-        ];
2289
-        $this->_redirect_after_action(
2290
-            ! EE_Error::has_error(),
2291
-            $amount > 0
2292
-                ? esc_html__('payment', 'event_espresso')
2293
-                : esc_html__('refund', 'event_espresso'),
2294
-            esc_html__('deleted', 'event_espresso'),
2295
-            $query_args
2296
-        );
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _registration_payment_data_array
2302
-     * adds info for 'owing' and 'paid' for each registration to the json response
2303
-     *
2304
-     * @access protected
2305
-     * @param array $REG_IDs
2306
-     * @return array
2307
-     * @throws EE_Error
2308
-     * @throws InvalidArgumentException
2309
-     * @throws InvalidDataTypeException
2310
-     * @throws InvalidInterfaceException
2311
-     * @throws ReflectionException
2312
-     */
2313
-    protected function _registration_payment_data_array($REG_IDs)
2314
-    {
2315
-        $registration_payment_data = [];
2316
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2317
-        if (! empty($REG_IDs)) {
2318
-            $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2319
-            foreach ($registrations as $registration) {
2320
-                if ($registration instanceof EE_Registration) {
2321
-                    $registration_payment_data[ $registration->ID() ] = [
2322
-                        'paid'  => $registration->pretty_paid(),
2323
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2324
-                    ];
2325
-                }
2326
-            }
2327
-        }
2328
-
2329
-        return $registration_payment_data;
2330
-    }
2331
-
2332
-
2333
-    /**
2334
-     * _maybe_send_notifications
2335
-     * determines whether or not the admin has indicated that notifications should be sent.
2336
-     * If so, will toggle a filter switch for delivering registration notices.
2337
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2338
-     *
2339
-     * @access protected
2340
-     * @param EE_Payment | null $payment
2341
-     */
2342
-    protected function _maybe_send_notifications($payment = null)
2343
-    {
2344
-        switch ($payment instanceof EE_Payment) {
2345
-            // payment notifications
2346
-            case true:
2347
-                if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2348
-                    $this->_process_payment_notification($payment);
2349
-                }
2350
-                break;
2351
-            // registration notifications
2352
-            case false:
2353
-                if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2354
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2355
-                }
2356
-                break;
2357
-        }
2358
-    }
2359
-
2360
-
2361
-    /**
2362
-     * _send_payment_reminder
2363
-     *    generates HTML for the View Transaction Details Admin page
2364
-     *
2365
-     * @access protected
2366
-     * @return void
2367
-     * @throws EE_Error
2368
-     * @throws InvalidArgumentException
2369
-     * @throws InvalidDataTypeException
2370
-     * @throws InvalidInterfaceException
2371
-     */
2372
-    protected function _send_payment_reminder()
2373
-    {
2374
-        $TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2375
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2376
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2377
-        $query_args  = $redirect_to
2378
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2379
-            : [];
2380
-        do_action(
2381
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2382
-            $transaction
2383
-        );
2384
-        $this->_redirect_after_action(
2385
-            false,
2386
-            esc_html__('payment reminder', 'event_espresso'),
2387
-            esc_html__('sent', 'event_espresso'),
2388
-            $query_args,
2389
-            true
2390
-        );
2391
-    }
2392
-
2393
-
2394
-    /**
2395
-     *  get_transactions
2396
-     *    get transactions for given parameters (used by list table)
2397
-     *
2398
-     * @param int     $per_page how many transactions displayed per page
2399
-     * @param boolean $count    return the count or objects
2400
-     * @param string  $view
2401
-     * @return EE_Transaction[]|int int = count || array of transaction objects
2402
-     * @throws EE_Error
2403
-     * @throws InvalidArgumentException
2404
-     * @throws InvalidDataTypeException
2405
-     * @throws InvalidInterfaceException
2406
-     * @throws ReflectionException
2407
-     */
2408
-    public function get_transactions($per_page, $count = false, $view = '')
2409
-    {
2410
-        $start_date = wp_strip_all_tags(
2411
-            $this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2412
-        );
2413
-        $end_date   = wp_strip_all_tags(
2414
-            $this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2415
-        );
2416
-
2417
-        // make sure our timestamps start and end right at the boundaries for each day
2418
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2419
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2420
-
2421
-
2422
-        // convert to timestamps
2423
-        $start_date = strtotime($start_date);
2424
-        $end_date   = strtotime($end_date);
2425
-
2426
-        // makes sure start date is the lowest value and vice versa
2427
-        $start_date = min($start_date, $end_date);
2428
-        $end_date   = max($start_date, $end_date);
2429
-
2430
-        // convert to correct format for query
2431
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2432
-            'TXN_timestamp',
2433
-            date('Y-m-d H:i:s', $start_date),
2434
-            'Y-m-d H:i:s'
2435
-        );
2436
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2437
-            'TXN_timestamp',
2438
-            date('Y-m-d H:i:s', $end_date),
2439
-            'Y-m-d H:i:s'
2440
-        );
2441
-
2442
-
2443
-        // set orderby
2444
-        $orderby = $this->request->getRequestParam('orderby');
2445
-
2446
-        switch ($orderby) {
2447
-            case 'TXN_ID':
2448
-                break;
2449
-            case 'ATT_fname':
2450
-                $orderby = 'Registration.Attendee.ATT_fname';
2451
-                break;
2452
-            case 'event_name':
2453
-                $orderby = 'Registration.Event.EVT_name';
2454
-                break;
2455
-            default: // 'TXN_timestamp'
2456
-                $orderby = 'TXN_timestamp';
2457
-        }
2458
-
2459
-        $sort         = $this->request->getRequestParam('order', 'DESC');
2460
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
2461
-
2462
-        $per_page = absint($per_page)
2463
-            ? $per_page
2464
-            : 10;
2465
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2466
-
2467
-        $offset = ($current_page - 1) * $per_page;
2468
-        $limit  = [$offset, $per_page];
2469
-
2470
-        $_where = [
2471
-            'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2472
-            'Registration.REG_count' => 1,
2473
-        ];
2474
-
2475
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2476
-        if ($EVT_ID) {
2477
-            $_where['Registration.EVT_ID'] = $EVT_ID;
2478
-        }
2479
-
2480
-        $search_term = $this->request->getRequestParam('s');
2481
-        if ($search_term) {
2482
-            $search_term  = '%' . $search_term . '%';
2483
-            $_where['OR'] = [
2484
-                'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2485
-                'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2486
-                'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2487
-                'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2488
-                'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2489
-                'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2490
-                'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2491
-                'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2492
-                'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2493
-                'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2494
-                'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2495
-                'Registration.REG_final_price'        => ['LIKE', $search_term],
2496
-                'Registration.REG_code'               => ['LIKE', $search_term],
2497
-                'Registration.REG_count'              => ['LIKE', $search_term],
2498
-                'Registration.REG_group_size'         => ['LIKE', $search_term],
2499
-                'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2500
-                'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2501
-                'Payment.PAY_source'                  => ['LIKE', $search_term],
2502
-                'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2503
-                'TXN_session_data'                    => ['LIKE', $search_term],
2504
-                'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2505
-            ];
2506
-        }
2507
-
2508
-        $status = $this->request->getRequestParam('status');
2509
-        // failed transactions
2510
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2511
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2512
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2513
-
2514
-        if ($failed) {
2515
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2516
-        } elseif ($abandoned) {
2517
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2518
-        } elseif ($incomplete) {
2519
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2520
-        } else {
2521
-            $_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2522
-            $_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2523
-        }
2524
-
2525
-        $query_params = apply_filters(
2526
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2527
-            [
2528
-                $_where,
2529
-                'order_by'                 => [$orderby => $sort],
2530
-                'limit'                    => $limit,
2531
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2532
-            ],
2533
-            $this->request->requestParams(),
2534
-            $view,
2535
-            $count
2536
-        );
2537
-
2538
-        return $count
2539
-            ? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2540
-            : EEM_Transaction::instance()->get_all($query_params);
2541
-    }
2542
-
2543
-
2544
-    /**
2545
-     * @throws EE_Error
2546
-     * @throws InvalidArgumentException
2547
-     * @throws InvalidDataTypeException
2548
-     * @throws InvalidInterfaceException
2549
-     * @throws ReflectionException
2550
-     * @throws RuntimeException
2551
-     * @since 4.9.79.p
2552
-     */
2553
-    public function recalculateLineItems()
2554
-    {
2555
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2556
-        /** @var EE_Transaction $transaction */
2557
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2558
-        $success     = $transaction->recalculateLineItems();
2559
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2560
-        $query_args  = $redirect_to
2561
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2562
-            : [];
2563
-        $this->_redirect_after_action(
2564
-            $success,
2565
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2566
-            esc_html__('recalculated', 'event_espresso'),
2567
-            $query_args,
2568
-            true
2569
-        );
2570
-    }
19
+	/**
20
+	 * @var EE_Transaction
21
+	 */
22
+	private $_transaction;
23
+
24
+	/**
25
+	 * @var EE_Session
26
+	 */
27
+	private $_session;
28
+
29
+	/**
30
+	 * @var array $_txn_status
31
+	 */
32
+	private static $_txn_status;
33
+
34
+	/**
35
+	 * @var array $_pay_status
36
+	 */
37
+	private static $_pay_status;
38
+
39
+	/**
40
+	 * @var array $_existing_reg_payment_REG_IDs
41
+	 */
42
+	protected $_existing_reg_payment_REG_IDs;
43
+
44
+
45
+	/**
46
+	 *    _init_page_props
47
+	 *
48
+	 * @return void
49
+	 */
50
+	protected function _init_page_props()
51
+	{
52
+		$this->page_slug        = TXN_PG_SLUG;
53
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
54
+		$this->_admin_base_url  = TXN_ADMIN_URL;
55
+		$this->_admin_base_path = TXN_ADMIN;
56
+	}
57
+
58
+
59
+	/**
60
+	 *    _ajax_hooks
61
+	 *
62
+	 * @return void
63
+	 */
64
+	protected function _ajax_hooks()
65
+	{
66
+		// add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
67
+		// add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
68
+		// add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
69
+	}
70
+
71
+
72
+	/**
73
+	 *    _define_page_props
74
+	 *
75
+	 * @return void
76
+	 */
77
+	protected function _define_page_props()
78
+	{
79
+		$this->_admin_page_title = $this->page_label;
80
+		$this->_labels           = [
81
+			'buttons' => [
82
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
83
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
84
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
85
+			],
86
+		];
87
+	}
88
+
89
+
90
+	/**
91
+	 *        grab url requests and route them
92
+	 *
93
+	 * @access private
94
+	 * @return void
95
+	 * @throws EE_Error
96
+	 * @throws InvalidArgumentException
97
+	 * @throws InvalidDataTypeException
98
+	 * @throws InvalidInterfaceException
99
+	 * @throws ReflectionException
100
+	 */
101
+	public function _set_page_routes()
102
+	{
103
+		$this->_set_transaction_status_array();
104
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
105
+
106
+		$this->_page_routes = [
107
+
108
+			'default' => [
109
+				'func'       => '_transactions_overview_list_table',
110
+				'capability' => 'ee_read_transactions',
111
+			],
112
+
113
+			'view_transaction' => [
114
+				'func'       => '_transaction_details',
115
+				'capability' => 'ee_read_transaction',
116
+				'obj_id'     => $TXN_ID,
117
+			],
118
+
119
+			'send_payment_reminder' => [
120
+				'func'       => '_send_payment_reminder',
121
+				'noheader'   => true,
122
+				'capability' => 'ee_send_message',
123
+			],
124
+
125
+			'espresso_apply_payment' => [
126
+				'func'       => [$this, 'apply_payments_or_refunds'],
127
+				'noheader'   => true,
128
+				'capability' => 'ee_edit_payments',
129
+			],
130
+
131
+			'espresso_apply_refund' => [
132
+				'func'       => [$this, 'apply_payments_or_refunds'],
133
+				'noheader'   => true,
134
+				'capability' => 'ee_edit_payments',
135
+			],
136
+
137
+			'espresso_delete_payment' => [
138
+				'func'       => [$this, 'delete_payment'],
139
+				'noheader'   => true,
140
+				'capability' => 'ee_delete_payments',
141
+			],
142
+
143
+			'espresso_recalculate_line_items' => [
144
+				'func'       => 'recalculateLineItems',
145
+				'noheader'   => true,
146
+				'capability' => 'ee_edit_payments',
147
+			],
148
+
149
+		];
150
+	}
151
+
152
+
153
+	protected function _set_page_config()
154
+	{
155
+		$TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
156
+		$this->_page_config = [
157
+			'default'          => [
158
+				'nav'           => [
159
+					'label' => esc_html__('Overview', 'event_espresso'),
160
+					'icon'  => 'dashicons-list-view',
161
+					'order' => 10,
162
+				],
163
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
164
+				'help_tabs'     => [
165
+					'transactions_overview_help_tab'                       => [
166
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
167
+						'filename' => 'transactions_overview',
168
+					],
169
+					'transactions_overview_table_column_headings_help_tab' => [
170
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
171
+						'filename' => 'transactions_overview_table_column_headings',
172
+					],
173
+					'transactions_overview_views_filters_help_tab'         => [
174
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
175
+						'filename' => 'transactions_overview_views_filters_search',
176
+					],
177
+				],
178
+				'require_nonce' => false,
179
+			],
180
+			'view_transaction' => [
181
+				'nav'       => [
182
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
183
+					'icon'       => 'dashicons-cart',
184
+					'order'      => 5,
185
+					'url'        => $TXN_ID
186
+						? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
187
+						: $this->_admin_base_url,
188
+					'persistent' => false,
189
+				],
190
+				'help_tabs' => [
191
+					'transactions_view_transaction_help_tab'                                              => [
192
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
193
+						'filename' => 'transactions_view_transaction',
194
+					],
195
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => [
196
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
197
+						'filename' => 'transactions_view_transaction_transaction_details_table',
198
+					],
199
+					'transactions_view_transaction_attendees_registered_help_tab'                         => [
200
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
201
+						'filename' => 'transactions_view_transaction_attendees_registered',
202
+					],
203
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
204
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
205
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
206
+					],
207
+				],
208
+				'qtips'     => ['Transaction_Details_Tips'],
209
+				'metaboxes' => ['_transaction_details_metaboxes'],
210
+
211
+				'require_nonce' => false,
212
+			],
213
+		];
214
+	}
215
+
216
+
217
+	/**
218
+	 * The below methods aren't used by this class currently
219
+	 */
220
+	protected function _add_screen_options()
221
+	{
222
+		// noop
223
+	}
224
+
225
+
226
+	protected function _add_feature_pointers()
227
+	{
228
+		// noop
229
+	}
230
+
231
+
232
+	public function admin_init()
233
+	{
234
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
235
+		$event_name    = $this->request->getRequestParam('event_name');
236
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
237
+		// IF a registration was JUST added via the admin...
238
+		if ($EVT_ID && $event_name && $redirect_from) {
239
+			// then set a cookie so that we can block any attempts to use
240
+			// the back button as a way to enter another registration.
241
+			setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
242
+			// and update the global
243
+			$_COOKIE['ee_registration_added'] = $EVT_ID;
244
+		}
245
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
246
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
247
+			'event_espresso'
248
+		);
249
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
250
+			'An error occurred! Please refresh the page and try again.',
251
+			'event_espresso'
252
+		);
253
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
254
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
255
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
256
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
257
+			'This transaction has been overpaid ! Payments Total',
258
+			'event_espresso'
259
+		);
260
+	}
261
+
262
+
263
+	public function admin_notices()
264
+	{
265
+		// noop
266
+	}
267
+
268
+
269
+	public function admin_footer_scripts()
270
+	{
271
+		// noop
272
+	}
273
+
274
+
275
+	/**
276
+	 * _set_transaction_status_array
277
+	 * sets list of transaction statuses
278
+	 *
279
+	 * @access private
280
+	 * @return void
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	private function _set_transaction_status_array()
288
+	{
289
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
290
+	}
291
+
292
+
293
+	/**
294
+	 * get_transaction_status_array
295
+	 * return the transaction status array for wp_list_table
296
+	 *
297
+	 * @access public
298
+	 * @return array
299
+	 */
300
+	public function get_transaction_status_array()
301
+	{
302
+		return self::$_txn_status;
303
+	}
304
+
305
+
306
+	/**
307
+	 *    get list of payment statuses
308
+	 *
309
+	 * @access private
310
+	 * @return void
311
+	 * @throws EE_Error
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 */
317
+	private function _get_payment_status_array()
318
+	{
319
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
320
+		$this->_template_args['payment_status'] = self::$_pay_status;
321
+	}
322
+
323
+
324
+	/**
325
+	 *    _add_screen_options_default
326
+	 *
327
+	 * @access protected
328
+	 * @return void
329
+	 * @throws InvalidArgumentException
330
+	 * @throws InvalidDataTypeException
331
+	 * @throws InvalidInterfaceException
332
+	 */
333
+	protected function _add_screen_options_default()
334
+	{
335
+		$this->_per_page_screen_option();
336
+	}
337
+
338
+
339
+	/**
340
+	 * load_scripts_styles
341
+	 *
342
+	 * @access public
343
+	 * @return void
344
+	 */
345
+	public function load_scripts_styles()
346
+	{
347
+		// enqueue style
348
+		wp_register_style(
349
+			'espresso_txn',
350
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
351
+			[],
352
+			EVENT_ESPRESSO_VERSION
353
+		);
354
+		wp_enqueue_style('espresso_txn');
355
+		// scripts
356
+		wp_register_script(
357
+			'espresso_txn',
358
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
359
+			[
360
+				'ee_admin_js',
361
+				'ee-datepicker',
362
+				'jquery-ui-datepicker',
363
+				'jquery-ui-draggable',
364
+				'ee-dialog',
365
+				'ee-accounting',
366
+				'ee-serialize-full-array',
367
+			],
368
+			EVENT_ESPRESSO_VERSION,
369
+			true
370
+		);
371
+		wp_enqueue_script('espresso_txn');
372
+	}
373
+
374
+
375
+	/**
376
+	 *    load_scripts_styles_view_transaction
377
+	 *
378
+	 * @access public
379
+	 * @return void
380
+	 */
381
+	public function load_scripts_styles_view_transaction()
382
+	{
383
+		// styles
384
+		wp_enqueue_style('espresso-ui-theme');
385
+	}
386
+
387
+
388
+	/**
389
+	 *    load_scripts_styles_default
390
+	 *
391
+	 * @access public
392
+	 * @return void
393
+	 */
394
+	public function load_scripts_styles_default()
395
+	{
396
+		// styles
397
+		wp_enqueue_style('espresso-ui-theme');
398
+	}
399
+
400
+
401
+	/**
402
+	 *    _set_list_table_views_default
403
+	 *
404
+	 * @access protected
405
+	 * @return void
406
+	 */
407
+	protected function _set_list_table_views_default()
408
+	{
409
+		$this->_views = [
410
+			'all'        => [
411
+				'slug'  => 'all',
412
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
413
+				'count' => 0,
414
+			],
415
+			'abandoned'  => [
416
+				'slug'  => 'abandoned',
417
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
418
+				'count' => 0,
419
+			],
420
+			'incomplete' => [
421
+				'slug'  => 'incomplete',
422
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
423
+				'count' => 0,
424
+			],
425
+		];
426
+		if (
427
+			/**
428
+			 * Filters whether a link to the "Failed Transactions" list table
429
+			 * appears on the Transactions Admin Page list table.
430
+			 * List display can be turned back on via the following:
431
+			 * add_filter(
432
+			 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
433
+			 *     '__return_true'
434
+			 * );
435
+			 *
436
+			 * @param boolean                 $display_failed_txns_list
437
+			 * @param Transactions_Admin_Page $this
438
+			 * @since 4.9.70.p
439
+			 */
440
+		apply_filters(
441
+			'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
442
+			false,
443
+			$this
444
+		)
445
+		) {
446
+			$this->_views['failed'] = [
447
+				'slug'  => 'failed',
448
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
449
+				'count' => 0,
450
+			];
451
+		}
452
+	}
453
+
454
+
455
+	/**
456
+	 * _set_transaction_object
457
+	 * This sets the _transaction property for the transaction details screen
458
+	 *
459
+	 * @access private
460
+	 * @return void
461
+	 * @throws EE_Error
462
+	 * @throws InvalidArgumentException
463
+	 * @throws RuntimeException
464
+	 * @throws InvalidDataTypeException
465
+	 * @throws InvalidInterfaceException
466
+	 * @throws ReflectionException
467
+	 */
468
+	private function _set_transaction_object()
469
+	{
470
+		if ($this->_transaction instanceof EE_Transaction) {
471
+			return;
472
+		} //get out we've already set the object
473
+
474
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
475
+
476
+		// get transaction object
477
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
478
+		$this->_session     = $this->_transaction instanceof EE_Transaction
479
+			? $this->_transaction->session_data()
480
+			: null;
481
+		if ($this->_transaction instanceof EE_Transaction) {
482
+			$this->_transaction->verify_abandoned_transaction_status();
483
+		}
484
+
485
+		if (! $this->_transaction instanceof EE_Transaction) {
486
+			$error_msg = sprintf(
487
+				esc_html__(
488
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
489
+					'event_espresso'
490
+				),
491
+				$TXN_ID
492
+			);
493
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
494
+		}
495
+	}
496
+
497
+
498
+	/**
499
+	 *    _transaction_legend_items
500
+	 *
501
+	 * @access protected
502
+	 * @return array
503
+	 * @throws EE_Error
504
+	 * @throws InvalidArgumentException
505
+	 * @throws ReflectionException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidInterfaceException
508
+	 */
509
+	protected function _transaction_legend_items()
510
+	{
511
+		EE_Registry::instance()->load_helper('MSG_Template');
512
+		$items = [];
513
+
514
+		if (
515
+			$this->capabilities->current_user_can(
516
+				'ee_read_global_messages',
517
+				'view_filtered_messages'
518
+			)
519
+		) {
520
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
521
+			if (
522
+				is_array($related_for_icon)
523
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
524
+			) {
525
+				$items['view_related_messages'] = [
526
+					'class' => $related_for_icon['css_class'],
527
+					'desc'  => $related_for_icon['label'],
528
+				];
529
+			}
530
+		}
531
+
532
+		$items = apply_filters(
533
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
534
+			array_merge(
535
+				$items,
536
+				[
537
+					'view_details'          => [
538
+						'class' => 'dashicons dashicons-cart',
539
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
540
+					],
541
+					'view_invoice'          => [
542
+						'class' => 'dashicons dashicons-media-spreadsheet',
543
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
544
+					],
545
+					'view_receipt'          => [
546
+						'class' => 'dashicons dashicons-text-page',
547
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
548
+					],
549
+					'view_registration'     => [
550
+						'class' => 'dashicons dashicons-clipboard',
551
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
552
+					],
553
+					'payment_overview_link' => [
554
+						'class' => 'dashicons dashicons-money',
555
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
556
+					],
557
+				]
558
+			)
559
+		);
560
+
561
+		if (
562
+			EEH_MSG_Template::is_mt_active('payment_reminder')
563
+			&& $this->capabilities->current_user_can(
564
+				'ee_send_message',
565
+				'espresso_transactions_send_payment_reminder'
566
+			)
567
+		) {
568
+			$items['send_payment_reminder'] = [
569
+				'class' => 'dashicons dashicons-email-alt',
570
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
571
+			];
572
+		} else {
573
+			$items['blank*'] = [
574
+				'class' => '',
575
+				'desc'  => '',
576
+			];
577
+		}
578
+		$more_items = apply_filters(
579
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
580
+			[
581
+				'overpaid'   => [
582
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
583
+					'desc'  => EEH_Template::pretty_status(
584
+						EEM_Transaction::overpaid_status_code,
585
+						false,
586
+						'sentence'
587
+					),
588
+				],
589
+				'complete'   => [
590
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
591
+					'desc'  => EEH_Template::pretty_status(
592
+						EEM_Transaction::complete_status_code,
593
+						false,
594
+						'sentence'
595
+					),
596
+				],
597
+				'incomplete' => [
598
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
599
+					'desc'  => EEH_Template::pretty_status(
600
+						EEM_Transaction::incomplete_status_code,
601
+						false,
602
+						'sentence'
603
+					),
604
+				],
605
+				'abandoned'  => [
606
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
607
+					'desc'  => EEH_Template::pretty_status(
608
+						EEM_Transaction::abandoned_status_code,
609
+						false,
610
+						'sentence'
611
+					),
612
+				],
613
+				'failed'     => [
614
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
615
+					'desc'  => EEH_Template::pretty_status(
616
+						EEM_Transaction::failed_status_code,
617
+						false,
618
+						'sentence'
619
+					),
620
+				],
621
+			]
622
+		);
623
+
624
+		return array_merge($items, $more_items);
625
+	}
626
+
627
+
628
+	/**
629
+	 *    _transactions_overview_list_table
630
+	 *
631
+	 * @access protected
632
+	 * @return void
633
+	 * @throws DomainException
634
+	 * @throws EE_Error
635
+	 * @throws InvalidArgumentException
636
+	 * @throws InvalidDataTypeException
637
+	 * @throws InvalidInterfaceException
638
+	 * @throws ReflectionException
639
+	 */
640
+	protected function _transactions_overview_list_table()
641
+	{
642
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
643
+
644
+		$EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
645
+		$event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
646
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
647
+			? sprintf(
648
+				esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
649
+				'<h3>',
650
+				'<a href="'
651
+				. EE_Admin_Page::add_query_args_and_nonce(
652
+					['action' => 'edit', 'post' => $event->ID()],
653
+					EVENTS_ADMIN_URL
654
+				)
655
+				. '" aria-label="'
656
+				. esc_attr__('Click to Edit event', 'event_espresso')
657
+				. '">' . $event->name() . '</a>',
658
+				'</h3>'
659
+			)
660
+			: '';
661
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
662
+		$this->display_admin_list_table_page_with_no_sidebar();
663
+	}
664
+
665
+
666
+	/**
667
+	 *    _transaction_details
668
+	 * generates HTML for the View Transaction Details Admin page
669
+	 *
670
+	 * @access protected
671
+	 * @return void
672
+	 * @throws DomainException
673
+	 * @throws EE_Error
674
+	 * @throws InvalidArgumentException
675
+	 * @throws InvalidDataTypeException
676
+	 * @throws InvalidInterfaceException
677
+	 * @throws RuntimeException
678
+	 * @throws ReflectionException
679
+	 */
680
+	protected function _transaction_details()
681
+	{
682
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
683
+
684
+		$this->_set_transaction_status_array();
685
+
686
+		$this->_template_args                      = [];
687
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
688
+
689
+		$this->_set_transaction_object();
690
+
691
+		if (! $this->_transaction instanceof EE_Transaction) {
692
+			return;
693
+		}
694
+
695
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
696
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
697
+
698
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
699
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
700
+
701
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
702
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
703
+		$this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
704
+
705
+		$txn_total  = $this->_transaction->total();
706
+		$total_paid = $this->_transaction->paid();
707
+		$amount_due = $txn_total - $total_paid;
708
+
709
+		$this->_template_args['grand_total'] = $txn_total;
710
+		$this->_template_args['total_paid']  = $total_paid;
711
+
712
+		$this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
713
+		$this->_template_args['amount_due_raw'] = $amount_due;
714
+
715
+		$this->_template_args['amount_due_class'] = '';
716
+
717
+		if ($txn_total === (float) 0) {
718
+			// free event
719
+			$this->_template_args['amount_due'] = false;
720
+		} elseif ($amount_due < (float) 0) {
721
+			// overpaid
722
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
723
+		} elseif ($amount_due > (float) 0) {
724
+			// monies owing
725
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
726
+		} elseif ($total_paid === (float) 0) {
727
+			// no payments made yet
728
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
729
+		}
730
+
731
+		$payment_method = $this->_transaction->payment_method();
732
+
733
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
734
+			? $payment_method->admin_name()
735
+			: esc_html__('Unknown', 'event_espresso');
736
+
737
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
738
+		// link back to overview
739
+		$this->_template_args['txn_overview_url'] = $this->request->getServerParam(
740
+			'HTTP_REFERER',
741
+			TXN_ADMIN_URL
742
+		);
743
+
744
+
745
+		// next link
746
+		$next_txn                                 = $this->_transaction->next(
747
+			null,
748
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
749
+			'TXN_ID'
750
+		);
751
+		$this->_template_args['next_transaction'] = $next_txn
752
+			? $this->_next_link(
753
+				EE_Admin_Page::add_query_args_and_nonce(
754
+					['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
755
+					TXN_ADMIN_URL
756
+				),
757
+				'dashicons dashicons-arrow-right ee-icon-size-22'
758
+			)
759
+			: '';
760
+		// previous link
761
+		$previous_txn                                 = $this->_transaction->previous(
762
+			null,
763
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
764
+			'TXN_ID'
765
+		);
766
+		$this->_template_args['previous_transaction'] = $previous_txn
767
+			? $this->_previous_link(
768
+				EE_Admin_Page::add_query_args_and_nonce(
769
+					['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
770
+					TXN_ADMIN_URL
771
+				),
772
+				'dashicons dashicons-arrow-left ee-icon-size-22'
773
+			)
774
+			: '';
775
+
776
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
777
+		$event_name    = $this->request->getRequestParam('event_name');
778
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
779
+
780
+		// were we just redirected here after adding a new registration ???
781
+		if ($EVT_ID && $event_name && $redirect_from) {
782
+			if (
783
+				$this->capabilities->current_user_can(
784
+					'ee_edit_registrations',
785
+					'espresso_registrations_new_registration',
786
+					$EVT_ID
787
+				)
788
+			) {
789
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
790
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
791
+					[
792
+						'page'     => 'espresso_registrations',
793
+						'action'   => 'new_registration',
794
+						'return'   => 'default',
795
+						'TXN_ID'   => $this->_transaction->ID(),
796
+						'event_id' => $EVT_ID,
797
+					],
798
+					REG_ADMIN_URL
799
+				);
800
+				$this->_admin_page_title .= '">';
801
+
802
+				$this->_admin_page_title .= sprintf(
803
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
804
+					htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
805
+				);
806
+				$this->_admin_page_title .= '</a>';
807
+			}
808
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
809
+		}
810
+		// grab messages at the last second
811
+		$this->_template_args['notices'] = EE_Error::get_notices();
812
+		// path to template
813
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
814
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
815
+			$template_path,
816
+			$this->_template_args,
817
+			true
818
+		);
819
+
820
+		// the details template wrapper
821
+		$this->display_admin_page_with_sidebar();
822
+	}
823
+
824
+
825
+	/**
826
+	 *        _transaction_details_metaboxes
827
+	 *
828
+	 * @access protected
829
+	 * @return void
830
+	 * @throws EE_Error
831
+	 * @throws InvalidArgumentException
832
+	 * @throws InvalidDataTypeException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws RuntimeException
835
+	 * @throws ReflectionException
836
+	 */
837
+	protected function _transaction_details_metaboxes()
838
+	{
839
+		$this->_set_transaction_object();
840
+
841
+		if (! $this->_transaction instanceof EE_Transaction) {
842
+			return;
843
+		}
844
+		$this->addMetaBox(
845
+			'edit-txn-details-mbox',
846
+			'<span>' . esc_html__('Transaction Details', 'event_espresso')
847
+			. '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
848
+			[$this, 'txn_details_meta_box'],
849
+			$this->_wp_page_slug
850
+		);
851
+		$this->addMetaBox(
852
+			'edit-txn-attendees-mbox',
853
+			'<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
854
+			. '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
855
+			[$this, 'txn_attendees_meta_box'],
856
+			$this->_wp_page_slug,
857
+			'normal',
858
+			'high',
859
+			['TXN_ID' => $this->_transaction->ID()]
860
+		);
861
+		$this->addMetaBox(
862
+			'edit-txn-registrant-mbox',
863
+			esc_html__('Primary Contact', 'event_espresso'),
864
+			[$this, 'txn_registrant_side_meta_box'],
865
+			$this->_wp_page_slug,
866
+			'side'
867
+		);
868
+		$this->addMetaBox(
869
+			'edit-txn-billing-info-mbox',
870
+			esc_html__('Billing Information', 'event_espresso'),
871
+			[$this, 'txn_billing_info_side_meta_box'],
872
+			$this->_wp_page_slug,
873
+			'side'
874
+		);
875
+	}
876
+
877
+
878
+	/**
879
+	 * Callback for transaction actions metabox.
880
+	 *
881
+	 * @param EE_Transaction|null $transaction
882
+	 * @return string
883
+	 * @throws DomainException
884
+	 * @throws EE_Error
885
+	 * @throws InvalidArgumentException
886
+	 * @throws InvalidDataTypeException
887
+	 * @throws InvalidInterfaceException
888
+	 * @throws ReflectionException
889
+	 * @throws RuntimeException
890
+	 */
891
+	public function getActionButtons(EE_Transaction $transaction = null)
892
+	{
893
+		$content = '';
894
+		$actions = [];
895
+		if (! $transaction instanceof EE_Transaction) {
896
+			return $content;
897
+		}
898
+		/** @var EE_Registration $primary_registration */
899
+		$primary_registration = $transaction->primary_registration();
900
+		$attendee             = $primary_registration instanceof EE_Registration
901
+			? $primary_registration->attendee()
902
+			: null;
903
+
904
+		if (
905
+			$attendee instanceof EE_Attendee
906
+			&& $this->capabilities->current_user_can(
907
+				'ee_send_message',
908
+				'espresso_transactions_send_payment_reminder'
909
+			)
910
+		) {
911
+			$actions['payment_reminder'] =
912
+				EEH_MSG_Template::is_mt_active('payment_reminder')
913
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
914
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
915
+					? EEH_Template::get_button_or_link(
916
+					EE_Admin_Page::add_query_args_and_nonce(
917
+						[
918
+							'action'      => 'send_payment_reminder',
919
+							'TXN_ID'      => $this->_transaction->ID(),
920
+							'redirect_to' => 'view_transaction',
921
+						],
922
+						TXN_ADMIN_URL
923
+					),
924
+					esc_html__(' Send Payment Reminder', 'event_espresso'),
925
+					'button button--secondary',
926
+					'dashicons dashicons-email-alt'
927
+				)
928
+					: '';
929
+		}
930
+
931
+		if (
932
+			$this->capabilities->current_user_can(
933
+				'ee_edit_payments',
934
+				'espresso_transactions_recalculate_line_items'
935
+			)
936
+		) {
937
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
938
+				EE_Admin_Page::add_query_args_and_nonce(
939
+					[
940
+						'action'      => 'espresso_recalculate_line_items',
941
+						'TXN_ID'      => $this->_transaction->ID(),
942
+						'redirect_to' => 'view_transaction',
943
+					],
944
+					TXN_ADMIN_URL
945
+				),
946
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
947
+				'button button--secondary',
948
+				'dashicons dashicons-update'
949
+			);
950
+		}
951
+
952
+		if (
953
+			$primary_registration instanceof EE_Registration
954
+			&& EEH_MSG_Template::is_mt_active('receipt')
955
+		) {
956
+			$actions['receipt'] = EEH_Template::get_button_or_link(
957
+				$primary_registration->receipt_url(),
958
+				esc_html__('View Receipt', 'event_espresso'),
959
+				'button button--secondary',
960
+				'dashicons dashicons-text-page'
961
+			);
962
+		}
963
+
964
+		if (
965
+			$primary_registration instanceof EE_Registration
966
+			&& EEH_MSG_Template::is_mt_active('invoice')
967
+		) {
968
+			$actions['invoice'] = EEH_Template::get_button_or_link(
969
+				$primary_registration->invoice_url(),
970
+				esc_html__('View Invoice', 'event_espresso'),
971
+				'button button--secondary',
972
+				'dashicons dashicons-media-spreadsheet'
973
+			);
974
+		}
975
+		$actions = array_filter(
976
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
977
+		);
978
+		if ($actions) {
979
+			$content .= implode('', $actions);
980
+		}
981
+		return $content;
982
+	}
983
+
984
+
985
+	/**
986
+	 * txn_details_meta_box
987
+	 * generates HTML for the Transaction main meta box
988
+	 *
989
+	 * @return void
990
+	 * @throws DomainException
991
+	 * @throws EE_Error
992
+	 * @throws InvalidArgumentException
993
+	 * @throws InvalidDataTypeException
994
+	 * @throws InvalidInterfaceException
995
+	 * @throws RuntimeException
996
+	 * @throws ReflectionException
997
+	 */
998
+	public function txn_details_meta_box()
999
+	{
1000
+		$this->_set_transaction_object();
1001
+		$this->_template_args['TXN_ID']              = $this->_transaction->ID();
1002
+		$this->_template_args['attendee']            =
1003
+			$this->_transaction->primary_registration() instanceof EE_Registration
1004
+				? $this->_transaction->primary_registration()->attendee()
1005
+				: null;
1006
+		$this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1007
+			'ee_edit_payments',
1008
+			'apply_payment_or_refund_from_registration_details'
1009
+		);
1010
+		$this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1011
+			'ee_delete_payments',
1012
+			'delete_payment_from_registration_details'
1013
+		);
1014
+
1015
+		// get line table
1016
+		EEH_Autoloader::register_line_item_display_autoloaders();
1017
+		$Line_Item_Display                       = new EE_Line_Item_Display(
1018
+			'admin_table',
1019
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1020
+		);
1021
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1022
+			$this->_transaction->total_line_item()
1023
+		);
1024
+		$this->_template_args['REG_code']        =
1025
+			$this->_transaction->primary_registration() instanceof EE_Registration
1026
+				? $this->_transaction->primary_registration()->reg_code()
1027
+				: null;
1028
+		// process taxes
1029
+		$taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1030
+		$this->_template_args['taxes'] = ! empty($taxes)
1031
+			? $taxes
1032
+			: false;
1033
+
1034
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1035
+			$this->_transaction->total(),
1036
+			false,
1037
+			false
1038
+		);
1039
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1040
+		$this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1041
+
1042
+		// process payment details
1043
+		$payments = $this->_transaction->payments();
1044
+		if (! empty($payments)) {
1045
+			$this->_template_args['payments']              = $payments;
1046
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1047
+		} else {
1048
+			$this->_template_args['payments']              = false;
1049
+			$this->_template_args['existing_reg_payments'] = [];
1050
+		}
1051
+
1052
+		$this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1053
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1054
+			['action' => 'espresso_delete_payment'],
1055
+			TXN_ADMIN_URL
1056
+		);
1057
+
1058
+		if (isset($txn_details['invoice_number'])) {
1059
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1060
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1061
+				'Invoice Number',
1062
+				'event_espresso'
1063
+			);
1064
+		}
1065
+
1066
+		$this->_template_args['txn_details']['registration_session']['value'] =
1067
+			$this->_transaction->primary_registration() instanceof EE_Registration
1068
+				? $this->_transaction->primary_registration()->session_ID()
1069
+				: null;
1070
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1071
+			'Registration Session',
1072
+			'event_espresso'
1073
+		);
1074
+
1075
+		$this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1076
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1077
+			'Transaction placed from IP',
1078
+			'event_espresso'
1079
+		);
1080
+
1081
+		$this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1082
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1083
+			'Registrant User Agent',
1084
+			'event_espresso'
1085
+		);
1086
+
1087
+		$reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1088
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1089
+			if ($reg_step_status === true) {
1090
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1091
+							  . sprintf(
1092
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1093
+								  ucwords(str_replace('_', ' ', $reg_step))
1094
+							  )
1095
+							  . '</div>';
1096
+			} elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1097
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1098
+							  . sprintf(
1099
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1100
+								  ucwords(str_replace('_', ' ', $reg_step)),
1101
+								  date(
1102
+									  get_option('date_format') . ' ' . get_option('time_format'),
1103
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1104
+								  )
1105
+							  )
1106
+							  . '</div>';
1107
+			} else {
1108
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1109
+							  . sprintf(
1110
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1111
+								  ucwords(str_replace('_', ' ', $reg_step))
1112
+							  )
1113
+							  . '</div>';
1114
+			}
1115
+		}
1116
+		$reg_steps                                                 .= '</ul>';
1117
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1118
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1119
+			'Registration Step Progress',
1120
+			'event_espresso'
1121
+		);
1122
+
1123
+
1124
+		$this->_get_registrations_to_apply_payment_to();
1125
+		$this->_get_payment_methods($payments);
1126
+		$this->_get_payment_status_array();
1127
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1128
+
1129
+		$this->_template_args['transaction_form_url']    = add_query_arg(
1130
+			[
1131
+				'action'  => 'edit_transaction',
1132
+				'process' => 'transaction',
1133
+			],
1134
+			TXN_ADMIN_URL
1135
+		);
1136
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(
1137
+			[
1138
+				'page'   => 'espresso_transactions',
1139
+				'action' => 'espresso_apply_payment',
1140
+			],
1141
+			TXN_ADMIN_URL
1142
+		);
1143
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1144
+			[
1145
+				'page'   => 'espresso_transactions',
1146
+				'action' => 'espresso_delete_payment',
1147
+			],
1148
+			TXN_ADMIN_URL
1149
+		);
1150
+
1151
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1152
+
1153
+		// 'espresso_delete_payment_nonce'
1154
+
1155
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1156
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1157
+	}
1158
+
1159
+
1160
+	/**
1161
+	 * _get_registration_payment_IDs
1162
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1163
+	 *
1164
+	 * @access protected
1165
+	 * @param EE_Payment[] $payments
1166
+	 * @return array
1167
+	 * @throws EE_Error
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws InvalidInterfaceException
1171
+	 * @throws ReflectionException
1172
+	 */
1173
+	protected function _get_registration_payment_IDs($payments = [])
1174
+	{
1175
+		$existing_reg_payments = [];
1176
+		// get all reg payments for these payments
1177
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1178
+			[
1179
+				[
1180
+					'PAY_ID' => [
1181
+						'IN',
1182
+						array_keys($payments),
1183
+					],
1184
+				],
1185
+			]
1186
+		);
1187
+		if (! empty($reg_payments)) {
1188
+			foreach ($payments as $payment) {
1189
+				if (! $payment instanceof EE_Payment) {
1190
+					continue;
1191
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1192
+					$existing_reg_payments[ $payment->ID() ] = [];
1193
+				}
1194
+				foreach ($reg_payments as $reg_payment) {
1195
+					if (
1196
+						$reg_payment instanceof EE_Registration_Payment
1197
+						&& $reg_payment->payment_ID() === $payment->ID()
1198
+					) {
1199
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1200
+					}
1201
+				}
1202
+			}
1203
+		}
1204
+
1205
+		return $existing_reg_payments;
1206
+	}
1207
+
1208
+
1209
+	/**
1210
+	 * _get_registrations_to_apply_payment_to
1211
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1212
+	 * which allows the admin to only apply the payment to the specific registrations
1213
+	 *
1214
+	 * @access protected
1215
+	 * @return void
1216
+	 * @throws EE_Error
1217
+	 * @throws InvalidArgumentException
1218
+	 * @throws InvalidDataTypeException
1219
+	 * @throws InvalidInterfaceException
1220
+	 * @throws ReflectionException
1221
+	 */
1222
+	protected function _get_registrations_to_apply_payment_to()
1223
+	{
1224
+		// we want any registration with an active status (ie: not deleted or cancelled)
1225
+		$query_params                      = [
1226
+			[
1227
+				'STS_ID' => [
1228
+					'IN',
1229
+					[
1230
+						RegStatus::APPROVED,
1231
+						RegStatus::PENDING_PAYMENT,
1232
+						RegStatus::AWAITING_REVIEW,
1233
+					],
1234
+				],
1235
+			],
1236
+		];
1237
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1238
+				'',
1239
+				'txn-admin-apply-payment-to-registrations-dv',
1240
+				'',
1241
+				'clear: both; margin: 1.5em 0 0; display: none;'
1242
+			);
1243
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1244
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1245
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1246
+			EEH_HTML::tr(
1247
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1248
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1249
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1250
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1251
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1252
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1253
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1254
+			)
1255
+		);
1256
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1257
+		// get registrations for TXN
1258
+		$registrations         = $this->_transaction->registrations($query_params);
1259
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1260
+		foreach ($registrations as $registration) {
1261
+			if ($registration instanceof EE_Registration) {
1262
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1263
+					? $registration->attendee()->full_name()
1264
+					: esc_html__('Unknown Attendee', 'event_espresso');
1265
+				$owing                             = $registration->final_price() - $registration->paid();
1266
+				$taxable                           = $registration->ticket()->taxable()
1267
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1268
+					: '';
1269
+				$checked                           = empty($existing_reg_payments)
1270
+													 || in_array($registration->ID(), $existing_reg_payments, true)
1271
+					? ' checked'
1272
+					: '';
1273
+				$disabled                          = $registration->final_price() > 0
1274
+					? ''
1275
+					: ' disabled';
1276
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1277
+					EEH_HTML::td($registration->ID()) .
1278
+					EEH_HTML::td($attendee_name) .
1279
+					EEH_HTML::td(
1280
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1281
+					) .
1282
+					EEH_HTML::td($registration->event_name()) .
1283
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1284
+					EEH_HTML::td(
1285
+						EEH_Template::format_currency($owing),
1286
+						'',
1287
+						'txn-admin-payment-owing-td jst-cntr'
1288
+					) .
1289
+					EEH_HTML::td(
1290
+						'<input type="checkbox" value="' . $registration->ID()
1291
+						. '" name="txn_admin_payment[registrations]"'
1292
+						. $checked . $disabled . '>',
1293
+						'',
1294
+						'jst-cntr'
1295
+					),
1296
+					'apply-payment-registration-row-' . $registration->ID()
1297
+				);
1298
+			}
1299
+		}
1300
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1301
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1302
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1303
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1304
+			esc_html__(
1305
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1306
+				'event_espresso'
1307
+			),
1308
+			'',
1309
+			'clear description'
1310
+		);
1311
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1312
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1313
+	}
1314
+
1315
+
1316
+	/**
1317
+	 * _get_reg_status_selection
1318
+	 *
1319
+	 * @return void
1320
+	 * @throws EE_Error
1321
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1322
+	 *         instead of events.
1323
+	 * @access protected
1324
+	 */
1325
+	protected function _get_reg_status_selection()
1326
+	{
1327
+		// first get all possible statuses
1328
+		$statuses = EEM_Registration::reg_status_array([], true);
1329
+		// let's add a "don't change" option.
1330
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1331
+		$status_array                                        = array_merge($status_array, $statuses);
1332
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1333
+			'txn_reg_status_change[reg_status]',
1334
+			$status_array,
1335
+			'NAN',
1336
+			'id="txn-admin-payment-reg-status-inp"',
1337
+			'txn-reg-status-change-reg-status'
1338
+		);
1339
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1340
+			'delete_txn_reg_status_change[reg_status]',
1341
+			$status_array,
1342
+			'NAN',
1343
+			'delete-txn-admin-payment-reg-status-inp',
1344
+			'delete-txn-reg-status-change-reg-status'
1345
+		);
1346
+	}
1347
+
1348
+
1349
+	/**
1350
+	 *    _get_payment_methods
1351
+	 * Gets all the payment methods available generally, or the ones that are already
1352
+	 * selected on these payments (in case their payment methods are no longer active).
1353
+	 * Has the side-effect of updating the template args' payment_methods item
1354
+	 *
1355
+	 * @access private
1356
+	 * @param EE_Payment[] to show on this page
1357
+	 * @return void
1358
+	 * @throws EE_Error
1359
+	 * @throws InvalidArgumentException
1360
+	 * @throws InvalidDataTypeException
1361
+	 * @throws InvalidInterfaceException
1362
+	 * @throws ReflectionException
1363
+	 */
1364
+	private function _get_payment_methods($payments = [])
1365
+	{
1366
+		$payment_methods_of_payments = [];
1367
+		foreach ($payments as $payment) {
1368
+			if ($payment instanceof EE_Payment) {
1369
+				$payment_methods_of_payments[] = $payment->ID();
1370
+			}
1371
+		}
1372
+		if ($payment_methods_of_payments) {
1373
+			$query_args = [
1374
+				[
1375
+					'OR*payment_method_for_payment' => [
1376
+						'PMD_ID'    => ['IN', $payment_methods_of_payments],
1377
+						'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1378
+					],
1379
+				],
1380
+			];
1381
+		} else {
1382
+			$query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1383
+		}
1384
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1385
+	}
1386
+
1387
+
1388
+	/**
1389
+	 * txn_attendees_meta_box
1390
+	 *    generates HTML for the Attendees Transaction main meta box
1391
+	 *
1392
+	 * @access public
1393
+	 * @param WP_Post $post
1394
+	 * @param array   $metabox
1395
+	 * @return void
1396
+	 * @throws DomainException
1397
+	 * @throws EE_Error
1398
+	 * @throws InvalidArgumentException
1399
+	 * @throws InvalidDataTypeException
1400
+	 * @throws InvalidInterfaceException
1401
+	 * @throws ReflectionException
1402
+	 */
1403
+	public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1404
+	{
1405
+		/** @noinspection NonSecureExtractUsageInspection */
1406
+		extract($metabox['args']);
1407
+		$this->_template_args['post']            = $post;
1408
+		$this->_template_args['event_attendees'] = [];
1409
+		// process items in cart
1410
+		$line_items = $this->_transaction->get_many_related(
1411
+			'Line_Item',
1412
+			[['LIN_type' => 'line-item']]
1413
+		);
1414
+		if (! empty($line_items)) {
1415
+			foreach ($line_items as $item) {
1416
+				if ($item instanceof EE_Line_Item) {
1417
+					switch ($item->OBJ_type()) {
1418
+						case 'Event':
1419
+							break;
1420
+						case 'Ticket':
1421
+							$ticket = $item->ticket();
1422
+							// right now we're only handling tickets here.
1423
+							// Cause its expected that only tickets will have attendees right?
1424
+							if (! $ticket instanceof EE_Ticket) {
1425
+								break;
1426
+							}
1427
+							try {
1428
+								$event_name = $ticket->get_event_name();
1429
+							} catch (Exception $e) {
1430
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1431
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1432
+							}
1433
+							$event_name   .= ' - ' . $item->name();
1434
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1435
+							// now get all of the registrations for this transaction that use this ticket
1436
+							$registrations = $ticket->registrations(
1437
+								[['TXN_ID' => $this->_transaction->ID()]]
1438
+							);
1439
+							foreach ($registrations as $registration) {
1440
+								if (! $registration instanceof EE_Registration) {
1441
+									break;
1442
+								}
1443
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1444
+									= $registration->status_ID();
1445
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1446
+									= $registration->count();
1447
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1448
+									= $event_name;
1449
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1450
+									= $ticket_price;
1451
+								// attendee info
1452
+								$attendee = $registration->get_first_related('Attendee');
1453
+								if ($attendee instanceof EE_Attendee) {
1454
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1455
+										= $attendee->ID();
1456
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1457
+										= $attendee->full_name();
1458
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1459
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1460
+										  . esc_html__(
1461
+											  ' Event',
1462
+											  'event_espresso'
1463
+										  )
1464
+										  . '">' . $attendee->email() . '</a>';
1465
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1466
+										= EEH_Address::format($attendee, 'inline', false, false);
1467
+								} else {
1468
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1469
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1470
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1471
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1472
+								}
1473
+							}
1474
+							break;
1475
+					}
1476
+				}
1477
+			}
1478
+
1479
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1480
+				[
1481
+					'action'  => 'edit_transaction',
1482
+					'process' => 'attendees',
1483
+				],
1484
+				TXN_ADMIN_URL
1485
+			);
1486
+			echo EEH_Template::display_template(
1487
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1488
+				$this->_template_args,
1489
+				true
1490
+			);
1491
+		} else {
1492
+			printf(
1493
+				esc_html__(
1494
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1495
+					'event_espresso'
1496
+				),
1497
+				'<p class="important-notice">',
1498
+				'</p>'
1499
+			);
1500
+		}
1501
+	}
1502
+
1503
+
1504
+	/**
1505
+	 * txn_registrant_side_meta_box
1506
+	 * generates HTML for the Edit Transaction side meta box
1507
+	 *
1508
+	 * @access public
1509
+	 * @return void
1510
+	 * @throws DomainException
1511
+	 * @throws EE_Error
1512
+	 * @throws InvalidArgumentException
1513
+	 * @throws InvalidDataTypeException
1514
+	 * @throws InvalidInterfaceException
1515
+	 * @throws ReflectionException
1516
+	 */
1517
+	public function txn_registrant_side_meta_box()
1518
+	{
1519
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1520
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1521
+			: null;
1522
+		if (! $primary_att instanceof EE_Attendee) {
1523
+			$this->_template_args['no_attendee_message'] = esc_html__(
1524
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1525
+				'event_espresso'
1526
+			);
1527
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1528
+		}
1529
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1530
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1531
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1532
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1533
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1534
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1535
+			[
1536
+				'action' => 'edit_attendee',
1537
+				'post'   => $primary_att->ID(),
1538
+			],
1539
+			REG_ADMIN_URL
1540
+		);
1541
+		// get formatted address for registrant
1542
+		$formatted_address                         = EEH_Address::format($primary_att);
1543
+		$formatted_address                         =
1544
+			$formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1545
+				? $formatted_address
1546
+				: '';
1547
+		$this->_template_args['formatted_address'] = $formatted_address;
1548
+		echo EEH_Template::display_template(
1549
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1550
+			$this->_template_args,
1551
+			true
1552
+		);
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * txn_billing_info_side_meta_box
1558
+	 *    generates HTML for the Edit Transaction side meta box
1559
+	 *
1560
+	 * @access public
1561
+	 * @return void
1562
+	 * @throws DomainException
1563
+	 */
1564
+	public function txn_billing_info_side_meta_box()
1565
+	{
1566
+		try {
1567
+			$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1568
+			$this->_template_args['billing_form_url'] = add_query_arg(
1569
+				['action' => 'edit_transaction', 'process' => 'billing'],
1570
+				TXN_ADMIN_URL
1571
+			);
1572
+		} catch (Exception $e) {
1573
+			$this->_template_args['billing_form'] = [];
1574
+			$this->_template_args['billing_form_url'] = '';
1575
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1576
+		}
1577
+
1578
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1579
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1580
+	}
1581
+
1582
+
1583
+	/**
1584
+	 * apply_payments_or_refunds
1585
+	 *    registers a payment or refund made towards a transaction
1586
+	 *
1587
+	 * @access public
1588
+	 * @return void
1589
+	 * @throws EE_Error
1590
+	 * @throws InvalidArgumentException
1591
+	 * @throws ReflectionException
1592
+	 * @throws RuntimeException
1593
+	 * @throws InvalidDataTypeException
1594
+	 * @throws InvalidInterfaceException
1595
+	 */
1596
+	public function apply_payments_or_refunds()
1597
+	{
1598
+		$valid_data = $this->_validate_payment_request_data();
1599
+		$has_access = $this->capabilities->current_user_can(
1600
+			'ee_edit_payments',
1601
+			'apply_payment_or_refund_from_registration_details'
1602
+		);
1603
+		$TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1604
+		$amount     = 0;
1605
+		if (! empty($valid_data) && $has_access) {
1606
+			$PAY_ID = $valid_data['PAY_ID'];
1607
+			// save  the new payment
1608
+			$payment = $this->_create_payment_from_request_data($valid_data);
1609
+			$amount  = $payment->amount();
1610
+			// get the TXN for this payment
1611
+			$transaction = $payment->transaction();
1612
+			// verify transaction
1613
+			if ($transaction instanceof EE_Transaction) {
1614
+				// calculate_total_payments_and_update_status
1615
+				$this->_process_transaction_payments($transaction);
1616
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1617
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1618
+				// apply payment to registrations (if applicable)
1619
+				if (! empty($REG_IDs)) {
1620
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1621
+					$this->_maybe_send_notifications();
1622
+					// now process status changes for the same registrations
1623
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1624
+				}
1625
+				$this->_maybe_send_notifications($payment);
1626
+				// prepare to render page
1627
+				do_action(
1628
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1629
+					$transaction,
1630
+					$payment
1631
+				);
1632
+			} else {
1633
+				EE_Error::add_error(
1634
+					esc_html__(
1635
+						'A valid Transaction for this payment could not be retrieved.',
1636
+						'event_espresso'
1637
+					),
1638
+					__FILE__,
1639
+					__FUNCTION__,
1640
+					__LINE__
1641
+				);
1642
+			}
1643
+		} elseif ($has_access) {
1644
+			EE_Error::add_error(
1645
+				esc_html__(
1646
+					'The payment form data could not be processed. Please try again.',
1647
+					'event_espresso'
1648
+				),
1649
+				__FILE__,
1650
+				__FUNCTION__,
1651
+				__LINE__
1652
+			);
1653
+		} else {
1654
+			EE_Error::add_error(
1655
+				esc_html__(
1656
+					'You do not have access to apply payments or refunds to a registration.',
1657
+					'event_espresso'
1658
+				),
1659
+				__FILE__,
1660
+				__FUNCTION__,
1661
+				__LINE__
1662
+			);
1663
+		}
1664
+		$query_args = [
1665
+			'page'   => 'espresso_transactions',
1666
+			'action' => 'view_transaction',
1667
+			'TXN_ID' => $TXD_ID,
1668
+		];
1669
+
1670
+		$this->_redirect_after_action(
1671
+			! EE_Error::has_error(),
1672
+			$amount > 0
1673
+				? esc_html__('payment', 'event_espresso')
1674
+				: esc_html__('refund', 'event_espresso'),
1675
+			esc_html__('processed', 'event_espresso'),
1676
+			$query_args
1677
+		);
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 * _validate_payment_request_data
1683
+	 *
1684
+	 * @return array
1685
+	 * @throws EE_Error
1686
+	 * @throws InvalidArgumentException
1687
+	 * @throws InvalidDataTypeException
1688
+	 * @throws InvalidInterfaceException
1689
+	 */
1690
+	protected function _validate_payment_request_data()
1691
+	{
1692
+		if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1693
+			return [];
1694
+		}
1695
+		$payment_form = $this->_generate_payment_form_section();
1696
+		try {
1697
+			if ($payment_form->was_submitted()) {
1698
+				$payment_form->receive_form_submission();
1699
+				if (! $payment_form->is_valid()) {
1700
+					$submission_error_messages = [];
1701
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1702
+						if ($validation_error instanceof EE_Validation_Error) {
1703
+							$form_input                  = $validation_error->get_form_section();
1704
+							$submission_error_messages[] = sprintf(
1705
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1706
+								$form_input instanceof EE_Form_Input_Base
1707
+									? $form_input->html_label_text()
1708
+									: '',
1709
+								$validation_error->getMessage()
1710
+							);
1711
+						}
1712
+					}
1713
+					EE_Error::add_error(
1714
+						implode('<br />', $submission_error_messages),
1715
+						__FILE__,
1716
+						__FUNCTION__,
1717
+						__LINE__
1718
+					);
1719
+					return [];
1720
+				}
1721
+			}
1722
+		} catch (EE_Error $e) {
1723
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1724
+			return [];
1725
+		}
1726
+
1727
+		return $payment_form->valid_data();
1728
+	}
1729
+
1730
+
1731
+	/**
1732
+	 * _generate_payment_form_section
1733
+	 *
1734
+	 * @return EE_Form_Section_Proper
1735
+	 * @throws EE_Error
1736
+	 */
1737
+	protected function _generate_payment_form_section()
1738
+	{
1739
+		return new EE_Form_Section_Proper(
1740
+			[
1741
+				'name'        => 'txn_admin_payment',
1742
+				'subsections' => [
1743
+					'PAY_ID'          => new EE_Text_Input(
1744
+						[
1745
+							'default'               => 0,
1746
+							'required'              => false,
1747
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1748
+							'validation_strategies' => [new EE_Int_Normalization()],
1749
+						]
1750
+					),
1751
+					'TXN_ID'          => new EE_Text_Input(
1752
+						[
1753
+							'default'               => 0,
1754
+							'required'              => true,
1755
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1756
+							'validation_strategies' => [new EE_Int_Normalization()],
1757
+						]
1758
+					),
1759
+					'type'            => new EE_Text_Input(
1760
+						[
1761
+							'default'               => 1,
1762
+							'required'              => true,
1763
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1764
+							'validation_strategies' => [new EE_Int_Normalization()],
1765
+						]
1766
+					),
1767
+					'amount'          => new EE_Text_Input(
1768
+						[
1769
+							'default'               => 0,
1770
+							'required'              => true,
1771
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1772
+							'validation_strategies' => [new EE_Float_Normalization()],
1773
+						]
1774
+					),
1775
+					'status'          => new EE_Text_Input(
1776
+						[
1777
+							'default'         => EEM_Payment::status_id_approved,
1778
+							'required'        => true,
1779
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1780
+						]
1781
+					),
1782
+					'PMD_ID'          => new EE_Text_Input(
1783
+						[
1784
+							'default'               => 2,
1785
+							'required'              => true,
1786
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1787
+							'validation_strategies' => [new EE_Int_Normalization()],
1788
+						]
1789
+					),
1790
+					'date'            => new EE_Text_Input(
1791
+						[
1792
+							'default'         => time(),
1793
+							'required'        => true,
1794
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1795
+						]
1796
+					),
1797
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1798
+						[
1799
+							'default'               => '',
1800
+							'required'              => false,
1801
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1802
+							'validation_strategies' => [
1803
+								new EE_Max_Length_Validation_Strategy(
1804
+									esc_html__('Input too long', 'event_espresso'),
1805
+									100
1806
+								),
1807
+							],
1808
+						]
1809
+					),
1810
+					'po_number'       => new EE_Text_Input(
1811
+						[
1812
+							'default'               => '',
1813
+							'required'              => false,
1814
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1815
+							'validation_strategies' => [
1816
+								new EE_Max_Length_Validation_Strategy(
1817
+									esc_html__('Input too long', 'event_espresso'),
1818
+									100
1819
+								),
1820
+							],
1821
+						]
1822
+					),
1823
+					'accounting'      => new EE_Text_Input(
1824
+						[
1825
+							'default'               => '',
1826
+							'required'              => false,
1827
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1828
+							'validation_strategies' => [
1829
+								new EE_Max_Length_Validation_Strategy(
1830
+									esc_html__('Input too long', 'event_espresso'),
1831
+									100
1832
+								),
1833
+							],
1834
+						]
1835
+					),
1836
+				],
1837
+			]
1838
+		);
1839
+	}
1840
+
1841
+
1842
+	/**
1843
+	 * _create_payment_from_request_data
1844
+	 *
1845
+	 * @param array $valid_data
1846
+	 * @return EE_Payment
1847
+	 * @throws EE_Error
1848
+	 * @throws InvalidArgumentException
1849
+	 * @throws InvalidDataTypeException
1850
+	 * @throws InvalidInterfaceException
1851
+	 * @throws ReflectionException
1852
+	 */
1853
+	protected function _create_payment_from_request_data($valid_data)
1854
+	{
1855
+		$PAY_ID = $valid_data['PAY_ID'];
1856
+		// get payment amount
1857
+		$amount = $valid_data['amount']
1858
+			? EEH_Money::strip_localized_money_formatting($valid_data['amount'])
1859
+			: 0;
1860
+		// payments have a type value of 1 and refunds have a type value of -1
1861
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1862
+		$amount = $valid_data['type'] < 0
1863
+			? $amount * -1
1864
+			: $amount;
1865
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1866
+		$date    = $valid_data['date']
1867
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1868
+			: date('Y-m-d g:i a', current_time('timestamp'));
1869
+		$payment = EE_Payment::new_instance(
1870
+			[
1871
+				'TXN_ID'              => $valid_data['TXN_ID'],
1872
+				'STS_ID'              => $valid_data['status'],
1873
+				'PAY_timestamp'       => $date,
1874
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1875
+				'PMD_ID'              => $valid_data['PMD_ID'],
1876
+				'PAY_amount'          => $amount,
1877
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1878
+				'PAY_po_number'       => $valid_data['po_number'],
1879
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1880
+				'PAY_details'         => $valid_data,
1881
+				'PAY_ID'              => $PAY_ID,
1882
+			],
1883
+			'',
1884
+			['Y-m-d', 'g:i a']
1885
+		);
1886
+
1887
+		if (! $payment->save()) {
1888
+			EE_Error::add_error(
1889
+				sprintf(
1890
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1891
+					$payment->ID()
1892
+				),
1893
+				__FILE__,
1894
+				__FUNCTION__,
1895
+				__LINE__
1896
+			);
1897
+		}
1898
+
1899
+		return $payment;
1900
+	}
1901
+
1902
+
1903
+	/**
1904
+	 * _process_transaction_payments
1905
+	 *
1906
+	 * @param EE_Transaction $transaction
1907
+	 * @return void
1908
+	 * @throws EE_Error
1909
+	 * @throws InvalidArgumentException
1910
+	 * @throws ReflectionException
1911
+	 * @throws InvalidDataTypeException
1912
+	 * @throws InvalidInterfaceException
1913
+	 */
1914
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1915
+	{
1916
+		/** @type EE_Transaction_Payments $transaction_payments */
1917
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1918
+		// update the transaction with this payment
1919
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1920
+			EE_Error::add_success(
1921
+				esc_html__(
1922
+					'The payment has been processed successfully.',
1923
+					'event_espresso'
1924
+				),
1925
+				__FILE__,
1926
+				__FUNCTION__,
1927
+				__LINE__
1928
+			);
1929
+		} else {
1930
+			EE_Error::add_error(
1931
+				esc_html__(
1932
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1933
+					'event_espresso'
1934
+				),
1935
+				__FILE__,
1936
+				__FUNCTION__,
1937
+				__LINE__
1938
+			);
1939
+		}
1940
+	}
1941
+
1942
+
1943
+	/**
1944
+	 * _get_REG_IDs_to_apply_payment_to
1945
+	 * returns a list of registration IDs that the payment will apply to
1946
+	 *
1947
+	 * @param EE_Payment $payment
1948
+	 * @return array
1949
+	 * @throws EE_Error
1950
+	 * @throws InvalidArgumentException
1951
+	 * @throws InvalidDataTypeException
1952
+	 * @throws InvalidInterfaceException
1953
+	 * @throws ReflectionException
1954
+	 */
1955
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1956
+	{
1957
+		// grab array of IDs for specific registrations to apply changes to
1958
+		$apply_to_all = $this->request->getRequestParam(
1959
+			'txn_admin_payment[apply_to_all_registrations]',
1960
+			false,
1961
+			DataType::BOOL
1962
+		);
1963
+		$REG_IDs      = ! $apply_to_all
1964
+			? $this->request->getRequestParam(
1965
+				'txn_admin_payment[registrations]',
1966
+				[],
1967
+				DataType::INT,
1968
+				true
1969
+			)
1970
+			: [];
1971
+		// nothing specified ? then get all reg IDs
1972
+		if ($apply_to_all || empty($REG_IDs)) {
1973
+			$registrations = $payment->transaction()->registrations(
1974
+				[
1975
+					[
1976
+						'STS_ID' => [
1977
+							'NOT_IN', [ RegStatus::CANCELLED ]
1978
+						]
1979
+					]
1980
+				]
1981
+			);
1982
+			$REG_IDs       = ! empty($registrations)
1983
+				? array_keys($registrations)
1984
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1985
+		}
1986
+		// ensure that REG_IDs are integers and NOT strings
1987
+		return array_map('absint', $REG_IDs);
1988
+	}
1989
+
1990
+
1991
+	/**
1992
+	 * @return array
1993
+	 */
1994
+	public function existing_reg_payment_REG_IDs()
1995
+	{
1996
+		return $this->_existing_reg_payment_REG_IDs;
1997
+	}
1998
+
1999
+
2000
+	/**
2001
+	 * @param array $existing_reg_payment_REG_IDs
2002
+	 */
2003
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2004
+	{
2005
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2006
+	}
2007
+
2008
+
2009
+	/**
2010
+	 * _get_existing_reg_payment_REG_IDs
2011
+	 * returns a list of registration IDs that the payment is currently related to
2012
+	 * as recorded in the database
2013
+	 *
2014
+	 * @param EE_Payment $payment
2015
+	 * @return array
2016
+	 * @throws EE_Error
2017
+	 * @throws InvalidArgumentException
2018
+	 * @throws InvalidDataTypeException
2019
+	 * @throws InvalidInterfaceException
2020
+	 * @throws ReflectionException
2021
+	 */
2022
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2023
+	{
2024
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2025
+			// let's get any existing reg payment records for this payment
2026
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2027
+			// but we only want the REG IDs, so grab the array keys
2028
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2029
+				? array_keys($existing_reg_payment_REG_IDs)
2030
+				: [];
2031
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2032
+		}
2033
+
2034
+		return $this->existing_reg_payment_REG_IDs();
2035
+	}
2036
+
2037
+
2038
+	/**
2039
+	 * _remove_existing_registration_payments
2040
+	 * this calculates the difference between existing relations
2041
+	 * to the supplied payment and the new list registration IDs,
2042
+	 * removes any related registrations that no longer apply,
2043
+	 * and then updates the registration paid fields
2044
+	 *
2045
+	 * @param EE_Payment $payment
2046
+	 * @param int        $PAY_ID
2047
+	 * @return bool;
2048
+	 * @throws EE_Error
2049
+	 * @throws InvalidArgumentException
2050
+	 * @throws ReflectionException
2051
+	 * @throws InvalidDataTypeException
2052
+	 * @throws InvalidInterfaceException
2053
+	 */
2054
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2055
+	{
2056
+		// newly created payments will have nothing recorded for $PAY_ID
2057
+		if (absint($PAY_ID) === 0) {
2058
+			return false;
2059
+		}
2060
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2061
+		if (empty($existing_reg_payment_REG_IDs)) {
2062
+			return false;
2063
+		}
2064
+		/** @type EE_Transaction_Payments $transaction_payments */
2065
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2066
+
2067
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2068
+			$payment,
2069
+			[
2070
+				[
2071
+					'PAY_ID' => $payment->ID(),
2072
+					'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2073
+				],
2074
+			]
2075
+		);
2076
+	}
2077
+
2078
+
2079
+	/**
2080
+	 * _update_registration_payments
2081
+	 * this applies the payments to the selected registrations
2082
+	 * but only if they have not already been paid for
2083
+	 *
2084
+	 * @param EE_Transaction $transaction
2085
+	 * @param EE_Payment     $payment
2086
+	 * @param array          $REG_IDs
2087
+	 * @return void
2088
+	 * @throws EE_Error
2089
+	 * @throws InvalidArgumentException
2090
+	 * @throws ReflectionException
2091
+	 * @throws RuntimeException
2092
+	 * @throws InvalidDataTypeException
2093
+	 * @throws InvalidInterfaceException
2094
+	 */
2095
+	protected function _update_registration_payments(
2096
+		EE_Transaction $transaction,
2097
+		EE_Payment $payment,
2098
+		$REG_IDs = []
2099
+	) {
2100
+		// we can pass our own custom set of registrations to RegistrationPayments::processRegistrationPayments()
2101
+		// so let's do that using our set of REG_IDs from the form
2102
+		$registration_query_where_params = [
2103
+			'REG_ID' => ['IN', $REG_IDs],
2104
+		];
2105
+		// but add in some conditions regarding payment,
2106
+		// so that we don't apply payments to registrations that are free or have already been paid for
2107
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2108
+		if (! $payment->is_a_refund()) {
2109
+			$registration_query_where_params['REG_final_price']  = ['!=', 0];
2110
+			$registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2111
+		}
2112
+		$registrations = $transaction->registrations([$registration_query_where_params]);
2113
+		if (! empty($registrations)) {
2114
+			/** @var RegistrationPayments $payment_processor */
2115
+			$payment_processor = LoaderFactory::getShared(RegistrationPayments::class);
2116
+			$payment_processor->processRegistrationPayments($transaction, $payment, $registrations);
2117
+		}
2118
+	}
2119
+
2120
+
2121
+	/**
2122
+	 * _process_registration_status_change
2123
+	 * This processes requested registration status changes for all the registrations
2124
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2125
+	 *
2126
+	 * @param EE_Transaction $transaction
2127
+	 * @param array          $REG_IDs
2128
+	 * @return bool
2129
+	 * @throws EE_Error
2130
+	 * @throws InvalidArgumentException
2131
+	 * @throws ReflectionException
2132
+	 * @throws InvalidDataTypeException
2133
+	 * @throws InvalidInterfaceException
2134
+	 */
2135
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2136
+	{
2137
+		// first if there is no change in status then we get out.
2138
+		$reg_status = $reg_status
2139
+			?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2140
+		if ($reg_status === 'NAN') {
2141
+			// no error message, no change requested, just nothing to do man.
2142
+			return false;
2143
+		}
2144
+		/** @type EE_Transaction_Processor $transaction_processor */
2145
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2146
+
2147
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2148
+		return $transaction_processor->manually_update_registration_statuses(
2149
+			$transaction,
2150
+			$reg_status,
2151
+			[['REG_ID' => ['IN', $REG_IDs]]]
2152
+		);
2153
+	}
2154
+
2155
+
2156
+	/**
2157
+	 * _build_payment_json_response
2158
+	 *
2159
+	 * @access public
2160
+	 * @param EE_Payment  $payment
2161
+	 * @param array       $REG_IDs
2162
+	 * @param bool | null $delete_txn_reg_status_change
2163
+	 * @return array
2164
+	 * @throws EE_Error
2165
+	 * @throws InvalidArgumentException
2166
+	 * @throws InvalidDataTypeException
2167
+	 * @throws InvalidInterfaceException
2168
+	 * @throws ReflectionException
2169
+	 */
2170
+	protected function _build_payment_json_response(
2171
+		EE_Payment $payment,
2172
+		$REG_IDs = [],
2173
+		$delete_txn_reg_status_change = null
2174
+	) {
2175
+		// was the payment deleted ?
2176
+		if (is_bool($delete_txn_reg_status_change)) {
2177
+			return [
2178
+				'PAY_ID'                       => $payment->ID(),
2179
+				'amount'                       => $payment->amount(),
2180
+				'total_paid'                   => $payment->transaction()->paid(),
2181
+				'txn_status'                   => $payment->transaction()->status_ID(),
2182
+				'pay_status'                   => $payment->STS_ID(),
2183
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2184
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2185
+			];
2186
+		}
2187
+
2188
+		$this->_get_payment_status_array();
2189
+		$payment_method = $payment->payment_method();
2190
+		return [
2191
+			'amount'           => $payment->amount(),
2192
+			'total_paid'       => $payment->transaction()->paid(),
2193
+			'txn_status'       => $payment->transaction()->status_ID(),
2194
+			'pay_status'       => $payment->STS_ID(),
2195
+			'PAY_ID'           => $payment->ID(),
2196
+			'STS_ID'           => $payment->STS_ID(),
2197
+			'status'           => self::$_pay_status[ $payment->STS_ID() ],
2198
+			'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2199
+			'method'           => strtoupper($payment->source()),
2200
+			'PM_ID'            => $payment_method instanceof EE_Payment_Method
2201
+				? $payment_method->ID()
2202
+				: 1,
2203
+			'gateway'          => $payment_method instanceof EE_Payment_Method
2204
+				? $payment_method->admin_name()
2205
+				: esc_html__('Unknown', 'event_espresso'),
2206
+			'gateway_response' => $payment->gateway_response(),
2207
+			'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2208
+			'po_number'        => $payment->po_number(),
2209
+			'extra_accntng'    => $payment->extra_accntng(),
2210
+			'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2211
+		];
2212
+	}
2213
+
2214
+
2215
+	/**
2216
+	 * delete_payment
2217
+	 *    delete a payment or refund made towards a transaction
2218
+	 *
2219
+	 * @access public
2220
+	 * @return void
2221
+	 * @throws EE_Error
2222
+	 * @throws InvalidArgumentException
2223
+	 * @throws ReflectionException
2224
+	 * @throws InvalidDataTypeException
2225
+	 * @throws InvalidInterfaceException
2226
+	 */
2227
+	public function delete_payment()
2228
+	{
2229
+		$TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2230
+		// $json_response_data = ['return_data' => false];
2231
+		$PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2232
+		$amount     = 0;
2233
+		$can_delete = $this->capabilities->current_user_can(
2234
+			'ee_delete_payments',
2235
+			'delete_payment_from_registration_details'
2236
+		);
2237
+		if ($PAY_ID && $can_delete) {
2238
+			$delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2239
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2240
+			if ($payment instanceof EE_Payment) {
2241
+				$amount  = $payment->amount();
2242
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2243
+				/** @type EE_Transaction_Payments $transaction_payments */
2244
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2245
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2246
+					if ($delete_txn_reg_status_change) {
2247
+						$this->_maybe_send_notifications();
2248
+						$this->_process_registration_status_change(
2249
+							$payment->transaction(),
2250
+							$REG_IDs,
2251
+							$delete_txn_reg_status_change
2252
+						);
2253
+					}
2254
+				}
2255
+			} else {
2256
+				EE_Error::add_error(
2257
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2258
+					__FILE__,
2259
+					__FUNCTION__,
2260
+					__LINE__
2261
+				);
2262
+			}
2263
+		} elseif ($can_delete) {
2264
+			EE_Error::add_error(
2265
+				esc_html__(
2266
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2267
+					'event_espresso'
2268
+				),
2269
+				__FILE__,
2270
+				__FUNCTION__,
2271
+				__LINE__
2272
+			);
2273
+		} else {
2274
+			EE_Error::add_error(
2275
+				esc_html__(
2276
+					'You do not have access to delete a payment.',
2277
+					'event_espresso'
2278
+				),
2279
+				__FILE__,
2280
+				__FUNCTION__,
2281
+				__LINE__
2282
+			);
2283
+		}
2284
+		$query_args = [
2285
+			'page'   => 'espresso_transactions',
2286
+			'action' => 'view_transaction',
2287
+			'TXN_ID' => $TXD_ID,
2288
+		];
2289
+		$this->_redirect_after_action(
2290
+			! EE_Error::has_error(),
2291
+			$amount > 0
2292
+				? esc_html__('payment', 'event_espresso')
2293
+				: esc_html__('refund', 'event_espresso'),
2294
+			esc_html__('deleted', 'event_espresso'),
2295
+			$query_args
2296
+		);
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _registration_payment_data_array
2302
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2303
+	 *
2304
+	 * @access protected
2305
+	 * @param array $REG_IDs
2306
+	 * @return array
2307
+	 * @throws EE_Error
2308
+	 * @throws InvalidArgumentException
2309
+	 * @throws InvalidDataTypeException
2310
+	 * @throws InvalidInterfaceException
2311
+	 * @throws ReflectionException
2312
+	 */
2313
+	protected function _registration_payment_data_array($REG_IDs)
2314
+	{
2315
+		$registration_payment_data = [];
2316
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2317
+		if (! empty($REG_IDs)) {
2318
+			$registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2319
+			foreach ($registrations as $registration) {
2320
+				if ($registration instanceof EE_Registration) {
2321
+					$registration_payment_data[ $registration->ID() ] = [
2322
+						'paid'  => $registration->pretty_paid(),
2323
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2324
+					];
2325
+				}
2326
+			}
2327
+		}
2328
+
2329
+		return $registration_payment_data;
2330
+	}
2331
+
2332
+
2333
+	/**
2334
+	 * _maybe_send_notifications
2335
+	 * determines whether or not the admin has indicated that notifications should be sent.
2336
+	 * If so, will toggle a filter switch for delivering registration notices.
2337
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2338
+	 *
2339
+	 * @access protected
2340
+	 * @param EE_Payment | null $payment
2341
+	 */
2342
+	protected function _maybe_send_notifications($payment = null)
2343
+	{
2344
+		switch ($payment instanceof EE_Payment) {
2345
+			// payment notifications
2346
+			case true:
2347
+				if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2348
+					$this->_process_payment_notification($payment);
2349
+				}
2350
+				break;
2351
+			// registration notifications
2352
+			case false:
2353
+				if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2354
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2355
+				}
2356
+				break;
2357
+		}
2358
+	}
2359
+
2360
+
2361
+	/**
2362
+	 * _send_payment_reminder
2363
+	 *    generates HTML for the View Transaction Details Admin page
2364
+	 *
2365
+	 * @access protected
2366
+	 * @return void
2367
+	 * @throws EE_Error
2368
+	 * @throws InvalidArgumentException
2369
+	 * @throws InvalidDataTypeException
2370
+	 * @throws InvalidInterfaceException
2371
+	 */
2372
+	protected function _send_payment_reminder()
2373
+	{
2374
+		$TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2375
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2376
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2377
+		$query_args  = $redirect_to
2378
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2379
+			: [];
2380
+		do_action(
2381
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2382
+			$transaction
2383
+		);
2384
+		$this->_redirect_after_action(
2385
+			false,
2386
+			esc_html__('payment reminder', 'event_espresso'),
2387
+			esc_html__('sent', 'event_espresso'),
2388
+			$query_args,
2389
+			true
2390
+		);
2391
+	}
2392
+
2393
+
2394
+	/**
2395
+	 *  get_transactions
2396
+	 *    get transactions for given parameters (used by list table)
2397
+	 *
2398
+	 * @param int     $per_page how many transactions displayed per page
2399
+	 * @param boolean $count    return the count or objects
2400
+	 * @param string  $view
2401
+	 * @return EE_Transaction[]|int int = count || array of transaction objects
2402
+	 * @throws EE_Error
2403
+	 * @throws InvalidArgumentException
2404
+	 * @throws InvalidDataTypeException
2405
+	 * @throws InvalidInterfaceException
2406
+	 * @throws ReflectionException
2407
+	 */
2408
+	public function get_transactions($per_page, $count = false, $view = '')
2409
+	{
2410
+		$start_date = wp_strip_all_tags(
2411
+			$this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2412
+		);
2413
+		$end_date   = wp_strip_all_tags(
2414
+			$this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2415
+		);
2416
+
2417
+		// make sure our timestamps start and end right at the boundaries for each day
2418
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2419
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2420
+
2421
+
2422
+		// convert to timestamps
2423
+		$start_date = strtotime($start_date);
2424
+		$end_date   = strtotime($end_date);
2425
+
2426
+		// makes sure start date is the lowest value and vice versa
2427
+		$start_date = min($start_date, $end_date);
2428
+		$end_date   = max($start_date, $end_date);
2429
+
2430
+		// convert to correct format for query
2431
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2432
+			'TXN_timestamp',
2433
+			date('Y-m-d H:i:s', $start_date),
2434
+			'Y-m-d H:i:s'
2435
+		);
2436
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2437
+			'TXN_timestamp',
2438
+			date('Y-m-d H:i:s', $end_date),
2439
+			'Y-m-d H:i:s'
2440
+		);
2441
+
2442
+
2443
+		// set orderby
2444
+		$orderby = $this->request->getRequestParam('orderby');
2445
+
2446
+		switch ($orderby) {
2447
+			case 'TXN_ID':
2448
+				break;
2449
+			case 'ATT_fname':
2450
+				$orderby = 'Registration.Attendee.ATT_fname';
2451
+				break;
2452
+			case 'event_name':
2453
+				$orderby = 'Registration.Event.EVT_name';
2454
+				break;
2455
+			default: // 'TXN_timestamp'
2456
+				$orderby = 'TXN_timestamp';
2457
+		}
2458
+
2459
+		$sort         = $this->request->getRequestParam('order', 'DESC');
2460
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
2461
+
2462
+		$per_page = absint($per_page)
2463
+			? $per_page
2464
+			: 10;
2465
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2466
+
2467
+		$offset = ($current_page - 1) * $per_page;
2468
+		$limit  = [$offset, $per_page];
2469
+
2470
+		$_where = [
2471
+			'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2472
+			'Registration.REG_count' => 1,
2473
+		];
2474
+
2475
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2476
+		if ($EVT_ID) {
2477
+			$_where['Registration.EVT_ID'] = $EVT_ID;
2478
+		}
2479
+
2480
+		$search_term = $this->request->getRequestParam('s');
2481
+		if ($search_term) {
2482
+			$search_term  = '%' . $search_term . '%';
2483
+			$_where['OR'] = [
2484
+				'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2485
+				'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2486
+				'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2487
+				'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2488
+				'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2489
+				'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2490
+				'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2491
+				'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2492
+				'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2493
+				'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2494
+				'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2495
+				'Registration.REG_final_price'        => ['LIKE', $search_term],
2496
+				'Registration.REG_code'               => ['LIKE', $search_term],
2497
+				'Registration.REG_count'              => ['LIKE', $search_term],
2498
+				'Registration.REG_group_size'         => ['LIKE', $search_term],
2499
+				'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2500
+				'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2501
+				'Payment.PAY_source'                  => ['LIKE', $search_term],
2502
+				'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2503
+				'TXN_session_data'                    => ['LIKE', $search_term],
2504
+				'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2505
+			];
2506
+		}
2507
+
2508
+		$status = $this->request->getRequestParam('status');
2509
+		// failed transactions
2510
+		$failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2511
+		$abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2512
+		$incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2513
+
2514
+		if ($failed) {
2515
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2516
+		} elseif ($abandoned) {
2517
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2518
+		} elseif ($incomplete) {
2519
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2520
+		} else {
2521
+			$_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2522
+			$_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2523
+		}
2524
+
2525
+		$query_params = apply_filters(
2526
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2527
+			[
2528
+				$_where,
2529
+				'order_by'                 => [$orderby => $sort],
2530
+				'limit'                    => $limit,
2531
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2532
+			],
2533
+			$this->request->requestParams(),
2534
+			$view,
2535
+			$count
2536
+		);
2537
+
2538
+		return $count
2539
+			? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2540
+			: EEM_Transaction::instance()->get_all($query_params);
2541
+	}
2542
+
2543
+
2544
+	/**
2545
+	 * @throws EE_Error
2546
+	 * @throws InvalidArgumentException
2547
+	 * @throws InvalidDataTypeException
2548
+	 * @throws InvalidInterfaceException
2549
+	 * @throws ReflectionException
2550
+	 * @throws RuntimeException
2551
+	 * @since 4.9.79.p
2552
+	 */
2553
+	public function recalculateLineItems()
2554
+	{
2555
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2556
+		/** @var EE_Transaction $transaction */
2557
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2558
+		$success     = $transaction->recalculateLineItems();
2559
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2560
+		$query_args  = $redirect_to
2561
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2562
+			: [];
2563
+		$this->_redirect_after_action(
2564
+			$success,
2565
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2566
+			esc_html__('recalculated', 'event_espresso'),
2567
+			$query_args,
2568
+			true
2569
+		);
2570
+	}
2571 2571
 }
Please login to merge, or discard this patch.
Spacing   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
             'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
247 247
             'event_espresso'
248 248
         );
249
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
249
+        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
250 250
             'An error occurred! Please refresh the page and try again.',
251 251
             'event_espresso'
252 252
         );
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
         // enqueue style
348 348
         wp_register_style(
349 349
             'espresso_txn',
350
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
350
+            TXN_ASSETS_URL.'espresso_transactions_admin.css',
351 351
             [],
352 352
             EVENT_ESPRESSO_VERSION
353 353
         );
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
         // scripts
356 356
         wp_register_script(
357 357
             'espresso_txn',
358
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
358
+            TXN_ASSETS_URL.'espresso_transactions_admin.js',
359 359
             [
360 360
                 'ee_admin_js',
361 361
                 'ee-datepicker',
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
             $this->_transaction->verify_abandoned_transaction_status();
483 483
         }
484 484
 
485
-        if (! $this->_transaction instanceof EE_Transaction) {
485
+        if ( ! $this->_transaction instanceof EE_Transaction) {
486 486
             $error_msg = sprintf(
487 487
                 esc_html__(
488 488
                     'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
@@ -579,7 +579,7 @@  discard block
 block discarded – undo
579 579
             'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
580 580
             [
581 581
                 'overpaid'   => [
582
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
582
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::overpaid_status_code,
583 583
                     'desc'  => EEH_Template::pretty_status(
584 584
                         EEM_Transaction::overpaid_status_code,
585 585
                         false,
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
                     ),
588 588
                 ],
589 589
                 'complete'   => [
590
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
590
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::complete_status_code,
591 591
                     'desc'  => EEH_Template::pretty_status(
592 592
                         EEM_Transaction::complete_status_code,
593 593
                         false,
@@ -595,7 +595,7 @@  discard block
 block discarded – undo
595 595
                     ),
596 596
                 ],
597 597
                 'incomplete' => [
598
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
598
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::incomplete_status_code,
599 599
                     'desc'  => EEH_Template::pretty_status(
600 600
                         EEM_Transaction::incomplete_status_code,
601 601
                         false,
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
                     ),
604 604
                 ],
605 605
                 'abandoned'  => [
606
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
606
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::abandoned_status_code,
607 607
                     'desc'  => EEH_Template::pretty_status(
608 608
                         EEM_Transaction::abandoned_status_code,
609 609
                         false,
@@ -611,7 +611,7 @@  discard block
 block discarded – undo
611 611
                     ),
612 612
                 ],
613 613
                 'failed'     => [
614
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
614
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::failed_status_code,
615 615
                     'desc'  => EEH_Template::pretty_status(
616 616
                         EEM_Transaction::failed_status_code,
617 617
                         false,
@@ -654,11 +654,11 @@  discard block
 block discarded – undo
654 654
                 )
655 655
                 . '" aria-label="'
656 656
                 . esc_attr__('Click to Edit event', 'event_espresso')
657
-                . '">' . $event->name() . '</a>',
657
+                . '">'.$event->name().'</a>',
658 658
                 '</h3>'
659 659
             )
660 660
             : '';
661
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
661
+        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
662 662
         $this->display_admin_list_table_page_with_no_sidebar();
663 663
     }
664 664
 
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
 
689 689
         $this->_set_transaction_object();
690 690
 
691
-        if (! $this->_transaction instanceof EE_Transaction) {
691
+        if ( ! $this->_transaction instanceof EE_Transaction) {
692 692
             return;
693 693
         }
694 694
 
@@ -698,7 +698,7 @@  discard block
 block discarded – undo
698 698
         $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
699 699
         $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
700 700
 
701
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
701
+        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->status_ID()];
702 702
         $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
703 703
         $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
704 704
 
@@ -743,7 +743,7 @@  discard block
 block discarded – undo
743 743
 
744 744
 
745 745
         // next link
746
-        $next_txn                                 = $this->_transaction->next(
746
+        $next_txn = $this->_transaction->next(
747 747
             null,
748 748
             [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
749 749
             'TXN_ID'
@@ -758,7 +758,7 @@  discard block
 block discarded – undo
758 758
             )
759 759
             : '';
760 760
         // previous link
761
-        $previous_txn                                 = $this->_transaction->previous(
761
+        $previous_txn = $this->_transaction->previous(
762 762
             null,
763 763
             [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
764 764
             'TXN_ID'
@@ -810,7 +810,7 @@  discard block
 block discarded – undo
810 810
         // grab messages at the last second
811 811
         $this->_template_args['notices'] = EE_Error::get_notices();
812 812
         // path to template
813
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
813
+        $template_path                             = TXN_TEMPLATE_PATH.'txn_admin_details_header.template.php';
814 814
         $this->_template_args['admin_page_header'] = EEH_Template::display_template(
815 815
             $template_path,
816 816
             $this->_template_args,
@@ -838,19 +838,19 @@  discard block
 block discarded – undo
838 838
     {
839 839
         $this->_set_transaction_object();
840 840
 
841
-        if (! $this->_transaction instanceof EE_Transaction) {
841
+        if ( ! $this->_transaction instanceof EE_Transaction) {
842 842
             return;
843 843
         }
844 844
         $this->addMetaBox(
845 845
             'edit-txn-details-mbox',
846
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
846
+            '<span>'.esc_html__('Transaction Details', 'event_espresso')
847 847
             . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
848 848
             [$this, 'txn_details_meta_box'],
849 849
             $this->_wp_page_slug
850 850
         );
851 851
         $this->addMetaBox(
852 852
             'edit-txn-attendees-mbox',
853
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
853
+            '<span>'.esc_html__('Attendees Registered in this Transaction', 'event_espresso')
854 854
             . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
855 855
             [$this, 'txn_attendees_meta_box'],
856 856
             $this->_wp_page_slug,
@@ -892,7 +892,7 @@  discard block
 block discarded – undo
892 892
     {
893 893
         $content = '';
894 894
         $actions = [];
895
-        if (! $transaction instanceof EE_Transaction) {
895
+        if ( ! $transaction instanceof EE_Transaction) {
896 896
             return $content;
897 897
         }
898 898
         /** @var EE_Registration $primary_registration */
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
             $this->_transaction->primary_registration() instanceof EE_Registration
1004 1004
                 ? $this->_transaction->primary_registration()->attendee()
1005 1005
                 : null;
1006
-        $this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1006
+        $this->_template_args['can_edit_payments'] = $this->capabilities->current_user_can(
1007 1007
             'ee_edit_payments',
1008 1008
             'apply_payment_or_refund_from_registration_details'
1009 1009
         );
@@ -1014,7 +1014,7 @@  discard block
 block discarded – undo
1014 1014
 
1015 1015
         // get line table
1016 1016
         EEH_Autoloader::register_line_item_display_autoloaders();
1017
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1017
+        $Line_Item_Display = new EE_Line_Item_Display(
1018 1018
             'admin_table',
1019 1019
             'EE_Admin_Table_Line_Item_Display_Strategy'
1020 1020
         );
@@ -1031,7 +1031,7 @@  discard block
 block discarded – undo
1031 1031
             ? $taxes
1032 1032
             : false;
1033 1033
 
1034
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1034
+        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1035 1035
             $this->_transaction->total(),
1036 1036
             false,
1037 1037
             false
@@ -1041,7 +1041,7 @@  discard block
 block discarded – undo
1041 1041
 
1042 1042
         // process payment details
1043 1043
         $payments = $this->_transaction->payments();
1044
-        if (! empty($payments)) {
1044
+        if ( ! empty($payments)) {
1045 1045
             $this->_template_args['payments']              = $payments;
1046 1046
             $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1047 1047
         } else {
@@ -1099,7 +1099,7 @@  discard block
 block discarded – undo
1099 1099
                                   esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1100 1100
                                   ucwords(str_replace('_', ' ', $reg_step)),
1101 1101
                                   date(
1102
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1102
+                                      get_option('date_format').' '.get_option('time_format'),
1103 1103
                                       $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1104 1104
                                   )
1105 1105
                               )
@@ -1113,7 +1113,7 @@  discard block
 block discarded – undo
1113 1113
                               . '</div>';
1114 1114
             }
1115 1115
         }
1116
-        $reg_steps                                                 .= '</ul>';
1116
+        $reg_steps .= '</ul>';
1117 1117
         $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1118 1118
         $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1119 1119
             'Registration Step Progress',
@@ -1126,14 +1126,14 @@  discard block
 block discarded – undo
1126 1126
         $this->_get_payment_status_array();
1127 1127
         $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1128 1128
 
1129
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1129
+        $this->_template_args['transaction_form_url'] = add_query_arg(
1130 1130
             [
1131 1131
                 'action'  => 'edit_transaction',
1132 1132
                 'process' => 'transaction',
1133 1133
             ],
1134 1134
             TXN_ADMIN_URL
1135 1135
         );
1136
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1136
+        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1137 1137
             [
1138 1138
                 'page'   => 'espresso_transactions',
1139 1139
                 'action' => 'espresso_apply_payment',
@@ -1152,7 +1152,7 @@  discard block
 block discarded – undo
1152 1152
 
1153 1153
         // 'espresso_delete_payment_nonce'
1154 1154
 
1155
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1155
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_txn_details.template.php';
1156 1156
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1157 1157
     }
1158 1158
 
@@ -1184,19 +1184,19 @@  discard block
 block discarded – undo
1184 1184
                 ],
1185 1185
             ]
1186 1186
         );
1187
-        if (! empty($reg_payments)) {
1187
+        if ( ! empty($reg_payments)) {
1188 1188
             foreach ($payments as $payment) {
1189
-                if (! $payment instanceof EE_Payment) {
1189
+                if ( ! $payment instanceof EE_Payment) {
1190 1190
                     continue;
1191
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1192
-                    $existing_reg_payments[ $payment->ID() ] = [];
1191
+                } elseif ( ! isset($existing_reg_payments[$payment->ID()])) {
1192
+                    $existing_reg_payments[$payment->ID()] = [];
1193 1193
                 }
1194 1194
                 foreach ($reg_payments as $reg_payment) {
1195 1195
                     if (
1196 1196
                         $reg_payment instanceof EE_Registration_Payment
1197 1197
                         && $reg_payment->payment_ID() === $payment->ID()
1198 1198
                     ) {
1199
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1199
+                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1200 1200
                     }
1201 1201
                 }
1202 1202
             }
@@ -1222,7 +1222,7 @@  discard block
 block discarded – undo
1222 1222
     protected function _get_registrations_to_apply_payment_to()
1223 1223
     {
1224 1224
         // we want any registration with an active status (ie: not deleted or cancelled)
1225
-        $query_params                      = [
1225
+        $query_params = [
1226 1226
             [
1227 1227
                 'STS_ID' => [
1228 1228
                     'IN',
@@ -1234,22 +1234,22 @@  discard block
 block discarded – undo
1234 1234
                 ],
1235 1235
             ],
1236 1236
         ];
1237
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1237
+        $registrations_to_apply_payment_to = EEH_HTML::br().EEH_HTML::div(
1238 1238
                 '',
1239 1239
                 'txn-admin-apply-payment-to-registrations-dv',
1240 1240
                 '',
1241 1241
                 'clear: both; margin: 1.5em 0 0; display: none;'
1242 1242
             );
1243
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1243
+        $registrations_to_apply_payment_to .= EEH_HTML::br().EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1244 1244
         $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1245 1245
         $registrations_to_apply_payment_to .= EEH_HTML::thead(
1246 1246
             EEH_HTML::tr(
1247
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1248
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1249
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1250
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1251
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1252
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1247
+                EEH_HTML::th(esc_html__('ID', 'event_espresso')).
1248
+                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')).
1249
+                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')).
1250
+                EEH_HTML::th(esc_html__('Event', 'event_espresso')).
1251
+                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr').
1252
+                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr').
1253 1253
                 EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1254 1254
             )
1255 1255
         );
@@ -1264,36 +1264,36 @@  discard block
 block discarded – undo
1264 1264
                     : esc_html__('Unknown Attendee', 'event_espresso');
1265 1265
                 $owing                             = $registration->final_price() - $registration->paid();
1266 1266
                 $taxable                           = $registration->ticket()->taxable()
1267
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1267
+                    ? ' <span class="smaller-text lt-grey-text"> '.esc_html__('+ tax', 'event_espresso').'</span>'
1268 1268
                     : '';
1269 1269
                 $checked                           = empty($existing_reg_payments)
1270 1270
                                                      || in_array($registration->ID(), $existing_reg_payments, true)
1271 1271
                     ? ' checked'
1272 1272
                     : '';
1273
-                $disabled                          = $registration->final_price() > 0
1273
+                $disabled = $registration->final_price() > 0
1274 1274
                     ? ''
1275 1275
                     : ' disabled';
1276 1276
                 $registrations_to_apply_payment_to .= EEH_HTML::tr(
1277
-                    EEH_HTML::td($registration->ID()) .
1278
-                    EEH_HTML::td($attendee_name) .
1277
+                    EEH_HTML::td($registration->ID()).
1278
+                    EEH_HTML::td($attendee_name).
1279 1279
                     EEH_HTML::td(
1280
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1281
-                    ) .
1282
-                    EEH_HTML::td($registration->event_name()) .
1283
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1280
+                        $registration->ticket()->name().' : '.$registration->ticket()->pretty_price().$taxable
1281
+                    ).
1282
+                    EEH_HTML::td($registration->event_name()).
1283
+                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr').
1284 1284
                     EEH_HTML::td(
1285 1285
                         EEH_Template::format_currency($owing),
1286 1286
                         '',
1287 1287
                         'txn-admin-payment-owing-td jst-cntr'
1288
-                    ) .
1288
+                    ).
1289 1289
                     EEH_HTML::td(
1290
-                        '<input type="checkbox" value="' . $registration->ID()
1290
+                        '<input type="checkbox" value="'.$registration->ID()
1291 1291
                         . '" name="txn_admin_payment[registrations]"'
1292
-                        . $checked . $disabled . '>',
1292
+                        . $checked.$disabled.'>',
1293 1293
                         '',
1294 1294
                         'jst-cntr'
1295 1295
                     ),
1296
-                    'apply-payment-registration-row-' . $registration->ID()
1296
+                    'apply-payment-registration-row-'.$registration->ID()
1297 1297
                 );
1298 1298
             }
1299 1299
         }
@@ -1308,7 +1308,7 @@  discard block
 block discarded – undo
1308 1308
             '',
1309 1309
             'clear description'
1310 1310
         );
1311
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1311
+        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1312 1312
         $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1313 1313
     }
1314 1314
 
@@ -1374,12 +1374,12 @@  discard block
 block discarded – undo
1374 1374
                 [
1375 1375
                     'OR*payment_method_for_payment' => [
1376 1376
                         'PMD_ID'    => ['IN', $payment_methods_of_payments],
1377
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1377
+                        'PMD_scope' => ['LIKE', '%'.EEM_Payment_Method::scope_admin.'%'],
1378 1378
                     ],
1379 1379
                 ],
1380 1380
             ];
1381 1381
         } else {
1382
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1382
+            $query_args = [['PMD_scope' => ['LIKE', '%'.EEM_Payment_Method::scope_admin.'%']]];
1383 1383
         }
1384 1384
         $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1385 1385
     }
@@ -1411,7 +1411,7 @@  discard block
 block discarded – undo
1411 1411
             'Line_Item',
1412 1412
             [['LIN_type' => 'line-item']]
1413 1413
         );
1414
-        if (! empty($line_items)) {
1414
+        if ( ! empty($line_items)) {
1415 1415
             foreach ($line_items as $item) {
1416 1416
                 if ($item instanceof EE_Line_Item) {
1417 1417
                     switch ($item->OBJ_type()) {
@@ -1421,7 +1421,7 @@  discard block
 block discarded – undo
1421 1421
                             $ticket = $item->ticket();
1422 1422
                             // right now we're only handling tickets here.
1423 1423
                             // Cause its expected that only tickets will have attendees right?
1424
-                            if (! $ticket instanceof EE_Ticket) {
1424
+                            if ( ! $ticket instanceof EE_Ticket) {
1425 1425
                                 break;
1426 1426
                             }
1427 1427
                             try {
@@ -1430,45 +1430,45 @@  discard block
 block discarded – undo
1430 1430
                                 EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1431 1431
                                 $event_name = esc_html__('Unknown Event', 'event_espresso');
1432 1432
                             }
1433
-                            $event_name   .= ' - ' . $item->name();
1433
+                            $event_name   .= ' - '.$item->name();
1434 1434
                             $ticket_price = EEH_Template::format_currency($item->unit_price());
1435 1435
                             // now get all of the registrations for this transaction that use this ticket
1436 1436
                             $registrations = $ticket->registrations(
1437 1437
                                 [['TXN_ID' => $this->_transaction->ID()]]
1438 1438
                             );
1439 1439
                             foreach ($registrations as $registration) {
1440
-                                if (! $registration instanceof EE_Registration) {
1440
+                                if ( ! $registration instanceof EE_Registration) {
1441 1441
                                     break;
1442 1442
                                 }
1443
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1443
+                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1444 1444
                                     = $registration->status_ID();
1445
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1445
+                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']
1446 1446
                                     = $registration->count();
1447
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1447
+                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1448 1448
                                     = $event_name;
1449
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1449
+                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1450 1450
                                     = $ticket_price;
1451 1451
                                 // attendee info
1452 1452
                                 $attendee = $registration->get_first_related('Attendee');
1453 1453
                                 if ($attendee instanceof EE_Attendee) {
1454
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1454
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']
1455 1455
                                         = $attendee->ID();
1456
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1456
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1457 1457
                                         = $attendee->full_name();
1458
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1459
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1458
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email']
1459
+                                        = '<a href="mailto:'.$attendee->email().'?subject='.$event_name
1460 1460
                                           . esc_html__(
1461 1461
                                               ' Event',
1462 1462
                                               'event_espresso'
1463 1463
                                           )
1464
-                                          . '">' . $attendee->email() . '</a>';
1465
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1464
+                                          . '">'.$attendee->email().'</a>';
1465
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address']
1466 1466
                                         = EEH_Address::format($attendee, 'inline', false, false);
1467 1467
                                 } else {
1468
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1469
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1470
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1471
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1468
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1469
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1470
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1471
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1472 1472
                                 }
1473 1473
                             }
1474 1474
                             break;
@@ -1484,7 +1484,7 @@  discard block
 block discarded – undo
1484 1484
                 TXN_ADMIN_URL
1485 1485
             );
1486 1486
             echo EEH_Template::display_template(
1487
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1487
+                TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_attendees.template.php',
1488 1488
                 $this->_template_args,
1489 1489
                 true
1490 1490
             );
@@ -1519,12 +1519,12 @@  discard block
 block discarded – undo
1519 1519
         $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1520 1520
             ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1521 1521
             : null;
1522
-        if (! $primary_att instanceof EE_Attendee) {
1522
+        if ( ! $primary_att instanceof EE_Attendee) {
1523 1523
             $this->_template_args['no_attendee_message'] = esc_html__(
1524 1524
                 'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1525 1525
                 'event_espresso'
1526 1526
             );
1527
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1527
+            $primary_att = EEM_Attendee::instance()->create_default_object();
1528 1528
         }
1529 1529
         $this->_template_args['ATT_ID']            = $primary_att->ID();
1530 1530
         $this->_template_args['prime_reg_fname']   = $primary_att->fname();
@@ -1546,7 +1546,7 @@  discard block
 block discarded – undo
1546 1546
                 : '';
1547 1547
         $this->_template_args['formatted_address'] = $formatted_address;
1548 1548
         echo EEH_Template::display_template(
1549
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1549
+            TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_registrant.template.php',
1550 1550
             $this->_template_args,
1551 1551
             true
1552 1552
         );
@@ -1575,7 +1575,7 @@  discard block
 block discarded – undo
1575 1575
             EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1576 1576
         }
1577 1577
 
1578
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1578
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_billing_info.template.php';
1579 1579
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1580 1580
     }
1581 1581
 
@@ -1602,7 +1602,7 @@  discard block
 block discarded – undo
1602 1602
         );
1603 1603
         $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1604 1604
         $amount     = 0;
1605
-        if (! empty($valid_data) && $has_access) {
1605
+        if ( ! empty($valid_data) && $has_access) {
1606 1606
             $PAY_ID = $valid_data['PAY_ID'];
1607 1607
             // save  the new payment
1608 1608
             $payment = $this->_create_payment_from_request_data($valid_data);
@@ -1616,7 +1616,7 @@  discard block
 block discarded – undo
1616 1616
                 $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1617 1617
                 $this->_remove_existing_registration_payments($payment, $PAY_ID);
1618 1618
                 // apply payment to registrations (if applicable)
1619
-                if (! empty($REG_IDs)) {
1619
+                if ( ! empty($REG_IDs)) {
1620 1620
                     $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1621 1621
                     $this->_maybe_send_notifications();
1622 1622
                     // now process status changes for the same registrations
@@ -1689,14 +1689,14 @@  discard block
 block discarded – undo
1689 1689
      */
1690 1690
     protected function _validate_payment_request_data()
1691 1691
     {
1692
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1692
+        if ( ! $this->request->requestParamIsSet('txn_admin_payment')) {
1693 1693
             return [];
1694 1694
         }
1695 1695
         $payment_form = $this->_generate_payment_form_section();
1696 1696
         try {
1697 1697
             if ($payment_form->was_submitted()) {
1698 1698
                 $payment_form->receive_form_submission();
1699
-                if (! $payment_form->is_valid()) {
1699
+                if ( ! $payment_form->is_valid()) {
1700 1700
                     $submission_error_messages = [];
1701 1701
                     foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1702 1702
                         if ($validation_error instanceof EE_Validation_Error) {
@@ -1884,7 +1884,7 @@  discard block
 block discarded – undo
1884 1884
             ['Y-m-d', 'g:i a']
1885 1885
         );
1886 1886
 
1887
-        if (! $payment->save()) {
1887
+        if ( ! $payment->save()) {
1888 1888
             EE_Error::add_error(
1889 1889
                 sprintf(
1890 1890
                     esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
@@ -1960,7 +1960,7 @@  discard block
 block discarded – undo
1960 1960
             false,
1961 1961
             DataType::BOOL
1962 1962
         );
1963
-        $REG_IDs      = ! $apply_to_all
1963
+        $REG_IDs = ! $apply_to_all
1964 1964
             ? $this->request->getRequestParam(
1965 1965
                 'txn_admin_payment[registrations]',
1966 1966
                 [],
@@ -1974,12 +1974,12 @@  discard block
 block discarded – undo
1974 1974
                 [
1975 1975
                     [
1976 1976
                         'STS_ID' => [
1977
-                            'NOT_IN', [ RegStatus::CANCELLED ]
1977
+                            'NOT_IN', [RegStatus::CANCELLED]
1978 1978
                         ]
1979 1979
                     ]
1980 1980
                 ]
1981 1981
             );
1982
-            $REG_IDs       = ! empty($registrations)
1982
+            $REG_IDs = ! empty($registrations)
1983 1983
                 ? array_keys($registrations)
1984 1984
                 : $this->_get_existing_reg_payment_REG_IDs($payment);
1985 1985
         }
@@ -2105,12 +2105,12 @@  discard block
 block discarded – undo
2105 2105
         // but add in some conditions regarding payment,
2106 2106
         // so that we don't apply payments to registrations that are free or have already been paid for
2107 2107
         // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2108
-        if (! $payment->is_a_refund()) {
2108
+        if ( ! $payment->is_a_refund()) {
2109 2109
             $registration_query_where_params['REG_final_price']  = ['!=', 0];
2110 2110
             $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2111 2111
         }
2112 2112
         $registrations = $transaction->registrations([$registration_query_where_params]);
2113
-        if (! empty($registrations)) {
2113
+        if ( ! empty($registrations)) {
2114 2114
             /** @var RegistrationPayments $payment_processor */
2115 2115
             $payment_processor = LoaderFactory::getShared(RegistrationPayments::class);
2116 2116
             $payment_processor->processRegistrationPayments($transaction, $payment, $registrations);
@@ -2194,7 +2194,7 @@  discard block
 block discarded – undo
2194 2194
             'pay_status'       => $payment->STS_ID(),
2195 2195
             'PAY_ID'           => $payment->ID(),
2196 2196
             'STS_ID'           => $payment->STS_ID(),
2197
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2197
+            'status'           => self::$_pay_status[$payment->STS_ID()],
2198 2198
             'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2199 2199
             'method'           => strtoupper($payment->source()),
2200 2200
             'PM_ID'            => $payment_method instanceof EE_Payment_Method
@@ -2314,11 +2314,11 @@  discard block
 block discarded – undo
2314 2314
     {
2315 2315
         $registration_payment_data = [];
2316 2316
         // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2317
-        if (! empty($REG_IDs)) {
2317
+        if ( ! empty($REG_IDs)) {
2318 2318
             $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2319 2319
             foreach ($registrations as $registration) {
2320 2320
                 if ($registration instanceof EE_Registration) {
2321
-                    $registration_payment_data[ $registration->ID() ] = [
2321
+                    $registration_payment_data[$registration->ID()] = [
2322 2322
                         'paid'  => $registration->pretty_paid(),
2323 2323
                         'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2324 2324
                     ];
@@ -2375,7 +2375,7 @@  discard block
 block discarded – undo
2375 2375
         $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2376 2376
         $redirect_to = $this->request->getRequestParam('redirect_to');
2377 2377
         $query_args  = $redirect_to
2378
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2378
+            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID, ]
2379 2379
             : [];
2380 2380
         do_action(
2381 2381
             'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
@@ -2415,8 +2415,8 @@  discard block
 block discarded – undo
2415 2415
         );
2416 2416
 
2417 2417
         // make sure our timestamps start and end right at the boundaries for each day
2418
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2419
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2418
+        $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
2419
+        $end_date   = date('Y-m-d', strtotime($end_date)).' 23:59:59';
2420 2420
 
2421 2421
 
2422 2422
         // convert to timestamps
@@ -2433,7 +2433,7 @@  discard block
 block discarded – undo
2433 2433
             date('Y-m-d H:i:s', $start_date),
2434 2434
             'Y-m-d H:i:s'
2435 2435
         );
2436
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2436
+        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2437 2437
             'TXN_timestamp',
2438 2438
             date('Y-m-d H:i:s', $end_date),
2439 2439
             'Y-m-d H:i:s'
@@ -2479,7 +2479,7 @@  discard block
 block discarded – undo
2479 2479
 
2480 2480
         $search_term = $this->request->getRequestParam('s');
2481 2481
         if ($search_term) {
2482
-            $search_term  = '%' . $search_term . '%';
2482
+            $search_term  = '%'.$search_term.'%';
2483 2483
             $_where['OR'] = [
2484 2484
                 'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2485 2485
                 'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
@@ -2507,9 +2507,9 @@  discard block
 block discarded – undo
2507 2507
 
2508 2508
         $status = $this->request->getRequestParam('status');
2509 2509
         // failed transactions
2510
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2511
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2512
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2510
+        $failed     = ( ! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2511
+        $abandoned  = ( ! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2512
+        $incomplete = ( ! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2513 2513
 
2514 2514
         if ($failed) {
2515 2515
             $_where['STS_ID'] = EEM_Transaction::failed_status_code;
@@ -2558,7 +2558,7 @@  discard block
 block discarded – undo
2558 2558
         $success     = $transaction->recalculateLineItems();
2559 2559
         $redirect_to = $this->request->getRequestParam('redirect_to');
2560 2560
         $query_args  = $redirect_to
2561
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2561
+            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID, ]
2562 2562
             : [];
2563 2563
         $this->_redirect_after_action(
2564 2564
             $success,
Please login to merge, or discard this patch.
admin_pages/general_settings/OrganizationSettings.php 1 patch
Indentation   +435 added lines, -435 removed lines patch added patch discarded remove patch
@@ -45,455 +45,455 @@
 block discarded – undo
45 45
  */
46 46
 class OrganizationSettings extends FormHandler
47 47
 {
48
-    protected EE_Organization_Config $organization_config;
48
+	protected EE_Organization_Config $organization_config;
49 49
 
50
-    protected EE_Core_Config $core_config;
50
+	protected EE_Core_Config $core_config;
51 51
 
52
-    protected EE_Network_Core_Config $network_core_config;
52
+	protected EE_Network_Core_Config $network_core_config;
53 53
 
54
-    protected CountrySubRegionDao $countrySubRegionDao;
54
+	protected CountrySubRegionDao $countrySubRegionDao;
55 55
 
56
-    private FeatureFlags $feature;
56
+	private FeatureFlags $feature;
57 57
 
58 58
 
59
-    /**
60
-     * Form constructor.
61
-     *
62
-     * @param EE_Registry            $registry
63
-     * @param EE_Organization_Config $organization_config
64
-     * @param EE_Core_Config         $core_config
65
-     * @param EE_Network_Core_Config $network_core_config
66
-     * @param CountrySubRegionDao    $countrySubRegionDao
67
-     * @param FeatureFlags           $feature
68
-     * @throws InvalidArgumentException
69
-     * @throws InvalidDataTypeException
70
-     * @throws DomainException
71
-     */
72
-    public function __construct(
73
-        EE_Registry $registry,
74
-        EE_Organization_Config $organization_config,
75
-        EE_Core_Config $core_config,
76
-        EE_Network_Core_Config $network_core_config,
77
-        CountrySubRegionDao $countrySubRegionDao,
78
-        FeatureFlags $feature
79
-    ) {
80
-        $this->organization_config = $organization_config;
81
-        $this->core_config         = $core_config;
82
-        $this->network_core_config = $network_core_config;
83
-        $this->countrySubRegionDao = $countrySubRegionDao;
84
-        $this->feature             = $feature;
85
-        parent::__construct(
86
-            esc_html__('Your Organization Settings', 'event_espresso'),
87
-            esc_html__('Your Organization Settings', 'event_espresso'),
88
-            'organization_settings',
89
-            '',
90
-            FormHandler::DO_NOT_SETUP_FORM,
91
-            $registry
92
-        );
93
-    }
59
+	/**
60
+	 * Form constructor.
61
+	 *
62
+	 * @param EE_Registry            $registry
63
+	 * @param EE_Organization_Config $organization_config
64
+	 * @param EE_Core_Config         $core_config
65
+	 * @param EE_Network_Core_Config $network_core_config
66
+	 * @param CountrySubRegionDao    $countrySubRegionDao
67
+	 * @param FeatureFlags           $feature
68
+	 * @throws InvalidArgumentException
69
+	 * @throws InvalidDataTypeException
70
+	 * @throws DomainException
71
+	 */
72
+	public function __construct(
73
+		EE_Registry $registry,
74
+		EE_Organization_Config $organization_config,
75
+		EE_Core_Config $core_config,
76
+		EE_Network_Core_Config $network_core_config,
77
+		CountrySubRegionDao $countrySubRegionDao,
78
+		FeatureFlags $feature
79
+	) {
80
+		$this->organization_config = $organization_config;
81
+		$this->core_config         = $core_config;
82
+		$this->network_core_config = $network_core_config;
83
+		$this->countrySubRegionDao = $countrySubRegionDao;
84
+		$this->feature             = $feature;
85
+		parent::__construct(
86
+			esc_html__('Your Organization Settings', 'event_espresso'),
87
+			esc_html__('Your Organization Settings', 'event_espresso'),
88
+			'organization_settings',
89
+			'',
90
+			FormHandler::DO_NOT_SETUP_FORM,
91
+			$registry
92
+		);
93
+	}
94 94
 
95 95
 
96
-    /**
97
-     * creates and returns the actual form
98
-     *
99
-     * @return EE_Form_Section_Proper
100
-     * @throws EE_Error
101
-     * @throws InvalidArgumentException
102
-     * @throws InvalidDataTypeException
103
-     * @throws InvalidInterfaceException
104
-     * @throws ReflectionException
105
-     */
106
-    public function generate(): EE_Form_Section_Proper
107
-    {
108
-        $has_sub_regions = EEM_State::instance()->count([['Country.CNT_ISO' => $this->organization_config->CNT_ISO]]);
109
-        $subsections     = [
110
-            'contact_information_hdr' => new EE_Form_Section_HTML(
111
-                EEH_HTML::h2(
112
-                    esc_html__('Contact Information', 'event_espresso')
113
-                    . ' '
114
-                    . EEH_HTML::span(EEH_Template::get_help_tab_link('contact_info_info')),
115
-                    '',
116
-                    'contact-information-hdr'
117
-                )
118
-            ),
119
-            'organization_name'       => new EE_Text_Input(
120
-                [
121
-                    'html_name'       => 'organization_name',
122
-                    'html_class'      => 'ee-input-width--reg',
123
-                    'html_label_text' => esc_html__('Organization Name', 'event_espresso'),
124
-                    'html_help_text'  => esc_html__(
125
-                        'Displayed on all emails and invoices.',
126
-                        'event_espresso'
127
-                    ),
128
-                    'default'         => $this->organization_config->get_pretty('name'),
129
-                    'required'        => false,
130
-                ]
131
-            ),
132
-            'organization_address_1'  => new EE_Text_Input(
133
-                [
134
-                    'html_name'       => 'organization_address_1',
135
-                    'html_class'      => 'ee-input-width--reg',
136
-                    'html_label_text' => esc_html__('Street Address', 'event_espresso'),
137
-                    'default'         => $this->organization_config->get_pretty('address_1'),
138
-                    'required'        => false,
139
-                ]
140
-            ),
141
-            'organization_address_2'  => new EE_Text_Input(
142
-                [
143
-                    'html_name'       => 'organization_address_2',
144
-                    'html_class'      => 'ee-input-width--reg',
145
-                    'html_label_text' => esc_html__('Street Address 2', 'event_espresso'),
146
-                    'default'         => $this->organization_config->get_pretty('address_2'),
147
-                    'required'        => false,
148
-                ]
149
-            ),
150
-            'organization_city'       => new EE_Text_Input(
151
-                [
152
-                    'html_name'       => 'organization_city',
153
-                    'html_class'      => 'ee-input-width--reg',
154
-                    'html_label_text' => esc_html__('City', 'event_espresso'),
155
-                    'default'         => $this->organization_config->get_pretty('city'),
156
-                    'required'        => false,
157
-                ]
158
-            ),
159
-            'organization_country'    => new EE_Country_Select_Input(
160
-                null,
161
-                [
162
-                    EE_Country_Select_Input::OPTION_GET_KEY => EE_Country_Select_Input::OPTION_GET_ALL,
163
-                    'html_name'                             => 'organization_country',
164
-                    'html_class'                            => 'ee-input-width--reg',
165
-                    'html_label_text'                       => esc_html__('Country', 'event_espresso'),
166
-                    'default'                               => $this->organization_config->CNT_ISO,
167
-                    'required'                              => false,
168
-                    'html_help_text'                        => sprintf(
169
-                        esc_html__(
170
-                            '%1$sThe Country set here will have the effect of setting the currency used for all ticket prices.%2$s',
171
-                            'event_espresso'
172
-                        ),
173
-                        '<span class="reminder-spn">',
174
-                        '</span>'
175
-                    ),
176
-                ]
177
-            ),
178
-            'organization_state'      => new EE_State_Select_Input(
179
-                null,
180
-                [
181
-                    'html_name'       => 'organization_state',
182
-                    'html_class'      => 'ee-input-width--reg',
183
-                    'html_label_text' => esc_html__('State/Province', 'event_espresso'),
184
-                    'default'         => $this->organization_config->STA_ID,
185
-                    'required'        => false,
186
-                    'html_help_text'  => empty($this->organization_config->STA_ID) || ! $has_sub_regions
187
-                        ? sprintf(
188
-                            esc_html__(
189
-                                'If the States/Provinces for the selected Country do not appear in this list, then click "Save".%3$sIf data exists, then the list will be populated when the page reloads and you will be able to make a selection at that time.%3$s%1$sMake sure you click "Save" again after selecting a State/Province that has just been loaded in order to keep that selection.%2$s',
190
-                                'event_espresso'
191
-                            ),
192
-                            '<span class="reminder-spn">',
193
-                            '</span>',
194
-                            '<br />'
195
-                        )
196
-                        : '',
197
-                ]
198
-            ),
199
-            'organization_zip'        => new EE_Text_Input(
200
-                [
201
-                    'html_name'       => 'organization_zip',
202
-                    'html_class'      => 'ee-input-width--small',
203
-                    'html_label_text' => esc_html__('Zip/Postal Code', 'event_espresso'),
204
-                    'default'         => $this->organization_config->get_pretty('zip'),
205
-                    'required'        => false,
206
-                ]
207
-            ),
208
-            'organization_email'      => new EE_Text_Input(
209
-                [
210
-                    'html_name'       => 'organization_email',
211
-                    'html_class'      => 'ee-input-width--reg',
212
-                    'html_label_text' => esc_html__('Primary Contact Email', 'event_espresso'),
213
-                    'html_help_text'  => sprintf(
214
-                        esc_html__(
215
-                            'This is where notifications go to when you use the %1$s and %2$s shortcodes in the message templates.',
216
-                            'event_espresso'
217
-                        ),
218
-                        '<code>[CO_FORMATTED_EMAIL]</code>',
219
-                        '<code>[CO_EMAIL]</code>'
220
-                    ),
221
-                    'default'         => $this->organization_config->get_pretty('email'),
222
-                    'required'        => false,
223
-                ]
224
-            ),
225
-            'organization_phone'      => new EE_Text_Input(
226
-                [
227
-                    'html_name'       => 'organization_phone',
228
-                    'html_class'      => 'ee-input-width--reg',
229
-                    'html_label_text' => esc_html__('Phone Number', 'event_espresso'),
230
-                    'html_help_text'  => esc_html__(
231
-                        'The phone number for your organization.',
232
-                        'event_espresso'
233
-                    ),
234
-                    'default'         => $this->organization_config->get_pretty('phone'),
235
-                    'required'        => false,
236
-                ]
237
-            ),
238
-            'organization_vat'        => new EE_Text_Input(
239
-                [
240
-                    'html_name'       => 'organization_vat',
241
-                    'html_class'      => 'ee-input-width--reg',
242
-                    'html_label_text' => esc_html__('VAT/Tax Number', 'event_espresso'),
243
-                    'html_help_text'  => esc_html__(
244
-                        'The VAT/Tax Number may be displayed on invoices and receipts.',
245
-                        'event_espresso'
246
-                    ),
247
-                    'default'         => $this->organization_config->get_pretty('vat'),
248
-                    'required'        => false,
249
-                ]
250
-            ),
251
-            'company_logo_hdr'        => new EE_Form_Section_HTML(
252
-                EEH_HTML::h2(
253
-                    esc_html__('Company Logo', 'event_espresso')
254
-                    . ' '
255
-                    . EEH_HTML::span(EEH_Template::get_help_tab_link('organization_logo_info')),
256
-                    '',
257
-                    'company-logo-hdr'
258
-                )
259
-            ),
260
-            'organization_logo_url'   => new EE_Admin_File_Uploader_Input(
261
-                [
262
-                    'html_name'       => 'organization_logo_url',
263
-                    'html_class'      => 'ee-input-width--big',
264
-                    'html_label_text' => esc_html__('Upload New Logo', 'event_espresso'),
265
-                    'html_help_text'  => esc_html__(
266
-                        'Your logo will be used on custom invoices, tickets, certificates, and payment templates.',
267
-                        'event_espresso'
268
-                    ),
269
-                    'default'         => $this->organization_config->get_pretty('logo_url'),
270
-                    'required'        => false,
271
-                ]
272
-            ),
273
-            'social_links_hdr'        => new EE_Form_Section_HTML(
274
-                EEH_HTML::h2(
275
-                    esc_html__('Social Links', 'event_espresso')
276
-                    . ' '
277
-                    . EEH_HTML::span(EEH_Template::get_help_tab_link('social_links_info'))
278
-                    . EEH_HTML::br()
279
-                    . EEH_HTML::p(
280
-                        esc_html__(
281
-                            'Enter any links to social accounts for your organization here',
282
-                            'event_espresso'
283
-                        ),
284
-                        '',
285
-                        'description'
286
-                    ),
287
-                    '',
288
-                    'social-links-hdr'
289
-                )
290
-            ),
291
-            'organization_facebook'   => new EE_Text_Input(
292
-                [
293
-                    'html_name'             => 'organization_facebook',
294
-                    'html_class'            => 'ee-input-width--reg',
295
-                    'html_label_text'       => esc_html__('Facebook', 'event_espresso'),
296
-                    'other_html_attributes' => ' placeholder="facebook.com/profile.name"',
297
-                    'default'               => $this->organization_config->get_pretty('facebook'),
298
-                    'required'              => false,
299
-                ]
300
-            ),
301
-            'organization_twitter'    => new EE_Text_Input(
302
-                [
303
-                    'html_name'             => 'organization_twitter',
304
-                    'html_class'            => 'ee-input-width--reg',
305
-                    'html_label_text'       => esc_html__('Twitter', 'event_espresso'),
306
-                    'other_html_attributes' => ' placeholder="twitter.com/twitterhandle"',
307
-                    'default'               => $this->organization_config->get_pretty('twitter'),
308
-                    'required'              => false,
309
-                ]
310
-            ),
311
-            'organization_linkedin'   => new EE_Text_Input(
312
-                [
313
-                    'html_name'             => 'organization_linkedin',
314
-                    'html_class'            => 'ee-input-width--reg',
315
-                    'html_label_text'       => esc_html__('LinkedIn', 'event_espresso'),
316
-                    'other_html_attributes' => ' placeholder="linkedin.com/in/profilename"',
317
-                    'default'               => $this->organization_config->get_pretty('linkedin'),
318
-                    'required'              => false,
319
-                ]
320
-            ),
321
-            'organization_pinterest'  => new EE_Text_Input(
322
-                [
323
-                    'html_name'             => 'organization_pinterest',
324
-                    'html_class'            => 'ee-input-width--reg',
325
-                    'html_label_text'       => esc_html__('Pinterest', 'event_espresso'),
326
-                    'other_html_attributes' => ' placeholder="pinterest.com/profilename"',
327
-                    'default'               => $this->organization_config->get_pretty('pinterest'),
328
-                    'required'              => false,
329
-                ]
330
-            ),
331
-            'organization_instagram'  => new EE_Text_Input(
332
-                [
333
-                    'html_name'             => 'organization_instagram',
334
-                    'html_class'            => 'ee-input-width--reg',
335
-                    'html_label_text'       => esc_html__('Instagram', 'event_espresso'),
336
-                    'other_html_attributes' => ' placeholder="instagram.com/handle"',
337
-                    'default'               => $this->organization_config->get_pretty('instagram'),
338
-                    'required'              => false,
339
-                ]
340
-            ),
341
-        ];
96
+	/**
97
+	 * creates and returns the actual form
98
+	 *
99
+	 * @return EE_Form_Section_Proper
100
+	 * @throws EE_Error
101
+	 * @throws InvalidArgumentException
102
+	 * @throws InvalidDataTypeException
103
+	 * @throws InvalidInterfaceException
104
+	 * @throws ReflectionException
105
+	 */
106
+	public function generate(): EE_Form_Section_Proper
107
+	{
108
+		$has_sub_regions = EEM_State::instance()->count([['Country.CNT_ISO' => $this->organization_config->CNT_ISO]]);
109
+		$subsections     = [
110
+			'contact_information_hdr' => new EE_Form_Section_HTML(
111
+				EEH_HTML::h2(
112
+					esc_html__('Contact Information', 'event_espresso')
113
+					. ' '
114
+					. EEH_HTML::span(EEH_Template::get_help_tab_link('contact_info_info')),
115
+					'',
116
+					'contact-information-hdr'
117
+				)
118
+			),
119
+			'organization_name'       => new EE_Text_Input(
120
+				[
121
+					'html_name'       => 'organization_name',
122
+					'html_class'      => 'ee-input-width--reg',
123
+					'html_label_text' => esc_html__('Organization Name', 'event_espresso'),
124
+					'html_help_text'  => esc_html__(
125
+						'Displayed on all emails and invoices.',
126
+						'event_espresso'
127
+					),
128
+					'default'         => $this->organization_config->get_pretty('name'),
129
+					'required'        => false,
130
+				]
131
+			),
132
+			'organization_address_1'  => new EE_Text_Input(
133
+				[
134
+					'html_name'       => 'organization_address_1',
135
+					'html_class'      => 'ee-input-width--reg',
136
+					'html_label_text' => esc_html__('Street Address', 'event_espresso'),
137
+					'default'         => $this->organization_config->get_pretty('address_1'),
138
+					'required'        => false,
139
+				]
140
+			),
141
+			'organization_address_2'  => new EE_Text_Input(
142
+				[
143
+					'html_name'       => 'organization_address_2',
144
+					'html_class'      => 'ee-input-width--reg',
145
+					'html_label_text' => esc_html__('Street Address 2', 'event_espresso'),
146
+					'default'         => $this->organization_config->get_pretty('address_2'),
147
+					'required'        => false,
148
+				]
149
+			),
150
+			'organization_city'       => new EE_Text_Input(
151
+				[
152
+					'html_name'       => 'organization_city',
153
+					'html_class'      => 'ee-input-width--reg',
154
+					'html_label_text' => esc_html__('City', 'event_espresso'),
155
+					'default'         => $this->organization_config->get_pretty('city'),
156
+					'required'        => false,
157
+				]
158
+			),
159
+			'organization_country'    => new EE_Country_Select_Input(
160
+				null,
161
+				[
162
+					EE_Country_Select_Input::OPTION_GET_KEY => EE_Country_Select_Input::OPTION_GET_ALL,
163
+					'html_name'                             => 'organization_country',
164
+					'html_class'                            => 'ee-input-width--reg',
165
+					'html_label_text'                       => esc_html__('Country', 'event_espresso'),
166
+					'default'                               => $this->organization_config->CNT_ISO,
167
+					'required'                              => false,
168
+					'html_help_text'                        => sprintf(
169
+						esc_html__(
170
+							'%1$sThe Country set here will have the effect of setting the currency used for all ticket prices.%2$s',
171
+							'event_espresso'
172
+						),
173
+						'<span class="reminder-spn">',
174
+						'</span>'
175
+					),
176
+				]
177
+			),
178
+			'organization_state'      => new EE_State_Select_Input(
179
+				null,
180
+				[
181
+					'html_name'       => 'organization_state',
182
+					'html_class'      => 'ee-input-width--reg',
183
+					'html_label_text' => esc_html__('State/Province', 'event_espresso'),
184
+					'default'         => $this->organization_config->STA_ID,
185
+					'required'        => false,
186
+					'html_help_text'  => empty($this->organization_config->STA_ID) || ! $has_sub_regions
187
+						? sprintf(
188
+							esc_html__(
189
+								'If the States/Provinces for the selected Country do not appear in this list, then click "Save".%3$sIf data exists, then the list will be populated when the page reloads and you will be able to make a selection at that time.%3$s%1$sMake sure you click "Save" again after selecting a State/Province that has just been loaded in order to keep that selection.%2$s',
190
+								'event_espresso'
191
+							),
192
+							'<span class="reminder-spn">',
193
+							'</span>',
194
+							'<br />'
195
+						)
196
+						: '',
197
+				]
198
+			),
199
+			'organization_zip'        => new EE_Text_Input(
200
+				[
201
+					'html_name'       => 'organization_zip',
202
+					'html_class'      => 'ee-input-width--small',
203
+					'html_label_text' => esc_html__('Zip/Postal Code', 'event_espresso'),
204
+					'default'         => $this->organization_config->get_pretty('zip'),
205
+					'required'        => false,
206
+				]
207
+			),
208
+			'organization_email'      => new EE_Text_Input(
209
+				[
210
+					'html_name'       => 'organization_email',
211
+					'html_class'      => 'ee-input-width--reg',
212
+					'html_label_text' => esc_html__('Primary Contact Email', 'event_espresso'),
213
+					'html_help_text'  => sprintf(
214
+						esc_html__(
215
+							'This is where notifications go to when you use the %1$s and %2$s shortcodes in the message templates.',
216
+							'event_espresso'
217
+						),
218
+						'<code>[CO_FORMATTED_EMAIL]</code>',
219
+						'<code>[CO_EMAIL]</code>'
220
+					),
221
+					'default'         => $this->organization_config->get_pretty('email'),
222
+					'required'        => false,
223
+				]
224
+			),
225
+			'organization_phone'      => new EE_Text_Input(
226
+				[
227
+					'html_name'       => 'organization_phone',
228
+					'html_class'      => 'ee-input-width--reg',
229
+					'html_label_text' => esc_html__('Phone Number', 'event_espresso'),
230
+					'html_help_text'  => esc_html__(
231
+						'The phone number for your organization.',
232
+						'event_espresso'
233
+					),
234
+					'default'         => $this->organization_config->get_pretty('phone'),
235
+					'required'        => false,
236
+				]
237
+			),
238
+			'organization_vat'        => new EE_Text_Input(
239
+				[
240
+					'html_name'       => 'organization_vat',
241
+					'html_class'      => 'ee-input-width--reg',
242
+					'html_label_text' => esc_html__('VAT/Tax Number', 'event_espresso'),
243
+					'html_help_text'  => esc_html__(
244
+						'The VAT/Tax Number may be displayed on invoices and receipts.',
245
+						'event_espresso'
246
+					),
247
+					'default'         => $this->organization_config->get_pretty('vat'),
248
+					'required'        => false,
249
+				]
250
+			),
251
+			'company_logo_hdr'        => new EE_Form_Section_HTML(
252
+				EEH_HTML::h2(
253
+					esc_html__('Company Logo', 'event_espresso')
254
+					. ' '
255
+					. EEH_HTML::span(EEH_Template::get_help_tab_link('organization_logo_info')),
256
+					'',
257
+					'company-logo-hdr'
258
+				)
259
+			),
260
+			'organization_logo_url'   => new EE_Admin_File_Uploader_Input(
261
+				[
262
+					'html_name'       => 'organization_logo_url',
263
+					'html_class'      => 'ee-input-width--big',
264
+					'html_label_text' => esc_html__('Upload New Logo', 'event_espresso'),
265
+					'html_help_text'  => esc_html__(
266
+						'Your logo will be used on custom invoices, tickets, certificates, and payment templates.',
267
+						'event_espresso'
268
+					),
269
+					'default'         => $this->organization_config->get_pretty('logo_url'),
270
+					'required'        => false,
271
+				]
272
+			),
273
+			'social_links_hdr'        => new EE_Form_Section_HTML(
274
+				EEH_HTML::h2(
275
+					esc_html__('Social Links', 'event_espresso')
276
+					. ' '
277
+					. EEH_HTML::span(EEH_Template::get_help_tab_link('social_links_info'))
278
+					. EEH_HTML::br()
279
+					. EEH_HTML::p(
280
+						esc_html__(
281
+							'Enter any links to social accounts for your organization here',
282
+							'event_espresso'
283
+						),
284
+						'',
285
+						'description'
286
+					),
287
+					'',
288
+					'social-links-hdr'
289
+				)
290
+			),
291
+			'organization_facebook'   => new EE_Text_Input(
292
+				[
293
+					'html_name'             => 'organization_facebook',
294
+					'html_class'            => 'ee-input-width--reg',
295
+					'html_label_text'       => esc_html__('Facebook', 'event_espresso'),
296
+					'other_html_attributes' => ' placeholder="facebook.com/profile.name"',
297
+					'default'               => $this->organization_config->get_pretty('facebook'),
298
+					'required'              => false,
299
+				]
300
+			),
301
+			'organization_twitter'    => new EE_Text_Input(
302
+				[
303
+					'html_name'             => 'organization_twitter',
304
+					'html_class'            => 'ee-input-width--reg',
305
+					'html_label_text'       => esc_html__('Twitter', 'event_espresso'),
306
+					'other_html_attributes' => ' placeholder="twitter.com/twitterhandle"',
307
+					'default'               => $this->organization_config->get_pretty('twitter'),
308
+					'required'              => false,
309
+				]
310
+			),
311
+			'organization_linkedin'   => new EE_Text_Input(
312
+				[
313
+					'html_name'             => 'organization_linkedin',
314
+					'html_class'            => 'ee-input-width--reg',
315
+					'html_label_text'       => esc_html__('LinkedIn', 'event_espresso'),
316
+					'other_html_attributes' => ' placeholder="linkedin.com/in/profilename"',
317
+					'default'               => $this->organization_config->get_pretty('linkedin'),
318
+					'required'              => false,
319
+				]
320
+			),
321
+			'organization_pinterest'  => new EE_Text_Input(
322
+				[
323
+					'html_name'             => 'organization_pinterest',
324
+					'html_class'            => 'ee-input-width--reg',
325
+					'html_label_text'       => esc_html__('Pinterest', 'event_espresso'),
326
+					'other_html_attributes' => ' placeholder="pinterest.com/profilename"',
327
+					'default'               => $this->organization_config->get_pretty('pinterest'),
328
+					'required'              => false,
329
+				]
330
+			),
331
+			'organization_instagram'  => new EE_Text_Input(
332
+				[
333
+					'html_name'             => 'organization_instagram',
334
+					'html_class'            => 'ee-input-width--reg',
335
+					'html_label_text'       => esc_html__('Instagram', 'event_espresso'),
336
+					'other_html_attributes' => ' placeholder="instagram.com/handle"',
337
+					'default'               => $this->organization_config->get_pretty('instagram'),
338
+					'required'              => false,
339
+				]
340
+			),
341
+		];
342 342
 
343 343
 
344
-        /** @var Domain $domain */
345
-        $domain = LoaderFactory::getShared(Domain::class);
346
-        if ($domain->isCaffeinated() && $this->feature->allowed('use_edd_plugin_licensing')) {
347
-            $subsections = EEH_Array::insert_into_array(
348
-                $subsections,
349
-                [
350
-                    'support_license_key_notice' => new EE_Form_Section_HTML(
351
-                        EEH_HTML::p(
352
-                            sprintf(
353
-                                esc_html__(
354
-                                    'Management for your Event Espresso Support License Key has been moved to the %1$sLicense Keys admin page%2$s',
355
-                                    'event_espresso'
356
-                                ),
357
-                                '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
358
-                                    [],
359
-                                    LICENSE_KEYS_ADMIN_URL
360
-                                ) . '">',
361
-                                '</a>'
362
-                            ),
363
-                            '',
364
-                            'ee-status-outline ee-status-bg--info'
365
-                        )
366
-                    ),
367
-                ],
368
-                'contact_information_hdr'
369
-            );
370
-        }
371
-        return apply_filters(
372
-            'FHEE__EventEspresso_admin_pages_general_settings_OrganizationSettings__generate__form',
373
-            new EE_Form_Section_Proper(
374
-                [
375
-                    'name'            => 'organization_settings',
376
-                    'html_id'         => 'organization_settings',
377
-                    'layout_strategy' => new EE_Admin_Two_Column_Layout(),
378
-                    'subsections'     => $subsections,
379
-                ]
380
-            ),
381
-            $this,
382
-            $has_sub_regions
383
-        );
384
-    }
344
+		/** @var Domain $domain */
345
+		$domain = LoaderFactory::getShared(Domain::class);
346
+		if ($domain->isCaffeinated() && $this->feature->allowed('use_edd_plugin_licensing')) {
347
+			$subsections = EEH_Array::insert_into_array(
348
+				$subsections,
349
+				[
350
+					'support_license_key_notice' => new EE_Form_Section_HTML(
351
+						EEH_HTML::p(
352
+							sprintf(
353
+								esc_html__(
354
+									'Management for your Event Espresso Support License Key has been moved to the %1$sLicense Keys admin page%2$s',
355
+									'event_espresso'
356
+								),
357
+								'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
358
+									[],
359
+									LICENSE_KEYS_ADMIN_URL
360
+								) . '">',
361
+								'</a>'
362
+							),
363
+							'',
364
+							'ee-status-outline ee-status-bg--info'
365
+						)
366
+					),
367
+				],
368
+				'contact_information_hdr'
369
+			);
370
+		}
371
+		return apply_filters(
372
+			'FHEE__EventEspresso_admin_pages_general_settings_OrganizationSettings__generate__form',
373
+			new EE_Form_Section_Proper(
374
+				[
375
+					'name'            => 'organization_settings',
376
+					'html_id'         => 'organization_settings',
377
+					'layout_strategy' => new EE_Admin_Two_Column_Layout(),
378
+					'subsections'     => $subsections,
379
+				]
380
+			),
381
+			$this,
382
+			$has_sub_regions
383
+		);
384
+	}
385 385
 
386 386
 
387
-    /**
388
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
389
-     * returns a string of HTML that can be directly echoed in a template
390
-     *
391
-     * @return string
392
-     * @throws EE_Error
393
-     * @throws InvalidArgumentException
394
-     * @throws InvalidDataTypeException
395
-     * @throws InvalidInterfaceException
396
-     * @throws LogicException
397
-     */
398
-    public function display()
399
-    {
400
-        $this->form()->enqueue_js();
401
-        return parent::display();
402
-    }
387
+	/**
388
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
389
+	 * returns a string of HTML that can be directly echoed in a template
390
+	 *
391
+	 * @return string
392
+	 * @throws EE_Error
393
+	 * @throws InvalidArgumentException
394
+	 * @throws InvalidDataTypeException
395
+	 * @throws InvalidInterfaceException
396
+	 * @throws LogicException
397
+	 */
398
+	public function display()
399
+	{
400
+		$this->form()->enqueue_js();
401
+		return parent::display();
402
+	}
403 403
 
404 404
 
405
-    /**
406
-     * handles processing the form submission
407
-     * returns true or false depending on whether the form was processed successfully or not
408
-     *
409
-     * @param array $form_data
410
-     * @return bool
411
-     * @throws InvalidFormSubmissionException
412
-     * @throws EE_Error
413
-     * @throws LogicException
414
-     * @throws InvalidArgumentException
415
-     * @throws InvalidDataTypeException
416
-     * @throws ReflectionException
417
-     */
418
-    public function process($form_data = []): bool
419
-    {
420
-        // process form
421
-        $valid_data = (array) parent::process($form_data);
422
-        if (empty($valid_data)) {
423
-            return false;
424
-        }
405
+	/**
406
+	 * handles processing the form submission
407
+	 * returns true or false depending on whether the form was processed successfully or not
408
+	 *
409
+	 * @param array $form_data
410
+	 * @return bool
411
+	 * @throws InvalidFormSubmissionException
412
+	 * @throws EE_Error
413
+	 * @throws LogicException
414
+	 * @throws InvalidArgumentException
415
+	 * @throws InvalidDataTypeException
416
+	 * @throws ReflectionException
417
+	 */
418
+	public function process($form_data = []): bool
419
+	{
420
+		// process form
421
+		$valid_data = (array) parent::process($form_data);
422
+		if (empty($valid_data)) {
423
+			return false;
424
+		}
425 425
 
426
-        if (is_main_site()) {
427
-            $this->network_core_config->site_license_key = isset($form_data['ee_site_license_key'])
428
-                ? sanitize_text_field($form_data['ee_site_license_key'])
429
-                : $this->network_core_config->site_license_key;
430
-        }
431
-        $this->organization_config->name         = isset($form_data['organization_name'])
432
-            ? sanitize_text_field($form_data['organization_name'])
433
-            : $this->organization_config->name;
434
-        $this->organization_config->address_1    = isset($form_data['organization_address_1'])
435
-            ? sanitize_text_field($form_data['organization_address_1'])
436
-            : $this->organization_config->address_1;
437
-        $this->organization_config->address_2    = isset($form_data['organization_address_2'])
438
-            ? sanitize_text_field($form_data['organization_address_2'])
439
-            : $this->organization_config->address_2;
440
-        $this->organization_config->city         = isset($form_data['organization_city'])
441
-            ? sanitize_text_field($form_data['organization_city'])
442
-            : $this->organization_config->city;
443
-        $this->organization_config->STA_ID       = isset($form_data['organization_state'])
444
-            ? absint($form_data['organization_state'])
445
-            : $this->organization_config->STA_ID;
446
-        $this->organization_config->CNT_ISO      = isset($form_data['organization_country'])
447
-            ? sanitize_text_field($form_data['organization_country'])
448
-            : $this->organization_config->CNT_ISO;
449
-        $this->organization_config->zip          = isset($form_data['organization_zip'])
450
-            ? sanitize_text_field($form_data['organization_zip'])
451
-            : $this->organization_config->zip;
452
-        $this->organization_config->email        = isset($form_data['organization_email'])
453
-            ? sanitize_email($form_data['organization_email'])
454
-            : $this->organization_config->email;
455
-        $this->organization_config->vat          = isset($form_data['organization_vat'])
456
-            ? sanitize_text_field($form_data['organization_vat'])
457
-            : $this->organization_config->vat;
458
-        $this->organization_config->phone        = isset($form_data['organization_phone'])
459
-            ? sanitize_text_field($form_data['organization_phone'])
460
-            : $this->organization_config->phone;
461
-        $this->organization_config->logo_url     = isset($form_data['organization_logo_url'])
462
-            ? esc_url_raw($form_data['organization_logo_url'])
463
-            : $this->organization_config->logo_url;
464
-        $this->organization_config->facebook     = isset($form_data['organization_facebook'])
465
-            ? esc_url_raw($form_data['organization_facebook'])
466
-            : $this->organization_config->facebook;
467
-        $this->organization_config->twitter      = isset($form_data['organization_twitter'])
468
-            ? esc_url_raw($form_data['organization_twitter'])
469
-            : $this->organization_config->twitter;
470
-        $this->organization_config->linkedin     = isset($form_data['organization_linkedin'])
471
-            ? esc_url_raw($form_data['organization_linkedin'])
472
-            : $this->organization_config->linkedin;
473
-        $this->organization_config->pinterest    = isset($form_data['organization_pinterest'])
474
-            ? esc_url_raw($form_data['organization_pinterest'])
475
-            : $this->organization_config->pinterest;
476
-        $this->organization_config->google       = isset($form_data['organization_google'])
477
-            ? esc_url_raw($form_data['organization_google'])
478
-            : $this->organization_config->google;
479
-        $this->organization_config->instagram    = isset($form_data['organization_instagram'])
480
-            ? esc_url_raw($form_data['organization_instagram'])
481
-            : $this->organization_config->instagram;
482
-        $this->core_config->ee_ueip_optin        = isset($form_data[ EE_Core_Config::OPTION_NAME_UXIP ][0])
483
-            ? filter_var($form_data[ EE_Core_Config::OPTION_NAME_UXIP ][0], FILTER_VALIDATE_BOOLEAN)
484
-            : false;
485
-        $this->core_config->ee_ueip_has_notified = true;
426
+		if (is_main_site()) {
427
+			$this->network_core_config->site_license_key = isset($form_data['ee_site_license_key'])
428
+				? sanitize_text_field($form_data['ee_site_license_key'])
429
+				: $this->network_core_config->site_license_key;
430
+		}
431
+		$this->organization_config->name         = isset($form_data['organization_name'])
432
+			? sanitize_text_field($form_data['organization_name'])
433
+			: $this->organization_config->name;
434
+		$this->organization_config->address_1    = isset($form_data['organization_address_1'])
435
+			? sanitize_text_field($form_data['organization_address_1'])
436
+			: $this->organization_config->address_1;
437
+		$this->organization_config->address_2    = isset($form_data['organization_address_2'])
438
+			? sanitize_text_field($form_data['organization_address_2'])
439
+			: $this->organization_config->address_2;
440
+		$this->organization_config->city         = isset($form_data['organization_city'])
441
+			? sanitize_text_field($form_data['organization_city'])
442
+			: $this->organization_config->city;
443
+		$this->organization_config->STA_ID       = isset($form_data['organization_state'])
444
+			? absint($form_data['organization_state'])
445
+			: $this->organization_config->STA_ID;
446
+		$this->organization_config->CNT_ISO      = isset($form_data['organization_country'])
447
+			? sanitize_text_field($form_data['organization_country'])
448
+			: $this->organization_config->CNT_ISO;
449
+		$this->organization_config->zip          = isset($form_data['organization_zip'])
450
+			? sanitize_text_field($form_data['organization_zip'])
451
+			: $this->organization_config->zip;
452
+		$this->organization_config->email        = isset($form_data['organization_email'])
453
+			? sanitize_email($form_data['organization_email'])
454
+			: $this->organization_config->email;
455
+		$this->organization_config->vat          = isset($form_data['organization_vat'])
456
+			? sanitize_text_field($form_data['organization_vat'])
457
+			: $this->organization_config->vat;
458
+		$this->organization_config->phone        = isset($form_data['organization_phone'])
459
+			? sanitize_text_field($form_data['organization_phone'])
460
+			: $this->organization_config->phone;
461
+		$this->organization_config->logo_url     = isset($form_data['organization_logo_url'])
462
+			? esc_url_raw($form_data['organization_logo_url'])
463
+			: $this->organization_config->logo_url;
464
+		$this->organization_config->facebook     = isset($form_data['organization_facebook'])
465
+			? esc_url_raw($form_data['organization_facebook'])
466
+			: $this->organization_config->facebook;
467
+		$this->organization_config->twitter      = isset($form_data['organization_twitter'])
468
+			? esc_url_raw($form_data['organization_twitter'])
469
+			: $this->organization_config->twitter;
470
+		$this->organization_config->linkedin     = isset($form_data['organization_linkedin'])
471
+			? esc_url_raw($form_data['organization_linkedin'])
472
+			: $this->organization_config->linkedin;
473
+		$this->organization_config->pinterest    = isset($form_data['organization_pinterest'])
474
+			? esc_url_raw($form_data['organization_pinterest'])
475
+			: $this->organization_config->pinterest;
476
+		$this->organization_config->google       = isset($form_data['organization_google'])
477
+			? esc_url_raw($form_data['organization_google'])
478
+			: $this->organization_config->google;
479
+		$this->organization_config->instagram    = isset($form_data['organization_instagram'])
480
+			? esc_url_raw($form_data['organization_instagram'])
481
+			: $this->organization_config->instagram;
482
+		$this->core_config->ee_ueip_optin        = isset($form_data[ EE_Core_Config::OPTION_NAME_UXIP ][0])
483
+			? filter_var($form_data[ EE_Core_Config::OPTION_NAME_UXIP ][0], FILTER_VALIDATE_BOOLEAN)
484
+			: false;
485
+		$this->core_config->ee_ueip_has_notified = true;
486 486
 
487
-        $this->registry->CFG->currency = new EE_Currency_Config(
488
-            $this->organization_config->CNT_ISO
489
-        );
490
-        /** @var EE_Country $country */
491
-        $country = EEM_Country::instance()->get_one_by_ID($this->organization_config->CNT_ISO);
492
-        if ($country instanceof EE_Country) {
493
-            $country->set('CNT_active', 1);
494
-            $country->save();
495
-            $this->countrySubRegionDao->saveCountrySubRegions($country);
496
-        }
497
-        return true;
498
-    }
487
+		$this->registry->CFG->currency = new EE_Currency_Config(
488
+			$this->organization_config->CNT_ISO
489
+		);
490
+		/** @var EE_Country $country */
491
+		$country = EEM_Country::instance()->get_one_by_ID($this->organization_config->CNT_ISO);
492
+		if ($country instanceof EE_Country) {
493
+			$country->set('CNT_active', 1);
494
+			$country->save();
495
+			$this->countrySubRegionDao->saveCountrySubRegions($country);
496
+		}
497
+		return true;
498
+	}
499 499
 }
Please login to merge, or discard this patch.
admin_pages/payments/templates/payment_log_details.template.php 1 patch
Braces   +5 added lines, -2 removed lines patch added patch discarded remove patch
@@ -76,7 +76,8 @@  discard block
 block discarded – undo
76 76
     </table>
77 77
 </div>
78 78
 
79
-<?php else: ?>
79
+<?php else {
80
+	: ?>
80 81
 
81 82
 <div class="padding">
82 83
     <table class="ee-payment-log-details widefat">
@@ -84,7 +85,9 @@  discard block
 block discarded – undo
84 85
             <tr>
85 86
                 <td>
86 87
                     <p class="ee-status-outline ee-status-bg--attention">
87
-                        <?php esc_html_e("Payment Log No Longer Exists", 'event_espresso'); ?>
88
+                        <?php esc_html_e("Payment Log No Longer Exists", 'event_espresso');
89
+}
90
+?>
88 91
                     </p>
89 92
                 </td>
90 93
             </tr>
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 2 patches
Indentation   +1295 added lines, -1295 removed lines patch added patch discarded remove patch
@@ -18,286 +18,286 @@  discard block
 block discarded – undo
18 18
  */
19 19
 class Payments_Admin_Page extends EE_Admin_Page
20 20
 {
21
-    /**
22
-     * Variables used for when we're re-sorting the logs results,
23
-     * in case we needed to do two queries, and we need to resort
24
-     *
25
-     * @var string
26
-     */
27
-    private $_sort_logs_again_direction;
28
-
29
-
30
-    /**
31
-     * @Constructor
32
-     * @access public
33
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
34
-     * @throws EE_Error
35
-     * @throws InvalidArgumentException
36
-     * @throws InvalidDataTypeException
37
-     * @throws InvalidInterfaceException
38
-     * @throws ReflectionException
39
-     */
40
-    public function __construct($routing = true)
41
-    {
42
-        parent::__construct($routing);
43
-    }
44
-
45
-
46
-    protected function _init_page_props()
47
-    {
48
-        $this->page_slug        = EE_PAYMENTS_PG_SLUG;
49
-        $this->page_label       = esc_html__('Payment Methods', 'event_espresso');
50
-        $this->_admin_base_url  = EE_PAYMENTS_ADMIN_URL;
51
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
52
-    }
53
-
54
-
55
-    protected function _ajax_hooks()
56
-    {
57
-        // todo: all hooks for ajax goes here.
58
-    }
59
-
60
-
61
-    protected function _define_page_props()
62
-    {
63
-        $this->_admin_page_title = $this->page_label;
64
-        $this->_labels           = [
65
-            'publishbox' => esc_html__('Update Settings', 'event_espresso'),
66
-        ];
67
-    }
68
-
69
-
70
-    /**
71
-     * @param string $sort_logs_again_direction
72
-     */
73
-    public function setSortLogsAgainDirection(string $sort_logs_again_direction): void
74
-    {
75
-        $this->_sort_logs_again_direction = $sort_logs_again_direction;
76
-    }
77
-
78
-
79
-    protected function _set_page_routes()
80
-    {
81
-        /**
82
-         * note that with payment method capabilities, although we've implemented
83
-         * capability mapping which will be used for accessing payment methods owned by
84
-         * other users.  This is not fully implemented yet in the payment method ui.
85
-         * Currently, only the "plural" caps are in active use.
86
-         * When cap mapping is implemented, some routes will need to use the singular form of
87
-         * capability method and also include the $id of the payment method for the route.
88
-         **/
89
-        $this->_page_routes = [
90
-            'default'                   => [
91
-                'func'       => '_payment_methods_list',
92
-                'capability' => 'ee_edit_payment_methods',
93
-            ],
94
-            'payment_settings'          => [
95
-                'func'       => '_payment_settings',
96
-                'capability' => 'ee_manage_gateways',
97
-            ],
98
-            'activate_payment_method'   => [
99
-                'func'       => '_activate_payment_method',
100
-                'noheader'   => true,
101
-                'capability' => 'ee_edit_payment_methods',
102
-            ],
103
-            'deactivate_payment_method' => [
104
-                'func'       => '_deactivate_payment_method',
105
-                'noheader'   => true,
106
-                'capability' => 'ee_delete_payment_methods',
107
-            ],
108
-            'update_payment_method'     => [
109
-                'func'               => '_update_payment_method',
110
-                'noheader'           => true,
111
-                'headers_sent_route' => 'default',
112
-                'capability'         => 'ee_edit_payment_methods',
113
-            ],
114
-            'update_payment_settings'   => [
115
-                'func'       => '_update_payment_settings',
116
-                'noheader'   => true,
117
-                'capability' => 'ee_manage_gateways',
118
-            ],
119
-            'payment_log'               => [
120
-                'func'       => '_payment_log_overview_list_table',
121
-                'capability' => 'ee_read_payment_methods',
122
-            ],
123
-            'payment_log_details'       => [
124
-                'func'       => '_payment_log_details',
125
-                'capability' => 'ee_read_payment_methods',
126
-            ],
127
-        ];
128
-    }
129
-
130
-
131
-    /**
132
-     * @throws EE_Error
133
-     * @throws ReflectionException
134
-     */
135
-    protected function _set_page_config()
136
-    {
137
-        $payment_method_list_config = [
138
-            'nav'           => [
139
-                'label' => esc_html__('Payment Methods', 'event_espresso'),
140
-                'icon'  => 'dashicons-bank',
141
-                'order' => 10,
142
-            ],
143
-            'metaboxes'     => $this->_default_espresso_metaboxes,
144
-            'help_tabs'     => array_merge(
145
-                [
146
-                    'payment_methods_overview_help_tab' => [
147
-                        'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
148
-                        'filename' => 'payment_methods_overview',
149
-                    ],
150
-                ],
151
-                $this->_add_payment_method_help_tabs()
152
-            ),
153
-            'require_nonce' => false,
154
-        ];
155
-        $this->_page_config         = [
156
-            'default'          => $payment_method_list_config,
157
-            'payment_settings' => [
158
-                'nav'           => [
159
-                    'label' => esc_html__('Settings', 'event_espresso'),
160
-                    'icon'  => 'dashicons-admin-generic',
161
-                    'order' => 20,
162
-                ],
163
-                'help_tabs'     => [
164
-                    'payment_methods_settings_help_tab' => [
165
-                        'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
166
-                        'filename' => 'payment_methods_settings',
167
-                    ],
168
-                ],
169
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
170
-                'require_nonce' => false,
171
-            ],
172
-            'payment_log'      => [
173
-                'nav'           => [
174
-                    'label' => esc_html__("Logs", 'event_espresso'),
175
-                    'icon'  => 'dashicons-text-page',
176
-                    'order' => 30,
177
-                ],
178
-                'list_table'    => 'Payment_Log_Admin_List_Table',
179
-                'metaboxes'     => $this->_default_espresso_metaboxes,
180
-                'require_nonce' => false,
181
-            ],
182
-        ];
183
-    }
184
-
185
-
186
-    /**
187
-     * @return array
188
-     * @throws DomainException
189
-     * @throws EE_Error
190
-     * @throws InvalidArgumentException
191
-     * @throws InvalidDataTypeException
192
-     * @throws InvalidInterfaceException
193
-     * @throws ReflectionException
194
-     */
195
-    protected function _add_payment_method_help_tabs(): array
196
-    {
197
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
198
-        $payment_method_types     = EE_Payment_Method_Manager::instance()->payment_method_types();
199
-        $all_pmt_help_tabs_config = [];
200
-        foreach ($payment_method_types as $payment_method_type) {
201
-            if (
202
-                ! $this->capabilities->current_user_can(
203
-                    $payment_method_type->cap_name(),
204
-                    'specific_payment_method_type_access'
205
-                )
206
-            ) {
207
-                continue;
208
-            }
209
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
210
-                $template_args                              = $config['template_args'] ?? [];
211
-                $template_args['admin_page_obj']            = $this;
212
-                $all_pmt_help_tabs_config[ $help_tab_name ] = [
213
-                    'title'   => $config['title'],
214
-                    'content' => EEH_Template::display_template(
215
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
216
-                        $template_args,
217
-                        true
218
-                    ),
219
-                ];
220
-            }
221
-        }
222
-        return $all_pmt_help_tabs_config;
223
-    }
224
-
225
-
226
-    // none of the below group are currently used for Gateway Settings
227
-    protected function _add_screen_options()
228
-    {
229
-    }
230
-
231
-
232
-    protected function _add_feature_pointers()
233
-    {
234
-    }
235
-
236
-
237
-    public function admin_init()
238
-    {
239
-    }
240
-
241
-
242
-    public function admin_notices()
243
-    {
244
-    }
245
-
246
-
247
-    public function admin_footer_scripts()
248
-    {
249
-    }
250
-
251
-
252
-    public function load_scripts_styles()
253
-    {
254
-        // styles
255
-        wp_enqueue_style('espresso-ui-theme');
256
-        wp_register_style(
257
-            'espresso_payments',
258
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
259
-            [],
260
-            EVENT_ESPRESSO_VERSION
261
-        );
262
-        // scripts
263
-        wp_enqueue_script('ee_admin_js');
264
-        wp_enqueue_script('ee-text-links');
265
-        wp_enqueue_script(
266
-            'espresso_payments',
267
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
268
-            ['ee-datepicker'],
269
-            EVENT_ESPRESSO_VERSION,
270
-            true
271
-        );
272
-    }
273
-
274
-
275
-    public function load_scripts_styles_default()
276
-    {
277
-        wp_enqueue_style('espresso_payments');
278
-        wp_enqueue_style('ee-text-links');
279
-    }
280
-
281
-
282
-    public function load_scripts_styles_payment_log_details()
283
-    {
284
-        wp_enqueue_style('espresso_payments');
285
-    }
286
-
287
-
288
-    /**
289
-     * @throws EE_Error
290
-     */
291
-    private function veryifyTablesExist()
292
-    {
293
-        /** @var TableAnalysis $table_analysis */
294
-        $table_analysis = LoaderFactory::getShared(TableAnalysis::class);
295
-        /** @var TableManager $table_manager */
296
-        $table_manager = LoaderFactory::getShared(TableManager::class);
297
-        if (! $table_analysis->tableExists('esp_payment_method')) {
298
-            $table_manager->createTable(
299
-                'esp_payment_method',
300
-                "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
21
+	/**
22
+	 * Variables used for when we're re-sorting the logs results,
23
+	 * in case we needed to do two queries, and we need to resort
24
+	 *
25
+	 * @var string
26
+	 */
27
+	private $_sort_logs_again_direction;
28
+
29
+
30
+	/**
31
+	 * @Constructor
32
+	 * @access public
33
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
34
+	 * @throws EE_Error
35
+	 * @throws InvalidArgumentException
36
+	 * @throws InvalidDataTypeException
37
+	 * @throws InvalidInterfaceException
38
+	 * @throws ReflectionException
39
+	 */
40
+	public function __construct($routing = true)
41
+	{
42
+		parent::__construct($routing);
43
+	}
44
+
45
+
46
+	protected function _init_page_props()
47
+	{
48
+		$this->page_slug        = EE_PAYMENTS_PG_SLUG;
49
+		$this->page_label       = esc_html__('Payment Methods', 'event_espresso');
50
+		$this->_admin_base_url  = EE_PAYMENTS_ADMIN_URL;
51
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
52
+	}
53
+
54
+
55
+	protected function _ajax_hooks()
56
+	{
57
+		// todo: all hooks for ajax goes here.
58
+	}
59
+
60
+
61
+	protected function _define_page_props()
62
+	{
63
+		$this->_admin_page_title = $this->page_label;
64
+		$this->_labels           = [
65
+			'publishbox' => esc_html__('Update Settings', 'event_espresso'),
66
+		];
67
+	}
68
+
69
+
70
+	/**
71
+	 * @param string $sort_logs_again_direction
72
+	 */
73
+	public function setSortLogsAgainDirection(string $sort_logs_again_direction): void
74
+	{
75
+		$this->_sort_logs_again_direction = $sort_logs_again_direction;
76
+	}
77
+
78
+
79
+	protected function _set_page_routes()
80
+	{
81
+		/**
82
+		 * note that with payment method capabilities, although we've implemented
83
+		 * capability mapping which will be used for accessing payment methods owned by
84
+		 * other users.  This is not fully implemented yet in the payment method ui.
85
+		 * Currently, only the "plural" caps are in active use.
86
+		 * When cap mapping is implemented, some routes will need to use the singular form of
87
+		 * capability method and also include the $id of the payment method for the route.
88
+		 **/
89
+		$this->_page_routes = [
90
+			'default'                   => [
91
+				'func'       => '_payment_methods_list',
92
+				'capability' => 'ee_edit_payment_methods',
93
+			],
94
+			'payment_settings'          => [
95
+				'func'       => '_payment_settings',
96
+				'capability' => 'ee_manage_gateways',
97
+			],
98
+			'activate_payment_method'   => [
99
+				'func'       => '_activate_payment_method',
100
+				'noheader'   => true,
101
+				'capability' => 'ee_edit_payment_methods',
102
+			],
103
+			'deactivate_payment_method' => [
104
+				'func'       => '_deactivate_payment_method',
105
+				'noheader'   => true,
106
+				'capability' => 'ee_delete_payment_methods',
107
+			],
108
+			'update_payment_method'     => [
109
+				'func'               => '_update_payment_method',
110
+				'noheader'           => true,
111
+				'headers_sent_route' => 'default',
112
+				'capability'         => 'ee_edit_payment_methods',
113
+			],
114
+			'update_payment_settings'   => [
115
+				'func'       => '_update_payment_settings',
116
+				'noheader'   => true,
117
+				'capability' => 'ee_manage_gateways',
118
+			],
119
+			'payment_log'               => [
120
+				'func'       => '_payment_log_overview_list_table',
121
+				'capability' => 'ee_read_payment_methods',
122
+			],
123
+			'payment_log_details'       => [
124
+				'func'       => '_payment_log_details',
125
+				'capability' => 'ee_read_payment_methods',
126
+			],
127
+		];
128
+	}
129
+
130
+
131
+	/**
132
+	 * @throws EE_Error
133
+	 * @throws ReflectionException
134
+	 */
135
+	protected function _set_page_config()
136
+	{
137
+		$payment_method_list_config = [
138
+			'nav'           => [
139
+				'label' => esc_html__('Payment Methods', 'event_espresso'),
140
+				'icon'  => 'dashicons-bank',
141
+				'order' => 10,
142
+			],
143
+			'metaboxes'     => $this->_default_espresso_metaboxes,
144
+			'help_tabs'     => array_merge(
145
+				[
146
+					'payment_methods_overview_help_tab' => [
147
+						'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
148
+						'filename' => 'payment_methods_overview',
149
+					],
150
+				],
151
+				$this->_add_payment_method_help_tabs()
152
+			),
153
+			'require_nonce' => false,
154
+		];
155
+		$this->_page_config         = [
156
+			'default'          => $payment_method_list_config,
157
+			'payment_settings' => [
158
+				'nav'           => [
159
+					'label' => esc_html__('Settings', 'event_espresso'),
160
+					'icon'  => 'dashicons-admin-generic',
161
+					'order' => 20,
162
+				],
163
+				'help_tabs'     => [
164
+					'payment_methods_settings_help_tab' => [
165
+						'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
166
+						'filename' => 'payment_methods_settings',
167
+					],
168
+				],
169
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
170
+				'require_nonce' => false,
171
+			],
172
+			'payment_log'      => [
173
+				'nav'           => [
174
+					'label' => esc_html__("Logs", 'event_espresso'),
175
+					'icon'  => 'dashicons-text-page',
176
+					'order' => 30,
177
+				],
178
+				'list_table'    => 'Payment_Log_Admin_List_Table',
179
+				'metaboxes'     => $this->_default_espresso_metaboxes,
180
+				'require_nonce' => false,
181
+			],
182
+		];
183
+	}
184
+
185
+
186
+	/**
187
+	 * @return array
188
+	 * @throws DomainException
189
+	 * @throws EE_Error
190
+	 * @throws InvalidArgumentException
191
+	 * @throws InvalidDataTypeException
192
+	 * @throws InvalidInterfaceException
193
+	 * @throws ReflectionException
194
+	 */
195
+	protected function _add_payment_method_help_tabs(): array
196
+	{
197
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
198
+		$payment_method_types     = EE_Payment_Method_Manager::instance()->payment_method_types();
199
+		$all_pmt_help_tabs_config = [];
200
+		foreach ($payment_method_types as $payment_method_type) {
201
+			if (
202
+				! $this->capabilities->current_user_can(
203
+					$payment_method_type->cap_name(),
204
+					'specific_payment_method_type_access'
205
+				)
206
+			) {
207
+				continue;
208
+			}
209
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
210
+				$template_args                              = $config['template_args'] ?? [];
211
+				$template_args['admin_page_obj']            = $this;
212
+				$all_pmt_help_tabs_config[ $help_tab_name ] = [
213
+					'title'   => $config['title'],
214
+					'content' => EEH_Template::display_template(
215
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
216
+						$template_args,
217
+						true
218
+					),
219
+				];
220
+			}
221
+		}
222
+		return $all_pmt_help_tabs_config;
223
+	}
224
+
225
+
226
+	// none of the below group are currently used for Gateway Settings
227
+	protected function _add_screen_options()
228
+	{
229
+	}
230
+
231
+
232
+	protected function _add_feature_pointers()
233
+	{
234
+	}
235
+
236
+
237
+	public function admin_init()
238
+	{
239
+	}
240
+
241
+
242
+	public function admin_notices()
243
+	{
244
+	}
245
+
246
+
247
+	public function admin_footer_scripts()
248
+	{
249
+	}
250
+
251
+
252
+	public function load_scripts_styles()
253
+	{
254
+		// styles
255
+		wp_enqueue_style('espresso-ui-theme');
256
+		wp_register_style(
257
+			'espresso_payments',
258
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
259
+			[],
260
+			EVENT_ESPRESSO_VERSION
261
+		);
262
+		// scripts
263
+		wp_enqueue_script('ee_admin_js');
264
+		wp_enqueue_script('ee-text-links');
265
+		wp_enqueue_script(
266
+			'espresso_payments',
267
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
268
+			['ee-datepicker'],
269
+			EVENT_ESPRESSO_VERSION,
270
+			true
271
+		);
272
+	}
273
+
274
+
275
+	public function load_scripts_styles_default()
276
+	{
277
+		wp_enqueue_style('espresso_payments');
278
+		wp_enqueue_style('ee-text-links');
279
+	}
280
+
281
+
282
+	public function load_scripts_styles_payment_log_details()
283
+	{
284
+		wp_enqueue_style('espresso_payments');
285
+	}
286
+
287
+
288
+	/**
289
+	 * @throws EE_Error
290
+	 */
291
+	private function veryifyTablesExist()
292
+	{
293
+		/** @var TableAnalysis $table_analysis */
294
+		$table_analysis = LoaderFactory::getShared(TableAnalysis::class);
295
+		/** @var TableManager $table_manager */
296
+		$table_manager = LoaderFactory::getShared(TableManager::class);
297
+		if (! $table_analysis->tableExists('esp_payment_method')) {
298
+			$table_manager->createTable(
299
+				'esp_payment_method',
300
+				"PMD_ID int(11) NOT NULL AUTO_INCREMENT,
301 301
 				PMD_type varchar(124) DEFAULT NULL,
302 302
 				PMD_name varchar(255) DEFAULT NULL,
303 303
 				PMD_desc text,
@@ -313,1023 +313,1023 @@  discard block
 block discarded – undo
313 313
 				PRIMARY KEY  (PMD_ID),
314 314
 				UNIQUE KEY PMD_slug_UNIQUE (PMD_slug),
315 315
 				KEY PMD_type (PMD_type)",
316
-                'InnoDB'
317
-            );
318
-        }
319
-        if (! $table_analysis->tableExists('esp_currency_payment_method')) {
320
-            $table_manager->createTable(
321
-                'esp_currency_payment_method',
322
-                "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
316
+				'InnoDB'
317
+			);
318
+		}
319
+		if (! $table_analysis->tableExists('esp_currency_payment_method')) {
320
+			$table_manager->createTable(
321
+				'esp_currency_payment_method',
322
+				"CPM_ID int(11) NOT NULL AUTO_INCREMENT,
323 323
 				CUR_code varchar(6) NOT NULL,
324 324
 				PMD_ID int(11) NOT NULL,
325 325
 				PRIMARY KEY  (CPM_ID),
326 326
 				KEY PMD_ID (PMD_ID)",
327
-                'InnoDB'
328
-            );
329
-        }
330
-    }
331
-
332
-
333
-    /**
334
-     * @throws EE_Error
335
-     * @throws ReflectionException
336
-     */
337
-    protected function _payment_methods_list()
338
-    {
339
-        $this->veryifyTablesExist();
340
-        /**
341
-         * first let's ensure payment methods have been set up.
342
-         * We do this here because when people activate a payment method for the first time (as an addon),
343
-         * it may not set up its capabilities or get registered correctly due to the loading process.
344
-         * However, people MUST set up the details for the payment method,
345
-         * so it's safe to do a recheck here.
346
-         */
347
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
348
-        EEM_Payment_Method::instance()->verify_button_urls();
349
-        // set up tabs, one for each payment method type
350
-        $tabs            = [];
351
-        $payment_methods = [];
352
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
353
-            // we don't want to show admin-only PMTs for now
354
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
355
-                continue;
356
-            }
357
-            // check access
358
-            if (
359
-                ! $this->capabilities->current_user_can(
360
-                    $pmt_obj->cap_name(),
361
-                    'specific_payment_method_type_access'
362
-                )
363
-            ) {
364
-                continue;
365
-            }
366
-            // check for any active pms of that type
367
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
368
-            if (! $payment_method instanceof EE_Payment_Method) {
369
-                $payment_method = EE_Payment_Method::new_instance(
370
-                    [
371
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
372
-                        'PMD_type'       => $pmt_obj->system_name(),
373
-                        'PMD_name'       => $pmt_obj->pretty_name(),
374
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
375
-                    ]
376
-                );
377
-            }
378
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
379
-        }
380
-        $payment_methods = apply_filters(
381
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
382
-            $payment_methods
383
-        );
384
-        foreach ($payment_methods as $payment_method) {
385
-            if ($payment_method instanceof EE_Payment_Method) {
386
-                $this->addMetaBox(
387
-                // html id
388
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
389
-                    // title
390
-                    sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
391
-                    // callback
392
-                    [$this, 'payment_method_settings_meta_box'],
393
-                    // post type
394
-                    null,
395
-                    // context
396
-                    'normal',
397
-                    // priority
398
-                    'default',
399
-                    // callback args
400
-                    ['payment_method' => $payment_method]
401
-                );
402
-                // setup for tabbed content
403
-                $tabs[ $payment_method->slug() ] = [
404
-                    'label' => $payment_method->admin_name(),
405
-                    'class' => $payment_method->active()
406
-                        ? 'gateway-active'
407
-                        : '',
408
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
409
-                    'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
410
-                    'slug'  => $payment_method->slug(),
411
-                    'icon'  => $payment_method->active()
412
-                        ? '<span class="dashicons dashicons-yes-alt"></span>'
413
-                        : '<span class="dashicons dashicons-remove"></span>',
414
-                ];
415
-            }
416
-        }
417
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
418
-            $tabs,
419
-            'payment_method_links',
420
-            '',
421
-            $this->_get_active_payment_method_slug()
422
-        );
423
-        $this->display_admin_page_with_sidebar();
424
-    }
425
-
426
-
427
-    /**
428
-     *   _get_active_payment_method_slug
429
-     *
430
-     * @return string
431
-     * @throws EE_Error
432
-     * @throws ReflectionException
433
-     */
434
-    protected function _get_active_payment_method_slug()
435
-    {
436
-        $payment_method_slug = false;
437
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
438
-        if (isset($this->_req_data['payment_method'])) {
439
-            // if they provided the current payment method, use it
440
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
441
-        }
442
-        /** @var EE_Payment_Method $payment_method */
443
-        $payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
444
-        // if that didn't work or wasn't provided, find another way to select the current pm
445
-        if (! $this->_verify_payment_method($payment_method)) {
446
-            // like, looking for an active one
447
-            $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
448
-            // test that one as well
449
-            if ($this->_verify_payment_method($payment_method)) {
450
-                $payment_method_slug = $payment_method->slug();
451
-            } else {
452
-                $payment_method_slug = 'paypal_standard';
453
-            }
454
-        }
455
-        return $payment_method_slug;
456
-    }
457
-
458
-
459
-    /**
460
-     *    payment_method_settings_meta_box
461
-     *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
462
-     *    capabilities to access it
463
-     *
464
-     * @param EE_Payment_Method|null $payment_method
465
-     * @return boolean
466
-     * @throws EE_Error
467
-     */
468
-    protected function _verify_payment_method(?EE_Payment_Method $payment_method): bool
469
-    {
470
-        return $payment_method instanceof EE_Payment_Method
471
-               && $payment_method->type_obj() instanceof EE_PMT_Base
472
-               && $this->capabilities->current_user_can(
473
-                $payment_method->type_obj()->cap_name(),
474
-                'specific_payment_method_type_access'
475
-            );
476
-    }
477
-
478
-
479
-    /**
480
-     *    payment_method_settings_meta_box
481
-     *
482
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
483
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
484
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
485
-     * @return void
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     */
489
-    public function payment_method_settings_meta_box($post_obj_which_is_null, array $metabox)
490
-    {
491
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
492
-            ? $metabox['args']['payment_method']
493
-            : null;
494
-        if (! $payment_method instanceof EE_Payment_Method) {
495
-            throw new EE_Error(
496
-                esc_html__(
497
-                    'Payment method metabox setup incorrectly. No Payment method object was supplied',
498
-                    'event_espresso'
499
-                )
500
-            );
501
-        }
502
-        $payment_method_scopes = $payment_method->active();
503
-        // if the payment method really exists show its form, otherwise the activation template
504
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
505
-            $form = $this->_generate_payment_method_settings_form($payment_method);
506
-            if ($form->form_data_present_in($this->_req_data)) {
507
-                $form->receive_form_submission($this->_req_data);
508
-            }
509
-            echo wp_kses(
510
-                $form->form_open() . $form->get_html_and_js() . $form->form_close(),
511
-                AllowedTags::getWithFormTags()
512
-            );
513
-        } else {
514
-            echo wp_kses(
515
-                $this->_activate_payment_method_button($payment_method)->get_html_and_js(),
516
-                AllowedTags::getWithFormTags()
517
-            );
518
-        }
519
-    }
520
-
521
-
522
-    /**
523
-     * Gets the form for all the settings related to this payment method type
524
-     *
525
-     * @access protected
526
-     * @param EE_Payment_Method|null $payment_method
527
-     * @return EE_Form_Section_Proper
528
-     * @throws EE_Error
529
-     * @throws ReflectionException
530
-     */
531
-    protected function _generate_payment_method_settings_form(
532
-        ?EE_Payment_Method $payment_method
533
-    ): EE_Form_Section_Proper {
534
-        if (! $payment_method instanceof EE_Payment_Method) {
535
-            return new EE_Form_Section_Proper();
536
-        }
537
-        $subsections = apply_filters(
538
-            'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
539
-            [
540
-                'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
541
-                'currency_support'        => $this->_currency_support($payment_method),
542
-                'payment_method_settings' => $this->_payment_method_settings($payment_method),
543
-                'update'                  => $this->_update_payment_method_button($payment_method),
544
-                'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
545
-                'fine_print'              => $this->_fine_print(),
546
-            ],
547
-            $payment_method
548
-        );
549
-        return new EE_Form_Section_Proper(
550
-            [
551
-                'name'            => $payment_method->slug() . '_settings_form',
552
-                'html_id'         => $payment_method->slug() . '_settings_form',
553
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
554
-                    [
555
-                        'action'         => 'update_payment_method',
556
-                        'payment_method' => $payment_method->slug(),
557
-                    ],
558
-                    EE_PAYMENTS_ADMIN_URL
559
-                ),
560
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
561
-                'subsections'     => array_filter($subsections),
562
-            ]
563
-        );
564
-    }
565
-
566
-
567
-    /**
568
-     * _pci_dss_compliance
569
-     *
570
-     * @access protected
571
-     * @param EE_Payment_Method $payment_method
572
-     * @return EE_Form_Section_HTML|null
573
-     * @throws EE_Error
574
-     */
575
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
576
-    {
577
-        if (! $payment_method->type_obj()->requires_https()) {
578
-            return null;
579
-        }
580
-        return new EE_Form_Section_HTML(
581
-            EEH_HTML::tr(
582
-                EEH_HTML::th(
583
-                    EEH_HTML::label(
584
-                        EEH_HTML::strong(
585
-                            esc_html__('IMPORTANT', 'event_espresso'),
586
-                            '',
587
-                            'important-notice'
588
-                        )
589
-                    )
590
-                ) .
591
-                EEH_HTML::td(
592
-                    EEH_HTML::div(
593
-                        EEH_HTML::strong(
594
-                            esc_html__(
595
-                                'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
596
-                                'event_espresso'
597
-                            )
598
-                        ),
599
-                        '',
600
-                        'ee-status-outline ee-status-bg--warning'
601
-                    )
602
-                    . EEH_HTML::br()
603
-
604
-                    . EEH_HTML::div(
605
-                        esc_html__('Learn more about ', 'event_espresso')
606
-                        . EEH_HTML::link(
607
-                            'https://www.pcisecuritystandards.org/merchants/index.php',
608
-                            esc_html__('PCI DSS compliance', 'event_espresso')
609
-                        ),
610
-                        '',
611
-                        'ee-status-outline ee-status-bg--info'
612
-                    )
613
-                )
614
-            )
615
-        );
616
-    }
617
-
618
-
619
-    /**
620
-     * _currency_support
621
-     *
622
-     * @access protected
623
-     * @param EE_Payment_Method $payment_method
624
-     * @return EE_Form_Section_HTML|null
625
-     * @throws EE_Error
626
-     */
627
-    protected function _currency_support(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
628
-    {
629
-        if ($payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
630
-            return null;
631
-        }
632
-        return new EE_Form_Section_HTML(
633
-            EEH_HTML::tr(
634
-                EEH_HTML::th(
635
-                    EEH_HTML::label(
636
-                        EEH_HTML::strong(
637
-                            esc_html__('IMPORTANT', 'event_espresso'),
638
-                            '',
639
-                            'important-notice'
640
-                        )
641
-                    )
642
-                ) .
643
-                EEH_HTML::td(
644
-                    EEH_HTML::div(
645
-                        EEH_HTML::strong(
646
-                            sprintf(
647
-                                esc_html__(
648
-                                    '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.',
649
-                                    'event_espresso'
650
-                                ),
651
-                                EE_Config::instance()->currency->code
652
-                            )
653
-                        ),
654
-                        '',
655
-                        'ee-status-outline ee-status-bg--warning'
656
-                    )
657
-                )
658
-            )
659
-        );
660
-    }
661
-
662
-
663
-    /**
664
-     * _update_payment_method_button
665
-     *
666
-     * @access protected
667
-     * @param EE_Payment_Method $payment_method
668
-     * @return EE_Payment_Method_Form
669
-     * @throws EE_Error
670
-     * @throws ReflectionException
671
-     */
672
-    protected function _payment_method_settings(EE_Payment_Method $payment_method): EE_Payment_Method_Form
673
-    {
674
-        // modify the form, so we only have/show fields that will be implemented for this version
675
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
676
-    }
677
-
678
-
679
-    /**
680
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
681
-     *
682
-     * @param EE_Form_Section_Proper $form_section
683
-     * @param string                 $payment_method_name
684
-     * @return EE_Payment_Method_Form
685
-     * @throws EE_Error
686
-     */
687
-    protected function _simplify_form(
688
-        EE_Form_Section_Proper $form_section,
689
-        string $payment_method_name = ''
690
-    ): EE_Payment_Method_Form {
691
-        if ($form_section instanceof EE_Payment_Method_Form) {
692
-            $form_section->exclude(
693
-                [
694
-                    'PMD_type', // don't want them changing the type
695
-                    'PMD_slug', // or the slug (probably never)
696
-                    'PMD_wp_user', // or the user's ID
697
-                    'Currency', // or the currency, until the rest of EE supports simultaneous currencies
698
-                ]
699
-            );
700
-            return $form_section;
701
-        }
702
-        throw new EE_Error(
703
-            sprintf(
704
-                esc_html__(
705
-                    'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
706
-                    'event_espresso'
707
-                ),
708
-                $payment_method_name
709
-            )
710
-        );
711
-    }
712
-
713
-
714
-    /**
715
-     * _update_payment_method_button
716
-     *
717
-     * @access protected
718
-     * @param EE_Payment_Method $payment_method
719
-     * @return EE_Form_Section_HTML
720
-     * @throws EE_Error
721
-     */
722
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
723
-    {
724
-        $update_button = new EE_Submit_Input(
725
-            [
726
-                'name'       => 'submit',
727
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
728
-                'default'    => sprintf(
729
-                    esc_html__('Update %s Payment Settings', 'event_espresso'),
730
-                    $payment_method->admin_name()
731
-                ),
732
-                'html_label' => EEH_HTML::nbsp(),
733
-            ]
734
-        );
735
-        return new EE_Form_Section_HTML(
736
-            EEH_HTML::tr(
737
-                EEH_HTML::th(
738
-                // esc_html__('Update Settings', 'event_espresso'),
739
-                    '&nbsp;',
740
-                    '',
741
-                    'ee-update-' . $payment_method->slug() . '-settings__label'
742
-                ) .
743
-                EEH_HTML::td(
744
-                    $update_button->get_html_for_input(),
745
-                    '',
746
-                    'ee-update-' . $payment_method->slug() . '-settings__input'
747
-                ),
748
-                '',
749
-                'ee-update-' . $payment_method->slug() . '-settings'
750
-            )
751
-        );
752
-    }
753
-
754
-
755
-    /**
756
-     * _deactivate_payment_method_button
757
-     *
758
-     * @access protected
759
-     * @param EE_Payment_Method $payment_method
760
-     * @return EE_Form_Section_HTML
761
-     */
762
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
763
-    {
764
-        $link_text_and_title = sprintf(
765
-            esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
766
-            $payment_method->admin_name()
767
-        );
768
-        return new EE_Form_Section_HTML(
769
-            EEH_HTML::tr(
770
-                EEH_HTML::th(
771
-                // esc_html__('Deactivate Payment Method', 'event_espresso'),
772
-                    '&nbsp;',
773
-                    '',
774
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__label'
775
-                ) .
776
-                EEH_HTML::td(
777
-                    EEH_HTML::link(
778
-                        EE_Admin_Page::add_query_args_and_nonce(
779
-                            [
780
-                                'action'         => 'deactivate_payment_method',
781
-                                'payment_method' => $payment_method->slug(),
782
-                            ],
783
-                            EE_PAYMENTS_ADMIN_URL
784
-                        ),
785
-                        $link_text_and_title,
786
-                        $link_text_and_title,
787
-                        'deactivate_' . $payment_method->slug(),
788
-                        'button button--secondary'
789
-                    ),
790
-                    '',
791
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__input'
792
-                ),
793
-                '',
794
-                'ee-deactivate-' . $payment_method->slug() . '-settings'
795
-            )
796
-        );
797
-    }
798
-
799
-
800
-    /**
801
-     * _activate_payment_method_button
802
-     *
803
-     * @access protected
804
-     * @param EE_Payment_Method $payment_method
805
-     * @return EE_Form_Section_Proper
806
-     * @throws EE_Error
807
-     */
808
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_Proper
809
-    {
810
-        $link_text_and_title = sprintf(
811
-            esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
812
-            $payment_method->admin_name()
813
-        );
814
-        return new EE_Form_Section_Proper(
815
-            [
816
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
817
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
818
-                'action'          => '#',
819
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
820
-                'subsections'     => apply_filters(
821
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
822
-                    [
823
-                        new EE_Form_Section_HTML(
824
-                            EEH_HTML::table(
825
-                                EEH_HTML::tr(
826
-                                    EEH_HTML::td(
827
-                                        $payment_method->type_obj()->introductory_html(),
828
-                                        '',
829
-                                        '',
830
-                                        '',
831
-                                        'colspan="2"'
832
-                                    )
833
-                                ) .
834
-                                EEH_HTML::tr(
835
-                                    EEH_HTML::th(
836
-                                        EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
837
-                                    ) .
838
-                                    EEH_HTML::td(
839
-                                        EEH_HTML::link(
840
-                                            EE_Admin_Page::add_query_args_and_nonce(
841
-                                                [
842
-                                                    'action'              => 'activate_payment_method',
843
-                                                    'payment_method_type' => $payment_method->type(),
844
-                                                ],
845
-                                                EE_PAYMENTS_ADMIN_URL
846
-                                            ),
847
-                                            $link_text_and_title,
848
-                                            $link_text_and_title,
849
-                                            'activate_' . $payment_method->slug(),
850
-                                            'button button--primary-alt'
851
-                                        )
852
-                                    )
853
-                                )
854
-                            )
855
-                        ),
856
-                    ],
857
-                    $payment_method
858
-                ),
859
-            ]
860
-        );
861
-    }
862
-
863
-
864
-    /**
865
-     * _fine_print
866
-     *
867
-     * @access protected
868
-     * @return EE_Form_Section_HTML
869
-     */
870
-    protected function _fine_print(): EE_Form_Section_HTML
871
-    {
872
-        return new EE_Form_Section_HTML(
873
-            EEH_HTML::tr(
874
-                EEH_HTML::th()
875
-                . EEH_HTML::thx()
876
-                . EEH_HTML::td(
877
-                    EEH_HTML::p(
878
-                        esc_html__('All fields marked with a * are required fields', 'event_espresso'),
879
-                        '',
880
-                        'grey-text'
881
-                    )
882
-                )
883
-            )
884
-        );
885
-    }
886
-
887
-
888
-    /**
889
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
890
-     *
891
-     * @throws EE_Error
892
-     * @throws ReflectionException
893
-     * @global WP_User $current_user
894
-     */
895
-    protected function _activate_payment_method()
896
-    {
897
-        if (isset($this->_req_data['payment_method_type'])) {
898
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
899
-            // see if one exists
900
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
901
-            $payment_method = EE_Payment_Method_Manager::instance()
902
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
903
-            $this->_redirect_after_action(
904
-                1,
905
-                'Payment Method',
906
-                'activated',
907
-                ['action' => 'default', 'payment_method' => $payment_method->slug()]
908
-            );
909
-        } else {
910
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
911
-        }
912
-    }
913
-
914
-
915
-    /**
916
-     * @throws EE_Error
917
-     * @throws ReflectionException
918
-     */
919
-    protected function _deactivate_payment_method()
920
-    {
921
-        if (isset($this->_req_data['payment_method'])) {
922
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
923
-            // deactivate it
924
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
925
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
926
-            $this->_redirect_after_action(
927
-                $count_updated,
928
-                'Payment Method',
929
-                'deactivated',
930
-                ['action' => 'default', 'payment_method' => $payment_method_slug]
931
-            );
932
-        } else {
933
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', ['action' => 'default']);
934
-        }
935
-    }
936
-
937
-
938
-    /**
939
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
940
-     * processing because we first need to identify WHICH form was processed and which payment method
941
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
942
-     * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
943
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
944
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
945
-     *
946
-     * @return void
947
-     * @throws EE_Error
948
-     * @throws ReflectionException
949
-     */
950
-    protected function _update_payment_method()
951
-    {
952
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
953
-            // ok let's find which gateway form to use based on the form input
954
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
955
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
956
-            $correct_pmt_form_to_use = null;
957
-            $payment_method          = null;
958
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
959
-                if ($payment_method instanceof EE_Payment_Method) {
960
-                    // get the form and simplify it, like what we do when we display it
961
-                    $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
962
-                    if ($pmt_form->form_data_present_in($this->_req_data)) {
963
-                        $correct_pmt_form_to_use = $pmt_form;
964
-                        break;
965
-                    }
966
-                }
967
-            }
968
-            // if we couldn't find the correct payment method type...
969
-            if (! $correct_pmt_form_to_use) {
970
-                EE_Error::add_error(
971
-                    esc_html__(
972
-                        "We could not find which payment method type your form submission related to. Please contact support",
973
-                        'event_espresso'
974
-                    ),
975
-                    __FILE__,
976
-                    __FUNCTION__,
977
-                    __LINE__
978
-                );
979
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
980
-            }
981
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
982
-            if ($correct_pmt_form_to_use->is_valid()) {
983
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
984
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
985
-                    throw new EE_Error(
986
-                        sprintf(
987
-                            esc_html__(
988
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
989
-                                'event_espresso'
990
-                            ),
991
-                            'payment_method_settings'
992
-                        )
993
-                    );
994
-                }
995
-                $payment_settings_subform->save();
996
-                /** @var $pm EE_Payment_Method */
997
-                $this->_redirect_after_action(
998
-                    true,
999
-                    'Payment Method',
1000
-                    'updated',
1001
-                    ['action' => 'default', 'payment_method' => $payment_method->slug()]
1002
-                );
1003
-            } else {
1004
-                EE_Error::add_error(
1005
-                    sprintf(
1006
-                        esc_html__(
1007
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
1008
-                            'event_espresso'
1009
-                        ),
1010
-                        $payment_method instanceof EE_Payment_Method
1011
-                            ? $payment_method->type_obj()->pretty_name()
1012
-                            : esc_html__('"(unknown)"', 'event_espresso')
1013
-                    ),
1014
-                    __FILE__,
1015
-                    __FUNCTION__,
1016
-                    __LINE__
1017
-                );
1018
-            }
1019
-        }
1020
-    }
1021
-
1022
-
1023
-    /**
1024
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
1025
-     *
1026
-     * @throws DomainException
1027
-     * @throws EE_Error
1028
-     * @throws InvalidArgumentException
1029
-     * @throws InvalidDataTypeException
1030
-     * @throws InvalidInterfaceException
1031
-     */
1032
-    protected function _payment_settings()
1033
-    {
1034
-        $form = $this->getPaymentSettingsForm();
1035
-        $this->_set_add_edit_form_tags('update_payment_settings');
1036
-        $this->_set_publish_post_box_vars();
1037
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1038
-            $form->get_html_and_js(),
1039
-            '',
1040
-            'padding'
1041
-        );
1042
-        $this->display_admin_page_with_sidebar();
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     *        _update_payment_settings
1048
-     *
1049
-     * @access protected
1050
-     * @return void
1051
-     * @throws EE_Error
1052
-     * @throws InvalidArgumentException
1053
-     * @throws InvalidDataTypeException
1054
-     * @throws InvalidInterfaceException
1055
-     */
1056
-    protected function _update_payment_settings()
1057
-    {
1058
-        $form = $this->getPaymentSettingsForm();
1059
-        if ($form->was_submitted($this->_req_data)) {
1060
-            $form->receive_form_submission($this->_req_data);
1061
-            if ($form->is_valid()) {
1062
-                /**
1063
-                 * @var $reg_config EE_Registration_Config
1064
-                 */
1065
-                $loader                                   = LoaderFactory::getLoader();
1066
-                $reg_config                               = $loader->getShared('EE_Registration_Config');
1067
-                $valid_data                               = $form->valid_data();
1068
-                $show_pending_payment_options             = $valid_data['show_pending_payment_options'] ?? null;
1069
-                $reg_config->show_pending_payment_options = $show_pending_payment_options === 'ON';
1070
-                $reg_config->gateway_log_lifespan         = $valid_data['gateway_log_lifespan'];
1071
-            }
1072
-        }
1073
-        EE_Registry::instance()->CFG = apply_filters(
1074
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
1075
-            EE_Registry::instance()->CFG
1076
-        );
1077
-
1078
-        $what    = esc_html__('Payment Settings', 'event_espresso');
1079
-        $success = $this->_update_espresso_configuration(
1080
-            $what,
1081
-            EE_Registry::instance()->CFG,
1082
-            __FILE__,
1083
-            __FUNCTION__,
1084
-            __LINE__
1085
-        );
1086
-        $this->_redirect_after_action(
1087
-            $success,
1088
-            $what,
1089
-            esc_html__('updated', 'event_espresso'),
1090
-            ['action' => 'payment_settings']
1091
-        );
1092
-    }
1093
-
1094
-
1095
-    /**
1096
-     * Gets the form used for updating payment settings
1097
-     *
1098
-     * @return EE_Form_Section_Proper
1099
-     * @throws EE_Error
1100
-     * @throws InvalidArgumentException
1101
-     * @throws InvalidDataTypeException
1102
-     * @throws InvalidInterfaceException
1103
-     */
1104
-    protected function getPaymentSettingsForm(): EE_Form_Section_Proper
1105
-    {
1106
-        /**
1107
-         * @var $reg_config EE_Registration_Config
1108
-         */
1109
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1110
-        return new EE_Form_Section_Proper(
1111
-            [
1112
-                'name'            => 'payment-settings',
1113
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1114
-                'subsections'     => [
1115
-                    'show_pending_payment_options' => new EE_Switch_Input(
1116
-                        [
1117
-                            'default'        => $reg_config->show_pending_payment_options
1118
-                                ? EE_Switch_Input::OPTION_ON
1119
-                                : EE_Switch_Input::OPTION_OFF,
1120
-                            'html_name'      => 'show_pending_payment_options',
1121
-                            'html_help_text' => esc_html__(
1122
-                                "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. ",
1123
-                                'event_espresso'
1124
-                            ),
1125
-                        ],
1126
-                        [
1127
-                            EE_Switch_Input::OPTION_OFF => esc_html__(
1128
-                                'pending payment options are NOT displayed',
1129
-                                'event_espresso'
1130
-                            ),
1131
-                            EE_Switch_Input::OPTION_ON  => esc_html__(
1132
-                                'pending payment options are displayed',
1133
-                                'event_espresso'
1134
-                            ),
1135
-                        ]
1136
-                    ),
1137
-                    'gateway_log_lifespan'         => new EE_Select_Input(
1138
-                        $reg_config->gatewayLogLifespanOptions(),
1139
-                        [
1140
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1141
-                            'html_help_text'  => esc_html__(
1142
-                                '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.',
1143
-                                'event_espresso'
1144
-                            ),
1145
-                            'default'         => $reg_config->gateway_log_lifespan,
1146
-                        ]
1147
-                    ),
1148
-                ],
1149
-            ]
1150
-        );
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * @throws EE_Error
1156
-     */
1157
-    protected function _payment_log_overview_list_table()
1158
-    {
1159
-        $this->display_admin_list_table_page_with_sidebar();
1160
-    }
1161
-
1162
-
1163
-    protected function _set_list_table_views_payment_log()
1164
-    {
1165
-        $this->_views = [
1166
-            'all' => [
1167
-                'slug'  => 'all',
1168
-                'label' => esc_html__('View All Logs', 'event_espresso'),
1169
-                'count' => 0,
1170
-            ],
1171
-        ];
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * @param int  $per_page
1177
-     * @param int  $current_page
1178
-     * @param bool $count
1179
-     * @return array|int
1180
-     * @throws EE_Error
1181
-     * @throws ReflectionException
1182
-     */
1183
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1184
-    {
1185
-        EE_Registry::instance()->load_model('Change_Log');
1186
-        // we may need to do multiple queries (joining differently), so we actually want an array of query params
1187
-        $query_params = [['LOG_type' => EEM_Change_Log::type_gateway]];
1188
-        // check if they've selected a specific payment method
1189
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1190
-            $query_params[0]['OR*pm_or_pay_pm'] = [
1191
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1192
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1193
-            ];
1194
-        }
1195
-        // take into account search
1196
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1197
-            $similarity_string                                                              =
1198
-                ['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1199
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1200
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1201
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1202
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name']                     = $similarity_string;
1203
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name']               = $similarity_string;
1204
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type']                     = $similarity_string;
1205
-            $query_params[0]['OR*s']['Payment_Method.PMD_name']                             = $similarity_string;
1206
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name']                       = $similarity_string;
1207
-            $query_params[0]['OR*s']['Payment_Method.PMD_type']                             = $similarity_string;
1208
-            $query_params[0]['OR*s']['LOG_message']                                         = $similarity_string;
1209
-        }
1210
-        if (
1211
-            isset($this->_req_data['payment-filter-start-date'])
1212
-            && isset($this->_req_data['payment-filter-end-date'])
1213
-        ) {
1214
-            // add date
1215
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1216
-            $end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1217
-            // make sure our timestamps start and end right at the boundaries for each day
1218
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1219
-            $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1220
-            // convert to timestamps
1221
-            $start_date = strtotime($start_date);
1222
-            $end_date   = strtotime($end_date);
1223
-            // makes sure start date is the lowest value and vice versa
1224
-            $start_date = min($start_date, $end_date);
1225
-            $end_date   = max($start_date, $end_date);
1226
-            // convert for query
1227
-            $start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1228
-                'LOG_time',
1229
-                date('Y-m-d H:i:s', $start_date),
1230
-                'Y-m-d H:i:s'
1231
-            );
1232
-            $end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1233
-                'LOG_time',
1234
-                date('Y-m-d H:i:s', $end_date),
1235
-                'Y-m-d H:i:s'
1236
-            );
1237
-            $query_params[0]['LOG_time'] = ['BETWEEN', [$start_date, $end_date]];
1238
-        }
1239
-        if ($count) {
1240
-            return EEM_Change_Log::instance()->count($query_params);
1241
-        }
1242
-        if (isset($this->_req_data['order'])) {
1243
-            $sort                     = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1244
-                ? $this->_req_data['order']
1245
-                : 'DESC';
1246
-            $query_params['order_by'] = ['LOG_time' => $sort];
1247
-        } else {
1248
-            $query_params['order_by'] = ['LOG_time' => 'DESC'];
1249
-        }
1250
-        $offset = ($current_page - 1) * $per_page;
1251
-        if (! isset($this->_req_data['download_results'])) {
1252
-            $query_params['limit'] = [$offset, $per_page];
1253
-        }
1254
-        // now they've requested to instead just download the file instead of viewing it.
1255
-        if (isset($this->_req_data['download_results'])) {
1256
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1257
-            header('Content-Disposition: attachment');
1258
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1259
-            echo '<h1> '
1260
-                 . sprintf(
1261
-                     esc_html__('Payment Logs for %1$s', 'event_espresso'),
1262
-                     esc_url_raw(site_url())
1263
-                 )
1264
-                 . '</h1 >';
1265
-            echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1266
-            echo esc_html(var_export($query_params, true));
1267
-            echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1268
-            echo esc_html(var_export($wpdb_results, true));
1269
-            die;
1270
-        }
1271
-        return EEM_Change_Log::instance()->get_all($query_params);
1272
-    }
1273
-
1274
-
1275
-    /**
1276
-     * Used by usort to RE-sort log query results, because we lose the ordering
1277
-     * because we're possibly combining the results from two queries
1278
-     *
1279
-     * @param EE_Change_Log $logA
1280
-     * @param EE_Change_Log $logB
1281
-     * @return int
1282
-     * @throws EE_Error
1283
-     * @throws ReflectionException
1284
-     */
1285
-    protected function _sort_logs_again($logA, $logB)
1286
-    {
1287
-        $timeA = $logA->get_raw('LOG_time');
1288
-        $timeB = $logB->get_raw('LOG_time');
1289
-        if ($timeA == $timeB) {
1290
-            return 0;
1291
-        }
1292
-        $comparison = $timeA < $timeB
1293
-            ? -1
1294
-            : 1;
1295
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1296
-            return $comparison * -1;
1297
-        }
1298
-        return $comparison;
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * @throws EE_Error
1304
-     * @throws ReflectionException
1305
-     */
1306
-    protected function _payment_log_details()
1307
-    {
1308
-        EE_Registry::instance()->load_model('Change_Log');
1309
-        /** @var $payment_log EE_Change_Log */
1310
-        $payment_log    = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1311
-        $payment_method = null;
1312
-        $transaction    = null;
1313
-        if ($payment_log instanceof EE_Change_Log) {
1314
-            if ($payment_log->object() instanceof EE_Payment) {
1315
-                $payment_method = $payment_log->object()->payment_method();
1316
-                $transaction    = $payment_log->object()->transaction();
1317
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1318
-                $payment_method = $payment_log->object();
1319
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1320
-                $transaction    = $payment_log->object();
1321
-                $payment_method = $transaction->payment_method();
1322
-            }
1323
-        }
1324
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1325
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1326
-            [
1327
-                'payment_log'    => $payment_log,
1328
-                'payment_method' => $payment_method,
1329
-                'transaction'    => $transaction,
1330
-            ],
1331
-            true
1332
-        );
1333
-        $this->display_admin_page_with_no_sidebar();
1334
-    }
327
+				'InnoDB'
328
+			);
329
+		}
330
+	}
331
+
332
+
333
+	/**
334
+	 * @throws EE_Error
335
+	 * @throws ReflectionException
336
+	 */
337
+	protected function _payment_methods_list()
338
+	{
339
+		$this->veryifyTablesExist();
340
+		/**
341
+		 * first let's ensure payment methods have been set up.
342
+		 * We do this here because when people activate a payment method for the first time (as an addon),
343
+		 * it may not set up its capabilities or get registered correctly due to the loading process.
344
+		 * However, people MUST set up the details for the payment method,
345
+		 * so it's safe to do a recheck here.
346
+		 */
347
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
348
+		EEM_Payment_Method::instance()->verify_button_urls();
349
+		// set up tabs, one for each payment method type
350
+		$tabs            = [];
351
+		$payment_methods = [];
352
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
353
+			// we don't want to show admin-only PMTs for now
354
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
355
+				continue;
356
+			}
357
+			// check access
358
+			if (
359
+				! $this->capabilities->current_user_can(
360
+					$pmt_obj->cap_name(),
361
+					'specific_payment_method_type_access'
362
+				)
363
+			) {
364
+				continue;
365
+			}
366
+			// check for any active pms of that type
367
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
368
+			if (! $payment_method instanceof EE_Payment_Method) {
369
+				$payment_method = EE_Payment_Method::new_instance(
370
+					[
371
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
372
+						'PMD_type'       => $pmt_obj->system_name(),
373
+						'PMD_name'       => $pmt_obj->pretty_name(),
374
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
375
+					]
376
+				);
377
+			}
378
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
379
+		}
380
+		$payment_methods = apply_filters(
381
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
382
+			$payment_methods
383
+		);
384
+		foreach ($payment_methods as $payment_method) {
385
+			if ($payment_method instanceof EE_Payment_Method) {
386
+				$this->addMetaBox(
387
+				// html id
388
+					'espresso_' . $payment_method->slug() . '_payment_settings',
389
+					// title
390
+					sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
391
+					// callback
392
+					[$this, 'payment_method_settings_meta_box'],
393
+					// post type
394
+					null,
395
+					// context
396
+					'normal',
397
+					// priority
398
+					'default',
399
+					// callback args
400
+					['payment_method' => $payment_method]
401
+				);
402
+				// setup for tabbed content
403
+				$tabs[ $payment_method->slug() ] = [
404
+					'label' => $payment_method->admin_name(),
405
+					'class' => $payment_method->active()
406
+						? 'gateway-active'
407
+						: '',
408
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
409
+					'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
410
+					'slug'  => $payment_method->slug(),
411
+					'icon'  => $payment_method->active()
412
+						? '<span class="dashicons dashicons-yes-alt"></span>'
413
+						: '<span class="dashicons dashicons-remove"></span>',
414
+				];
415
+			}
416
+		}
417
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
418
+			$tabs,
419
+			'payment_method_links',
420
+			'',
421
+			$this->_get_active_payment_method_slug()
422
+		);
423
+		$this->display_admin_page_with_sidebar();
424
+	}
425
+
426
+
427
+	/**
428
+	 *   _get_active_payment_method_slug
429
+	 *
430
+	 * @return string
431
+	 * @throws EE_Error
432
+	 * @throws ReflectionException
433
+	 */
434
+	protected function _get_active_payment_method_slug()
435
+	{
436
+		$payment_method_slug = false;
437
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
438
+		if (isset($this->_req_data['payment_method'])) {
439
+			// if they provided the current payment method, use it
440
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
441
+		}
442
+		/** @var EE_Payment_Method $payment_method */
443
+		$payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
444
+		// if that didn't work or wasn't provided, find another way to select the current pm
445
+		if (! $this->_verify_payment_method($payment_method)) {
446
+			// like, looking for an active one
447
+			$payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
448
+			// test that one as well
449
+			if ($this->_verify_payment_method($payment_method)) {
450
+				$payment_method_slug = $payment_method->slug();
451
+			} else {
452
+				$payment_method_slug = 'paypal_standard';
453
+			}
454
+		}
455
+		return $payment_method_slug;
456
+	}
457
+
458
+
459
+	/**
460
+	 *    payment_method_settings_meta_box
461
+	 *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
462
+	 *    capabilities to access it
463
+	 *
464
+	 * @param EE_Payment_Method|null $payment_method
465
+	 * @return boolean
466
+	 * @throws EE_Error
467
+	 */
468
+	protected function _verify_payment_method(?EE_Payment_Method $payment_method): bool
469
+	{
470
+		return $payment_method instanceof EE_Payment_Method
471
+			   && $payment_method->type_obj() instanceof EE_PMT_Base
472
+			   && $this->capabilities->current_user_can(
473
+				$payment_method->type_obj()->cap_name(),
474
+				'specific_payment_method_type_access'
475
+			);
476
+	}
477
+
478
+
479
+	/**
480
+	 *    payment_method_settings_meta_box
481
+	 *
482
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
483
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
484
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
485
+	 * @return void
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 */
489
+	public function payment_method_settings_meta_box($post_obj_which_is_null, array $metabox)
490
+	{
491
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
492
+			? $metabox['args']['payment_method']
493
+			: null;
494
+		if (! $payment_method instanceof EE_Payment_Method) {
495
+			throw new EE_Error(
496
+				esc_html__(
497
+					'Payment method metabox setup incorrectly. No Payment method object was supplied',
498
+					'event_espresso'
499
+				)
500
+			);
501
+		}
502
+		$payment_method_scopes = $payment_method->active();
503
+		// if the payment method really exists show its form, otherwise the activation template
504
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
505
+			$form = $this->_generate_payment_method_settings_form($payment_method);
506
+			if ($form->form_data_present_in($this->_req_data)) {
507
+				$form->receive_form_submission($this->_req_data);
508
+			}
509
+			echo wp_kses(
510
+				$form->form_open() . $form->get_html_and_js() . $form->form_close(),
511
+				AllowedTags::getWithFormTags()
512
+			);
513
+		} else {
514
+			echo wp_kses(
515
+				$this->_activate_payment_method_button($payment_method)->get_html_and_js(),
516
+				AllowedTags::getWithFormTags()
517
+			);
518
+		}
519
+	}
520
+
521
+
522
+	/**
523
+	 * Gets the form for all the settings related to this payment method type
524
+	 *
525
+	 * @access protected
526
+	 * @param EE_Payment_Method|null $payment_method
527
+	 * @return EE_Form_Section_Proper
528
+	 * @throws EE_Error
529
+	 * @throws ReflectionException
530
+	 */
531
+	protected function _generate_payment_method_settings_form(
532
+		?EE_Payment_Method $payment_method
533
+	): EE_Form_Section_Proper {
534
+		if (! $payment_method instanceof EE_Payment_Method) {
535
+			return new EE_Form_Section_Proper();
536
+		}
537
+		$subsections = apply_filters(
538
+			'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
539
+			[
540
+				'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
541
+				'currency_support'        => $this->_currency_support($payment_method),
542
+				'payment_method_settings' => $this->_payment_method_settings($payment_method),
543
+				'update'                  => $this->_update_payment_method_button($payment_method),
544
+				'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
545
+				'fine_print'              => $this->_fine_print(),
546
+			],
547
+			$payment_method
548
+		);
549
+		return new EE_Form_Section_Proper(
550
+			[
551
+				'name'            => $payment_method->slug() . '_settings_form',
552
+				'html_id'         => $payment_method->slug() . '_settings_form',
553
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
554
+					[
555
+						'action'         => 'update_payment_method',
556
+						'payment_method' => $payment_method->slug(),
557
+					],
558
+					EE_PAYMENTS_ADMIN_URL
559
+				),
560
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
561
+				'subsections'     => array_filter($subsections),
562
+			]
563
+		);
564
+	}
565
+
566
+
567
+	/**
568
+	 * _pci_dss_compliance
569
+	 *
570
+	 * @access protected
571
+	 * @param EE_Payment_Method $payment_method
572
+	 * @return EE_Form_Section_HTML|null
573
+	 * @throws EE_Error
574
+	 */
575
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
576
+	{
577
+		if (! $payment_method->type_obj()->requires_https()) {
578
+			return null;
579
+		}
580
+		return new EE_Form_Section_HTML(
581
+			EEH_HTML::tr(
582
+				EEH_HTML::th(
583
+					EEH_HTML::label(
584
+						EEH_HTML::strong(
585
+							esc_html__('IMPORTANT', 'event_espresso'),
586
+							'',
587
+							'important-notice'
588
+						)
589
+					)
590
+				) .
591
+				EEH_HTML::td(
592
+					EEH_HTML::div(
593
+						EEH_HTML::strong(
594
+							esc_html__(
595
+								'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
596
+								'event_espresso'
597
+							)
598
+						),
599
+						'',
600
+						'ee-status-outline ee-status-bg--warning'
601
+					)
602
+					. EEH_HTML::br()
603
+
604
+					. EEH_HTML::div(
605
+						esc_html__('Learn more about ', 'event_espresso')
606
+						. EEH_HTML::link(
607
+							'https://www.pcisecuritystandards.org/merchants/index.php',
608
+							esc_html__('PCI DSS compliance', 'event_espresso')
609
+						),
610
+						'',
611
+						'ee-status-outline ee-status-bg--info'
612
+					)
613
+				)
614
+			)
615
+		);
616
+	}
617
+
618
+
619
+	/**
620
+	 * _currency_support
621
+	 *
622
+	 * @access protected
623
+	 * @param EE_Payment_Method $payment_method
624
+	 * @return EE_Form_Section_HTML|null
625
+	 * @throws EE_Error
626
+	 */
627
+	protected function _currency_support(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
628
+	{
629
+		if ($payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
630
+			return null;
631
+		}
632
+		return new EE_Form_Section_HTML(
633
+			EEH_HTML::tr(
634
+				EEH_HTML::th(
635
+					EEH_HTML::label(
636
+						EEH_HTML::strong(
637
+							esc_html__('IMPORTANT', 'event_espresso'),
638
+							'',
639
+							'important-notice'
640
+						)
641
+					)
642
+				) .
643
+				EEH_HTML::td(
644
+					EEH_HTML::div(
645
+						EEH_HTML::strong(
646
+							sprintf(
647
+								esc_html__(
648
+									'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.',
649
+									'event_espresso'
650
+								),
651
+								EE_Config::instance()->currency->code
652
+							)
653
+						),
654
+						'',
655
+						'ee-status-outline ee-status-bg--warning'
656
+					)
657
+				)
658
+			)
659
+		);
660
+	}
661
+
662
+
663
+	/**
664
+	 * _update_payment_method_button
665
+	 *
666
+	 * @access protected
667
+	 * @param EE_Payment_Method $payment_method
668
+	 * @return EE_Payment_Method_Form
669
+	 * @throws EE_Error
670
+	 * @throws ReflectionException
671
+	 */
672
+	protected function _payment_method_settings(EE_Payment_Method $payment_method): EE_Payment_Method_Form
673
+	{
674
+		// modify the form, so we only have/show fields that will be implemented for this version
675
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
676
+	}
677
+
678
+
679
+	/**
680
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
681
+	 *
682
+	 * @param EE_Form_Section_Proper $form_section
683
+	 * @param string                 $payment_method_name
684
+	 * @return EE_Payment_Method_Form
685
+	 * @throws EE_Error
686
+	 */
687
+	protected function _simplify_form(
688
+		EE_Form_Section_Proper $form_section,
689
+		string $payment_method_name = ''
690
+	): EE_Payment_Method_Form {
691
+		if ($form_section instanceof EE_Payment_Method_Form) {
692
+			$form_section->exclude(
693
+				[
694
+					'PMD_type', // don't want them changing the type
695
+					'PMD_slug', // or the slug (probably never)
696
+					'PMD_wp_user', // or the user's ID
697
+					'Currency', // or the currency, until the rest of EE supports simultaneous currencies
698
+				]
699
+			);
700
+			return $form_section;
701
+		}
702
+		throw new EE_Error(
703
+			sprintf(
704
+				esc_html__(
705
+					'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
706
+					'event_espresso'
707
+				),
708
+				$payment_method_name
709
+			)
710
+		);
711
+	}
712
+
713
+
714
+	/**
715
+	 * _update_payment_method_button
716
+	 *
717
+	 * @access protected
718
+	 * @param EE_Payment_Method $payment_method
719
+	 * @return EE_Form_Section_HTML
720
+	 * @throws EE_Error
721
+	 */
722
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
723
+	{
724
+		$update_button = new EE_Submit_Input(
725
+			[
726
+				'name'       => 'submit',
727
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
728
+				'default'    => sprintf(
729
+					esc_html__('Update %s Payment Settings', 'event_espresso'),
730
+					$payment_method->admin_name()
731
+				),
732
+				'html_label' => EEH_HTML::nbsp(),
733
+			]
734
+		);
735
+		return new EE_Form_Section_HTML(
736
+			EEH_HTML::tr(
737
+				EEH_HTML::th(
738
+				// esc_html__('Update Settings', 'event_espresso'),
739
+					'&nbsp;',
740
+					'',
741
+					'ee-update-' . $payment_method->slug() . '-settings__label'
742
+				) .
743
+				EEH_HTML::td(
744
+					$update_button->get_html_for_input(),
745
+					'',
746
+					'ee-update-' . $payment_method->slug() . '-settings__input'
747
+				),
748
+				'',
749
+				'ee-update-' . $payment_method->slug() . '-settings'
750
+			)
751
+		);
752
+	}
753
+
754
+
755
+	/**
756
+	 * _deactivate_payment_method_button
757
+	 *
758
+	 * @access protected
759
+	 * @param EE_Payment_Method $payment_method
760
+	 * @return EE_Form_Section_HTML
761
+	 */
762
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
763
+	{
764
+		$link_text_and_title = sprintf(
765
+			esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
766
+			$payment_method->admin_name()
767
+		);
768
+		return new EE_Form_Section_HTML(
769
+			EEH_HTML::tr(
770
+				EEH_HTML::th(
771
+				// esc_html__('Deactivate Payment Method', 'event_espresso'),
772
+					'&nbsp;',
773
+					'',
774
+					'ee-deactivate-' . $payment_method->slug() . '-settings__label'
775
+				) .
776
+				EEH_HTML::td(
777
+					EEH_HTML::link(
778
+						EE_Admin_Page::add_query_args_and_nonce(
779
+							[
780
+								'action'         => 'deactivate_payment_method',
781
+								'payment_method' => $payment_method->slug(),
782
+							],
783
+							EE_PAYMENTS_ADMIN_URL
784
+						),
785
+						$link_text_and_title,
786
+						$link_text_and_title,
787
+						'deactivate_' . $payment_method->slug(),
788
+						'button button--secondary'
789
+					),
790
+					'',
791
+					'ee-deactivate-' . $payment_method->slug() . '-settings__input'
792
+				),
793
+				'',
794
+				'ee-deactivate-' . $payment_method->slug() . '-settings'
795
+			)
796
+		);
797
+	}
798
+
799
+
800
+	/**
801
+	 * _activate_payment_method_button
802
+	 *
803
+	 * @access protected
804
+	 * @param EE_Payment_Method $payment_method
805
+	 * @return EE_Form_Section_Proper
806
+	 * @throws EE_Error
807
+	 */
808
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_Proper
809
+	{
810
+		$link_text_and_title = sprintf(
811
+			esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
812
+			$payment_method->admin_name()
813
+		);
814
+		return new EE_Form_Section_Proper(
815
+			[
816
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
817
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
818
+				'action'          => '#',
819
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
820
+				'subsections'     => apply_filters(
821
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
822
+					[
823
+						new EE_Form_Section_HTML(
824
+							EEH_HTML::table(
825
+								EEH_HTML::tr(
826
+									EEH_HTML::td(
827
+										$payment_method->type_obj()->introductory_html(),
828
+										'',
829
+										'',
830
+										'',
831
+										'colspan="2"'
832
+									)
833
+								) .
834
+								EEH_HTML::tr(
835
+									EEH_HTML::th(
836
+										EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
837
+									) .
838
+									EEH_HTML::td(
839
+										EEH_HTML::link(
840
+											EE_Admin_Page::add_query_args_and_nonce(
841
+												[
842
+													'action'              => 'activate_payment_method',
843
+													'payment_method_type' => $payment_method->type(),
844
+												],
845
+												EE_PAYMENTS_ADMIN_URL
846
+											),
847
+											$link_text_and_title,
848
+											$link_text_and_title,
849
+											'activate_' . $payment_method->slug(),
850
+											'button button--primary-alt'
851
+										)
852
+									)
853
+								)
854
+							)
855
+						),
856
+					],
857
+					$payment_method
858
+				),
859
+			]
860
+		);
861
+	}
862
+
863
+
864
+	/**
865
+	 * _fine_print
866
+	 *
867
+	 * @access protected
868
+	 * @return EE_Form_Section_HTML
869
+	 */
870
+	protected function _fine_print(): EE_Form_Section_HTML
871
+	{
872
+		return new EE_Form_Section_HTML(
873
+			EEH_HTML::tr(
874
+				EEH_HTML::th()
875
+				. EEH_HTML::thx()
876
+				. EEH_HTML::td(
877
+					EEH_HTML::p(
878
+						esc_html__('All fields marked with a * are required fields', 'event_espresso'),
879
+						'',
880
+						'grey-text'
881
+					)
882
+				)
883
+			)
884
+		);
885
+	}
886
+
887
+
888
+	/**
889
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
890
+	 *
891
+	 * @throws EE_Error
892
+	 * @throws ReflectionException
893
+	 * @global WP_User $current_user
894
+	 */
895
+	protected function _activate_payment_method()
896
+	{
897
+		if (isset($this->_req_data['payment_method_type'])) {
898
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
899
+			// see if one exists
900
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
901
+			$payment_method = EE_Payment_Method_Manager::instance()
902
+													   ->activate_a_payment_method_of_type($payment_method_type);
903
+			$this->_redirect_after_action(
904
+				1,
905
+				'Payment Method',
906
+				'activated',
907
+				['action' => 'default', 'payment_method' => $payment_method->slug()]
908
+			);
909
+		} else {
910
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
911
+		}
912
+	}
913
+
914
+
915
+	/**
916
+	 * @throws EE_Error
917
+	 * @throws ReflectionException
918
+	 */
919
+	protected function _deactivate_payment_method()
920
+	{
921
+		if (isset($this->_req_data['payment_method'])) {
922
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
923
+			// deactivate it
924
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
925
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
926
+			$this->_redirect_after_action(
927
+				$count_updated,
928
+				'Payment Method',
929
+				'deactivated',
930
+				['action' => 'default', 'payment_method' => $payment_method_slug]
931
+			);
932
+		} else {
933
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', ['action' => 'default']);
934
+		}
935
+	}
936
+
937
+
938
+	/**
939
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
940
+	 * processing because we first need to identify WHICH form was processed and which payment method
941
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
942
+	 * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
943
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
944
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
945
+	 *
946
+	 * @return void
947
+	 * @throws EE_Error
948
+	 * @throws ReflectionException
949
+	 */
950
+	protected function _update_payment_method()
951
+	{
952
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
953
+			// ok let's find which gateway form to use based on the form input
954
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
955
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
956
+			$correct_pmt_form_to_use = null;
957
+			$payment_method          = null;
958
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
959
+				if ($payment_method instanceof EE_Payment_Method) {
960
+					// get the form and simplify it, like what we do when we display it
961
+					$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
962
+					if ($pmt_form->form_data_present_in($this->_req_data)) {
963
+						$correct_pmt_form_to_use = $pmt_form;
964
+						break;
965
+					}
966
+				}
967
+			}
968
+			// if we couldn't find the correct payment method type...
969
+			if (! $correct_pmt_form_to_use) {
970
+				EE_Error::add_error(
971
+					esc_html__(
972
+						"We could not find which payment method type your form submission related to. Please contact support",
973
+						'event_espresso'
974
+					),
975
+					__FILE__,
976
+					__FUNCTION__,
977
+					__LINE__
978
+				);
979
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
980
+			}
981
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
982
+			if ($correct_pmt_form_to_use->is_valid()) {
983
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
984
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
985
+					throw new EE_Error(
986
+						sprintf(
987
+							esc_html__(
988
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
989
+								'event_espresso'
990
+							),
991
+							'payment_method_settings'
992
+						)
993
+					);
994
+				}
995
+				$payment_settings_subform->save();
996
+				/** @var $pm EE_Payment_Method */
997
+				$this->_redirect_after_action(
998
+					true,
999
+					'Payment Method',
1000
+					'updated',
1001
+					['action' => 'default', 'payment_method' => $payment_method->slug()]
1002
+				);
1003
+			} else {
1004
+				EE_Error::add_error(
1005
+					sprintf(
1006
+						esc_html__(
1007
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
1008
+							'event_espresso'
1009
+						),
1010
+						$payment_method instanceof EE_Payment_Method
1011
+							? $payment_method->type_obj()->pretty_name()
1012
+							: esc_html__('"(unknown)"', 'event_espresso')
1013
+					),
1014
+					__FILE__,
1015
+					__FUNCTION__,
1016
+					__LINE__
1017
+				);
1018
+			}
1019
+		}
1020
+	}
1021
+
1022
+
1023
+	/**
1024
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
1025
+	 *
1026
+	 * @throws DomainException
1027
+	 * @throws EE_Error
1028
+	 * @throws InvalidArgumentException
1029
+	 * @throws InvalidDataTypeException
1030
+	 * @throws InvalidInterfaceException
1031
+	 */
1032
+	protected function _payment_settings()
1033
+	{
1034
+		$form = $this->getPaymentSettingsForm();
1035
+		$this->_set_add_edit_form_tags('update_payment_settings');
1036
+		$this->_set_publish_post_box_vars();
1037
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1038
+			$form->get_html_and_js(),
1039
+			'',
1040
+			'padding'
1041
+		);
1042
+		$this->display_admin_page_with_sidebar();
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 *        _update_payment_settings
1048
+	 *
1049
+	 * @access protected
1050
+	 * @return void
1051
+	 * @throws EE_Error
1052
+	 * @throws InvalidArgumentException
1053
+	 * @throws InvalidDataTypeException
1054
+	 * @throws InvalidInterfaceException
1055
+	 */
1056
+	protected function _update_payment_settings()
1057
+	{
1058
+		$form = $this->getPaymentSettingsForm();
1059
+		if ($form->was_submitted($this->_req_data)) {
1060
+			$form->receive_form_submission($this->_req_data);
1061
+			if ($form->is_valid()) {
1062
+				/**
1063
+				 * @var $reg_config EE_Registration_Config
1064
+				 */
1065
+				$loader                                   = LoaderFactory::getLoader();
1066
+				$reg_config                               = $loader->getShared('EE_Registration_Config');
1067
+				$valid_data                               = $form->valid_data();
1068
+				$show_pending_payment_options             = $valid_data['show_pending_payment_options'] ?? null;
1069
+				$reg_config->show_pending_payment_options = $show_pending_payment_options === 'ON';
1070
+				$reg_config->gateway_log_lifespan         = $valid_data['gateway_log_lifespan'];
1071
+			}
1072
+		}
1073
+		EE_Registry::instance()->CFG = apply_filters(
1074
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
1075
+			EE_Registry::instance()->CFG
1076
+		);
1077
+
1078
+		$what    = esc_html__('Payment Settings', 'event_espresso');
1079
+		$success = $this->_update_espresso_configuration(
1080
+			$what,
1081
+			EE_Registry::instance()->CFG,
1082
+			__FILE__,
1083
+			__FUNCTION__,
1084
+			__LINE__
1085
+		);
1086
+		$this->_redirect_after_action(
1087
+			$success,
1088
+			$what,
1089
+			esc_html__('updated', 'event_espresso'),
1090
+			['action' => 'payment_settings']
1091
+		);
1092
+	}
1093
+
1094
+
1095
+	/**
1096
+	 * Gets the form used for updating payment settings
1097
+	 *
1098
+	 * @return EE_Form_Section_Proper
1099
+	 * @throws EE_Error
1100
+	 * @throws InvalidArgumentException
1101
+	 * @throws InvalidDataTypeException
1102
+	 * @throws InvalidInterfaceException
1103
+	 */
1104
+	protected function getPaymentSettingsForm(): EE_Form_Section_Proper
1105
+	{
1106
+		/**
1107
+		 * @var $reg_config EE_Registration_Config
1108
+		 */
1109
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1110
+		return new EE_Form_Section_Proper(
1111
+			[
1112
+				'name'            => 'payment-settings',
1113
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1114
+				'subsections'     => [
1115
+					'show_pending_payment_options' => new EE_Switch_Input(
1116
+						[
1117
+							'default'        => $reg_config->show_pending_payment_options
1118
+								? EE_Switch_Input::OPTION_ON
1119
+								: EE_Switch_Input::OPTION_OFF,
1120
+							'html_name'      => 'show_pending_payment_options',
1121
+							'html_help_text' => esc_html__(
1122
+								"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. ",
1123
+								'event_espresso'
1124
+							),
1125
+						],
1126
+						[
1127
+							EE_Switch_Input::OPTION_OFF => esc_html__(
1128
+								'pending payment options are NOT displayed',
1129
+								'event_espresso'
1130
+							),
1131
+							EE_Switch_Input::OPTION_ON  => esc_html__(
1132
+								'pending payment options are displayed',
1133
+								'event_espresso'
1134
+							),
1135
+						]
1136
+					),
1137
+					'gateway_log_lifespan'         => new EE_Select_Input(
1138
+						$reg_config->gatewayLogLifespanOptions(),
1139
+						[
1140
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1141
+							'html_help_text'  => esc_html__(
1142
+								'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.',
1143
+								'event_espresso'
1144
+							),
1145
+							'default'         => $reg_config->gateway_log_lifespan,
1146
+						]
1147
+					),
1148
+				],
1149
+			]
1150
+		);
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * @throws EE_Error
1156
+	 */
1157
+	protected function _payment_log_overview_list_table()
1158
+	{
1159
+		$this->display_admin_list_table_page_with_sidebar();
1160
+	}
1161
+
1162
+
1163
+	protected function _set_list_table_views_payment_log()
1164
+	{
1165
+		$this->_views = [
1166
+			'all' => [
1167
+				'slug'  => 'all',
1168
+				'label' => esc_html__('View All Logs', 'event_espresso'),
1169
+				'count' => 0,
1170
+			],
1171
+		];
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * @param int  $per_page
1177
+	 * @param int  $current_page
1178
+	 * @param bool $count
1179
+	 * @return array|int
1180
+	 * @throws EE_Error
1181
+	 * @throws ReflectionException
1182
+	 */
1183
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1184
+	{
1185
+		EE_Registry::instance()->load_model('Change_Log');
1186
+		// we may need to do multiple queries (joining differently), so we actually want an array of query params
1187
+		$query_params = [['LOG_type' => EEM_Change_Log::type_gateway]];
1188
+		// check if they've selected a specific payment method
1189
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1190
+			$query_params[0]['OR*pm_or_pay_pm'] = [
1191
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1192
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1193
+			];
1194
+		}
1195
+		// take into account search
1196
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1197
+			$similarity_string                                                              =
1198
+				['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1199
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1200
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1201
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1202
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name']                     = $similarity_string;
1203
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name']               = $similarity_string;
1204
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type']                     = $similarity_string;
1205
+			$query_params[0]['OR*s']['Payment_Method.PMD_name']                             = $similarity_string;
1206
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name']                       = $similarity_string;
1207
+			$query_params[0]['OR*s']['Payment_Method.PMD_type']                             = $similarity_string;
1208
+			$query_params[0]['OR*s']['LOG_message']                                         = $similarity_string;
1209
+		}
1210
+		if (
1211
+			isset($this->_req_data['payment-filter-start-date'])
1212
+			&& isset($this->_req_data['payment-filter-end-date'])
1213
+		) {
1214
+			// add date
1215
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1216
+			$end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1217
+			// make sure our timestamps start and end right at the boundaries for each day
1218
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1219
+			$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1220
+			// convert to timestamps
1221
+			$start_date = strtotime($start_date);
1222
+			$end_date   = strtotime($end_date);
1223
+			// makes sure start date is the lowest value and vice versa
1224
+			$start_date = min($start_date, $end_date);
1225
+			$end_date   = max($start_date, $end_date);
1226
+			// convert for query
1227
+			$start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1228
+				'LOG_time',
1229
+				date('Y-m-d H:i:s', $start_date),
1230
+				'Y-m-d H:i:s'
1231
+			);
1232
+			$end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1233
+				'LOG_time',
1234
+				date('Y-m-d H:i:s', $end_date),
1235
+				'Y-m-d H:i:s'
1236
+			);
1237
+			$query_params[0]['LOG_time'] = ['BETWEEN', [$start_date, $end_date]];
1238
+		}
1239
+		if ($count) {
1240
+			return EEM_Change_Log::instance()->count($query_params);
1241
+		}
1242
+		if (isset($this->_req_data['order'])) {
1243
+			$sort                     = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1244
+				? $this->_req_data['order']
1245
+				: 'DESC';
1246
+			$query_params['order_by'] = ['LOG_time' => $sort];
1247
+		} else {
1248
+			$query_params['order_by'] = ['LOG_time' => 'DESC'];
1249
+		}
1250
+		$offset = ($current_page - 1) * $per_page;
1251
+		if (! isset($this->_req_data['download_results'])) {
1252
+			$query_params['limit'] = [$offset, $per_page];
1253
+		}
1254
+		// now they've requested to instead just download the file instead of viewing it.
1255
+		if (isset($this->_req_data['download_results'])) {
1256
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1257
+			header('Content-Disposition: attachment');
1258
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1259
+			echo '<h1> '
1260
+				 . sprintf(
1261
+					 esc_html__('Payment Logs for %1$s', 'event_espresso'),
1262
+					 esc_url_raw(site_url())
1263
+				 )
1264
+				 . '</h1 >';
1265
+			echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1266
+			echo esc_html(var_export($query_params, true));
1267
+			echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1268
+			echo esc_html(var_export($wpdb_results, true));
1269
+			die;
1270
+		}
1271
+		return EEM_Change_Log::instance()->get_all($query_params);
1272
+	}
1273
+
1274
+
1275
+	/**
1276
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1277
+	 * because we're possibly combining the results from two queries
1278
+	 *
1279
+	 * @param EE_Change_Log $logA
1280
+	 * @param EE_Change_Log $logB
1281
+	 * @return int
1282
+	 * @throws EE_Error
1283
+	 * @throws ReflectionException
1284
+	 */
1285
+	protected function _sort_logs_again($logA, $logB)
1286
+	{
1287
+		$timeA = $logA->get_raw('LOG_time');
1288
+		$timeB = $logB->get_raw('LOG_time');
1289
+		if ($timeA == $timeB) {
1290
+			return 0;
1291
+		}
1292
+		$comparison = $timeA < $timeB
1293
+			? -1
1294
+			: 1;
1295
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1296
+			return $comparison * -1;
1297
+		}
1298
+		return $comparison;
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * @throws EE_Error
1304
+	 * @throws ReflectionException
1305
+	 */
1306
+	protected function _payment_log_details()
1307
+	{
1308
+		EE_Registry::instance()->load_model('Change_Log');
1309
+		/** @var $payment_log EE_Change_Log */
1310
+		$payment_log    = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1311
+		$payment_method = null;
1312
+		$transaction    = null;
1313
+		if ($payment_log instanceof EE_Change_Log) {
1314
+			if ($payment_log->object() instanceof EE_Payment) {
1315
+				$payment_method = $payment_log->object()->payment_method();
1316
+				$transaction    = $payment_log->object()->transaction();
1317
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1318
+				$payment_method = $payment_log->object();
1319
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1320
+				$transaction    = $payment_log->object();
1321
+				$payment_method = $transaction->payment_method();
1322
+			}
1323
+		}
1324
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1325
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1326
+			[
1327
+				'payment_log'    => $payment_log,
1328
+				'payment_method' => $payment_method,
1329
+				'transaction'    => $transaction,
1330
+			],
1331
+			true
1332
+		);
1333
+		$this->display_admin_page_with_no_sidebar();
1334
+	}
1335 1335
 }
Please login to merge, or discard this patch.
Spacing   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
             ),
153 153
             'require_nonce' => false,
154 154
         ];
155
-        $this->_page_config         = [
155
+        $this->_page_config = [
156 156
             'default'          => $payment_method_list_config,
157 157
             'payment_settings' => [
158 158
                 'nav'           => [
@@ -209,10 +209,10 @@  discard block
 block discarded – undo
209 209
             foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
210 210
                 $template_args                              = $config['template_args'] ?? [];
211 211
                 $template_args['admin_page_obj']            = $this;
212
-                $all_pmt_help_tabs_config[ $help_tab_name ] = [
212
+                $all_pmt_help_tabs_config[$help_tab_name] = [
213 213
                     'title'   => $config['title'],
214 214
                     'content' => EEH_Template::display_template(
215
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
215
+                        $payment_method_type->file_folder().'help_tabs/'.$config['filename'].'.help_tab.php',
216 216
                         $template_args,
217 217
                         true
218 218
                     ),
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
         wp_enqueue_style('espresso-ui-theme');
256 256
         wp_register_style(
257 257
             'espresso_payments',
258
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
258
+            EE_PAYMENTS_ASSETS_URL.'ee-payments.css',
259 259
             [],
260 260
             EVENT_ESPRESSO_VERSION
261 261
         );
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
         wp_enqueue_script('ee-text-links');
265 265
         wp_enqueue_script(
266 266
             'espresso_payments',
267
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
267
+            EE_PAYMENTS_ASSETS_URL.'espresso_payments_admin.js',
268 268
             ['ee-datepicker'],
269 269
             EVENT_ESPRESSO_VERSION,
270 270
             true
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
         $table_analysis = LoaderFactory::getShared(TableAnalysis::class);
295 295
         /** @var TableManager $table_manager */
296 296
         $table_manager = LoaderFactory::getShared(TableManager::class);
297
-        if (! $table_analysis->tableExists('esp_payment_method')) {
297
+        if ( ! $table_analysis->tableExists('esp_payment_method')) {
298 298
             $table_manager->createTable(
299 299
                 'esp_payment_method',
300 300
                 "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
                 'InnoDB'
317 317
             );
318 318
         }
319
-        if (! $table_analysis->tableExists('esp_currency_payment_method')) {
319
+        if ( ! $table_analysis->tableExists('esp_currency_payment_method')) {
320 320
             $table_manager->createTable(
321 321
                 'esp_currency_payment_method',
322 322
                 "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
             }
366 366
             // check for any active pms of that type
367 367
             $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
368
-            if (! $payment_method instanceof EE_Payment_Method) {
368
+            if ( ! $payment_method instanceof EE_Payment_Method) {
369 369
                 $payment_method = EE_Payment_Method::new_instance(
370 370
                     [
371 371
                         'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
                     ]
376 376
                 );
377 377
             }
378
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
378
+            $payment_methods[$payment_method->slug()] = $payment_method;
379 379
         }
380 380
         $payment_methods = apply_filters(
381 381
             'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
@@ -385,7 +385,7 @@  discard block
 block discarded – undo
385 385
             if ($payment_method instanceof EE_Payment_Method) {
386 386
                 $this->addMetaBox(
387 387
                 // html id
388
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
388
+                    'espresso_'.$payment_method->slug().'_payment_settings',
389 389
                     // title
390 390
                     sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
391 391
                     // callback
@@ -400,12 +400,12 @@  discard block
 block discarded – undo
400 400
                     ['payment_method' => $payment_method]
401 401
                 );
402 402
                 // setup for tabbed content
403
-                $tabs[ $payment_method->slug() ] = [
403
+                $tabs[$payment_method->slug()] = [
404 404
                     'label' => $payment_method->admin_name(),
405 405
                     'class' => $payment_method->active()
406 406
                         ? 'gateway-active'
407 407
                         : '',
408
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
408
+                    'href'  => 'espresso_'.$payment_method->slug().'_payment_settings',
409 409
                     'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
410 410
                     'slug'  => $payment_method->slug(),
411 411
                     'icon'  => $payment_method->active()
@@ -442,7 +442,7 @@  discard block
 block discarded – undo
442 442
         /** @var EE_Payment_Method $payment_method */
443 443
         $payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
444 444
         // if that didn't work or wasn't provided, find another way to select the current pm
445
-        if (! $this->_verify_payment_method($payment_method)) {
445
+        if ( ! $this->_verify_payment_method($payment_method)) {
446 446
             // like, looking for an active one
447 447
             $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
448 448
             // test that one as well
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
         $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
492 492
             ? $metabox['args']['payment_method']
493 493
             : null;
494
-        if (! $payment_method instanceof EE_Payment_Method) {
494
+        if ( ! $payment_method instanceof EE_Payment_Method) {
495 495
             throw new EE_Error(
496 496
                 esc_html__(
497 497
                     'Payment method metabox setup incorrectly. No Payment method object was supplied',
@@ -507,7 +507,7 @@  discard block
 block discarded – undo
507 507
                 $form->receive_form_submission($this->_req_data);
508 508
             }
509 509
             echo wp_kses(
510
-                $form->form_open() . $form->get_html_and_js() . $form->form_close(),
510
+                $form->form_open().$form->get_html_and_js().$form->form_close(),
511 511
                 AllowedTags::getWithFormTags()
512 512
             );
513 513
         } else {
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
     protected function _generate_payment_method_settings_form(
532 532
         ?EE_Payment_Method $payment_method
533 533
     ): EE_Form_Section_Proper {
534
-        if (! $payment_method instanceof EE_Payment_Method) {
534
+        if ( ! $payment_method instanceof EE_Payment_Method) {
535 535
             return new EE_Form_Section_Proper();
536 536
         }
537 537
         $subsections = apply_filters(
@@ -548,8 +548,8 @@  discard block
 block discarded – undo
548 548
         );
549 549
         return new EE_Form_Section_Proper(
550 550
             [
551
-                'name'            => $payment_method->slug() . '_settings_form',
552
-                'html_id'         => $payment_method->slug() . '_settings_form',
551
+                'name'            => $payment_method->slug().'_settings_form',
552
+                'html_id'         => $payment_method->slug().'_settings_form',
553 553
                 'action'          => EE_Admin_Page::add_query_args_and_nonce(
554 554
                     [
555 555
                         'action'         => 'update_payment_method',
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
      */
575 575
     protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
576 576
     {
577
-        if (! $payment_method->type_obj()->requires_https()) {
577
+        if ( ! $payment_method->type_obj()->requires_https()) {
578 578
             return null;
579 579
         }
580 580
         return new EE_Form_Section_HTML(
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
                             'important-notice'
588 588
                         )
589 589
                     )
590
-                ) .
590
+                ).
591 591
                 EEH_HTML::td(
592 592
                     EEH_HTML::div(
593 593
                         EEH_HTML::strong(
@@ -639,7 +639,7 @@  discard block
 block discarded – undo
639 639
                             'important-notice'
640 640
                         )
641 641
                     )
642
-                ) .
642
+                ).
643 643
                 EEH_HTML::td(
644 644
                     EEH_HTML::div(
645 645
                         EEH_HTML::strong(
@@ -724,7 +724,7 @@  discard block
 block discarded – undo
724 724
         $update_button = new EE_Submit_Input(
725 725
             [
726 726
                 'name'       => 'submit',
727
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
727
+                'html_id'    => 'save_'.$payment_method->slug().'_settings',
728 728
                 'default'    => sprintf(
729 729
                     esc_html__('Update %s Payment Settings', 'event_espresso'),
730 730
                     $payment_method->admin_name()
@@ -738,15 +738,15 @@  discard block
 block discarded – undo
738 738
                 // esc_html__('Update Settings', 'event_espresso'),
739 739
                     '&nbsp;',
740 740
                     '',
741
-                    'ee-update-' . $payment_method->slug() . '-settings__label'
742
-                ) .
741
+                    'ee-update-'.$payment_method->slug().'-settings__label'
742
+                ).
743 743
                 EEH_HTML::td(
744 744
                     $update_button->get_html_for_input(),
745 745
                     '',
746
-                    'ee-update-' . $payment_method->slug() . '-settings__input'
746
+                    'ee-update-'.$payment_method->slug().'-settings__input'
747 747
                 ),
748 748
                 '',
749
-                'ee-update-' . $payment_method->slug() . '-settings'
749
+                'ee-update-'.$payment_method->slug().'-settings'
750 750
             )
751 751
         );
752 752
     }
@@ -771,8 +771,8 @@  discard block
 block discarded – undo
771 771
                 // esc_html__('Deactivate Payment Method', 'event_espresso'),
772 772
                     '&nbsp;',
773 773
                     '',
774
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__label'
775
-                ) .
774
+                    'ee-deactivate-'.$payment_method->slug().'-settings__label'
775
+                ).
776 776
                 EEH_HTML::td(
777 777
                     EEH_HTML::link(
778 778
                         EE_Admin_Page::add_query_args_and_nonce(
@@ -784,14 +784,14 @@  discard block
 block discarded – undo
784 784
                         ),
785 785
                         $link_text_and_title,
786 786
                         $link_text_and_title,
787
-                        'deactivate_' . $payment_method->slug(),
787
+                        'deactivate_'.$payment_method->slug(),
788 788
                         'button button--secondary'
789 789
                     ),
790 790
                     '',
791
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__input'
791
+                    'ee-deactivate-'.$payment_method->slug().'-settings__input'
792 792
                 ),
793 793
                 '',
794
-                'ee-deactivate-' . $payment_method->slug() . '-settings'
794
+                'ee-deactivate-'.$payment_method->slug().'-settings'
795 795
             )
796 796
         );
797 797
     }
@@ -813,8 +813,8 @@  discard block
 block discarded – undo
813 813
         );
814 814
         return new EE_Form_Section_Proper(
815 815
             [
816
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
817
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
816
+                'name'            => 'activate_'.$payment_method->slug().'_settings_form',
817
+                'html_id'         => 'activate_'.$payment_method->slug().'_settings_form',
818 818
                 'action'          => '#',
819 819
                 'layout_strategy' => new EE_Admin_Two_Column_Layout(),
820 820
                 'subsections'     => apply_filters(
@@ -830,11 +830,11 @@  discard block
 block discarded – undo
830 830
                                         '',
831 831
                                         'colspan="2"'
832 832
                                     )
833
-                                ) .
833
+                                ).
834 834
                                 EEH_HTML::tr(
835 835
                                     EEH_HTML::th(
836 836
                                         EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
837
-                                    ) .
837
+                                    ).
838 838
                                     EEH_HTML::td(
839 839
                                         EEH_HTML::link(
840 840
                                             EE_Admin_Page::add_query_args_and_nonce(
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
                                             ),
847 847
                                             $link_text_and_title,
848 848
                                             $link_text_and_title,
849
-                                            'activate_' . $payment_method->slug(),
849
+                                            'activate_'.$payment_method->slug(),
850 850
                                             'button button--primary-alt'
851 851
                                         )
852 852
                                     )
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 }
967 967
             }
968 968
             // if we couldn't find the correct payment method type...
969
-            if (! $correct_pmt_form_to_use) {
969
+            if ( ! $correct_pmt_form_to_use) {
970 970
                 EE_Error::add_error(
971 971
                     esc_html__(
972 972
                         "We could not find which payment method type your form submission related to. Please contact support",
@@ -981,7 +981,7 @@  discard block
 block discarded – undo
981 981
             $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
982 982
             if ($correct_pmt_form_to_use->is_valid()) {
983 983
                 $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
984
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
984
+                if ( ! $payment_settings_subform instanceof EE_Payment_Method_Form) {
985 985
                     throw new EE_Error(
986 986
                         sprintf(
987 987
                             esc_html__(
@@ -1195,7 +1195,7 @@  discard block
 block discarded – undo
1195 1195
         // take into account search
1196 1196
         if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1197 1197
             $similarity_string                                                              =
1198
-                ['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1198
+                ['LIKE', '%'.str_replace("", "%", $this->_req_data['s']).'%'];
1199 1199
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1200 1200
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1201 1201
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
@@ -1215,8 +1215,8 @@  discard block
 block discarded – undo
1215 1215
             $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1216 1216
             $end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1217 1217
             // make sure our timestamps start and end right at the boundaries for each day
1218
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1219
-            $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1218
+            $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
1219
+            $end_date   = date('Y-m-d', strtotime($end_date)).' 23:59:59';
1220 1220
             // convert to timestamps
1221 1221
             $start_date = strtotime($start_date);
1222 1222
             $end_date   = strtotime($end_date);
@@ -1224,12 +1224,12 @@  discard block
 block discarded – undo
1224 1224
             $start_date = min($start_date, $end_date);
1225 1225
             $end_date   = max($start_date, $end_date);
1226 1226
             // convert for query
1227
-            $start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1227
+            $start_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1228 1228
                 'LOG_time',
1229 1229
                 date('Y-m-d H:i:s', $start_date),
1230 1230
                 'Y-m-d H:i:s'
1231 1231
             );
1232
-            $end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1232
+            $end_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1233 1233
                 'LOG_time',
1234 1234
                 date('Y-m-d H:i:s', $end_date),
1235 1235
                 'Y-m-d H:i:s'
@@ -1248,23 +1248,23 @@  discard block
 block discarded – undo
1248 1248
             $query_params['order_by'] = ['LOG_time' => 'DESC'];
1249 1249
         }
1250 1250
         $offset = ($current_page - 1) * $per_page;
1251
-        if (! isset($this->_req_data['download_results'])) {
1251
+        if ( ! isset($this->_req_data['download_results'])) {
1252 1252
             $query_params['limit'] = [$offset, $per_page];
1253 1253
         }
1254 1254
         // now they've requested to instead just download the file instead of viewing it.
1255 1255
         if (isset($this->_req_data['download_results'])) {
1256 1256
             $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1257 1257
             header('Content-Disposition: attachment');
1258
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1258
+            header("Content-Disposition: attachment; filename=ee_payment_logs_for_".sanitize_key(site_url()));
1259 1259
             echo '<h1> '
1260 1260
                  . sprintf(
1261 1261
                      esc_html__('Payment Logs for %1$s', 'event_espresso'),
1262 1262
                      esc_url_raw(site_url())
1263 1263
                  )
1264 1264
                  . '</h1 >';
1265
-            echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1265
+            echo '<h3>'.esc_html__('Query:', 'event_espresso').'</h3>';
1266 1266
             echo esc_html(var_export($query_params, true));
1267
-            echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1267
+            echo '<h3>'.esc_html__('Results:', 'event_espresso').'</h3>';
1268 1268
             echo esc_html(var_export($wpdb_results, true));
1269 1269
             die;
1270 1270
         }
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
             }
1323 1323
         }
1324 1324
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1325
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1325
+            EE_PAYMENTS_TEMPLATE_PATH.'payment_log_details.template.php',
1326 1326
             [
1327 1327
                 'payment_log'    => $payment_log,
1328 1328
                 'payment_method' => $payment_method,
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2973 added lines, -2973 removed lines patch added patch discarded remove patch
@@ -22,2980 +22,2980 @@
 block discarded – undo
22 22
  */
23 23
 class Events_Admin_Page extends EE_Admin_Page_CPT
24 24
 {
25
-    /**
26
-     * primary key for the event model
27
-     */
28
-    private int $EVT_ID = 0;
29
-
30
-    /**
31
-     * This will hold the event object for event_details screen.
32
-     *
33
-     * @var EE_Event|null $_event
34
-     */
35
-    protected ?EE_Event $_event = null;
36
-
37
-    /**
38
-     * This will hold the category object for category_details screen.
39
-     */
40
-    protected ?stdClass $_category = null;
41
-
42
-    protected ?EEM_Event $_event_model = null;
43
-
44
-    /**
45
-     * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
-     */
47
-    protected $_cpt_model_obj;
48
-
49
-    protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
-
51
-    protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
-
53
-
54
-    /**
55
-     * Initialize page props for this admin page group.
56
-     */
57
-    protected function _init_page_props()
58
-    {
59
-        // is there a evt_id in the request?
60
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
-        $this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
-        $this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
-
64
-        $this->page_slug        = EVENTS_PG_SLUG;
65
-        $this->page_label       = EVENTS_LABEL;
66
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels           = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        $this->_page_routes = [
128
-            'default'                       => [
129
-                'func'       => [$this, '_events_overview_list_table'],
130
-                'capability' => 'ee_read_events',
131
-            ],
132
-            'create_new'                    => [
133
-                'func'       => [$this, '_create_new_cpt_item'],
134
-                'capability' => 'ee_edit_events',
135
-            ],
136
-            'edit'                          => [
137
-                'func'       => [$this, '_edit_cpt_item'],
138
-                'capability' => 'ee_edit_event',
139
-                'obj_id'     => $this->EVT_ID,
140
-            ],
141
-            'copy_event'                    => [
142
-                'func'       => [$this, '_copy_events'],
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $this->EVT_ID,
145
-                'noheader'   => true,
146
-            ],
147
-            'trash_event'                   => [
148
-                'func'       => [$this, '_trash_or_restore_event'],
149
-                'args'       => ['event_status' => 'trash'],
150
-                'capability' => 'ee_delete_event',
151
-                'obj_id'     => $this->EVT_ID,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_events'                  => [
155
-                'func'       => [$this, '_trash_or_restore_events'],
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_events',
158
-                'noheader'   => true,
159
-            ],
160
-            'restore_event'                 => [
161
-                'func'       => [$this, '_trash_or_restore_event'],
162
-                'args'       => ['event_status' => 'draft'],
163
-                'capability' => 'ee_delete_event',
164
-                'obj_id'     => $this->EVT_ID,
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_events'                => [
168
-                'func'       => [$this, '_trash_or_restore_events'],
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_events',
171
-                'noheader'   => true,
172
-            ],
173
-            'delete_event'                  => [
174
-                'func'       => [$this, '_delete_event'],
175
-                'capability' => 'ee_delete_event',
176
-                'obj_id'     => $this->EVT_ID,
177
-                'noheader'   => true,
178
-            ],
179
-            'delete_events'                 => [
180
-                'func'       => [$this, '_delete_events'],
181
-                'capability' => 'ee_delete_events',
182
-                'noheader'   => true,
183
-            ],
184
-            'view_report'                   => [
185
-                'func'       => [$this, '_view_report'],
186
-                'capability' => 'ee_edit_events',
187
-            ],
188
-            'default_event_settings'        => [
189
-                'func'       => [$this, '_default_event_settings'],
190
-                'capability' => 'manage_options',
191
-            ],
192
-            'update_default_event_settings' => [
193
-                'func'       => [$this, '_update_default_event_settings'],
194
-                'capability' => 'manage_options',
195
-                'noheader'   => true,
196
-            ],
197
-            'template_settings'             => [
198
-                'func'       => [$this, '_template_settings'],
199
-                'capability' => 'manage_options',
200
-            ],
201
-            // event category tab related
202
-            'add_category'                  => [
203
-                'func'       => [$this, '_category_details'],
204
-                'capability' => 'ee_edit_event_category',
205
-                'args'       => ['view' => 'add'],
206
-            ],
207
-            'edit_category'                 => [
208
-                'func'       => [$this, '_category_details'],
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => ['view' => 'edit'],
211
-            ],
212
-            'delete_categories'             => [
213
-                'func'       => [$this, '_delete_categories'],
214
-                'capability' => 'ee_delete_event_category',
215
-                'noheader'   => true,
216
-            ],
217
-            'delete_category'               => [
218
-                'func'       => [$this, '_delete_categories'],
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ],
222
-            'insert_category'               => [
223
-                'func'       => [$this, '_insert_or_update_category'],
224
-                'args'       => ['new_category' => true],
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ],
228
-            'update_category'               => [
229
-                'func'       => [$this, '_insert_or_update_category'],
230
-                'args'       => ['new_category' => false],
231
-                'capability' => 'ee_edit_event_category',
232
-                'noheader'   => true,
233
-            ],
234
-            'category_list'                 => [
235
-                'func'       => [$this, '_category_list_table'],
236
-                'capability' => 'ee_manage_event_categories',
237
-            ],
238
-            'preview_deletion'              => [
239
-                'func'       => [$this, 'previewDeletion'],
240
-                'capability' => 'ee_delete_events',
241
-            ],
242
-            'confirm_deletion'              => [
243
-                'func'       => [$this, 'confirmDeletion'],
244
-                'capability' => 'ee_delete_events',
245
-                'noheader'   => true,
246
-            ],
247
-        ];
248
-    }
249
-
250
-
251
-    /**
252
-     * Set the _page_config property for this admin page group.
253
-     */
254
-    protected function _set_page_config()
255
-    {
256
-        $post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
-        $this->_page_config = [
259
-            'default'                => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Events_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'events_overview_help_tab'                       => [
268
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
269
-                        'filename' => 'events_overview',
270
-                    ],
271
-                    'events_overview_table_column_headings_help_tab' => [
272
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'events_overview_table_column_headings',
274
-                    ],
275
-                    'events_overview_filters_help_tab'               => [
276
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
-                        'filename' => 'events_overview_filters',
278
-                    ],
279
-                    'events_overview_view_help_tab'                  => [
280
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
-                        'filename' => 'events_overview_views',
282
-                    ],
283
-                    'events_overview_other_help_tab'                 => [
284
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
-                        'filename' => 'events_overview_other',
286
-                    ],
287
-                ],
288
-                'require_nonce' => false,
289
-            ],
290
-            'create_new'             => [
291
-                'nav'           => [
292
-                    'label'      => esc_html__('Add New Event', 'event_espresso'),
293
-                    'icon'       => 'dashicons-plus-alt',
294
-                    'order'      => 15,
295
-                    'persistent' => false,
296
-                ],
297
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
-                'help_tabs'     => [
299
-                    'event_editor_help_tab'                            => [
300
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
301
-                        'filename' => 'event_editor',
302
-                    ],
303
-                    'event_editor_title_richtexteditor_help_tab'       => [
304
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
-                        'filename' => 'event_editor_title_richtexteditor',
306
-                    ],
307
-                    'event_editor_venue_details_help_tab'              => [
308
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
-                        'filename' => 'event_editor_venue_details',
310
-                    ],
311
-                    'event_editor_event_datetimes_help_tab'            => [
312
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
-                        'filename' => 'event_editor_event_datetimes',
314
-                    ],
315
-                    'event_editor_event_tickets_help_tab'              => [
316
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
-                        'filename' => 'event_editor_event_tickets',
318
-                    ],
319
-                    'event_editor_event_registration_options_help_tab' => [
320
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
-                        'filename' => 'event_editor_event_registration_options',
322
-                    ],
323
-                    'event_editor_tags_categories_help_tab'            => [
324
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
-                        'filename' => 'event_editor_tags_categories',
326
-                    ],
327
-                    'event_editor_questions_registrants_help_tab'      => [
328
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
-                        'filename' => 'event_editor_questions_registrants',
330
-                    ],
331
-                    'event_editor_save_new_event_help_tab'             => [
332
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
333
-                        'filename' => 'event_editor_save_new_event',
334
-                    ],
335
-                    'event_editor_other_help_tab'                      => [
336
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
337
-                        'filename' => 'event_editor_other',
338
-                    ],
339
-                ],
340
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
-                'require_nonce' => false,
342
-            ],
343
-            'edit'                   => [
344
-                'nav'           => [
345
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
346
-                    'icon'       => 'dashicons-edit',
347
-                    'order'      => 15,
348
-                    'persistent' => false,
349
-                    'url'        => $post_id
350
-                        ? EE_Admin_Page::add_query_args_and_nonce(
351
-                            ['post' => $post_id, 'action' => 'edit'],
352
-                            $this->_current_page_view_url
353
-                        )
354
-                        : $this->_admin_base_url,
355
-                ],
356
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
-                'help_tabs'     => [
358
-                    'event_editor_help_tab'                            => [
359
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
360
-                        'filename' => 'event_editor',
361
-                    ],
362
-                    'event_editor_title_richtexteditor_help_tab'       => [
363
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
-                        'filename' => 'event_editor_title_richtexteditor',
365
-                    ],
366
-                    'event_editor_venue_details_help_tab'              => [
367
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
-                        'filename' => 'event_editor_venue_details',
369
-                    ],
370
-                    'event_editor_event_datetimes_help_tab'            => [
371
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_datetimes',
373
-                    ],
374
-                    'event_editor_event_tickets_help_tab'              => [
375
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
-                        'filename' => 'event_editor_event_tickets',
377
-                    ],
378
-                    'event_editor_event_registration_options_help_tab' => [
379
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
-                        'filename' => 'event_editor_event_registration_options',
381
-                    ],
382
-                    'event_editor_tags_categories_help_tab'            => [
383
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
-                        'filename' => 'event_editor_tags_categories',
385
-                    ],
386
-                    'event_editor_questions_registrants_help_tab'      => [
387
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
-                        'filename' => 'event_editor_questions_registrants',
389
-                    ],
390
-                    'event_editor_save_new_event_help_tab'             => [
391
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
392
-                        'filename' => 'event_editor_save_new_event',
393
-                    ],
394
-                    'event_editor_other_help_tab'                      => [
395
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
396
-                        'filename' => 'event_editor_other',
397
-                    ],
398
-                ],
399
-                'require_nonce' => false,
400
-            ],
401
-            'default_event_settings' => [
402
-                'nav'           => [
403
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
404
-                    'icon'  => 'dashicons-admin-generic',
405
-                    'order' => 40,
406
-                ],
407
-                'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
-                'labels'        => [
409
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
-                ],
411
-                'help_tabs'     => [
412
-                    'default_settings_help_tab'        => [
413
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
-                        'filename' => 'events_default_settings',
415
-                    ],
416
-                    'default_settings_status_help_tab' => [
417
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
-                        'filename' => 'events_default_settings_status',
419
-                    ],
420
-                    'default_maximum_tickets_help_tab' => [
421
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
-                        'filename' => 'events_default_settings_max_tickets',
423
-                    ],
424
-                ],
425
-                'require_nonce' => false,
426
-            ],
427
-            // template settings
428
-            'template_settings'      => [
429
-                'nav'           => [
430
-                    'label' => esc_html__('Templates', 'event_espresso'),
431
-                    'icon'  => 'dashicons-layout',
432
-                    'order' => 30,
433
-                ],
434
-                'metaboxes'     => $this->_default_espresso_metaboxes,
435
-                'help_tabs'     => [
436
-                    'general_settings_templates_help_tab' => [
437
-                        'title'    => esc_html__('Templates', 'event_espresso'),
438
-                        'filename' => 'general_settings_templates',
439
-                    ],
440
-                ],
441
-                'require_nonce' => false,
442
-            ],
443
-            // event category stuff
444
-            'add_category'           => [
445
-                'nav'           => [
446
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
447
-                    'icon'       => 'dashicons-plus-alt',
448
-                    'order'      => 25,
449
-                    'persistent' => false,
450
-                ],
451
-                'help_tabs'     => [
452
-                    'add_category_help_tab' => [
453
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
-                        'filename' => 'events_add_category',
455
-                    ],
456
-                ],
457
-                'metaboxes'     => ['_publish_post_box'],
458
-                'require_nonce' => false,
459
-            ],
460
-            'edit_category'          => [
461
-                'nav'           => [
462
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
463
-                    'icon'       => 'dashicons-edit',
464
-                    'order'      => 25,
465
-                    'persistent' => false,
466
-                    'url'        => $EVT_CAT_ID
467
-                        ? add_query_arg(
468
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
469
-                            $this->_current_page_view_url
470
-                        )
471
-                        : $this->_admin_base_url,
472
-                ],
473
-                'help_tabs'     => [
474
-                    'edit_category_help_tab' => [
475
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
-                        'filename' => 'events_edit_category',
477
-                    ],
478
-                ],
479
-                'metaboxes'     => ['_publish_post_box'],
480
-                'require_nonce' => false,
481
-            ],
482
-            'category_list'          => [
483
-                'nav'           => [
484
-                    'label' => esc_html__('Categories', 'event_espresso'),
485
-                    'icon'  => 'dashicons-networking',
486
-                    'order' => 20,
487
-                ],
488
-                'list_table'    => 'Event_Categories_Admin_List_Table',
489
-                'help_tabs'     => [
490
-                    'events_categories_help_tab'                       => [
491
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
492
-                        'filename' => 'events_categories',
493
-                    ],
494
-                    'events_categories_table_column_headings_help_tab' => [
495
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
-                        'filename' => 'events_categories_table_column_headings',
497
-                    ],
498
-                    'events_categories_view_help_tab'                  => [
499
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
-                        'filename' => 'events_categories_views',
501
-                    ],
502
-                    'events_categories_other_help_tab'                 => [
503
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
-                        'filename' => 'events_categories_other',
505
-                    ],
506
-                ],
507
-                'metaboxes'     => $this->_default_espresso_metaboxes,
508
-                'require_nonce' => false,
509
-            ],
510
-            'preview_deletion'       => [
511
-                'nav'           => [
512
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
-                    'icon'       => 'dashicons-remove',
514
-                    'order'      => 15,
515
-                    'persistent' => false,
516
-                    'url'        => '',
517
-                ],
518
-                'require_nonce' => false,
519
-            ],
520
-        ];
521
-    }
522
-
523
-
524
-    /**
525
-     * Used to register any global screen options if necessary for every route in this admin page group.
526
-     */
527
-    protected function _add_screen_options()
528
-    {
529
-    }
530
-
531
-
532
-    /**
533
-     * Implementing the screen options for the 'default' route.
534
-     *
535
-     * @throws InvalidArgumentException
536
-     * @throws InvalidDataTypeException
537
-     * @throws InvalidInterfaceException
538
-     */
539
-    protected function _add_screen_options_default()
540
-    {
541
-        $this->_per_page_screen_option();
542
-    }
543
-
544
-
545
-    /**
546
-     * Implementing screen options for the category list route.
547
-     *
548
-     * @throws InvalidArgumentException
549
-     * @throws InvalidDataTypeException
550
-     * @throws InvalidInterfaceException
551
-     */
552
-    protected function _add_screen_options_category_list()
553
-    {
554
-        $page_title              = $this->_admin_page_title;
555
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
-        $this->_per_page_screen_option();
557
-        $this->_admin_page_title = $page_title;
558
-    }
559
-
560
-
561
-    /**
562
-     * Used to register any global feature pointers for the admin page group.
563
-     */
564
-    protected function _add_feature_pointers()
565
-    {
566
-    }
567
-
568
-
569
-    /**
570
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
571
-     */
572
-    public function load_scripts_styles()
573
-    {
574
-        wp_enqueue_style(
575
-            'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
577
-            [],
578
-            EVENT_ESPRESSO_VERSION
579
-        );
580
-        wp_enqueue_style(
581
-            'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
-            [],
584
-            EVENT_ESPRESSO_VERSION
585
-        );
586
-        // scripts
587
-        wp_enqueue_script(
588
-            'event_editor_js',
589
-            EVENTS_ASSETS_URL . 'event_editor.js',
590
-            [
591
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
593
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
594
-            ],
595
-            EVENT_ESPRESSO_VERSION,
596
-            true
597
-        );
598
-    }
599
-
600
-
601
-    /**
602
-     * Enqueuing scripts and styles specific to this view
603
-     */
604
-    public function load_scripts_styles_create_new()
605
-    {
606
-        $this->load_scripts_styles_edit();
607
-    }
608
-
609
-
610
-    /**
611
-     * Enqueuing scripts and styles specific to this view
612
-     */
613
-    public function load_scripts_styles_edit()
614
-    {
615
-        // styles
616
-        wp_enqueue_style('espresso-ui-theme');
617
-        wp_enqueue_style(
618
-            'event-editor-css',
619
-            EVENTS_ASSETS_URL . 'event-editor.css',
620
-            ['ee-admin-css'],
621
-            EVENT_ESPRESSO_VERSION
622
-        );
623
-        // scripts
624
-        if (! $this->admin_config->useAdvancedEditor()) {
625
-            wp_enqueue_script(
626
-                'event-datetime-metabox',
627
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
628
-                ['event_editor_js', 'ee-datepicker'],
629
-                EVENT_ESPRESSO_VERSION
630
-            );
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     * Populating the _views property for the category list table view.
637
-     */
638
-    protected function _set_list_table_views_category_list()
639
-    {
640
-        $this->_views = [
641
-            'all' => [
642
-                'slug'        => 'all',
643
-                'label'       => esc_html__('All', 'event_espresso'),
644
-                'count'       => 0,
645
-                'bulk_action' => [
646
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
647
-                ],
648
-            ],
649
-        ];
650
-    }
651
-
652
-
653
-    /**
654
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
655
-     */
656
-    public function admin_init()
657
-    {
658
-        EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
659
-            esc_html__(
660
-                'Do you really want to delete this image? Please remember to update your event to complete the removal.',
661
-                'event_espresso'
662
-            )
663
-        );
664
-
665
-        EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
666
-            __(
667
-                'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
668
-                'event_espresso'
669
-            )
670
-        );
671
-    }
672
-
673
-
674
-    /**
675
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
676
-     * group.
677
-     */
678
-    public function admin_notices()
679
-    {
680
-    }
681
-
682
-
683
-    /**
684
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
685
-     * this admin page group.
686
-     */
687
-    public function admin_footer_scripts()
688
-    {
689
-    }
690
-
691
-
692
-    /**
693
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
694
-     * warning (via EE_Error::add_error());
695
-     *
696
-     * @param EE_Event|null $event Event object
697
-     * @param string        $req_type
698
-     * @return void
699
-     * @throws EE_Error
700
-     * @throws ReflectionException
701
-     */
702
-    public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703
-    {
704
-        // don't need to do this when processing
705
-        if (! empty($req_type)) {
706
-            return;
707
-        }
708
-        // no event?
709
-        if (! $event instanceof EE_Event) {
710
-            $event = $this->_cpt_model_obj;
711
-        }
712
-        // STILL no event?
713
-        if (! $event instanceof EE_Event) {
714
-            return;
715
-        }
716
-        // don't need to keep calling this
717
-        remove_action(
718
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
719
-            [$this, 'verify_event_edit']
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 ee-help-tab-link">',
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
25
+	/**
26
+	 * primary key for the event model
27
+	 */
28
+	private int $EVT_ID = 0;
29
+
30
+	/**
31
+	 * This will hold the event object for event_details screen.
32
+	 *
33
+	 * @var EE_Event|null $_event
34
+	 */
35
+	protected ?EE_Event $_event = null;
36
+
37
+	/**
38
+	 * This will hold the category object for category_details screen.
39
+	 */
40
+	protected ?stdClass $_category = null;
41
+
42
+	protected ?EEM_Event $_event_model = null;
43
+
44
+	/**
45
+	 * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
+	 */
47
+	protected $_cpt_model_obj;
48
+
49
+	protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
+
51
+	protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
+
53
+
54
+	/**
55
+	 * Initialize page props for this admin page group.
56
+	 */
57
+	protected function _init_page_props()
58
+	{
59
+		// is there a evt_id in the request?
60
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
+		$this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
+		$this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
+
64
+		$this->page_slug        = EVENTS_PG_SLUG;
65
+		$this->page_label       = EVENTS_LABEL;
66
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels           = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		$this->_page_routes = [
128
+			'default'                       => [
129
+				'func'       => [$this, '_events_overview_list_table'],
130
+				'capability' => 'ee_read_events',
131
+			],
132
+			'create_new'                    => [
133
+				'func'       => [$this, '_create_new_cpt_item'],
134
+				'capability' => 'ee_edit_events',
135
+			],
136
+			'edit'                          => [
137
+				'func'       => [$this, '_edit_cpt_item'],
138
+				'capability' => 'ee_edit_event',
139
+				'obj_id'     => $this->EVT_ID,
140
+			],
141
+			'copy_event'                    => [
142
+				'func'       => [$this, '_copy_events'],
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $this->EVT_ID,
145
+				'noheader'   => true,
146
+			],
147
+			'trash_event'                   => [
148
+				'func'       => [$this, '_trash_or_restore_event'],
149
+				'args'       => ['event_status' => 'trash'],
150
+				'capability' => 'ee_delete_event',
151
+				'obj_id'     => $this->EVT_ID,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_events'                  => [
155
+				'func'       => [$this, '_trash_or_restore_events'],
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_events',
158
+				'noheader'   => true,
159
+			],
160
+			'restore_event'                 => [
161
+				'func'       => [$this, '_trash_or_restore_event'],
162
+				'args'       => ['event_status' => 'draft'],
163
+				'capability' => 'ee_delete_event',
164
+				'obj_id'     => $this->EVT_ID,
165
+				'noheader'   => true,
166
+			],
167
+			'restore_events'                => [
168
+				'func'       => [$this, '_trash_or_restore_events'],
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_events',
171
+				'noheader'   => true,
172
+			],
173
+			'delete_event'                  => [
174
+				'func'       => [$this, '_delete_event'],
175
+				'capability' => 'ee_delete_event',
176
+				'obj_id'     => $this->EVT_ID,
177
+				'noheader'   => true,
178
+			],
179
+			'delete_events'                 => [
180
+				'func'       => [$this, '_delete_events'],
181
+				'capability' => 'ee_delete_events',
182
+				'noheader'   => true,
183
+			],
184
+			'view_report'                   => [
185
+				'func'       => [$this, '_view_report'],
186
+				'capability' => 'ee_edit_events',
187
+			],
188
+			'default_event_settings'        => [
189
+				'func'       => [$this, '_default_event_settings'],
190
+				'capability' => 'manage_options',
191
+			],
192
+			'update_default_event_settings' => [
193
+				'func'       => [$this, '_update_default_event_settings'],
194
+				'capability' => 'manage_options',
195
+				'noheader'   => true,
196
+			],
197
+			'template_settings'             => [
198
+				'func'       => [$this, '_template_settings'],
199
+				'capability' => 'manage_options',
200
+			],
201
+			// event category tab related
202
+			'add_category'                  => [
203
+				'func'       => [$this, '_category_details'],
204
+				'capability' => 'ee_edit_event_category',
205
+				'args'       => ['view' => 'add'],
206
+			],
207
+			'edit_category'                 => [
208
+				'func'       => [$this, '_category_details'],
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => ['view' => 'edit'],
211
+			],
212
+			'delete_categories'             => [
213
+				'func'       => [$this, '_delete_categories'],
214
+				'capability' => 'ee_delete_event_category',
215
+				'noheader'   => true,
216
+			],
217
+			'delete_category'               => [
218
+				'func'       => [$this, '_delete_categories'],
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			],
222
+			'insert_category'               => [
223
+				'func'       => [$this, '_insert_or_update_category'],
224
+				'args'       => ['new_category' => true],
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			],
228
+			'update_category'               => [
229
+				'func'       => [$this, '_insert_or_update_category'],
230
+				'args'       => ['new_category' => false],
231
+				'capability' => 'ee_edit_event_category',
232
+				'noheader'   => true,
233
+			],
234
+			'category_list'                 => [
235
+				'func'       => [$this, '_category_list_table'],
236
+				'capability' => 'ee_manage_event_categories',
237
+			],
238
+			'preview_deletion'              => [
239
+				'func'       => [$this, 'previewDeletion'],
240
+				'capability' => 'ee_delete_events',
241
+			],
242
+			'confirm_deletion'              => [
243
+				'func'       => [$this, 'confirmDeletion'],
244
+				'capability' => 'ee_delete_events',
245
+				'noheader'   => true,
246
+			],
247
+		];
248
+	}
249
+
250
+
251
+	/**
252
+	 * Set the _page_config property for this admin page group.
253
+	 */
254
+	protected function _set_page_config()
255
+	{
256
+		$post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
+		$this->_page_config = [
259
+			'default'                => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Events_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'events_overview_help_tab'                       => [
268
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
269
+						'filename' => 'events_overview',
270
+					],
271
+					'events_overview_table_column_headings_help_tab' => [
272
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'events_overview_table_column_headings',
274
+					],
275
+					'events_overview_filters_help_tab'               => [
276
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
+						'filename' => 'events_overview_filters',
278
+					],
279
+					'events_overview_view_help_tab'                  => [
280
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
+						'filename' => 'events_overview_views',
282
+					],
283
+					'events_overview_other_help_tab'                 => [
284
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
+						'filename' => 'events_overview_other',
286
+					],
287
+				],
288
+				'require_nonce' => false,
289
+			],
290
+			'create_new'             => [
291
+				'nav'           => [
292
+					'label'      => esc_html__('Add New Event', 'event_espresso'),
293
+					'icon'       => 'dashicons-plus-alt',
294
+					'order'      => 15,
295
+					'persistent' => false,
296
+				],
297
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
+				'help_tabs'     => [
299
+					'event_editor_help_tab'                            => [
300
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
301
+						'filename' => 'event_editor',
302
+					],
303
+					'event_editor_title_richtexteditor_help_tab'       => [
304
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
+						'filename' => 'event_editor_title_richtexteditor',
306
+					],
307
+					'event_editor_venue_details_help_tab'              => [
308
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
+						'filename' => 'event_editor_venue_details',
310
+					],
311
+					'event_editor_event_datetimes_help_tab'            => [
312
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
+						'filename' => 'event_editor_event_datetimes',
314
+					],
315
+					'event_editor_event_tickets_help_tab'              => [
316
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
+						'filename' => 'event_editor_event_tickets',
318
+					],
319
+					'event_editor_event_registration_options_help_tab' => [
320
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
+						'filename' => 'event_editor_event_registration_options',
322
+					],
323
+					'event_editor_tags_categories_help_tab'            => [
324
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
+						'filename' => 'event_editor_tags_categories',
326
+					],
327
+					'event_editor_questions_registrants_help_tab'      => [
328
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
+						'filename' => 'event_editor_questions_registrants',
330
+					],
331
+					'event_editor_save_new_event_help_tab'             => [
332
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
333
+						'filename' => 'event_editor_save_new_event',
334
+					],
335
+					'event_editor_other_help_tab'                      => [
336
+						'title'    => esc_html__('Event Other', 'event_espresso'),
337
+						'filename' => 'event_editor_other',
338
+					],
339
+				],
340
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
+				'require_nonce' => false,
342
+			],
343
+			'edit'                   => [
344
+				'nav'           => [
345
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
346
+					'icon'       => 'dashicons-edit',
347
+					'order'      => 15,
348
+					'persistent' => false,
349
+					'url'        => $post_id
350
+						? EE_Admin_Page::add_query_args_and_nonce(
351
+							['post' => $post_id, 'action' => 'edit'],
352
+							$this->_current_page_view_url
353
+						)
354
+						: $this->_admin_base_url,
355
+				],
356
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
+				'help_tabs'     => [
358
+					'event_editor_help_tab'                            => [
359
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
360
+						'filename' => 'event_editor',
361
+					],
362
+					'event_editor_title_richtexteditor_help_tab'       => [
363
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
+						'filename' => 'event_editor_title_richtexteditor',
365
+					],
366
+					'event_editor_venue_details_help_tab'              => [
367
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
+						'filename' => 'event_editor_venue_details',
369
+					],
370
+					'event_editor_event_datetimes_help_tab'            => [
371
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
+						'filename' => 'event_editor_event_datetimes',
373
+					],
374
+					'event_editor_event_tickets_help_tab'              => [
375
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
+						'filename' => 'event_editor_event_tickets',
377
+					],
378
+					'event_editor_event_registration_options_help_tab' => [
379
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
+						'filename' => 'event_editor_event_registration_options',
381
+					],
382
+					'event_editor_tags_categories_help_tab'            => [
383
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
+						'filename' => 'event_editor_tags_categories',
385
+					],
386
+					'event_editor_questions_registrants_help_tab'      => [
387
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
+						'filename' => 'event_editor_questions_registrants',
389
+					],
390
+					'event_editor_save_new_event_help_tab'             => [
391
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
392
+						'filename' => 'event_editor_save_new_event',
393
+					],
394
+					'event_editor_other_help_tab'                      => [
395
+						'title'    => esc_html__('Event Other', 'event_espresso'),
396
+						'filename' => 'event_editor_other',
397
+					],
398
+				],
399
+				'require_nonce' => false,
400
+			],
401
+			'default_event_settings' => [
402
+				'nav'           => [
403
+					'label' => esc_html__('Default Settings', 'event_espresso'),
404
+					'icon'  => 'dashicons-admin-generic',
405
+					'order' => 40,
406
+				],
407
+				'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
+				'labels'        => [
409
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
+				],
411
+				'help_tabs'     => [
412
+					'default_settings_help_tab'        => [
413
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
+						'filename' => 'events_default_settings',
415
+					],
416
+					'default_settings_status_help_tab' => [
417
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
+						'filename' => 'events_default_settings_status',
419
+					],
420
+					'default_maximum_tickets_help_tab' => [
421
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
+						'filename' => 'events_default_settings_max_tickets',
423
+					],
424
+				],
425
+				'require_nonce' => false,
426
+			],
427
+			// template settings
428
+			'template_settings'      => [
429
+				'nav'           => [
430
+					'label' => esc_html__('Templates', 'event_espresso'),
431
+					'icon'  => 'dashicons-layout',
432
+					'order' => 30,
433
+				],
434
+				'metaboxes'     => $this->_default_espresso_metaboxes,
435
+				'help_tabs'     => [
436
+					'general_settings_templates_help_tab' => [
437
+						'title'    => esc_html__('Templates', 'event_espresso'),
438
+						'filename' => 'general_settings_templates',
439
+					],
440
+				],
441
+				'require_nonce' => false,
442
+			],
443
+			// event category stuff
444
+			'add_category'           => [
445
+				'nav'           => [
446
+					'label'      => esc_html__('Add Category', 'event_espresso'),
447
+					'icon'       => 'dashicons-plus-alt',
448
+					'order'      => 25,
449
+					'persistent' => false,
450
+				],
451
+				'help_tabs'     => [
452
+					'add_category_help_tab' => [
453
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
+						'filename' => 'events_add_category',
455
+					],
456
+				],
457
+				'metaboxes'     => ['_publish_post_box'],
458
+				'require_nonce' => false,
459
+			],
460
+			'edit_category'          => [
461
+				'nav'           => [
462
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
463
+					'icon'       => 'dashicons-edit',
464
+					'order'      => 25,
465
+					'persistent' => false,
466
+					'url'        => $EVT_CAT_ID
467
+						? add_query_arg(
468
+							['EVT_CAT_ID' => $EVT_CAT_ID],
469
+							$this->_current_page_view_url
470
+						)
471
+						: $this->_admin_base_url,
472
+				],
473
+				'help_tabs'     => [
474
+					'edit_category_help_tab' => [
475
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
+						'filename' => 'events_edit_category',
477
+					],
478
+				],
479
+				'metaboxes'     => ['_publish_post_box'],
480
+				'require_nonce' => false,
481
+			],
482
+			'category_list'          => [
483
+				'nav'           => [
484
+					'label' => esc_html__('Categories', 'event_espresso'),
485
+					'icon'  => 'dashicons-networking',
486
+					'order' => 20,
487
+				],
488
+				'list_table'    => 'Event_Categories_Admin_List_Table',
489
+				'help_tabs'     => [
490
+					'events_categories_help_tab'                       => [
491
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
492
+						'filename' => 'events_categories',
493
+					],
494
+					'events_categories_table_column_headings_help_tab' => [
495
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
+						'filename' => 'events_categories_table_column_headings',
497
+					],
498
+					'events_categories_view_help_tab'                  => [
499
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
+						'filename' => 'events_categories_views',
501
+					],
502
+					'events_categories_other_help_tab'                 => [
503
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
+						'filename' => 'events_categories_other',
505
+					],
506
+				],
507
+				'metaboxes'     => $this->_default_espresso_metaboxes,
508
+				'require_nonce' => false,
509
+			],
510
+			'preview_deletion'       => [
511
+				'nav'           => [
512
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
+					'icon'       => 'dashicons-remove',
514
+					'order'      => 15,
515
+					'persistent' => false,
516
+					'url'        => '',
517
+				],
518
+				'require_nonce' => false,
519
+			],
520
+		];
521
+	}
522
+
523
+
524
+	/**
525
+	 * Used to register any global screen options if necessary for every route in this admin page group.
526
+	 */
527
+	protected function _add_screen_options()
528
+	{
529
+	}
530
+
531
+
532
+	/**
533
+	 * Implementing the screen options for the 'default' route.
534
+	 *
535
+	 * @throws InvalidArgumentException
536
+	 * @throws InvalidDataTypeException
537
+	 * @throws InvalidInterfaceException
538
+	 */
539
+	protected function _add_screen_options_default()
540
+	{
541
+		$this->_per_page_screen_option();
542
+	}
543
+
544
+
545
+	/**
546
+	 * Implementing screen options for the category list route.
547
+	 *
548
+	 * @throws InvalidArgumentException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws InvalidInterfaceException
551
+	 */
552
+	protected function _add_screen_options_category_list()
553
+	{
554
+		$page_title              = $this->_admin_page_title;
555
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
+		$this->_per_page_screen_option();
557
+		$this->_admin_page_title = $page_title;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Used to register any global feature pointers for the admin page group.
563
+	 */
564
+	protected function _add_feature_pointers()
565
+	{
566
+	}
567
+
568
+
569
+	/**
570
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
571
+	 */
572
+	public function load_scripts_styles()
573
+	{
574
+		wp_enqueue_style(
575
+			'events-admin-css',
576
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
577
+			[],
578
+			EVENT_ESPRESSO_VERSION
579
+		);
580
+		wp_enqueue_style(
581
+			'ee-cat-admin',
582
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
+			[],
584
+			EVENT_ESPRESSO_VERSION
585
+		);
586
+		// scripts
587
+		wp_enqueue_script(
588
+			'event_editor_js',
589
+			EVENTS_ASSETS_URL . 'event_editor.js',
590
+			[
591
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
593
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
594
+			],
595
+			EVENT_ESPRESSO_VERSION,
596
+			true
597
+		);
598
+	}
599
+
600
+
601
+	/**
602
+	 * Enqueuing scripts and styles specific to this view
603
+	 */
604
+	public function load_scripts_styles_create_new()
605
+	{
606
+		$this->load_scripts_styles_edit();
607
+	}
608
+
609
+
610
+	/**
611
+	 * Enqueuing scripts and styles specific to this view
612
+	 */
613
+	public function load_scripts_styles_edit()
614
+	{
615
+		// styles
616
+		wp_enqueue_style('espresso-ui-theme');
617
+		wp_enqueue_style(
618
+			'event-editor-css',
619
+			EVENTS_ASSETS_URL . 'event-editor.css',
620
+			['ee-admin-css'],
621
+			EVENT_ESPRESSO_VERSION
622
+		);
623
+		// scripts
624
+		if (! $this->admin_config->useAdvancedEditor()) {
625
+			wp_enqueue_script(
626
+				'event-datetime-metabox',
627
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
628
+				['event_editor_js', 'ee-datepicker'],
629
+				EVENT_ESPRESSO_VERSION
630
+			);
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 * Populating the _views property for the category list table view.
637
+	 */
638
+	protected function _set_list_table_views_category_list()
639
+	{
640
+		$this->_views = [
641
+			'all' => [
642
+				'slug'        => 'all',
643
+				'label'       => esc_html__('All', 'event_espresso'),
644
+				'count'       => 0,
645
+				'bulk_action' => [
646
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
647
+				],
648
+			],
649
+		];
650
+	}
651
+
652
+
653
+	/**
654
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
655
+	 */
656
+	public function admin_init()
657
+	{
658
+		EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
659
+			esc_html__(
660
+				'Do you really want to delete this image? Please remember to update your event to complete the removal.',
661
+				'event_espresso'
662
+			)
663
+		);
664
+
665
+		EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
666
+			__(
667
+				'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
668
+				'event_espresso'
669
+			)
670
+		);
671
+	}
672
+
673
+
674
+	/**
675
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
676
+	 * group.
677
+	 */
678
+	public function admin_notices()
679
+	{
680
+	}
681
+
682
+
683
+	/**
684
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
685
+	 * this admin page group.
686
+	 */
687
+	public function admin_footer_scripts()
688
+	{
689
+	}
690
+
691
+
692
+	/**
693
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
694
+	 * warning (via EE_Error::add_error());
695
+	 *
696
+	 * @param EE_Event|null $event Event object
697
+	 * @param string        $req_type
698
+	 * @return void
699
+	 * @throws EE_Error
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703
+	{
704
+		// don't need to do this when processing
705
+		if (! empty($req_type)) {
706
+			return;
707
+		}
708
+		// no event?
709
+		if (! $event instanceof EE_Event) {
710
+			$event = $this->_cpt_model_obj;
711
+		}
712
+		// STILL no event?
713
+		if (! $event instanceof EE_Event) {
714
+			return;
715
+		}
716
+		// don't need to keep calling this
717
+		remove_action(
718
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
719
+			[$this, 'verify_event_edit']
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 ee-help-tab-link">',
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
+	 * @throws ReflectionException
802
+	 */
803
+	protected function _create_new_cpt_item()
804
+	{
805
+		$has_timezone_string = get_option('timezone_string');
806
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
807
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808
+			EE_Error::add_attention(
809
+				sprintf(
810
+					esc_html__(
811
+						'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',
812
+						'event_espresso'
813
+					),
814
+					'<br>',
815
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
816
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
817
+					. '</select>',
818
+					'<button class="button button--secondary timezone-submit">',
819
+					'</button><span class="spinner"></span>'
820
+				),
821
+				__FILE__,
822
+				__FUNCTION__,
823
+				__LINE__
824
+			);
825
+		}
826
+		parent::_create_new_cpt_item();
827
+	}
828
+
829
+
830
+	/**
831
+	 * Sets the _views property for the default route in this admin page group.
832
+	 */
833
+	protected function _set_list_table_views_default()
834
+	{
835
+		$this->_views = [
836
+			'all'   => [
837
+				'slug'        => 'all',
838
+				'label'       => esc_html__('View All Events', 'event_espresso'),
839
+				'count'       => 0,
840
+				'bulk_action' => [
841
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
842
+				],
843
+			],
844
+			'draft' => [
845
+				'slug'        => 'draft',
846
+				'label'       => esc_html__('Draft', 'event_espresso'),
847
+				'count'       => 0,
848
+				'bulk_action' => [
849
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
850
+				],
851
+			],
852
+		];
853
+		if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
854
+			$this->_views['trash'] = [
855
+				'slug'        => 'trash',
856
+				'label'       => esc_html__('Trash', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => [
859
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
860
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
861
+				],
862
+			];
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Provides the legend item array for the default list table view.
869
+	 *
870
+	 * @return array
871
+	 * @throws EE_Error
872
+	 * @throws EE_Error
873
+	 */
874
+	protected function _event_legend_items(): array
875
+	{
876
+		$items    = [
877
+			'view_details'   => [
878
+				'class' => 'dashicons dashicons-visibility',
879
+				'desc'  => esc_html__('View Event', 'event_espresso'),
880
+			],
881
+			'edit_event'     => [
882
+				'class' => 'dashicons dashicons-calendar-alt',
883
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
884
+			],
885
+			'view_attendees' => [
886
+				'class' => 'dashicons dashicons-groups',
887
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
888
+			],
889
+		];
890
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891
+		$statuses = [
892
+			'sold_out_status'  => [
893
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
894
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895
+			],
896
+			'active_status'    => [
897
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
898
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899
+			],
900
+			'upcoming_status'  => [
901
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
902
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903
+			],
904
+			'postponed_status' => [
905
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
906
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907
+			],
908
+			'cancelled_status' => [
909
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
910
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911
+			],
912
+			'expired_status'   => [
913
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
914
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915
+			],
916
+			'inactive_status'  => [
917
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
918
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919
+			],
920
+		];
921
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
922
+		return array_merge($items, $statuses);
923
+	}
924
+
925
+
926
+	/**
927
+	 * @return EEM_Event
928
+	 * @throws EE_Error
929
+	 * @throws InvalidArgumentException
930
+	 * @throws InvalidDataTypeException
931
+	 * @throws InvalidInterfaceException
932
+	 * @throws ReflectionException
933
+	 */
934
+	private function _event_model(): EEM_Event
935
+	{
936
+		if (! $this->_event_model instanceof EEM_Event) {
937
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
938
+		}
939
+		return $this->_event_model;
940
+	}
941
+
942
+
943
+	/**
944
+	 * Adds extra buttons to the WP CPT permalink field row.
945
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
946
+	 *
947
+	 * @param string      $return    the current html
948
+	 * @param int         $id        the post id for the page
949
+	 * @param string|null $new_title What the title is
950
+	 * @param string|null $new_slug  what the slug is
951
+	 * @return string            The new html string for the permalink area
952
+	 * @deprecated 5.0.0.p
953
+	 * @see        TicketSelectorShortcodeButton::addButton
954
+	 */
955
+	public function extra_permalink_field_buttons(
956
+		string $return,
957
+		int $id,
958
+		?string $new_title,
959
+		?string $new_slug
960
+	): string {
961
+		return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
962
+	}
963
+
964
+
965
+	/**
966
+	 * _events_overview_list_table
967
+	 * This contains the logic for showing the events_overview list
968
+	 *
969
+	 * @access protected
970
+	 * @return void
971
+	 * @throws DomainException
972
+	 * @throws EE_Error
973
+	 * @throws InvalidArgumentException
974
+	 * @throws InvalidDataTypeException
975
+	 * @throws InvalidInterfaceException
976
+	 */
977
+	protected function _events_overview_list_table()
978
+	{
979
+		$after_list_table = [];
980
+		$links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
981
+		$links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
982
+		$links_html       .= EEH_HTML::div(
983
+			EEH_Template::get_button_or_link(
984
+				get_post_type_archive_link(EspressoPostType::EVENTS),
985
+				esc_html__('View Event Archive Page', 'event_espresso'),
986
+				'button button--small button--secondary'
987
+			),
988
+			'',
989
+			'ee-admin-button-row ee-admin-button-row--align-start'
990
+		);
991
+		$links_html       .= EEH_HTML::divx();
992
+
993
+		$after_list_table['view_event_list_button'] = $links_html;
994
+
995
+		$after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
+		$this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
997
+				'create_new',
998
+				'add',
999
+				[],
1000
+				'add-new-h2'
1001
+			);
1002
+
1003
+		$this->_template_args['after_list_table'] = array_merge(
1004
+			(array) $this->_template_args['after_list_table'],
1005
+			$after_list_table
1006
+		);
1007
+		$this->display_admin_list_table_page_with_no_sidebar();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * this allows for extra misc actions in the default WP publish box
1013
+	 *
1014
+	 * @return void
1015
+	 * @throws DomainException
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 * @throws ReflectionException
1021
+	 */
1022
+	public function extra_misc_actions_publish_box()
1023
+	{
1024
+		$this->_generate_publish_box_extra_content();
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
+	 * saved.
1031
+	 * Typically you would use this to save any additional data.
1032
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
+	 * ALSO very important.  When a post transitions from scheduled to published,
1034
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1036
+	 *
1037
+	 * @access protected
1038
+	 * @abstract
1039
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1040
+	 * @param WP_Post $post    The post object of the cpt that was saved.
1041
+	 * @return void
1042
+	 * @throws EE_Error
1043
+	 * @throws InvalidArgumentException
1044
+	 * @throws InvalidDataTypeException
1045
+	 * @throws InvalidInterfaceException
1046
+	 * @throws ReflectionException
1047
+	 */
1048
+	protected function _insert_update_cpt_item($post_id, $post)
1049
+	{
1050
+		if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1051
+			// get out we're not processing an event save.
1052
+			return;
1053
+		}
1054
+		$event_values = [
1055
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1056
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1057
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058
+		];
1059
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1062
+				'display_ticket_selector',
1063
+				false,
1064
+				'bool'
1065
+			);
1066
+			$event_values['EVT_additional_limit']            = min(
1067
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068
+				$this->request->getRequestParam(
1069
+					'additional_limit',
1070
+					EEM_Event::get_default_additional_limit(),
1071
+					'int'
1072
+				)
1073
+			);
1074
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1075
+				'EVT_default_registration_status',
1076
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1077
+			);
1078
+
1079
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1080
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1081
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1082
+		} elseif ($post instanceof WP_Post) {
1083
+			$event_values['EVT_name'] = $post->post_title;
1084
+			$event_values['EVT_desc'] = $post->post_content;
1085
+		}
1086
+		// update event
1087
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
+		// get event_object for other metaboxes...
1089
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
+		// i have to set up where conditions to override the filters in the model
1091
+		// that filter out auto-draft and inherit statuses so we GET the inherit id!
1092
+		/** @var EE_Event $event */
1093
+		$event = $this->_event_model()->get_one(
1094
+			[
1095
+				[
1096
+					$this->_event_model()->primary_key_name() => $post_id,
1097
+					'OR'                                      => [
1098
+						'status'   => $post->post_status,
1099
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1100
+						// but the returned object here has a status of "publish", so use the original post status as well
1101
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1102
+					],
1103
+					'status' => ['NOT IN', ['auto-draft']],
1104
+				],
1105
+			]
1106
+		);
1107
+
1108
+		if (! $event instanceof EE_Event) {
1109
+			return;
1110
+		}
1111
+
1112
+		// the following are default callbacks for event attachment updates
1113
+		// that can be overridden by caffeinated functionality and/or addons.
1114
+		$event_update_callbacks = [];
1115
+		if (! $this->admin_config->useAdvancedEditor()) {
1116
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118
+		}
1119
+		$event_update_callbacks = apply_filters(
1120
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1121
+			$event_update_callbacks
1122
+		);
1123
+
1124
+		$att_success = true;
1125
+		foreach ($event_update_callbacks as $e_callback) {
1126
+			$_success = is_callable($e_callback)
1127
+				? $e_callback($event, $this->request->requestParams())
1128
+				: false;
1129
+			// if ANY of these updates fail then we want the appropriate global error message
1130
+			$att_success = $_success !== false ? $att_success : false;
1131
+		}
1132
+		// any errors?
1133
+		if ($success && $att_success === false) {
1134
+			EE_Error::add_error(
1135
+				esc_html__(
1136
+					'Event Details saved successfully but something went wrong with saving attachments.',
1137
+					'event_espresso'
1138
+				),
1139
+				__FILE__,
1140
+				__FUNCTION__,
1141
+				__LINE__
1142
+			);
1143
+		} elseif ($success === false) {
1144
+			EE_Error::add_error(
1145
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1146
+				__FILE__,
1147
+				__FUNCTION__,
1148
+				__LINE__
1149
+			);
1150
+		}
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * @param int $post_id
1156
+	 * @param int $revision_id
1157
+	 * @throws EE_Error
1158
+	 * @throws EE_Error
1159
+	 * @throws ReflectionException
1160
+	 * @see parent::restore_item()
1161
+	 */
1162
+	protected function _restore_cpt_item(int $post_id, int $revision_id)
1163
+	{
1164
+		// copy existing event meta to new post
1165
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1166
+		if ($post_evt instanceof EE_Event) {
1167
+			// meta revision restore
1168
+			$post_evt->restore_revision($revision_id);
1169
+			// related objs restore
1170
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1171
+		}
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * Attach the venue to the Event
1177
+	 *
1178
+	 * @param EE_Event $event Event Object to add the venue to
1179
+	 * @param array    $data  The request data from the form
1180
+	 * @return bool           Success or fail.
1181
+	 * @throws EE_Error
1182
+	 * @throws ReflectionException
1183
+	 */
1184
+	protected function _default_venue_update(EE_Event $event, array $data): bool
1185
+	{
1186
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1187
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1188
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189
+		// very important.  If we don't have a venue name...
1190
+		// then we'll get out because not necessary to create empty venue
1191
+		if (empty($data['venue_title'])) {
1192
+			return false;
1193
+		}
1194
+		$venue_array = [
1195
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1196
+			'VNU_name'            => $data['venue_title'],
1197
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1198
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1199
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1200
+				? $data['venue_short_description']
1201
+				: null,
1202
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1203
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1204
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1205
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1206
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1207
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1208
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1209
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1210
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1211
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1212
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1213
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1214
+			'status'              => 'publish',
1215
+		];
1216
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
+		if (! empty($venue_id)) {
1218
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1219
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1220
+			// we've gotta make sure that the venue is always attached to a revision..
1221
+			// add_relation_to should take care of making sure that the relation is already present.
1222
+			$event->_add_relation_to($venue_id, 'Venue');
1223
+			return $rows_affected > 0;
1224
+		}
1225
+		// we insert the venue
1226
+		$venue_id = $venue_model->insert($venue_array);
1227
+		$event->_add_relation_to($venue_id, 'Venue');
1228
+		return ! empty($venue_id);
1229
+		// when we have the ancestor come in it's already been handled by the revision save.
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1235
+	 *
1236
+	 * @param EE_Event $event The Event object we're attaching data to
1237
+	 * @param array    $data  The request data from the form
1238
+	 * @return array
1239
+	 * @throws EE_Error
1240
+	 * @throws ReflectionException
1241
+	 * @throws Exception
1242
+	 */
1243
+	protected function _default_tickets_update(EE_Event $event, array $data): array
1244
+	{
1245
+		if ($this->admin_config->useAdvancedEditor()) {
1246
+			return [];
1247
+		}
1248
+		$datetime       = null;
1249
+		$saved_tickets  = [];
1250
+		$event_timezone = $event->get_timezone();
1251
+		$date_formats   = ['Y-m-d', 'h:i a'];
1252
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1253
+			// trim all values to ensure any excess whitespace is removed.
1254
+			$datetime_data                = array_map('trim', $datetime_data);
1255
+			$datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1256
+					? $datetime_data['DTT_EVT_end']
1257
+					: $datetime_data['DTT_EVT_start'];
1258
+			$datetime_values              = [
1259
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1260
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1261
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1262
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1263
+				'DTT_order'     => $row,
1264
+			];
1265
+			// if we have an id then let's get existing object first and then set the new values.
1266
+			//  Otherwise we instantiate a new object for save.
1267
+			if (! empty($datetime_data['DTT_ID'])) {
1268
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
+				if (! $datetime instanceof EE_Datetime) {
1270
+					throw new RuntimeException(
1271
+						sprintf(
1272
+							esc_html__(
1273
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1274
+								'event_espresso'
1275
+							),
1276
+							$datetime_data['DTT_ID']
1277
+						)
1278
+					);
1279
+				}
1280
+				$datetime->set_date_format($date_formats[0]);
1281
+				$datetime->set_time_format($date_formats[1]);
1282
+				foreach ($datetime_values as $field => $value) {
1283
+					$datetime->set($field, $value);
1284
+				}
1285
+			} else {
1286
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287
+			}
1288
+			if (! $datetime instanceof EE_Datetime) {
1289
+				throw new RuntimeException(
1290
+					sprintf(
1291
+						esc_html__(
1292
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1293
+							'event_espresso'
1294
+						),
1295
+						print_r($datetime_values, true)
1296
+					)
1297
+				);
1298
+			}
1299
+			// before going any further make sure our dates are setup correctly
1300
+			// so that the end date is always equal or greater than the start date.
1301
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1302
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1303
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1304
+			}
1305
+			$datetime->save();
1306
+			$event->_add_relation_to($datetime, 'Datetime');
1307
+		}
1308
+		// no datetimes get deleted so we don't do any of that logic here.
1309
+		// update tickets next
1310
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1311
+
1312
+		// set up some default start and end dates in case those are not present in the incoming data
1313
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1315
+		// use the start date of the first datetime for the end date
1316
+		$first_datetime   = $event->first_datetime();
1317
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1318
+
1319
+		// now process the incoming data
1320
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321
+			$update_prices = false;
1322
+			$ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1323
+			// trim inputs to ensure any excess whitespace is removed.
1324
+			$ticket_data   = array_map('trim', $ticket_data);
1325
+			$ticket_values = [
1326
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1327
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1328
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1329
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1330
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1331
+					? $ticket_data['TKT_start_date']
1332
+					: $default_start_date,
1333
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1334
+					? $ticket_data['TKT_end_date']
1335
+					: $default_end_date,
1336
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1337
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1338
+					? $ticket_data['TKT_qty']
1339
+					: EE_INF,
1340
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1341
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1342
+					? $ticket_data['TKT_uses']
1343
+					: EE_INF,
1344
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1345
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1346
+				'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1347
+				'TKT_price'       => (float) $ticket_price,
1348
+				'TKT_row'         => $row,
1349
+			];
1350
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1351
+			// which means in turn that the prices will become new prices as well.
1352
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1353
+				$ticket_values['TKT_ID']         = 0;
1354
+				$ticket_values['TKT_is_default'] = 0;
1355
+				$update_prices                   = true;
1356
+			}
1357
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1358
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1359
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1361
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
+			if (! empty($ticket_data['TKT_ID'])) {
1363
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
+				if (! $existing_ticket instanceof EE_Ticket) {
1365
+					throw new RuntimeException(
1366
+						sprintf(
1367
+							esc_html__(
1368
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1369
+								'event_espresso'
1370
+							),
1371
+							$ticket_data['TKT_ID']
1372
+						)
1373
+					);
1374
+				}
1375
+				$ticket_sold = $existing_ticket->count_related(
1376
+						'Registration',
1377
+						[
1378
+							[
1379
+								'STS_ID' => [
1380
+									'NOT IN',
1381
+									[RegStatus::INCOMPLETE],
1382
+								],
1383
+							],
1384
+						]
1385
+					) > 0;
1386
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1387
+				// if they are different then we create a new ticket (if $ticket_sold)
1388
+				// if they aren't different then we go ahead and modify existing ticket.
1389
+				$create_new_ticket = $ticket_sold
1390
+									 && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1391
+									 && ! $existing_ticket->deleted();
1392
+				$existing_ticket->set_date_format($date_formats[0]);
1393
+				$existing_ticket->set_time_format($date_formats[1]);
1394
+				// set new values
1395
+				foreach ($ticket_values as $field => $value) {
1396
+					if ($field == 'TKT_qty') {
1397
+						$existing_ticket->set_qty($value);
1398
+					} elseif ($field == 'TKT_price') {
1399
+						$existing_ticket->set('TKT_price', $ticket_price);
1400
+					} else {
1401
+						$existing_ticket->set($field, $value);
1402
+					}
1403
+				}
1404
+				$ticket = $existing_ticket;
1405
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1406
+				//  Otherwise we have to create a new ticket.
1407
+				if ($create_new_ticket) {
1408
+					// archive the old ticket first
1409
+					$existing_ticket->set('TKT_deleted', 1);
1410
+					$existing_ticket->save();
1411
+					// make sure this ticket is still recorded in our $saved_tickets
1412
+					// so we don't run it through the regular trash routine.
1413
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1414
+					// create new ticket that's a copy of the existing except,
1415
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1416
+					$new_ticket = clone $existing_ticket;
1417
+					$new_ticket->set('TKT_ID', 0);
1418
+					$new_ticket->set('TKT_deleted', 0);
1419
+					$new_ticket->set('TKT_sold', 0);
1420
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1421
+					$update_prices = true;
1422
+					$ticket        = $new_ticket;
1423
+				}
1424
+			} else {
1425
+				// no TKT_id so a new ticket
1426
+				$ticket_values['TKT_price'] = $ticket_price;
1427
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428
+				$update_prices              = true;
1429
+			}
1430
+			if (! $ticket instanceof EE_Ticket) {
1431
+				throw new RuntimeException(
1432
+					sprintf(
1433
+						esc_html__(
1434
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1435
+							'event_espresso'
1436
+						),
1437
+						print_r($ticket_values, true)
1438
+					)
1439
+				);
1440
+			}
1441
+			// cap ticket qty by datetime reg limits
1442
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1443
+			// update ticket.
1444
+			$ticket->save();
1445
+			// before going any further make sure our dates are setup correctly
1446
+			// so that the end date is always equal or greater than the start date.
1447
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1448
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1449
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1450
+				$ticket->save();
1451
+			}
1452
+			// initially let's add the ticket to the datetime
1453
+			$datetime->_add_relation_to($ticket, 'Ticket');
1454
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1455
+			// add prices to ticket
1456
+			$prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
+				? $data['edit_prices'][ $row ]
1458
+				: [];
1459
+			$this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460
+		}
1461
+		// however now we need to handle permanently deleting tickets via the ui.
1462
+		// Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1463
+		// However, it does allow for deleting tickets that have no tickets sold,
1464
+		// in which case we want to get rid of permanently because there is no need to save in db.
1465
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1466
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1467
+		foreach ($tickets_removed as $id) {
1468
+			$id = absint($id);
1469
+			// get the ticket for this id
1470
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1472
+				continue;
1473
+			}
1474
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1475
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1476
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1477
+			foreach ($related_datetimes as $related_datetime) {
1478
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1479
+			}
1480
+			// need to do the same for prices (except these prices can also be deleted because again,
1481
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1482
+			$ticket_to_remove->delete_related_permanently('Price');
1483
+			// finally let's delete this ticket
1484
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1485
+			$ticket_to_remove->delete_permanently();
1486
+		}
1487
+		return [$datetime, $saved_tickets];
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * This attaches a list of given prices to a ticket.
1493
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1494
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1495
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1496
+	 *
1497
+	 * @access  private
1498
+	 * @param array     $prices_data Array of prices from the form.
1499
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1500
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1501
+	 * @return  void
1502
+	 * @throws EE_Error
1503
+	 * @throws ReflectionException
1504
+	 */
1505
+	private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1506
+	{
1507
+		$timezone = $ticket->get_timezone();
1508
+		foreach ($prices_data as $row => $price_data) {
1509
+			$price_values = [
1510
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1511
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1512
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1513
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1514
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1515
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1516
+				'PRC_order'      => $row,
1517
+			];
1518
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1519
+				$price_values['PRC_ID'] = 0;
1520
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1521
+			} else {
1522
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1523
+				// update this price with new values
1524
+				foreach ($price_values as $field => $new_price) {
1525
+					$price->set($field, $new_price);
1526
+				}
1527
+			}
1528
+			if (! $price instanceof EE_Price) {
1529
+				throw new RuntimeException(
1530
+					sprintf(
1531
+						esc_html__(
1532
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1533
+							'event_espresso'
1534
+						),
1535
+						print_r($price_values, true)
1536
+					)
1537
+				);
1538
+			}
1539
+			$price->save();
1540
+			$ticket->_add_relation_to($price, 'Price');
1541
+		}
1542
+	}
1543
+
1544
+
1545
+	/**
1546
+	 * Add in our autosave ajax handlers
1547
+	 */
1548
+	protected function _ee_autosave_create_new()
1549
+	{
1550
+	}
1551
+
1552
+
1553
+	/**
1554
+	 * More autosave handlers.
1555
+	 */
1556
+	protected function _ee_autosave_edit()
1557
+	{
1558
+	}
1559
+
1560
+
1561
+	/**
1562
+	 * @throws EE_Error
1563
+	 * @throws ReflectionException
1564
+	 */
1565
+	private function _generate_publish_box_extra_content()
1566
+	{
1567
+		// load formatter helper
1568
+		// args for getting related registrations
1569
+		$approved_query_args        = [
1570
+			[
1571
+				'REG_deleted' => 0,
1572
+				'STS_ID'      => RegStatus::APPROVED,
1573
+			],
1574
+		];
1575
+		$not_approved_query_args    = [
1576
+			[
1577
+				'REG_deleted' => 0,
1578
+				'STS_ID'      => RegStatus::AWAITING_REVIEW,
1579
+			],
1580
+		];
1581
+		$pending_payment_query_args = [
1582
+			[
1583
+				'REG_deleted' => 0,
1584
+				'STS_ID'      => RegStatus::PENDING_PAYMENT,
1585
+			],
1586
+		];
1587
+		// publish box
1588
+		$publish_box_extra_args = [
1589
+			'view_approved_reg_url'        => add_query_arg(
1590
+				[
1591
+					'action'      => 'default',
1592
+					'event_id'    => $this->_cpt_model_obj->ID(),
1593
+					'_reg_status' => RegStatus::APPROVED,
1594
+					'use_filters' => true,
1595
+				],
1596
+				REG_ADMIN_URL
1597
+			),
1598
+			'view_not_approved_reg_url'    => add_query_arg(
1599
+				[
1600
+					'action'      => 'default',
1601
+					'event_id'    => $this->_cpt_model_obj->ID(),
1602
+					'_reg_status' => RegStatus::AWAITING_REVIEW,
1603
+					'use_filters' => true,
1604
+				],
1605
+				REG_ADMIN_URL
1606
+			),
1607
+			'view_pending_payment_reg_url' => add_query_arg(
1608
+				[
1609
+					'action'      => 'default',
1610
+					'event_id'    => $this->_cpt_model_obj->ID(),
1611
+					'_reg_status' => RegStatus::PENDING_PAYMENT,
1612
+					'use_filters' => true,
1613
+				],
1614
+				REG_ADMIN_URL
1615
+			),
1616
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1617
+				'Registration',
1618
+				$approved_query_args
1619
+			),
1620
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1621
+				'Registration',
1622
+				$not_approved_query_args
1623
+			),
1624
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1625
+				'Registration',
1626
+				$pending_payment_query_args
1627
+			),
1628
+			'misc_pub_section_class'       => apply_filters(
1629
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1630
+				'misc-pub-section'
1631
+			),
1632
+		];
1633
+		ob_start();
1634
+		do_action(
1635
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1636
+			$this->_cpt_model_obj
1637
+		);
1638
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639
+		// load template
1640
+		EEH_Template::display_template(
1641
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1642
+			$publish_box_extra_args
1643
+		);
1644
+	}
1645
+
1646
+
1647
+	/**
1648
+	 * @return EE_Event
1649
+	 */
1650
+	public function get_event_object()
1651
+	{
1652
+		return $this->_cpt_model_obj;
1653
+	}
1654
+
1655
+
1656
+
1657
+
1658
+	/** METABOXES * */
1659
+	/**
1660
+	 * _register_event_editor_meta_boxes
1661
+	 * add all metaboxes related to the event_editor
1662
+	 *
1663
+	 * @return void
1664
+	 * @throws EE_Error
1665
+	 * @throws ReflectionException
1666
+	 */
1667
+	protected function _register_event_editor_meta_boxes()
1668
+	{
1669
+		$this->verify_cpt_object();
1670
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673
+			$this->addMetaBox(
1674
+				'espresso_event_editor_event_options',
1675
+				esc_html__('Event Registration Options', 'event_espresso'),
1676
+				[$this, 'registration_options_meta_box'],
1677
+				$this->page_slug,
1678
+				'side'
1679
+			);
1680
+		}
1681
+		if (! $use_advanced_editor) {
1682
+			$this->addMetaBox(
1683
+				'espresso_event_editor_tickets',
1684
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1685
+				[$this, 'ticket_metabox'],
1686
+				$this->page_slug,
1687
+				'normal',
1688
+				'high'
1689
+			);
1690
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691
+			add_action(
1692
+				'add_meta_boxes_espresso_events',
1693
+				function () {
1694
+					global $current_screen;
1695
+					remove_meta_box('authordiv', $current_screen, 'normal');
1696
+				},
1697
+				99
1698
+			);
1699
+		}
1700
+		// NOTE: if you're looking for other metaboxes in here,
1701
+		// where a metabox has a related management page in the admin
1702
+		// you will find it setup in the related management page's "_Hooks" file.
1703
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1704
+	}
1705
+
1706
+
1707
+	/**
1708
+	 * @throws DomainException
1709
+	 * @throws EE_Error
1710
+	 * @throws ReflectionException
1711
+	 */
1712
+	public function ticket_metabox()
1713
+	{
1714
+		$existing_datetime_ids = $existing_ticket_ids = [];
1715
+		// defaults for template args
1716
+		$template_args = [
1717
+			'ticket_rows'       => '',
1718
+			'total_ticket_rows' => 1,
1719
+			'trash_icon'        => 'dashicons dashicons-lock',
1720
+			'disabled'          => '',
1721
+		];
1722
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723
+		/**
1724
+		 * 1. Start with retrieving Datetimes
1725
+		 * 2. Fore each datetime get related tickets
1726
+		 * 3. For each ticket get related prices
1727
+		 */
1728
+		/** @var EEM_Datetime $datetime_model */
1729
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1730
+		/** @var EEM_Ticket $datetime_model */
1731
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1732
+		$times        = $datetime_model->get_all_event_dates($event_id);
1733
+		/** @type EE_Datetime $first_datetime */
1734
+		$first_datetime = reset($times);
1735
+		// do we get related tickets?
1736
+		if (
1737
+			$first_datetime instanceof EE_Datetime
1738
+			&& $first_datetime->ID() !== 0
1739
+		) {
1740
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1741
+			$template_args['time']   = $first_datetime;
1742
+			$related_tickets         = $first_datetime->tickets(
1743
+				[
1744
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1745
+					'default_where_conditions' => 'none',
1746
+				]
1747
+			);
1748
+			if (! empty($related_tickets)) {
1749
+				$template_args['total_ticket_rows'] = count($related_tickets);
1750
+				$row                                = 0;
1751
+				foreach ($related_tickets as $ticket) {
1752
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1753
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754
+					$row++;
1755
+				}
1756
+			} else {
1757
+				$template_args['total_ticket_rows'] = 1;
1758
+				/** @type EE_Ticket $ticket */
1759
+				$ticket                       = $ticket_model->create_default_object();
1760
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761
+			}
1762
+		} else {
1763
+			$template_args['time'] = $times[0];
1764
+			/** @type EE_Ticket[] $tickets */
1765
+			$tickets                      = $ticket_model->get_all_default_tickets();
1766
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767
+			// NOTE: we're just sending the first default row
1768
+			// (decaf can't manage default tickets so this should be sufficient);
1769
+		}
1770
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1771
+			'event_editor_event_datetimes_help_tab'
1772
+		);
1773
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1774
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1775
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1776
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1777
+			$ticket_model->create_default_object(),
1778
+			true
1779
+		);
1780
+		$template                                  = apply_filters(
1781
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1783
+		);
1784
+		EEH_Template::display_template($template, $template_args);
1785
+	}
1786
+
1787
+
1788
+	/**
1789
+	 * Setup an individual ticket form for the decaf event editor page
1790
+	 *
1791
+	 * @access private
1792
+	 * @param EE_Ticket $ticket   the ticket object
1793
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1794
+	 * @param int       $row
1795
+	 * @return string generated html for the ticket row.
1796
+	 * @throws EE_Error
1797
+	 * @throws ReflectionException
1798
+	 */
1799
+	private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800
+	{
1801
+		$template_args = [
1802
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1803
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804
+				? ' tkt-archived'
1805
+				: '',
1806
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1807
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1808
+			'TKT_name'            => $ticket->get('TKT_name'),
1809
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1810
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1811
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1812
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
+			'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817
+				? 'dashicons dashicons-post-trash clickable'
1818
+				: 'dashicons dashicons-lock entity-locked',
1819
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820
+				: ' disabled=disabled',
1821
+		];
1822
+
1823
+		$price         = $ticket->ID() !== 0
1824
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1825
+			: null;
1826
+		$price         = $price instanceof EE_Price
1827
+			? $price
1828
+			: EEM_Price::instance()->create_default_object();
1829
+		$price_args    = [
1830
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1831
+			'PRC_amount'            => $price->get('PRC_amount'),
1832
+			'PRT_ID'                => $price->get('PRT_ID'),
1833
+			'PRC_ID'                => $price->get('PRC_ID'),
1834
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1835
+		];
1836
+		// make sure we have default start and end dates if skeleton
1837
+		// handle rows that should NOT be empty
1838
+		if (empty($template_args['TKT_start_date'])) {
1839
+			// if empty then the start date will be now.
1840
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1841
+		}
1842
+		if (empty($template_args['TKT_end_date'])) {
1843
+			// get the earliest datetime (if present);
1844
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1845
+				? $this->_cpt_model_obj->get_first_related(
1846
+					'Datetime',
1847
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1848
+				)
1849
+				: null;
1850
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1851
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1852
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1853
+		}
1854
+		$template_args = array_merge($template_args, $price_args);
1855
+		$template      = apply_filters(
1856
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1858
+			$ticket
1859
+		);
1860
+		return EEH_Template::display_template($template, $template_args, true);
1861
+	}
1862
+
1863
+
1864
+	/**
1865
+	 * @throws EE_Error
1866
+	 * @throws ReflectionException
1867
+	 */
1868
+	public function registration_options_meta_box()
1869
+	{
1870
+		$yes_no_values             = [
1871
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873
+		];
1874
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1875
+			[
1876
+				RegStatus::CANCELLED,
1877
+				RegStatus::DECLINED,
1878
+				RegStatus::INCOMPLETE,
1879
+			],
1880
+			true
1881
+		);
1882
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1883
+		$template_args['_event']                          = $this->_cpt_model_obj;
1884
+		$template_args['event']                           = $this->_cpt_model_obj;
1885
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1886
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1887
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1888
+			'default_reg_status',
1889
+			$default_reg_status_values,
1890
+			$this->_cpt_model_obj->default_registration_status(),
1891
+			'',
1892
+			'ee-input-width--reg',
1893
+			false
1894
+		);
1895
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1896
+			'display_desc',
1897
+			$yes_no_values,
1898
+			$this->_cpt_model_obj->display_description()
1899
+		);
1900
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1901
+			'display_ticket_selector',
1902
+			$yes_no_values,
1903
+			$this->_cpt_model_obj->display_ticket_selector(),
1904
+			'',
1905
+			'ee-input-width--small',
1906
+			false
1907
+		);
1908
+		$template_args['additional_registration_options'] = apply_filters(
1909
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1910
+			'',
1911
+			$template_args,
1912
+			$yes_no_values,
1913
+			$default_reg_status_values
1914
+		);
1915
+		EEH_Template::display_template(
1916
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1917
+			$template_args
1918
+		);
1919
+	}
1920
+
1921
+
1922
+	/**
1923
+	 * _get_events()
1924
+	 * This method simply returns all the events (for the given _view and paging)
1925
+	 *
1926
+	 * @access public
1927
+	 * @param int  $per_page     count of items per page (20 default);
1928
+	 * @param int  $current_page what is the current page being viewed.
1929
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1930
+	 *                           If FALSE then we return an array of event objects
1931
+	 *                           that match the given _view and paging parameters.
1932
+	 * @return array|int         an array of event objects or a count of them.
1933
+	 * @throws Exception
1934
+	 */
1935
+	public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1936
+	{
1937
+		$EEM_Event   = $this->_event_model();
1938
+		$offset      = ($current_page - 1) * $per_page;
1939
+		$limit       = $count ? null : $offset . ',' . $per_page;
1940
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941
+		$order       = $this->request->getRequestParam('order', 'DESC');
1942
+		$month_range = $this->request->getRequestParam('month_range');
1943
+		$where  = [];
1944
+		$status = $this->request->getRequestParam('status');
1945
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1946
+		// determine what post_status our condition will have for the query.
1947
+		switch ($status) {
1948
+			case 'month':
1949
+			case 'today':
1950
+			case null:
1951
+			case 'all':
1952
+				break;
1953
+			case 'draft':
1954
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1955
+				break;
1956
+			default:
1957
+				$where['status'] = $status;
1958
+		}
1959
+		// categories? The default for all categories is -1
1960
+		$category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1961
+		if ($category !== -1) {
1962
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1963
+			$where['Term_Taxonomy.term_id']  = $category;
1964
+		}
1965
+		// date where conditions
1966
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1967
+		if ($month_range) {
1968
+			$where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1969
+		} elseif ($status === 'today') {
1970
+			$DateTime                        = new DateTime(
1971
+				'now',
1972
+				new DateTimeZone($timezone_string)
1973
+			);
1974
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1975
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1976
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
+		} elseif ($status === 'month') {
1978
+			$now                             = date('Y-m-01');
1979
+			$DateTime                        = new DateTime(
1980
+				$now,
1981
+				new DateTimeZone($timezone_string)
1982
+			);
1983
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1984
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1985
+														->setTime(23, 59, 59)
1986
+														->format(implode(' ', $start_formats));
1987
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988
+		}
1989
+		if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990
+			$where['EVT_wp_user'] = get_current_user_id();
1991
+		} else {
1992
+			if (! isset($where['status'])) {
1993
+				if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994
+					$where['OR'] = [
1995
+						'status*restrict_private' => ['!=', 'private'],
1996
+						'AND'                     => [
1997
+							'status*inclusive' => ['=', 'private'],
1998
+							'EVT_wp_user'      => get_current_user_id(),
1999
+						],
2000
+					];
2001
+				}
2002
+			}
2003
+		}
2004
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2005
+		if (
2006
+			$wp_user
2007
+			&& $wp_user !== get_current_user_id()
2008
+			&& $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2009
+		) {
2010
+			$where['EVT_wp_user'] = $wp_user;
2011
+		}
2012
+		// search query handling
2013
+		$search_term = $this->request->getRequestParam('s');
2014
+		if ($search_term) {
2015
+			$search_term = '%' . $search_term . '%';
2016
+			$where['OR'] = [
2017
+				'EVT_name'       => ['LIKE', $search_term],
2018
+				'EVT_desc'       => ['LIKE', $search_term],
2019
+				'EVT_short_desc' => ['LIKE', $search_term],
2020
+			];
2021
+		}
2022
+		// filter events by venue.
2023
+		$venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2024
+		if ($venue) {
2025
+			$where['Venue.VNU_ID'] = $venue;
2026
+		}
2027
+		$request_params = $this->request->requestParams();
2028
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2029
+		$query_params   = apply_filters(
2030
+			'FHEE__Events_Admin_Page__get_events__query_params',
2031
+			[
2032
+				$where,
2033
+				'limit'    => $limit,
2034
+				'order_by' => $orderby,
2035
+				'order'    => $order,
2036
+				'group_by' => 'EVT_ID',
2037
+			],
2038
+			$request_params
2039
+		);
2040
+
2041
+		// let's first check if we have special requests coming in.
2042
+		$active_status = $this->request->getRequestParam('active_status');
2043
+		if ($active_status) {
2044
+			switch ($active_status) {
2045
+				case 'upcoming':
2046
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2047
+				case 'expired':
2048
+					return $EEM_Event->get_expired_events($query_params, $count);
2049
+				case 'active':
2050
+					return $EEM_Event->get_active_events($query_params, $count);
2051
+				case 'inactive':
2052
+					return $EEM_Event->get_inactive_events($query_params, $count);
2053
+			}
2054
+		}
2055
+
2056
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2057
+	}
2058
+
2059
+
2060
+	/**
2061
+	 * @param string $month_range
2062
+	 * @param string $timezone_string
2063
+	 * @return array
2064
+	 * @throws Exception
2065
+	 * @since 5.0.21.p
2066
+	 */
2067
+	public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2068
+	{
2069
+		$timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2070
+		$pieces = explode(' ', $month_range, 3);
2071
+		// simulate the FIRST day of the month, that fixes issues for months like February
2072
+		// where PHP doesn't know what to assume for date.
2073
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2074
+		$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2075
+		$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2076
+		$DateTime = new DateTime(
2077
+			"$year_r-$month_r-01 00:00:00",
2078
+			new DateTimeZone($timezone_string)
2079
+		);
2080
+		$start    = $DateTime->getTimestamp();
2081
+		// set the datetime to be the end of the month
2082
+		$DateTime->setDate(
2083
+			$year_r,
2084
+			$month_r,
2085
+			$DateTime->format('t')
2086
+		)->setTime(23, 59, 59);
2087
+		$end                             = $DateTime->getTimestamp();
2088
+		return ['BETWEEN', [$start, $end]];
2089
+	}
2090
+
2091
+
2092
+	/**
2093
+	 * handling for WordPress CPT actions (trash, restore, delete)
2094
+	 *
2095
+	 * @param string $post_id
2096
+	 * @throws EE_Error
2097
+	 * @throws ReflectionException
2098
+	 */
2099
+	public function trash_cpt_item($post_id)
2100
+	{
2101
+		$this->request->setRequestParam('EVT_ID', $post_id);
2102
+		$this->_trash_or_restore_event('trash', false);
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * @param string $post_id
2108
+	 * @throws EE_Error
2109
+	 * @throws ReflectionException
2110
+	 */
2111
+	public function restore_cpt_item($post_id)
2112
+	{
2113
+		$this->request->setRequestParam('EVT_ID', $post_id);
2114
+		$this->_trash_or_restore_event('draft', false);
2115
+	}
2116
+
2117
+
2118
+	/**
2119
+	 * @param string $post_id
2120
+	 * @throws EE_Error
2121
+	 * @throws EE_Error
2122
+	 */
2123
+	public function delete_cpt_item($post_id)
2124
+	{
2125
+		throw new EE_Error(
2126
+			esc_html__(
2127
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2128
+				'event_espresso'
2129
+			)
2130
+		);
2131
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2132
+		// $this->_delete_event();
2133
+	}
2134
+
2135
+
2136
+	/**
2137
+	 * _trash_or_restore_event
2138
+	 *
2139
+	 * @access protected
2140
+	 * @param string $event_status
2141
+	 * @param bool   $redirect_after
2142
+	 * @throws EE_Error
2143
+	 * @throws EE_Error
2144
+	 * @throws ReflectionException
2145
+	 */
2146
+	protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2147
+	{
2148
+		// loop thru events
2149
+		if ($this->EVT_ID) {
2150
+			// clean status
2151
+			$event_status = sanitize_key($event_status);
2152
+			// grab status
2153
+			if (! empty($event_status)) {
2154
+				$success = $this->_change_event_status($this->EVT_ID, $event_status);
2155
+			} else {
2156
+				$success = false;
2157
+				$msg     = esc_html__(
2158
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2159
+					'event_espresso'
2160
+				);
2161
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2162
+			}
2163
+		} else {
2164
+			$success = false;
2165
+			$msg     = esc_html__(
2166
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2167
+				'event_espresso'
2168
+			);
2169
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2170
+		}
2171
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2172
+		if ($redirect_after) {
2173
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2174
+		}
2175
+	}
2176
+
2177
+
2178
+	/**
2179
+	 * _trash_or_restore_events
2180
+	 *
2181
+	 * @access protected
2182
+	 * @param string $event_status
2183
+	 * @return void
2184
+	 * @throws EE_Error
2185
+	 * @throws EE_Error
2186
+	 * @throws ReflectionException
2187
+	 */
2188
+	protected function _trash_or_restore_events(string $event_status = 'trash')
2189
+	{
2190
+		// clean status
2191
+		$event_status = sanitize_key($event_status);
2192
+		// grab status
2193
+		if (! empty($event_status)) {
2194
+			$success = true;
2195
+			// determine the event id and set to array.
2196
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2197
+			// loop thru events
2198
+			foreach ($EVT_IDs as $EVT_ID) {
2199
+				if ($EVT_ID = absint($EVT_ID)) {
2200
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2201
+					$success = $results !== false ? $success : false;
2202
+				} else {
2203
+					$msg = sprintf(
2204
+						esc_html__(
2205
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2206
+							'event_espresso'
2207
+						),
2208
+						$EVT_ID
2209
+					);
2210
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
+					$success = false;
2212
+				}
2213
+			}
2214
+		} else {
2215
+			$success = false;
2216
+			$msg     = esc_html__(
2217
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2218
+				'event_espresso'
2219
+			);
2220
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
+		}
2222
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2223
+		$success = $success ? 2 : false;
2224
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2225
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2226
+	}
2227
+
2228
+
2229
+	/**
2230
+	 * @param int    $EVT_ID
2231
+	 * @param string $event_status
2232
+	 * @return bool
2233
+	 * @throws EE_Error
2234
+	 * @throws ReflectionException
2235
+	 */
2236
+	private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237
+	{
2238
+		// grab event id
2239
+		if (! $EVT_ID) {
2240
+			$msg = esc_html__(
2241
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2242
+				'event_espresso'
2243
+			);
2244
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2245
+			return false;
2246
+		}
2247
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2248
+		// clean status
2249
+		$event_status = sanitize_key($event_status);
2250
+		// grab status
2251
+		if (empty($event_status)) {
2252
+			$msg = esc_html__(
2253
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2254
+				'event_espresso'
2255
+			);
2256
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2257
+			return false;
2258
+		}
2259
+		// was event trashed or restored ?
2260
+		switch ($event_status) {
2261
+			case 'draft':
2262
+				$action = 'restored from the trash';
2263
+				$hook   = 'AHEE_event_restored_from_trash';
2264
+				break;
2265
+			case 'trash':
2266
+				$action = 'moved to the trash';
2267
+				$hook   = 'AHEE_event_moved_to_trash';
2268
+				break;
2269
+			default:
2270
+				$action = 'updated';
2271
+				$hook   = false;
2272
+		}
2273
+		// use class to change status
2274
+		$this->_cpt_model_obj->set_status($event_status);
2275
+		$success = $this->_cpt_model_obj->save();
2276
+		if (! $success) {
2277
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279
+			return false;
2280
+		}
2281
+		if ($hook) {
2282
+			do_action($hook);
2283
+			// fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2284
+			// because events side step that and it otherwise won't get called
2285
+			do_action(
2286
+				'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2287
+				$this->_cpt_model_obj,
2288
+				$hook === 'AHEE_event_moved_to_trash',
2289
+				$success
2290
+			);
2291
+		}
2292
+		return true;
2293
+	}
2294
+
2295
+
2296
+	/**
2297
+	 * @param array $event_ids
2298
+	 * @return array
2299
+	 * @since   4.10.23.p
2300
+	 */
2301
+	private function cleanEventIds(array $event_ids): array
2302
+	{
2303
+		return array_map('absint', $event_ids);
2304
+	}
2305
+
2306
+
2307
+	/**
2308
+	 * @return array
2309
+	 * @since   4.10.23.p
2310
+	 */
2311
+	private function getEventIdsFromRequest(): array
2312
+	{
2313
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2314
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2315
+		} else {
2316
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2317
+		}
2318
+	}
2319
+
2320
+
2321
+	/**
2322
+	 * @param bool $preview_delete
2323
+	 * @throws EE_Error
2324
+	 * @throws ReflectionException
2325
+	 */
2326
+	protected function _delete_event(bool $preview_delete = true)
2327
+	{
2328
+		$this->_delete_events($preview_delete);
2329
+	}
2330
+
2331
+
2332
+	/**
2333
+	 * Gets the tree traversal batch persister.
2334
+	 *
2335
+	 * @return NodeGroupDao
2336
+	 * @throws InvalidArgumentException
2337
+	 * @throws InvalidDataTypeException
2338
+	 * @throws InvalidInterfaceException
2339
+	 * @since 4.10.12.p
2340
+	 */
2341
+	protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342
+	{
2343
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344
+			$this->model_obj_node_group_persister =
2345
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346
+		}
2347
+		return $this->model_obj_node_group_persister;
2348
+	}
2349
+
2350
+
2351
+	/**
2352
+	 * @param bool $preview_delete
2353
+	 * @return void
2354
+	 * @throws EE_Error
2355
+	 * @throws ReflectionException
2356
+	 */
2357
+	protected function _delete_events(bool $preview_delete = true)
2358
+	{
2359
+		$event_ids = $this->getEventIdsFromRequest();
2360
+		if ($preview_delete) {
2361
+			$this->generateDeletionPreview($event_ids);
2362
+		} else {
2363
+			foreach ($event_ids as $event_id) {
2364
+				$event = EEM_Event::instance()->get_one_by_ID($event_id);
2365
+				if ($event instanceof EE_Event) {
2366
+					$event->delete_permanently();
2367
+				}
2368
+			}
2369
+		}
2370
+	}
2371
+
2372
+
2373
+	/**
2374
+	 * @param array $event_ids
2375
+	 */
2376
+	protected function generateDeletionPreview(array $event_ids)
2377
+	{
2378
+		$event_ids = $this->cleanEventIds($event_ids);
2379
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2380
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2381
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2382
+			[
2383
+				'action'            => 'preview_deletion',
2384
+				'deletion_job_code' => $deletion_job_code,
2385
+			],
2386
+			$this->_admin_base_url
2387
+		);
2388
+		EEH_URL::safeRedirectAndExit(
2389
+			EE_Admin_Page::add_query_args_and_nonce(
2390
+				[
2391
+					'page'              => EED_Batch::PAGE_SLUG,
2392
+					'batch'             => EED_Batch::batch_job,
2393
+					'EVT_IDs'           => $event_ids,
2394
+					'deletion_job_code' => $deletion_job_code,
2395
+					'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2396
+					'return_url'        => urlencode($return_url),
2397
+				],
2398
+				admin_url()
2399
+			)
2400
+		);
2401
+	}
2402
+
2403
+
2404
+	/**
2405
+	 * Checks for a POST submission
2406
+	 *
2407
+	 * @since 4.10.12.p
2408
+	 */
2409
+	protected function confirmDeletion()
2410
+	{
2411
+		$deletion_redirect_logic = $this->getLoader()->getShared(
2412
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2413
+		);
2414
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2415
+	}
2416
+
2417
+
2418
+	/**
2419
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2420
+	 *
2421
+	 * @throws EE_Error
2422
+	 * @since 4.10.12.p
2423
+	 */
2424
+	protected function previewDeletion()
2425
+	{
2426
+		$preview_deletion_logic = $this->getLoader()->getShared(
2427
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2428
+		);
2429
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2430
+		$this->display_admin_page_with_no_sidebar();
2431
+	}
2432
+
2433
+
2434
+	/**
2435
+	 * get total number of events
2436
+	 *
2437
+	 * @access public
2438
+	 * @return int
2439
+	 * @throws EE_Error
2440
+	 * @throws EE_Error
2441
+	 * @throws ReflectionException
2442
+	 */
2443
+	public function total_events(): int
2444
+	{
2445
+		return EEM_Event::instance()->count(
2446
+			['caps' => 'read_admin'],
2447
+			'EVT_ID',
2448
+			true
2449
+		);
2450
+	}
2451
+
2452
+
2453
+	/**
2454
+	 * get total number of draft events
2455
+	 *
2456
+	 * @access public
2457
+	 * @return int
2458
+	 * @throws EE_Error
2459
+	 * @throws EE_Error
2460
+	 * @throws ReflectionException
2461
+	 */
2462
+	public function total_events_draft(): int
2463
+	{
2464
+		return EEM_Event::instance()->count(
2465
+			[
2466
+				['status' => ['IN', ['draft', 'auto-draft']]],
2467
+				'caps' => 'read_admin',
2468
+			],
2469
+			'EVT_ID',
2470
+			true
2471
+		);
2472
+	}
2473
+
2474
+
2475
+	/**
2476
+	 * get total number of trashed events
2477
+	 *
2478
+	 * @access public
2479
+	 * @return int
2480
+	 * @throws EE_Error
2481
+	 * @throws EE_Error
2482
+	 * @throws ReflectionException
2483
+	 */
2484
+	public function total_trashed_events(): int
2485
+	{
2486
+		return EEM_Event::instance()->count(
2487
+			[
2488
+				['status' => 'trash'],
2489
+				'caps' => 'read_admin',
2490
+			],
2491
+			'EVT_ID',
2492
+			true
2493
+		);
2494
+	}
2495
+
2496
+
2497
+	/**
2498
+	 *    _default_event_settings
2499
+	 *    This generates the Default Settings Tab
2500
+	 *
2501
+	 * @return void
2502
+	 * @throws DomainException
2503
+	 * @throws EE_Error
2504
+	 * @throws InvalidArgumentException
2505
+	 * @throws InvalidDataTypeException
2506
+	 * @throws InvalidInterfaceException
2507
+	 * @throws ReflectionException
2508
+	 */
2509
+	protected function _default_event_settings()
2510
+	{
2511
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2512
+		$this->_set_publish_post_box_vars();
2513
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
2514
+			$this->_default_event_settings_form()->get_html(),
2515
+			'',
2516
+			'padding'
2517
+		);
2518
+		$this->display_admin_page_with_sidebar();
2519
+	}
2520
+
2521
+
2522
+	/**
2523
+	 * Return the form for event settings.
2524
+	 *
2525
+	 * @return EE_Form_Section_Proper
2526
+	 * @throws EE_Error
2527
+	 * @throws ReflectionException
2528
+	 */
2529
+	protected function _default_event_settings_form(): EE_Form_Section_Proper
2530
+	{
2531
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2532
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2533
+		// exclude
2534
+			[
2535
+				RegStatus::CANCELLED,
2536
+				RegStatus::DECLINED,
2537
+				RegStatus::INCOMPLETE,
2538
+				RegStatus::WAIT_LIST,
2539
+			],
2540
+			true
2541
+		);
2542
+		// setup Advanced Editor ???
2543
+		if (
2544
+			$this->raw_req_action === 'default_event_settings'
2545
+			|| $this->raw_req_action === 'update_default_event_settings'
2546
+		) {
2547
+			$this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2548
+		}
2549
+		return new EE_Form_Section_Proper(
2550
+			[
2551
+				'name'            => 'update_default_event_settings',
2552
+				'html_id'         => 'update_default_event_settings',
2553
+				'html_class'      => 'form-table',
2554
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2555
+				'subsections'     => apply_filters(
2556
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2557
+					[
2558
+						'defaults_section_header' => new EE_Form_Section_HTML(
2559
+							EEH_HTML::h2(
2560
+								esc_html__('Default Settings', 'event_espresso'),
2561
+								'',
2562
+								'ee-admin-settings-hdr'
2563
+							)
2564
+						),
2565
+						'default_reg_status'      => new EE_Select_Input(
2566
+							$registration_stati_for_selection,
2567
+							[
2568
+								'default'         => isset($registration_config->default_STS_ID)
2569
+													 && array_key_exists(
2570
+														 $registration_config->default_STS_ID,
2571
+														 $registration_stati_for_selection
2572
+													 )
2573
+									? sanitize_text_field($registration_config->default_STS_ID)
2574
+									: RegStatus::PENDING_PAYMENT,
2575
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2576
+													 . EEH_Template::get_help_tab_link(
2577
+										'default_settings_status_help_tab'
2578
+									),
2579
+								'html_help_text'  => esc_html__(
2580
+									'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.',
2581
+									'event_espresso'
2582
+								),
2583
+								'html_class'      => 'ee-input-width--small',
2584
+							]
2585
+						),
2586
+						'default_max_tickets'     => new EE_Integer_Input(
2587
+							[
2588
+								'default'         => $registration_config->default_maximum_number_of_tickets
2589
+													 ?? EEM_Event::get_default_additional_limit(),
2590
+								'html_label_text' => esc_html__(
2591
+														 'Default Maximum Tickets Allowed Per Order:',
2592
+														 'event_espresso'
2593
+													 )
2594
+													 . EEH_Template::get_help_tab_link(
2595
+										'default_maximum_tickets_help_tab"'
2596
+									),
2597
+								'html_help_text'  => esc_html__(
2598
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2599
+									'event_espresso'
2600
+								),
2601
+								'html_class'      => 'ee-input-width--tiny',
2602
+							]
2603
+						),
2604
+					]
2605
+				),
2606
+			]
2607
+		);
2608
+	}
2609
+
2610
+
2611
+	/**
2612
+	 * @return void
2613
+	 * @throws EE_Error
2614
+	 * @throws InvalidArgumentException
2615
+	 * @throws InvalidDataTypeException
2616
+	 * @throws InvalidInterfaceException
2617
+	 * @throws ReflectionException
2618
+	 */
2619
+	protected function _update_default_event_settings()
2620
+	{
2621
+		$form = $this->_default_event_settings_form();
2622
+		if ($form->was_submitted()) {
2623
+			$form->receive_form_submission();
2624
+			if ($form->is_valid()) {
2625
+				$registration_config = EE_Registry::instance()->CFG->registration;
2626
+				$valid_data          = $form->valid_data();
2627
+				if (isset($valid_data['default_reg_status'])) {
2628
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2629
+				}
2630
+				if (isset($valid_data['default_max_tickets'])) {
2631
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2632
+				}
2633
+				do_action(
2634
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2635
+					$valid_data,
2636
+					EE_Registry::instance()->CFG,
2637
+					$this
2638
+				);
2639
+				// update because data was valid!
2640
+				EE_Registry::instance()->CFG->update_espresso_config();
2641
+				EE_Error::overwrite_success();
2642
+				EE_Error::add_success(
2643
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2644
+				);
2645
+			}
2646
+		}
2647
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2648
+	}
2649
+
2650
+
2651
+	/*************        Templates        *************
795 2652
      *
796
-     * @return void
797
-     * @throws EE_Error
798
-     * @throws InvalidArgumentException
799
-     * @throws InvalidDataTypeException
800
-     * @throws InvalidInterfaceException
801
-     * @throws ReflectionException
802
-     */
803
-    protected function _create_new_cpt_item()
804
-    {
805
-        $has_timezone_string = get_option('timezone_string');
806
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
807
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808
-            EE_Error::add_attention(
809
-                sprintf(
810
-                    esc_html__(
811
-                        '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',
812
-                        'event_espresso'
813
-                    ),
814
-                    '<br>',
815
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
816
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
817
-                    . '</select>',
818
-                    '<button class="button button--secondary timezone-submit">',
819
-                    '</button><span class="spinner"></span>'
820
-                ),
821
-                __FILE__,
822
-                __FUNCTION__,
823
-                __LINE__
824
-            );
825
-        }
826
-        parent::_create_new_cpt_item();
827
-    }
828
-
829
-
830
-    /**
831
-     * Sets the _views property for the default route in this admin page group.
832
-     */
833
-    protected function _set_list_table_views_default()
834
-    {
835
-        $this->_views = [
836
-            'all'   => [
837
-                'slug'        => 'all',
838
-                'label'       => esc_html__('View All Events', 'event_espresso'),
839
-                'count'       => 0,
840
-                'bulk_action' => [
841
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
842
-                ],
843
-            ],
844
-            'draft' => [
845
-                'slug'        => 'draft',
846
-                'label'       => esc_html__('Draft', 'event_espresso'),
847
-                'count'       => 0,
848
-                'bulk_action' => [
849
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
850
-                ],
851
-            ],
852
-        ];
853
-        if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
854
-            $this->_views['trash'] = [
855
-                'slug'        => 'trash',
856
-                'label'       => esc_html__('Trash', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => [
859
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
860
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
861
-                ],
862
-            ];
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Provides the legend item array for the default list table view.
869
-     *
870
-     * @return array
871
-     * @throws EE_Error
872
-     * @throws EE_Error
873
-     */
874
-    protected function _event_legend_items(): array
875
-    {
876
-        $items    = [
877
-            'view_details'   => [
878
-                'class' => 'dashicons dashicons-visibility',
879
-                'desc'  => esc_html__('View Event', 'event_espresso'),
880
-            ],
881
-            'edit_event'     => [
882
-                'class' => 'dashicons dashicons-calendar-alt',
883
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
884
-            ],
885
-            'view_attendees' => [
886
-                'class' => 'dashicons dashicons-groups',
887
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
888
-            ],
889
-        ];
890
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891
-        $statuses = [
892
-            'sold_out_status'  => [
893
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
894
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895
-            ],
896
-            'active_status'    => [
897
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
898
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899
-            ],
900
-            'upcoming_status'  => [
901
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
902
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903
-            ],
904
-            'postponed_status' => [
905
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
906
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907
-            ],
908
-            'cancelled_status' => [
909
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
910
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911
-            ],
912
-            'expired_status'   => [
913
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
914
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915
-            ],
916
-            'inactive_status'  => [
917
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
918
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919
-            ],
920
-        ];
921
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
922
-        return array_merge($items, $statuses);
923
-    }
924
-
925
-
926
-    /**
927
-     * @return EEM_Event
928
-     * @throws EE_Error
929
-     * @throws InvalidArgumentException
930
-     * @throws InvalidDataTypeException
931
-     * @throws InvalidInterfaceException
932
-     * @throws ReflectionException
933
-     */
934
-    private function _event_model(): EEM_Event
935
-    {
936
-        if (! $this->_event_model instanceof EEM_Event) {
937
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
938
-        }
939
-        return $this->_event_model;
940
-    }
941
-
942
-
943
-    /**
944
-     * Adds extra buttons to the WP CPT permalink field row.
945
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
946
-     *
947
-     * @param string      $return    the current html
948
-     * @param int         $id        the post id for the page
949
-     * @param string|null $new_title What the title is
950
-     * @param string|null $new_slug  what the slug is
951
-     * @return string            The new html string for the permalink area
952
-     * @deprecated 5.0.0.p
953
-     * @see        TicketSelectorShortcodeButton::addButton
954
-     */
955
-    public function extra_permalink_field_buttons(
956
-        string $return,
957
-        int $id,
958
-        ?string $new_title,
959
-        ?string $new_slug
960
-    ): string {
961
-        return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
962
-    }
963
-
964
-
965
-    /**
966
-     * _events_overview_list_table
967
-     * This contains the logic for showing the events_overview list
968
-     *
969
-     * @access protected
970
-     * @return void
971
-     * @throws DomainException
972
-     * @throws EE_Error
973
-     * @throws InvalidArgumentException
974
-     * @throws InvalidDataTypeException
975
-     * @throws InvalidInterfaceException
976
-     */
977
-    protected function _events_overview_list_table()
978
-    {
979
-        $after_list_table = [];
980
-        $links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
981
-        $links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
982
-        $links_html       .= EEH_HTML::div(
983
-            EEH_Template::get_button_or_link(
984
-                get_post_type_archive_link(EspressoPostType::EVENTS),
985
-                esc_html__('View Event Archive Page', 'event_espresso'),
986
-                'button button--small button--secondary'
987
-            ),
988
-            '',
989
-            'ee-admin-button-row ee-admin-button-row--align-start'
990
-        );
991
-        $links_html       .= EEH_HTML::divx();
992
-
993
-        $after_list_table['view_event_list_button'] = $links_html;
994
-
995
-        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
997
-                'create_new',
998
-                'add',
999
-                [],
1000
-                'add-new-h2'
1001
-            );
1002
-
1003
-        $this->_template_args['after_list_table'] = array_merge(
1004
-            (array) $this->_template_args['after_list_table'],
1005
-            $after_list_table
1006
-        );
1007
-        $this->display_admin_list_table_page_with_no_sidebar();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * this allows for extra misc actions in the default WP publish box
1013
-     *
1014
-     * @return void
1015
-     * @throws DomainException
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     * @throws ReflectionException
1021
-     */
1022
-    public function extra_misc_actions_publish_box()
1023
-    {
1024
-        $this->_generate_publish_box_extra_content();
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
-     * saved.
1031
-     * Typically you would use this to save any additional data.
1032
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
-     * ALSO very important.  When a post transitions from scheduled to published,
1034
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
-     * other meta saves. So MAKE sure that you handle this accordingly.
1036
-     *
1037
-     * @access protected
1038
-     * @abstract
1039
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1040
-     * @param WP_Post $post    The post object of the cpt that was saved.
1041
-     * @return void
1042
-     * @throws EE_Error
1043
-     * @throws InvalidArgumentException
1044
-     * @throws InvalidDataTypeException
1045
-     * @throws InvalidInterfaceException
1046
-     * @throws ReflectionException
1047
-     */
1048
-    protected function _insert_update_cpt_item($post_id, $post)
1049
-    {
1050
-        if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1051
-            // get out we're not processing an event save.
1052
-            return;
1053
-        }
1054
-        $event_values = [
1055
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1056
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1057
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058
-        ];
1059
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1062
-                'display_ticket_selector',
1063
-                false,
1064
-                'bool'
1065
-            );
1066
-            $event_values['EVT_additional_limit']            = min(
1067
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068
-                $this->request->getRequestParam(
1069
-                    'additional_limit',
1070
-                    EEM_Event::get_default_additional_limit(),
1071
-                    'int'
1072
-                )
1073
-            );
1074
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1075
-                'EVT_default_registration_status',
1076
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1077
-            );
1078
-
1079
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1080
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1081
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1082
-        } elseif ($post instanceof WP_Post) {
1083
-            $event_values['EVT_name'] = $post->post_title;
1084
-            $event_values['EVT_desc'] = $post->post_content;
1085
-        }
1086
-        // update event
1087
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
-        // get event_object for other metaboxes...
1089
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
-        // i have to set up where conditions to override the filters in the model
1091
-        // that filter out auto-draft and inherit statuses so we GET the inherit id!
1092
-        /** @var EE_Event $event */
1093
-        $event = $this->_event_model()->get_one(
1094
-            [
1095
-                [
1096
-                    $this->_event_model()->primary_key_name() => $post_id,
1097
-                    'OR'                                      => [
1098
-                        'status'   => $post->post_status,
1099
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1100
-                        // but the returned object here has a status of "publish", so use the original post status as well
1101
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1102
-                    ],
1103
-                    'status' => ['NOT IN', ['auto-draft']],
1104
-                ],
1105
-            ]
1106
-        );
1107
-
1108
-        if (! $event instanceof EE_Event) {
1109
-            return;
1110
-        }
1111
-
1112
-        // the following are default callbacks for event attachment updates
1113
-        // that can be overridden by caffeinated functionality and/or addons.
1114
-        $event_update_callbacks = [];
1115
-        if (! $this->admin_config->useAdvancedEditor()) {
1116
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118
-        }
1119
-        $event_update_callbacks = apply_filters(
1120
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1121
-            $event_update_callbacks
1122
-        );
1123
-
1124
-        $att_success = true;
1125
-        foreach ($event_update_callbacks as $e_callback) {
1126
-            $_success = is_callable($e_callback)
1127
-                ? $e_callback($event, $this->request->requestParams())
1128
-                : false;
1129
-            // if ANY of these updates fail then we want the appropriate global error message
1130
-            $att_success = $_success !== false ? $att_success : false;
1131
-        }
1132
-        // any errors?
1133
-        if ($success && $att_success === false) {
1134
-            EE_Error::add_error(
1135
-                esc_html__(
1136
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1137
-                    'event_espresso'
1138
-                ),
1139
-                __FILE__,
1140
-                __FUNCTION__,
1141
-                __LINE__
1142
-            );
1143
-        } elseif ($success === false) {
1144
-            EE_Error::add_error(
1145
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1146
-                __FILE__,
1147
-                __FUNCTION__,
1148
-                __LINE__
1149
-            );
1150
-        }
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * @param int $post_id
1156
-     * @param int $revision_id
1157
-     * @throws EE_Error
1158
-     * @throws EE_Error
1159
-     * @throws ReflectionException
1160
-     * @see parent::restore_item()
1161
-     */
1162
-    protected function _restore_cpt_item(int $post_id, int $revision_id)
1163
-    {
1164
-        // copy existing event meta to new post
1165
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1166
-        if ($post_evt instanceof EE_Event) {
1167
-            // meta revision restore
1168
-            $post_evt->restore_revision($revision_id);
1169
-            // related objs restore
1170
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1171
-        }
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * Attach the venue to the Event
1177
-     *
1178
-     * @param EE_Event $event Event Object to add the venue to
1179
-     * @param array    $data  The request data from the form
1180
-     * @return bool           Success or fail.
1181
-     * @throws EE_Error
1182
-     * @throws ReflectionException
1183
-     */
1184
-    protected function _default_venue_update(EE_Event $event, array $data): bool
1185
-    {
1186
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1187
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1188
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189
-        // very important.  If we don't have a venue name...
1190
-        // then we'll get out because not necessary to create empty venue
1191
-        if (empty($data['venue_title'])) {
1192
-            return false;
1193
-        }
1194
-        $venue_array = [
1195
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1196
-            'VNU_name'            => $data['venue_title'],
1197
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1198
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1199
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1200
-                ? $data['venue_short_description']
1201
-                : null,
1202
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1203
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1204
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1205
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1206
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1207
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1208
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1209
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1210
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1211
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1212
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1213
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1214
-            'status'              => 'publish',
1215
-        ];
1216
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
-        if (! empty($venue_id)) {
1218
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1219
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1220
-            // we've gotta make sure that the venue is always attached to a revision..
1221
-            // add_relation_to should take care of making sure that the relation is already present.
1222
-            $event->_add_relation_to($venue_id, 'Venue');
1223
-            return $rows_affected > 0;
1224
-        }
1225
-        // we insert the venue
1226
-        $venue_id = $venue_model->insert($venue_array);
1227
-        $event->_add_relation_to($venue_id, 'Venue');
1228
-        return ! empty($venue_id);
1229
-        // when we have the ancestor come in it's already been handled by the revision save.
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1235
-     *
1236
-     * @param EE_Event $event The Event object we're attaching data to
1237
-     * @param array    $data  The request data from the form
1238
-     * @return array
1239
-     * @throws EE_Error
1240
-     * @throws ReflectionException
1241
-     * @throws Exception
1242
-     */
1243
-    protected function _default_tickets_update(EE_Event $event, array $data): array
1244
-    {
1245
-        if ($this->admin_config->useAdvancedEditor()) {
1246
-            return [];
1247
-        }
1248
-        $datetime       = null;
1249
-        $saved_tickets  = [];
1250
-        $event_timezone = $event->get_timezone();
1251
-        $date_formats   = ['Y-m-d', 'h:i a'];
1252
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1253
-            // trim all values to ensure any excess whitespace is removed.
1254
-            $datetime_data                = array_map('trim', $datetime_data);
1255
-            $datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1256
-                    ? $datetime_data['DTT_EVT_end']
1257
-                    : $datetime_data['DTT_EVT_start'];
1258
-            $datetime_values              = [
1259
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1260
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1261
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1262
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1263
-                'DTT_order'     => $row,
1264
-            ];
1265
-            // if we have an id then let's get existing object first and then set the new values.
1266
-            //  Otherwise we instantiate a new object for save.
1267
-            if (! empty($datetime_data['DTT_ID'])) {
1268
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
-                if (! $datetime instanceof EE_Datetime) {
1270
-                    throw new RuntimeException(
1271
-                        sprintf(
1272
-                            esc_html__(
1273
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1274
-                                'event_espresso'
1275
-                            ),
1276
-                            $datetime_data['DTT_ID']
1277
-                        )
1278
-                    );
1279
-                }
1280
-                $datetime->set_date_format($date_formats[0]);
1281
-                $datetime->set_time_format($date_formats[1]);
1282
-                foreach ($datetime_values as $field => $value) {
1283
-                    $datetime->set($field, $value);
1284
-                }
1285
-            } else {
1286
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287
-            }
1288
-            if (! $datetime instanceof EE_Datetime) {
1289
-                throw new RuntimeException(
1290
-                    sprintf(
1291
-                        esc_html__(
1292
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1293
-                            'event_espresso'
1294
-                        ),
1295
-                        print_r($datetime_values, true)
1296
-                    )
1297
-                );
1298
-            }
1299
-            // before going any further make sure our dates are setup correctly
1300
-            // so that the end date is always equal or greater than the start date.
1301
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1302
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1303
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1304
-            }
1305
-            $datetime->save();
1306
-            $event->_add_relation_to($datetime, 'Datetime');
1307
-        }
1308
-        // no datetimes get deleted so we don't do any of that logic here.
1309
-        // update tickets next
1310
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1311
-
1312
-        // set up some default start and end dates in case those are not present in the incoming data
1313
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1315
-        // use the start date of the first datetime for the end date
1316
-        $first_datetime   = $event->first_datetime();
1317
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1318
-
1319
-        // now process the incoming data
1320
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321
-            $update_prices = false;
1322
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1323
-            // trim inputs to ensure any excess whitespace is removed.
1324
-            $ticket_data   = array_map('trim', $ticket_data);
1325
-            $ticket_values = [
1326
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1327
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1328
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1329
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1330
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1331
-                    ? $ticket_data['TKT_start_date']
1332
-                    : $default_start_date,
1333
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1334
-                    ? $ticket_data['TKT_end_date']
1335
-                    : $default_end_date,
1336
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1337
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1338
-                    ? $ticket_data['TKT_qty']
1339
-                    : EE_INF,
1340
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1341
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1342
-                    ? $ticket_data['TKT_uses']
1343
-                    : EE_INF,
1344
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1345
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1346
-                'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1347
-                'TKT_price'       => (float) $ticket_price,
1348
-                'TKT_row'         => $row,
1349
-            ];
1350
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1351
-            // which means in turn that the prices will become new prices as well.
1352
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1353
-                $ticket_values['TKT_ID']         = 0;
1354
-                $ticket_values['TKT_is_default'] = 0;
1355
-                $update_prices                   = true;
1356
-            }
1357
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1358
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1359
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1361
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
-            if (! empty($ticket_data['TKT_ID'])) {
1363
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
-                if (! $existing_ticket instanceof EE_Ticket) {
1365
-                    throw new RuntimeException(
1366
-                        sprintf(
1367
-                            esc_html__(
1368
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1369
-                                'event_espresso'
1370
-                            ),
1371
-                            $ticket_data['TKT_ID']
1372
-                        )
1373
-                    );
1374
-                }
1375
-                $ticket_sold = $existing_ticket->count_related(
1376
-                        'Registration',
1377
-                        [
1378
-                            [
1379
-                                'STS_ID' => [
1380
-                                    'NOT IN',
1381
-                                    [RegStatus::INCOMPLETE],
1382
-                                ],
1383
-                            ],
1384
-                        ]
1385
-                    ) > 0;
1386
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1387
-                // if they are different then we create a new ticket (if $ticket_sold)
1388
-                // if they aren't different then we go ahead and modify existing ticket.
1389
-                $create_new_ticket = $ticket_sold
1390
-                                     && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1391
-                                     && ! $existing_ticket->deleted();
1392
-                $existing_ticket->set_date_format($date_formats[0]);
1393
-                $existing_ticket->set_time_format($date_formats[1]);
1394
-                // set new values
1395
-                foreach ($ticket_values as $field => $value) {
1396
-                    if ($field == 'TKT_qty') {
1397
-                        $existing_ticket->set_qty($value);
1398
-                    } elseif ($field == 'TKT_price') {
1399
-                        $existing_ticket->set('TKT_price', $ticket_price);
1400
-                    } else {
1401
-                        $existing_ticket->set($field, $value);
1402
-                    }
1403
-                }
1404
-                $ticket = $existing_ticket;
1405
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1406
-                //  Otherwise we have to create a new ticket.
1407
-                if ($create_new_ticket) {
1408
-                    // archive the old ticket first
1409
-                    $existing_ticket->set('TKT_deleted', 1);
1410
-                    $existing_ticket->save();
1411
-                    // make sure this ticket is still recorded in our $saved_tickets
1412
-                    // so we don't run it through the regular trash routine.
1413
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1414
-                    // create new ticket that's a copy of the existing except,
1415
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1416
-                    $new_ticket = clone $existing_ticket;
1417
-                    $new_ticket->set('TKT_ID', 0);
1418
-                    $new_ticket->set('TKT_deleted', 0);
1419
-                    $new_ticket->set('TKT_sold', 0);
1420
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1421
-                    $update_prices = true;
1422
-                    $ticket        = $new_ticket;
1423
-                }
1424
-            } else {
1425
-                // no TKT_id so a new ticket
1426
-                $ticket_values['TKT_price'] = $ticket_price;
1427
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428
-                $update_prices              = true;
1429
-            }
1430
-            if (! $ticket instanceof EE_Ticket) {
1431
-                throw new RuntimeException(
1432
-                    sprintf(
1433
-                        esc_html__(
1434
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1435
-                            'event_espresso'
1436
-                        ),
1437
-                        print_r($ticket_values, true)
1438
-                    )
1439
-                );
1440
-            }
1441
-            // cap ticket qty by datetime reg limits
1442
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1443
-            // update ticket.
1444
-            $ticket->save();
1445
-            // before going any further make sure our dates are setup correctly
1446
-            // so that the end date is always equal or greater than the start date.
1447
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1448
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1449
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1450
-                $ticket->save();
1451
-            }
1452
-            // initially let's add the ticket to the datetime
1453
-            $datetime->_add_relation_to($ticket, 'Ticket');
1454
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1455
-            // add prices to ticket
1456
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
-                ? $data['edit_prices'][ $row ]
1458
-                : [];
1459
-            $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460
-        }
1461
-        // however now we need to handle permanently deleting tickets via the ui.
1462
-        // Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1463
-        // However, it does allow for deleting tickets that have no tickets sold,
1464
-        // in which case we want to get rid of permanently because there is no need to save in db.
1465
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1466
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1467
-        foreach ($tickets_removed as $id) {
1468
-            $id = absint($id);
1469
-            // get the ticket for this id
1470
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1472
-                continue;
1473
-            }
1474
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1475
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1476
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1477
-            foreach ($related_datetimes as $related_datetime) {
1478
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1479
-            }
1480
-            // need to do the same for prices (except these prices can also be deleted because again,
1481
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1482
-            $ticket_to_remove->delete_related_permanently('Price');
1483
-            // finally let's delete this ticket
1484
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1485
-            $ticket_to_remove->delete_permanently();
1486
-        }
1487
-        return [$datetime, $saved_tickets];
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * This attaches a list of given prices to a ticket.
1493
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1494
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1495
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1496
-     *
1497
-     * @access  private
1498
-     * @param array     $prices_data Array of prices from the form.
1499
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1500
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1501
-     * @return  void
1502
-     * @throws EE_Error
1503
-     * @throws ReflectionException
1504
-     */
1505
-    private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1506
-    {
1507
-        $timezone = $ticket->get_timezone();
1508
-        foreach ($prices_data as $row => $price_data) {
1509
-            $price_values = [
1510
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1511
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1512
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1513
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1514
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1515
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1516
-                'PRC_order'      => $row,
1517
-            ];
1518
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1519
-                $price_values['PRC_ID'] = 0;
1520
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1521
-            } else {
1522
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1523
-                // update this price with new values
1524
-                foreach ($price_values as $field => $new_price) {
1525
-                    $price->set($field, $new_price);
1526
-                }
1527
-            }
1528
-            if (! $price instanceof EE_Price) {
1529
-                throw new RuntimeException(
1530
-                    sprintf(
1531
-                        esc_html__(
1532
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1533
-                            'event_espresso'
1534
-                        ),
1535
-                        print_r($price_values, true)
1536
-                    )
1537
-                );
1538
-            }
1539
-            $price->save();
1540
-            $ticket->_add_relation_to($price, 'Price');
1541
-        }
1542
-    }
1543
-
1544
-
1545
-    /**
1546
-     * Add in our autosave ajax handlers
1547
-     */
1548
-    protected function _ee_autosave_create_new()
1549
-    {
1550
-    }
1551
-
1552
-
1553
-    /**
1554
-     * More autosave handlers.
1555
-     */
1556
-    protected function _ee_autosave_edit()
1557
-    {
1558
-    }
1559
-
1560
-
1561
-    /**
1562
-     * @throws EE_Error
1563
-     * @throws ReflectionException
1564
-     */
1565
-    private function _generate_publish_box_extra_content()
1566
-    {
1567
-        // load formatter helper
1568
-        // args for getting related registrations
1569
-        $approved_query_args        = [
1570
-            [
1571
-                'REG_deleted' => 0,
1572
-                'STS_ID'      => RegStatus::APPROVED,
1573
-            ],
1574
-        ];
1575
-        $not_approved_query_args    = [
1576
-            [
1577
-                'REG_deleted' => 0,
1578
-                'STS_ID'      => RegStatus::AWAITING_REVIEW,
1579
-            ],
1580
-        ];
1581
-        $pending_payment_query_args = [
1582
-            [
1583
-                'REG_deleted' => 0,
1584
-                'STS_ID'      => RegStatus::PENDING_PAYMENT,
1585
-            ],
1586
-        ];
1587
-        // publish box
1588
-        $publish_box_extra_args = [
1589
-            'view_approved_reg_url'        => add_query_arg(
1590
-                [
1591
-                    'action'      => 'default',
1592
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1593
-                    '_reg_status' => RegStatus::APPROVED,
1594
-                    'use_filters' => true,
1595
-                ],
1596
-                REG_ADMIN_URL
1597
-            ),
1598
-            'view_not_approved_reg_url'    => add_query_arg(
1599
-                [
1600
-                    'action'      => 'default',
1601
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1602
-                    '_reg_status' => RegStatus::AWAITING_REVIEW,
1603
-                    'use_filters' => true,
1604
-                ],
1605
-                REG_ADMIN_URL
1606
-            ),
1607
-            'view_pending_payment_reg_url' => add_query_arg(
1608
-                [
1609
-                    'action'      => 'default',
1610
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1611
-                    '_reg_status' => RegStatus::PENDING_PAYMENT,
1612
-                    'use_filters' => true,
1613
-                ],
1614
-                REG_ADMIN_URL
1615
-            ),
1616
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1617
-                'Registration',
1618
-                $approved_query_args
1619
-            ),
1620
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1621
-                'Registration',
1622
-                $not_approved_query_args
1623
-            ),
1624
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1625
-                'Registration',
1626
-                $pending_payment_query_args
1627
-            ),
1628
-            'misc_pub_section_class'       => apply_filters(
1629
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1630
-                'misc-pub-section'
1631
-            ),
1632
-        ];
1633
-        ob_start();
1634
-        do_action(
1635
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1636
-            $this->_cpt_model_obj
1637
-        );
1638
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639
-        // load template
1640
-        EEH_Template::display_template(
1641
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1642
-            $publish_box_extra_args
1643
-        );
1644
-    }
1645
-
1646
-
1647
-    /**
1648
-     * @return EE_Event
1649
-     */
1650
-    public function get_event_object()
1651
-    {
1652
-        return $this->_cpt_model_obj;
1653
-    }
1654
-
1655
-
1656
-
1657
-
1658
-    /** METABOXES * */
1659
-    /**
1660
-     * _register_event_editor_meta_boxes
1661
-     * add all metaboxes related to the event_editor
1662
-     *
1663
-     * @return void
1664
-     * @throws EE_Error
1665
-     * @throws ReflectionException
1666
-     */
1667
-    protected function _register_event_editor_meta_boxes()
1668
-    {
1669
-        $this->verify_cpt_object();
1670
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673
-            $this->addMetaBox(
1674
-                'espresso_event_editor_event_options',
1675
-                esc_html__('Event Registration Options', 'event_espresso'),
1676
-                [$this, 'registration_options_meta_box'],
1677
-                $this->page_slug,
1678
-                'side'
1679
-            );
1680
-        }
1681
-        if (! $use_advanced_editor) {
1682
-            $this->addMetaBox(
1683
-                'espresso_event_editor_tickets',
1684
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1685
-                [$this, 'ticket_metabox'],
1686
-                $this->page_slug,
1687
-                'normal',
1688
-                'high'
1689
-            );
1690
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691
-            add_action(
1692
-                'add_meta_boxes_espresso_events',
1693
-                function () {
1694
-                    global $current_screen;
1695
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1696
-                },
1697
-                99
1698
-            );
1699
-        }
1700
-        // NOTE: if you're looking for other metaboxes in here,
1701
-        // where a metabox has a related management page in the admin
1702
-        // you will find it setup in the related management page's "_Hooks" file.
1703
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1704
-    }
1705
-
1706
-
1707
-    /**
1708
-     * @throws DomainException
1709
-     * @throws EE_Error
1710
-     * @throws ReflectionException
1711
-     */
1712
-    public function ticket_metabox()
1713
-    {
1714
-        $existing_datetime_ids = $existing_ticket_ids = [];
1715
-        // defaults for template args
1716
-        $template_args = [
1717
-            'ticket_rows'       => '',
1718
-            'total_ticket_rows' => 1,
1719
-            'trash_icon'        => 'dashicons dashicons-lock',
1720
-            'disabled'          => '',
1721
-        ];
1722
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723
-        /**
1724
-         * 1. Start with retrieving Datetimes
1725
-         * 2. Fore each datetime get related tickets
1726
-         * 3. For each ticket get related prices
1727
-         */
1728
-        /** @var EEM_Datetime $datetime_model */
1729
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1730
-        /** @var EEM_Ticket $datetime_model */
1731
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1732
-        $times        = $datetime_model->get_all_event_dates($event_id);
1733
-        /** @type EE_Datetime $first_datetime */
1734
-        $first_datetime = reset($times);
1735
-        // do we get related tickets?
1736
-        if (
1737
-            $first_datetime instanceof EE_Datetime
1738
-            && $first_datetime->ID() !== 0
1739
-        ) {
1740
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1741
-            $template_args['time']   = $first_datetime;
1742
-            $related_tickets         = $first_datetime->tickets(
1743
-                [
1744
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1745
-                    'default_where_conditions' => 'none',
1746
-                ]
1747
-            );
1748
-            if (! empty($related_tickets)) {
1749
-                $template_args['total_ticket_rows'] = count($related_tickets);
1750
-                $row                                = 0;
1751
-                foreach ($related_tickets as $ticket) {
1752
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1753
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754
-                    $row++;
1755
-                }
1756
-            } else {
1757
-                $template_args['total_ticket_rows'] = 1;
1758
-                /** @type EE_Ticket $ticket */
1759
-                $ticket                       = $ticket_model->create_default_object();
1760
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761
-            }
1762
-        } else {
1763
-            $template_args['time'] = $times[0];
1764
-            /** @type EE_Ticket[] $tickets */
1765
-            $tickets                      = $ticket_model->get_all_default_tickets();
1766
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767
-            // NOTE: we're just sending the first default row
1768
-            // (decaf can't manage default tickets so this should be sufficient);
1769
-        }
1770
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1771
-            'event_editor_event_datetimes_help_tab'
1772
-        );
1773
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1774
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1775
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1776
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1777
-            $ticket_model->create_default_object(),
1778
-            true
1779
-        );
1780
-        $template                                  = apply_filters(
1781
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1783
-        );
1784
-        EEH_Template::display_template($template, $template_args);
1785
-    }
1786
-
1787
-
1788
-    /**
1789
-     * Setup an individual ticket form for the decaf event editor page
1790
-     *
1791
-     * @access private
1792
-     * @param EE_Ticket $ticket   the ticket object
1793
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1794
-     * @param int       $row
1795
-     * @return string generated html for the ticket row.
1796
-     * @throws EE_Error
1797
-     * @throws ReflectionException
1798
-     */
1799
-    private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800
-    {
1801
-        $template_args = [
1802
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1803
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804
-                ? ' tkt-archived'
1805
-                : '',
1806
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1807
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1808
-            'TKT_name'            => $ticket->get('TKT_name'),
1809
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1810
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1811
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1812
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817
-                ? 'dashicons dashicons-post-trash clickable'
1818
-                : 'dashicons dashicons-lock entity-locked',
1819
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820
-                : ' disabled=disabled',
1821
-        ];
1822
-
1823
-        $price         = $ticket->ID() !== 0
1824
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1825
-            : null;
1826
-        $price         = $price instanceof EE_Price
1827
-            ? $price
1828
-            : EEM_Price::instance()->create_default_object();
1829
-        $price_args    = [
1830
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1831
-            'PRC_amount'            => $price->get('PRC_amount'),
1832
-            'PRT_ID'                => $price->get('PRT_ID'),
1833
-            'PRC_ID'                => $price->get('PRC_ID'),
1834
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1835
-        ];
1836
-        // make sure we have default start and end dates if skeleton
1837
-        // handle rows that should NOT be empty
1838
-        if (empty($template_args['TKT_start_date'])) {
1839
-            // if empty then the start date will be now.
1840
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1841
-        }
1842
-        if (empty($template_args['TKT_end_date'])) {
1843
-            // get the earliest datetime (if present);
1844
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1845
-                ? $this->_cpt_model_obj->get_first_related(
1846
-                    'Datetime',
1847
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1848
-                )
1849
-                : null;
1850
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1851
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1852
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1853
-        }
1854
-        $template_args = array_merge($template_args, $price_args);
1855
-        $template      = apply_filters(
1856
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1858
-            $ticket
1859
-        );
1860
-        return EEH_Template::display_template($template, $template_args, true);
1861
-    }
1862
-
1863
-
1864
-    /**
1865
-     * @throws EE_Error
1866
-     * @throws ReflectionException
1867
-     */
1868
-    public function registration_options_meta_box()
1869
-    {
1870
-        $yes_no_values             = [
1871
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873
-        ];
1874
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1875
-            [
1876
-                RegStatus::CANCELLED,
1877
-                RegStatus::DECLINED,
1878
-                RegStatus::INCOMPLETE,
1879
-            ],
1880
-            true
1881
-        );
1882
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1883
-        $template_args['_event']                          = $this->_cpt_model_obj;
1884
-        $template_args['event']                           = $this->_cpt_model_obj;
1885
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1886
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1887
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1888
-            'default_reg_status',
1889
-            $default_reg_status_values,
1890
-            $this->_cpt_model_obj->default_registration_status(),
1891
-            '',
1892
-            'ee-input-width--reg',
1893
-            false
1894
-        );
1895
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1896
-            'display_desc',
1897
-            $yes_no_values,
1898
-            $this->_cpt_model_obj->display_description()
1899
-        );
1900
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1901
-            'display_ticket_selector',
1902
-            $yes_no_values,
1903
-            $this->_cpt_model_obj->display_ticket_selector(),
1904
-            '',
1905
-            'ee-input-width--small',
1906
-            false
1907
-        );
1908
-        $template_args['additional_registration_options'] = apply_filters(
1909
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1910
-            '',
1911
-            $template_args,
1912
-            $yes_no_values,
1913
-            $default_reg_status_values
1914
-        );
1915
-        EEH_Template::display_template(
1916
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1917
-            $template_args
1918
-        );
1919
-    }
1920
-
1921
-
1922
-    /**
1923
-     * _get_events()
1924
-     * This method simply returns all the events (for the given _view and paging)
1925
-     *
1926
-     * @access public
1927
-     * @param int  $per_page     count of items per page (20 default);
1928
-     * @param int  $current_page what is the current page being viewed.
1929
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1930
-     *                           If FALSE then we return an array of event objects
1931
-     *                           that match the given _view and paging parameters.
1932
-     * @return array|int         an array of event objects or a count of them.
1933
-     * @throws Exception
1934
-     */
1935
-    public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1936
-    {
1937
-        $EEM_Event   = $this->_event_model();
1938
-        $offset      = ($current_page - 1) * $per_page;
1939
-        $limit       = $count ? null : $offset . ',' . $per_page;
1940
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941
-        $order       = $this->request->getRequestParam('order', 'DESC');
1942
-        $month_range = $this->request->getRequestParam('month_range');
1943
-        $where  = [];
1944
-        $status = $this->request->getRequestParam('status');
1945
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1946
-        // determine what post_status our condition will have for the query.
1947
-        switch ($status) {
1948
-            case 'month':
1949
-            case 'today':
1950
-            case null:
1951
-            case 'all':
1952
-                break;
1953
-            case 'draft':
1954
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1955
-                break;
1956
-            default:
1957
-                $where['status'] = $status;
1958
-        }
1959
-        // categories? The default for all categories is -1
1960
-        $category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1961
-        if ($category !== -1) {
1962
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1963
-            $where['Term_Taxonomy.term_id']  = $category;
1964
-        }
1965
-        // date where conditions
1966
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1967
-        if ($month_range) {
1968
-            $where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1969
-        } elseif ($status === 'today') {
1970
-            $DateTime                        = new DateTime(
1971
-                'now',
1972
-                new DateTimeZone($timezone_string)
1973
-            );
1974
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1975
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1976
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
-        } elseif ($status === 'month') {
1978
-            $now                             = date('Y-m-01');
1979
-            $DateTime                        = new DateTime(
1980
-                $now,
1981
-                new DateTimeZone($timezone_string)
1982
-            );
1983
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1984
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1985
-                                                        ->setTime(23, 59, 59)
1986
-                                                        ->format(implode(' ', $start_formats));
1987
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988
-        }
1989
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990
-            $where['EVT_wp_user'] = get_current_user_id();
1991
-        } else {
1992
-            if (! isset($where['status'])) {
1993
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994
-                    $where['OR'] = [
1995
-                        'status*restrict_private' => ['!=', 'private'],
1996
-                        'AND'                     => [
1997
-                            'status*inclusive' => ['=', 'private'],
1998
-                            'EVT_wp_user'      => get_current_user_id(),
1999
-                        ],
2000
-                    ];
2001
-                }
2002
-            }
2003
-        }
2004
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2005
-        if (
2006
-            $wp_user
2007
-            && $wp_user !== get_current_user_id()
2008
-            && $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2009
-        ) {
2010
-            $where['EVT_wp_user'] = $wp_user;
2011
-        }
2012
-        // search query handling
2013
-        $search_term = $this->request->getRequestParam('s');
2014
-        if ($search_term) {
2015
-            $search_term = '%' . $search_term . '%';
2016
-            $where['OR'] = [
2017
-                'EVT_name'       => ['LIKE', $search_term],
2018
-                'EVT_desc'       => ['LIKE', $search_term],
2019
-                'EVT_short_desc' => ['LIKE', $search_term],
2020
-            ];
2021
-        }
2022
-        // filter events by venue.
2023
-        $venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2024
-        if ($venue) {
2025
-            $where['Venue.VNU_ID'] = $venue;
2026
-        }
2027
-        $request_params = $this->request->requestParams();
2028
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2029
-        $query_params   = apply_filters(
2030
-            'FHEE__Events_Admin_Page__get_events__query_params',
2031
-            [
2032
-                $where,
2033
-                'limit'    => $limit,
2034
-                'order_by' => $orderby,
2035
-                'order'    => $order,
2036
-                'group_by' => 'EVT_ID',
2037
-            ],
2038
-            $request_params
2039
-        );
2040
-
2041
-        // let's first check if we have special requests coming in.
2042
-        $active_status = $this->request->getRequestParam('active_status');
2043
-        if ($active_status) {
2044
-            switch ($active_status) {
2045
-                case 'upcoming':
2046
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2047
-                case 'expired':
2048
-                    return $EEM_Event->get_expired_events($query_params, $count);
2049
-                case 'active':
2050
-                    return $EEM_Event->get_active_events($query_params, $count);
2051
-                case 'inactive':
2052
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2053
-            }
2054
-        }
2055
-
2056
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2057
-    }
2058
-
2059
-
2060
-    /**
2061
-     * @param string $month_range
2062
-     * @param string $timezone_string
2063
-     * @return array
2064
-     * @throws Exception
2065
-     * @since 5.0.21.p
2066
-     */
2067
-    public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2068
-    {
2069
-        $timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2070
-        $pieces = explode(' ', $month_range, 3);
2071
-        // simulate the FIRST day of the month, that fixes issues for months like February
2072
-        // where PHP doesn't know what to assume for date.
2073
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2074
-        $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2075
-        $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2076
-        $DateTime = new DateTime(
2077
-            "$year_r-$month_r-01 00:00:00",
2078
-            new DateTimeZone($timezone_string)
2079
-        );
2080
-        $start    = $DateTime->getTimestamp();
2081
-        // set the datetime to be the end of the month
2082
-        $DateTime->setDate(
2083
-            $year_r,
2084
-            $month_r,
2085
-            $DateTime->format('t')
2086
-        )->setTime(23, 59, 59);
2087
-        $end                             = $DateTime->getTimestamp();
2088
-        return ['BETWEEN', [$start, $end]];
2089
-    }
2090
-
2091
-
2092
-    /**
2093
-     * handling for WordPress CPT actions (trash, restore, delete)
2094
-     *
2095
-     * @param string $post_id
2096
-     * @throws EE_Error
2097
-     * @throws ReflectionException
2098
-     */
2099
-    public function trash_cpt_item($post_id)
2100
-    {
2101
-        $this->request->setRequestParam('EVT_ID', $post_id);
2102
-        $this->_trash_or_restore_event('trash', false);
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * @param string $post_id
2108
-     * @throws EE_Error
2109
-     * @throws ReflectionException
2110
-     */
2111
-    public function restore_cpt_item($post_id)
2112
-    {
2113
-        $this->request->setRequestParam('EVT_ID', $post_id);
2114
-        $this->_trash_or_restore_event('draft', false);
2115
-    }
2116
-
2117
-
2118
-    /**
2119
-     * @param string $post_id
2120
-     * @throws EE_Error
2121
-     * @throws EE_Error
2122
-     */
2123
-    public function delete_cpt_item($post_id)
2124
-    {
2125
-        throw new EE_Error(
2126
-            esc_html__(
2127
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2128
-                'event_espresso'
2129
-            )
2130
-        );
2131
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2132
-        // $this->_delete_event();
2133
-    }
2134
-
2135
-
2136
-    /**
2137
-     * _trash_or_restore_event
2138
-     *
2139
-     * @access protected
2140
-     * @param string $event_status
2141
-     * @param bool   $redirect_after
2142
-     * @throws EE_Error
2143
-     * @throws EE_Error
2144
-     * @throws ReflectionException
2145
-     */
2146
-    protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2147
-    {
2148
-        // loop thru events
2149
-        if ($this->EVT_ID) {
2150
-            // clean status
2151
-            $event_status = sanitize_key($event_status);
2152
-            // grab status
2153
-            if (! empty($event_status)) {
2154
-                $success = $this->_change_event_status($this->EVT_ID, $event_status);
2155
-            } else {
2156
-                $success = false;
2157
-                $msg     = esc_html__(
2158
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2159
-                    'event_espresso'
2160
-                );
2161
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2162
-            }
2163
-        } else {
2164
-            $success = false;
2165
-            $msg     = esc_html__(
2166
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2167
-                'event_espresso'
2168
-            );
2169
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2170
-        }
2171
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2172
-        if ($redirect_after) {
2173
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2174
-        }
2175
-    }
2176
-
2177
-
2178
-    /**
2179
-     * _trash_or_restore_events
2180
-     *
2181
-     * @access protected
2182
-     * @param string $event_status
2183
-     * @return void
2184
-     * @throws EE_Error
2185
-     * @throws EE_Error
2186
-     * @throws ReflectionException
2187
-     */
2188
-    protected function _trash_or_restore_events(string $event_status = 'trash')
2189
-    {
2190
-        // clean status
2191
-        $event_status = sanitize_key($event_status);
2192
-        // grab status
2193
-        if (! empty($event_status)) {
2194
-            $success = true;
2195
-            // determine the event id and set to array.
2196
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2197
-            // loop thru events
2198
-            foreach ($EVT_IDs as $EVT_ID) {
2199
-                if ($EVT_ID = absint($EVT_ID)) {
2200
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2201
-                    $success = $results !== false ? $success : false;
2202
-                } else {
2203
-                    $msg = sprintf(
2204
-                        esc_html__(
2205
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2206
-                            'event_espresso'
2207
-                        ),
2208
-                        $EVT_ID
2209
-                    );
2210
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2211
-                    $success = false;
2212
-                }
2213
-            }
2214
-        } else {
2215
-            $success = false;
2216
-            $msg     = esc_html__(
2217
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2218
-                'event_espresso'
2219
-            );
2220
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2221
-        }
2222
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2223
-        $success = $success ? 2 : false;
2224
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2225
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2226
-    }
2227
-
2228
-
2229
-    /**
2230
-     * @param int    $EVT_ID
2231
-     * @param string $event_status
2232
-     * @return bool
2233
-     * @throws EE_Error
2234
-     * @throws ReflectionException
2235
-     */
2236
-    private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237
-    {
2238
-        // grab event id
2239
-        if (! $EVT_ID) {
2240
-            $msg = esc_html__(
2241
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2242
-                'event_espresso'
2243
-            );
2244
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2245
-            return false;
2246
-        }
2247
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2248
-        // clean status
2249
-        $event_status = sanitize_key($event_status);
2250
-        // grab status
2251
-        if (empty($event_status)) {
2252
-            $msg = esc_html__(
2253
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2254
-                'event_espresso'
2255
-            );
2256
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2257
-            return false;
2258
-        }
2259
-        // was event trashed or restored ?
2260
-        switch ($event_status) {
2261
-            case 'draft':
2262
-                $action = 'restored from the trash';
2263
-                $hook   = 'AHEE_event_restored_from_trash';
2264
-                break;
2265
-            case 'trash':
2266
-                $action = 'moved to the trash';
2267
-                $hook   = 'AHEE_event_moved_to_trash';
2268
-                break;
2269
-            default:
2270
-                $action = 'updated';
2271
-                $hook   = false;
2272
-        }
2273
-        // use class to change status
2274
-        $this->_cpt_model_obj->set_status($event_status);
2275
-        $success = $this->_cpt_model_obj->save();
2276
-        if (! $success) {
2277
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279
-            return false;
2280
-        }
2281
-        if ($hook) {
2282
-            do_action($hook);
2283
-            // fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2284
-            // because events side step that and it otherwise won't get called
2285
-            do_action(
2286
-                'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2287
-                $this->_cpt_model_obj,
2288
-                $hook === 'AHEE_event_moved_to_trash',
2289
-                $success
2290
-            );
2291
-        }
2292
-        return true;
2293
-    }
2294
-
2295
-
2296
-    /**
2297
-     * @param array $event_ids
2298
-     * @return array
2299
-     * @since   4.10.23.p
2300
-     */
2301
-    private function cleanEventIds(array $event_ids): array
2302
-    {
2303
-        return array_map('absint', $event_ids);
2304
-    }
2305
-
2306
-
2307
-    /**
2308
-     * @return array
2309
-     * @since   4.10.23.p
2310
-     */
2311
-    private function getEventIdsFromRequest(): array
2312
-    {
2313
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2314
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2315
-        } else {
2316
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2317
-        }
2318
-    }
2319
-
2320
-
2321
-    /**
2322
-     * @param bool $preview_delete
2323
-     * @throws EE_Error
2324
-     * @throws ReflectionException
2325
-     */
2326
-    protected function _delete_event(bool $preview_delete = true)
2327
-    {
2328
-        $this->_delete_events($preview_delete);
2329
-    }
2330
-
2331
-
2332
-    /**
2333
-     * Gets the tree traversal batch persister.
2334
-     *
2335
-     * @return NodeGroupDao
2336
-     * @throws InvalidArgumentException
2337
-     * @throws InvalidDataTypeException
2338
-     * @throws InvalidInterfaceException
2339
-     * @since 4.10.12.p
2340
-     */
2341
-    protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342
-    {
2343
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344
-            $this->model_obj_node_group_persister =
2345
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346
-        }
2347
-        return $this->model_obj_node_group_persister;
2348
-    }
2349
-
2350
-
2351
-    /**
2352
-     * @param bool $preview_delete
2353
-     * @return void
2354
-     * @throws EE_Error
2355
-     * @throws ReflectionException
2356
-     */
2357
-    protected function _delete_events(bool $preview_delete = true)
2358
-    {
2359
-        $event_ids = $this->getEventIdsFromRequest();
2360
-        if ($preview_delete) {
2361
-            $this->generateDeletionPreview($event_ids);
2362
-        } else {
2363
-            foreach ($event_ids as $event_id) {
2364
-                $event = EEM_Event::instance()->get_one_by_ID($event_id);
2365
-                if ($event instanceof EE_Event) {
2366
-                    $event->delete_permanently();
2367
-                }
2368
-            }
2369
-        }
2370
-    }
2371
-
2372
-
2373
-    /**
2374
-     * @param array $event_ids
2375
-     */
2376
-    protected function generateDeletionPreview(array $event_ids)
2377
-    {
2378
-        $event_ids = $this->cleanEventIds($event_ids);
2379
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2380
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2381
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2382
-            [
2383
-                'action'            => 'preview_deletion',
2384
-                'deletion_job_code' => $deletion_job_code,
2385
-            ],
2386
-            $this->_admin_base_url
2387
-        );
2388
-        EEH_URL::safeRedirectAndExit(
2389
-            EE_Admin_Page::add_query_args_and_nonce(
2390
-                [
2391
-                    'page'              => EED_Batch::PAGE_SLUG,
2392
-                    'batch'             => EED_Batch::batch_job,
2393
-                    'EVT_IDs'           => $event_ids,
2394
-                    'deletion_job_code' => $deletion_job_code,
2395
-                    'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2396
-                    'return_url'        => urlencode($return_url),
2397
-                ],
2398
-                admin_url()
2399
-            )
2400
-        );
2401
-    }
2402
-
2403
-
2404
-    /**
2405
-     * Checks for a POST submission
2406
-     *
2407
-     * @since 4.10.12.p
2408
-     */
2409
-    protected function confirmDeletion()
2410
-    {
2411
-        $deletion_redirect_logic = $this->getLoader()->getShared(
2412
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2413
-        );
2414
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2415
-    }
2416
-
2417
-
2418
-    /**
2419
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2420
-     *
2421
-     * @throws EE_Error
2422
-     * @since 4.10.12.p
2423
-     */
2424
-    protected function previewDeletion()
2425
-    {
2426
-        $preview_deletion_logic = $this->getLoader()->getShared(
2427
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2428
-        );
2429
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2430
-        $this->display_admin_page_with_no_sidebar();
2431
-    }
2432
-
2433
-
2434
-    /**
2435
-     * get total number of events
2436
-     *
2437
-     * @access public
2438
-     * @return int
2439
-     * @throws EE_Error
2440
-     * @throws EE_Error
2441
-     * @throws ReflectionException
2442
-     */
2443
-    public function total_events(): int
2444
-    {
2445
-        return EEM_Event::instance()->count(
2446
-            ['caps' => 'read_admin'],
2447
-            'EVT_ID',
2448
-            true
2449
-        );
2450
-    }
2451
-
2452
-
2453
-    /**
2454
-     * get total number of draft events
2455
-     *
2456
-     * @access public
2457
-     * @return int
2458
-     * @throws EE_Error
2459
-     * @throws EE_Error
2460
-     * @throws ReflectionException
2461
-     */
2462
-    public function total_events_draft(): int
2463
-    {
2464
-        return EEM_Event::instance()->count(
2465
-            [
2466
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2467
-                'caps' => 'read_admin',
2468
-            ],
2469
-            'EVT_ID',
2470
-            true
2471
-        );
2472
-    }
2473
-
2474
-
2475
-    /**
2476
-     * get total number of trashed events
2477
-     *
2478
-     * @access public
2479
-     * @return int
2480
-     * @throws EE_Error
2481
-     * @throws EE_Error
2482
-     * @throws ReflectionException
2483
-     */
2484
-    public function total_trashed_events(): int
2485
-    {
2486
-        return EEM_Event::instance()->count(
2487
-            [
2488
-                ['status' => 'trash'],
2489
-                'caps' => 'read_admin',
2490
-            ],
2491
-            'EVT_ID',
2492
-            true
2493
-        );
2494
-    }
2495
-
2496
-
2497
-    /**
2498
-     *    _default_event_settings
2499
-     *    This generates the Default Settings Tab
2500
-     *
2501
-     * @return void
2502
-     * @throws DomainException
2503
-     * @throws EE_Error
2504
-     * @throws InvalidArgumentException
2505
-     * @throws InvalidDataTypeException
2506
-     * @throws InvalidInterfaceException
2507
-     * @throws ReflectionException
2508
-     */
2509
-    protected function _default_event_settings()
2510
-    {
2511
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2512
-        $this->_set_publish_post_box_vars();
2513
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
2514
-            $this->_default_event_settings_form()->get_html(),
2515
-            '',
2516
-            'padding'
2517
-        );
2518
-        $this->display_admin_page_with_sidebar();
2519
-    }
2520
-
2521
-
2522
-    /**
2523
-     * Return the form for event settings.
2524
-     *
2525
-     * @return EE_Form_Section_Proper
2526
-     * @throws EE_Error
2527
-     * @throws ReflectionException
2528
-     */
2529
-    protected function _default_event_settings_form(): EE_Form_Section_Proper
2530
-    {
2531
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2532
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2533
-        // exclude
2534
-            [
2535
-                RegStatus::CANCELLED,
2536
-                RegStatus::DECLINED,
2537
-                RegStatus::INCOMPLETE,
2538
-                RegStatus::WAIT_LIST,
2539
-            ],
2540
-            true
2541
-        );
2542
-        // setup Advanced Editor ???
2543
-        if (
2544
-            $this->raw_req_action === 'default_event_settings'
2545
-            || $this->raw_req_action === 'update_default_event_settings'
2546
-        ) {
2547
-            $this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2548
-        }
2549
-        return new EE_Form_Section_Proper(
2550
-            [
2551
-                'name'            => 'update_default_event_settings',
2552
-                'html_id'         => 'update_default_event_settings',
2553
-                'html_class'      => 'form-table',
2554
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2555
-                'subsections'     => apply_filters(
2556
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2557
-                    [
2558
-                        'defaults_section_header' => new EE_Form_Section_HTML(
2559
-                            EEH_HTML::h2(
2560
-                                esc_html__('Default Settings', 'event_espresso'),
2561
-                                '',
2562
-                                'ee-admin-settings-hdr'
2563
-                            )
2564
-                        ),
2565
-                        'default_reg_status'      => new EE_Select_Input(
2566
-                            $registration_stati_for_selection,
2567
-                            [
2568
-                                'default'         => isset($registration_config->default_STS_ID)
2569
-                                                     && array_key_exists(
2570
-                                                         $registration_config->default_STS_ID,
2571
-                                                         $registration_stati_for_selection
2572
-                                                     )
2573
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2574
-                                    : RegStatus::PENDING_PAYMENT,
2575
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2576
-                                                     . EEH_Template::get_help_tab_link(
2577
-                                        'default_settings_status_help_tab'
2578
-                                    ),
2579
-                                'html_help_text'  => esc_html__(
2580
-                                    '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.',
2581
-                                    'event_espresso'
2582
-                                ),
2583
-                                'html_class'      => 'ee-input-width--small',
2584
-                            ]
2585
-                        ),
2586
-                        'default_max_tickets'     => new EE_Integer_Input(
2587
-                            [
2588
-                                'default'         => $registration_config->default_maximum_number_of_tickets
2589
-                                                     ?? EEM_Event::get_default_additional_limit(),
2590
-                                'html_label_text' => esc_html__(
2591
-                                                         'Default Maximum Tickets Allowed Per Order:',
2592
-                                                         'event_espresso'
2593
-                                                     )
2594
-                                                     . EEH_Template::get_help_tab_link(
2595
-                                        'default_maximum_tickets_help_tab"'
2596
-                                    ),
2597
-                                'html_help_text'  => esc_html__(
2598
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2599
-                                    'event_espresso'
2600
-                                ),
2601
-                                'html_class'      => 'ee-input-width--tiny',
2602
-                            ]
2603
-                        ),
2604
-                    ]
2605
-                ),
2606
-            ]
2607
-        );
2608
-    }
2609
-
2610
-
2611
-    /**
2612
-     * @return void
2613
-     * @throws EE_Error
2614
-     * @throws InvalidArgumentException
2615
-     * @throws InvalidDataTypeException
2616
-     * @throws InvalidInterfaceException
2617
-     * @throws ReflectionException
2618
-     */
2619
-    protected function _update_default_event_settings()
2620
-    {
2621
-        $form = $this->_default_event_settings_form();
2622
-        if ($form->was_submitted()) {
2623
-            $form->receive_form_submission();
2624
-            if ($form->is_valid()) {
2625
-                $registration_config = EE_Registry::instance()->CFG->registration;
2626
-                $valid_data          = $form->valid_data();
2627
-                if (isset($valid_data['default_reg_status'])) {
2628
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2629
-                }
2630
-                if (isset($valid_data['default_max_tickets'])) {
2631
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2632
-                }
2633
-                do_action(
2634
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2635
-                    $valid_data,
2636
-                    EE_Registry::instance()->CFG,
2637
-                    $this
2638
-                );
2639
-                // update because data was valid!
2640
-                EE_Registry::instance()->CFG->update_espresso_config();
2641
-                EE_Error::overwrite_success();
2642
-                EE_Error::add_success(
2643
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2644
-                );
2645
-            }
2646
-        }
2647
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2648
-    }
2649
-
2650
-
2651
-    /*************        Templates        *************
2652
-     *
2653
-     * @throws EE_Error
2654
-     */
2655
-    protected function _template_settings()
2656
-    {
2657
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2658
-        $this->_template_args['preview_img']  = '<img src="'
2659
-                                                . EVENTS_ASSETS_URL
2660
-                                                . '/images/'
2661
-                                                . 'caffeinated_template_features.jpg" alt="'
2662
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2663
-                                                . '" />';
2664
-        $this->_template_args['preview_text'] = '<strong>'
2665
-                                                . esc_html__(
2666
-                                                    '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.',
2667
-                                                    'event_espresso'
2668
-                                                ) . '</strong>';
2669
-        $this->display_admin_caf_preview_page('template_settings_tab');
2670
-    }
2671
-
2672
-
2673
-    /** Event Category Stuff **/
2674
-    /**
2675
-     * set the _category property with the category object for the loaded page.
2676
-     *
2677
-     * @access private
2678
-     * @return void
2679
-     */
2680
-    private function _set_category_object()
2681
-    {
2682
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2683
-            return;
2684
-        } //already have the category object so get out.
2685
-        // set default category object
2686
-        $this->_set_empty_category_object();
2687
-        // only set if we've got an id
2688
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
-        if (! $category_ID) {
2690
-            return;
2691
-        }
2692
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
-        if (! empty($term)) {
2694
-            $this->_category->category_name       = $term->name;
2695
-            $this->_category->category_identifier = $term->slug;
2696
-            $this->_category->category_desc       = $term->description;
2697
-            $this->_category->id                  = $term->term_id;
2698
-            $this->_category->parent              = $term->parent;
2699
-        }
2700
-    }
2701
-
2702
-
2703
-    /**
2704
-     * Clears out category properties.
2705
-     */
2706
-    private function _set_empty_category_object()
2707
-    {
2708
-        $this->_category                = new stdClass();
2709
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2710
-        $this->_category->id            = $this->_category->parent = 0;
2711
-    }
2712
-
2713
-
2714
-    /**
2715
-     * @throws DomainException
2716
-     * @throws EE_Error
2717
-     * @throws InvalidArgumentException
2718
-     * @throws InvalidDataTypeException
2719
-     * @throws InvalidInterfaceException
2720
-     */
2721
-    protected function _category_list_table()
2722
-    {
2723
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2724
-        $this->_admin_page_title .= ' ';
2725
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2726
-            'add_category',
2727
-            'add_category',
2728
-            [],
2729
-            'add-new-h2'
2730
-        );
2731
-        $this->display_admin_list_table_page_with_sidebar();
2732
-    }
2733
-
2734
-
2735
-    /**
2736
-     * Output category details view.
2737
-     *
2738
-     * @throws EE_Error
2739
-     * @throws EE_Error
2740
-     */
2741
-    protected function _category_details($view)
2742
-    {
2743
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2744
-        $this->_set_add_edit_form_tags($route);
2745
-        $this->_set_category_object();
2746
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2747
-        $delete_action = 'delete_category';
2748
-        // custom redirect
2749
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2750
-            ['action' => 'category_list'],
2751
-            $this->_admin_base_url
2752
-        );
2753
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2754
-        // take care of contents
2755
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2756
-        $this->display_admin_page_with_sidebar();
2757
-    }
2758
-
2759
-
2760
-    /**
2761
-     * Output category details content.
2762
-     *
2763
-     * @throws DomainException
2764
-     */
2765
-    protected function _category_details_content(): string
2766
-    {
2767
-        $editor_args['category_desc'] = [
2768
-            'type'          => 'wp_editor',
2769
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2770
-            'class'         => 'my_editor_custom',
2771
-            'wpeditor_args' => ['media_buttons' => false],
2772
-        ];
2773
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2774
-        $all_terms                    = get_terms(
2775
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2776
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2777
-        );
2778
-        // setup category select for term parents.
2779
-        $category_select_values[] = [
2780
-            'text' => esc_html__('No Parent', 'event_espresso'),
2781
-            'id'   => 0,
2782
-        ];
2783
-        foreach ($all_terms as $term) {
2784
-            $category_select_values[] = [
2785
-                'text' => $term->name,
2786
-                'id'   => $term->term_id,
2787
-            ];
2788
-        }
2789
-        $category_select = EEH_Form_Fields::select_input(
2790
-            'category_parent',
2791
-            $category_select_values,
2792
-            $this->_category->parent
2793
-        );
2794
-        $template_args   = [
2795
-            'category'                 => $this->_category,
2796
-            'category_select'          => $category_select,
2797
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2798
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2799
-            'disable'                  => '',
2800
-            'disabled_message'         => false,
2801
-        ];
2802
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2803
-        return EEH_Template::display_template($template, $template_args, true);
2804
-    }
2805
-
2806
-
2807
-    /**
2808
-     * Handles deleting categories.
2809
-     *
2810
-     * @throws EE_Error
2811
-     */
2812
-    protected function _delete_categories()
2813
-    {
2814
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2815
-        foreach ($category_IDs as $category_ID) {
2816
-            $this->_delete_category($category_ID);
2817
-        }
2818
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2819
-        $query_args = [
2820
-            'action' => 'category_list',
2821
-        ];
2822
-        $this->_redirect_after_action(0, '', '', $query_args);
2823
-    }
2824
-
2825
-
2826
-    /**
2827
-     * Handles deleting specific category.
2828
-     *
2829
-     * @param int $cat_id
2830
-     */
2831
-    protected function _delete_category(int $cat_id)
2832
-    {
2833
-        $cat_id = absint($cat_id);
2834
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2835
-    }
2836
-
2837
-
2838
-    /**
2839
-     * Handles triggering the update or insertion of a new category.
2840
-     *
2841
-     * @param bool $new_category true means we're triggering the insert of a new category.
2842
-     * @throws EE_Error
2843
-     * @throws EE_Error
2844
-     */
2845
-    protected function _insert_or_update_category(bool $new_category)
2846
-    {
2847
-        $cat_id  = $this->_insert_category($new_category);
2848
-        $success = 0; // we already have a success message so lets not send another.
2849
-        if ($cat_id) {
2850
-            $query_args = [
2851
-                'action'     => 'edit_category',
2852
-                'EVT_CAT_ID' => $cat_id,
2853
-            ];
2854
-        } else {
2855
-            $query_args = ['action' => 'add_category'];
2856
-        }
2857
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2858
-    }
2859
-
2860
-
2861
-    /**
2862
-     * Inserts or updates category
2863
-     *
2864
-     * @param bool $new_category (true indicates we're updating a category).
2865
-     * @return bool|mixed|string
2866
-     */
2867
-    private function _insert_category(bool $new_category)
2868
-    {
2869
-        $category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2870
-        $category_name       = $this->request->getRequestParam('category_name', '');
2871
-        $category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2872
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2873
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2874
-
2875
-        if (empty($category_name)) {
2876
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2877
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2878
-            return 0;
2879
-        }
2880
-        $term_args = [
2881
-            'name'        => $category_name,
2882
-            'description' => $category_desc,
2883
-            'parent'      => $category_parent,
2884
-        ];
2885
-        // was the category_identifier input disabled?
2886
-        if ($category_identifier) {
2887
-            $term_args['slug'] = $category_identifier;
2888
-        }
2889
-        $insert_ids = $new_category
2890
-            ? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2891
-            : wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2892
-
2893
-        if ($insert_ids instanceof WP_Error) {
2894
-            EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2895
-            return 0;
2896
-        }
2897
-        $category_ID = $insert_ids['term_id'] ?? 0;
2898
-        if (! $category_ID) {
2899
-            EE_Error::add_error(
2900
-                esc_html__(
2901
-                    'An error occurred and the category has not been saved to the database.',
2902
-                    'event_espresso'
2903
-                ),
2904
-                __FILE__,
2905
-                __FUNCTION__,
2906
-                __LINE__
2907
-            );
2908
-            return 0;
2909
-        }
2910
-        EE_Error::add_success(
2911
-            sprintf(
2912
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2913
-                $category_name
2914
-            )
2915
-        );
2916
-        return $category_ID;
2917
-    }
2918
-
2919
-
2920
-    /**
2921
-     * Gets categories or count of categories matching the arguments in the request.
2922
-     *
2923
-     * @param int  $per_page
2924
-     * @param int  $current_page
2925
-     * @param bool $count
2926
-     * @return EE_Term_Taxonomy[]|int
2927
-     * @throws EE_Error
2928
-     * @throws ReflectionException
2929
-     */
2930
-    public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2931
-    {
2932
-        // testing term stuff
2933
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2934
-        $order       = $this->request->getRequestParam('order', 'DESC');
2935
-        $limit       = ($current_page - 1) * $per_page;
2936
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937
-        $search_term = $this->request->getRequestParam('s');
2938
-        if ($search_term) {
2939
-            $search_term = '%' . $search_term . '%';
2940
-            $where['OR'] = [
2941
-                'Term.name'   => ['LIKE', $search_term],
2942
-                'description' => ['LIKE', $search_term],
2943
-            ];
2944
-        }
2945
-        $query_params = [
2946
-            $where,
2947
-            'order_by'   => [$orderby => $order],
2948
-            'limit'      => $limit . ',' . $per_page,
2949
-            'force_join' => ['Term'],
2950
-        ];
2951
-        return $count
2952
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2953
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2954
-    }
2955
-
2956
-    /* end category stuff */
2957
-
2958
-
2959
-    /**************/
2960
-
2961
-
2962
-    /**
2963
-     * Callback for the `ee_save_timezone_setting` ajax action.
2964
-     *
2965
-     * @throws EE_Error
2966
-     * @throws InvalidArgumentException
2967
-     * @throws InvalidDataTypeException
2968
-     * @throws InvalidInterfaceException
2969
-     */
2970
-    public function saveTimezoneString()
2971
-    {
2972
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2973
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2974
-            EE_Error::add_error(
2975
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2976
-                __FILE__,
2977
-                __FUNCTION__,
2978
-                __LINE__
2979
-            );
2980
-            $this->_template_args['error'] = true;
2981
-            $this->_return_json();
2982
-        }
2983
-
2984
-        update_option('timezone_string', $timezone_string);
2985
-        EE_Error::add_success(
2986
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2987
-        );
2988
-        $this->_template_args['success'] = true;
2989
-        $this->_return_json(true, ['action' => 'create_new']);
2990
-    }
2991
-
2992
-
2993
-    /**
2994 2653
      * @throws EE_Error
2995
-     * @deprecated 4.10.25.p
2996 2654
      */
2997
-    public function save_timezonestring_setting()
2998
-    {
2999
-        $this->saveTimezoneString();
3000
-    }
2655
+	protected function _template_settings()
2656
+	{
2657
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2658
+		$this->_template_args['preview_img']  = '<img src="'
2659
+												. EVENTS_ASSETS_URL
2660
+												. '/images/'
2661
+												. 'caffeinated_template_features.jpg" alt="'
2662
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2663
+												. '" />';
2664
+		$this->_template_args['preview_text'] = '<strong>'
2665
+												. esc_html__(
2666
+													'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.',
2667
+													'event_espresso'
2668
+												) . '</strong>';
2669
+		$this->display_admin_caf_preview_page('template_settings_tab');
2670
+	}
2671
+
2672
+
2673
+	/** Event Category Stuff **/
2674
+	/**
2675
+	 * set the _category property with the category object for the loaded page.
2676
+	 *
2677
+	 * @access private
2678
+	 * @return void
2679
+	 */
2680
+	private function _set_category_object()
2681
+	{
2682
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2683
+			return;
2684
+		} //already have the category object so get out.
2685
+		// set default category object
2686
+		$this->_set_empty_category_object();
2687
+		// only set if we've got an id
2688
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
+		if (! $category_ID) {
2690
+			return;
2691
+		}
2692
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
+		if (! empty($term)) {
2694
+			$this->_category->category_name       = $term->name;
2695
+			$this->_category->category_identifier = $term->slug;
2696
+			$this->_category->category_desc       = $term->description;
2697
+			$this->_category->id                  = $term->term_id;
2698
+			$this->_category->parent              = $term->parent;
2699
+		}
2700
+	}
2701
+
2702
+
2703
+	/**
2704
+	 * Clears out category properties.
2705
+	 */
2706
+	private function _set_empty_category_object()
2707
+	{
2708
+		$this->_category                = new stdClass();
2709
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2710
+		$this->_category->id            = $this->_category->parent = 0;
2711
+	}
2712
+
2713
+
2714
+	/**
2715
+	 * @throws DomainException
2716
+	 * @throws EE_Error
2717
+	 * @throws InvalidArgumentException
2718
+	 * @throws InvalidDataTypeException
2719
+	 * @throws InvalidInterfaceException
2720
+	 */
2721
+	protected function _category_list_table()
2722
+	{
2723
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2724
+		$this->_admin_page_title .= ' ';
2725
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2726
+			'add_category',
2727
+			'add_category',
2728
+			[],
2729
+			'add-new-h2'
2730
+		);
2731
+		$this->display_admin_list_table_page_with_sidebar();
2732
+	}
2733
+
2734
+
2735
+	/**
2736
+	 * Output category details view.
2737
+	 *
2738
+	 * @throws EE_Error
2739
+	 * @throws EE_Error
2740
+	 */
2741
+	protected function _category_details($view)
2742
+	{
2743
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2744
+		$this->_set_add_edit_form_tags($route);
2745
+		$this->_set_category_object();
2746
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2747
+		$delete_action = 'delete_category';
2748
+		// custom redirect
2749
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2750
+			['action' => 'category_list'],
2751
+			$this->_admin_base_url
2752
+		);
2753
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2754
+		// take care of contents
2755
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2756
+		$this->display_admin_page_with_sidebar();
2757
+	}
2758
+
2759
+
2760
+	/**
2761
+	 * Output category details content.
2762
+	 *
2763
+	 * @throws DomainException
2764
+	 */
2765
+	protected function _category_details_content(): string
2766
+	{
2767
+		$editor_args['category_desc'] = [
2768
+			'type'          => 'wp_editor',
2769
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2770
+			'class'         => 'my_editor_custom',
2771
+			'wpeditor_args' => ['media_buttons' => false],
2772
+		];
2773
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2774
+		$all_terms                    = get_terms(
2775
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2776
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2777
+		);
2778
+		// setup category select for term parents.
2779
+		$category_select_values[] = [
2780
+			'text' => esc_html__('No Parent', 'event_espresso'),
2781
+			'id'   => 0,
2782
+		];
2783
+		foreach ($all_terms as $term) {
2784
+			$category_select_values[] = [
2785
+				'text' => $term->name,
2786
+				'id'   => $term->term_id,
2787
+			];
2788
+		}
2789
+		$category_select = EEH_Form_Fields::select_input(
2790
+			'category_parent',
2791
+			$category_select_values,
2792
+			$this->_category->parent
2793
+		);
2794
+		$template_args   = [
2795
+			'category'                 => $this->_category,
2796
+			'category_select'          => $category_select,
2797
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2798
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2799
+			'disable'                  => '',
2800
+			'disabled_message'         => false,
2801
+		];
2802
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2803
+		return EEH_Template::display_template($template, $template_args, true);
2804
+	}
2805
+
2806
+
2807
+	/**
2808
+	 * Handles deleting categories.
2809
+	 *
2810
+	 * @throws EE_Error
2811
+	 */
2812
+	protected function _delete_categories()
2813
+	{
2814
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2815
+		foreach ($category_IDs as $category_ID) {
2816
+			$this->_delete_category($category_ID);
2817
+		}
2818
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2819
+		$query_args = [
2820
+			'action' => 'category_list',
2821
+		];
2822
+		$this->_redirect_after_action(0, '', '', $query_args);
2823
+	}
2824
+
2825
+
2826
+	/**
2827
+	 * Handles deleting specific category.
2828
+	 *
2829
+	 * @param int $cat_id
2830
+	 */
2831
+	protected function _delete_category(int $cat_id)
2832
+	{
2833
+		$cat_id = absint($cat_id);
2834
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2835
+	}
2836
+
2837
+
2838
+	/**
2839
+	 * Handles triggering the update or insertion of a new category.
2840
+	 *
2841
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2842
+	 * @throws EE_Error
2843
+	 * @throws EE_Error
2844
+	 */
2845
+	protected function _insert_or_update_category(bool $new_category)
2846
+	{
2847
+		$cat_id  = $this->_insert_category($new_category);
2848
+		$success = 0; // we already have a success message so lets not send another.
2849
+		if ($cat_id) {
2850
+			$query_args = [
2851
+				'action'     => 'edit_category',
2852
+				'EVT_CAT_ID' => $cat_id,
2853
+			];
2854
+		} else {
2855
+			$query_args = ['action' => 'add_category'];
2856
+		}
2857
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2858
+	}
2859
+
2860
+
2861
+	/**
2862
+	 * Inserts or updates category
2863
+	 *
2864
+	 * @param bool $new_category (true indicates we're updating a category).
2865
+	 * @return bool|mixed|string
2866
+	 */
2867
+	private function _insert_category(bool $new_category)
2868
+	{
2869
+		$category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2870
+		$category_name       = $this->request->getRequestParam('category_name', '');
2871
+		$category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2872
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2873
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2874
+
2875
+		if (empty($category_name)) {
2876
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2877
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2878
+			return 0;
2879
+		}
2880
+		$term_args = [
2881
+			'name'        => $category_name,
2882
+			'description' => $category_desc,
2883
+			'parent'      => $category_parent,
2884
+		];
2885
+		// was the category_identifier input disabled?
2886
+		if ($category_identifier) {
2887
+			$term_args['slug'] = $category_identifier;
2888
+		}
2889
+		$insert_ids = $new_category
2890
+			? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2891
+			: wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2892
+
2893
+		if ($insert_ids instanceof WP_Error) {
2894
+			EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2895
+			return 0;
2896
+		}
2897
+		$category_ID = $insert_ids['term_id'] ?? 0;
2898
+		if (! $category_ID) {
2899
+			EE_Error::add_error(
2900
+				esc_html__(
2901
+					'An error occurred and the category has not been saved to the database.',
2902
+					'event_espresso'
2903
+				),
2904
+				__FILE__,
2905
+				__FUNCTION__,
2906
+				__LINE__
2907
+			);
2908
+			return 0;
2909
+		}
2910
+		EE_Error::add_success(
2911
+			sprintf(
2912
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2913
+				$category_name
2914
+			)
2915
+		);
2916
+		return $category_ID;
2917
+	}
2918
+
2919
+
2920
+	/**
2921
+	 * Gets categories or count of categories matching the arguments in the request.
2922
+	 *
2923
+	 * @param int  $per_page
2924
+	 * @param int  $current_page
2925
+	 * @param bool $count
2926
+	 * @return EE_Term_Taxonomy[]|int
2927
+	 * @throws EE_Error
2928
+	 * @throws ReflectionException
2929
+	 */
2930
+	public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2931
+	{
2932
+		// testing term stuff
2933
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2934
+		$order       = $this->request->getRequestParam('order', 'DESC');
2935
+		$limit       = ($current_page - 1) * $per_page;
2936
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937
+		$search_term = $this->request->getRequestParam('s');
2938
+		if ($search_term) {
2939
+			$search_term = '%' . $search_term . '%';
2940
+			$where['OR'] = [
2941
+				'Term.name'   => ['LIKE', $search_term],
2942
+				'description' => ['LIKE', $search_term],
2943
+			];
2944
+		}
2945
+		$query_params = [
2946
+			$where,
2947
+			'order_by'   => [$orderby => $order],
2948
+			'limit'      => $limit . ',' . $per_page,
2949
+			'force_join' => ['Term'],
2950
+		];
2951
+		return $count
2952
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2953
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2954
+	}
2955
+
2956
+	/* end category stuff */
2957
+
2958
+
2959
+	/**************/
2960
+
2961
+
2962
+	/**
2963
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2964
+	 *
2965
+	 * @throws EE_Error
2966
+	 * @throws InvalidArgumentException
2967
+	 * @throws InvalidDataTypeException
2968
+	 * @throws InvalidInterfaceException
2969
+	 */
2970
+	public function saveTimezoneString()
2971
+	{
2972
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2973
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2974
+			EE_Error::add_error(
2975
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2976
+				__FILE__,
2977
+				__FUNCTION__,
2978
+				__LINE__
2979
+			);
2980
+			$this->_template_args['error'] = true;
2981
+			$this->_return_json();
2982
+		}
2983
+
2984
+		update_option('timezone_string', $timezone_string);
2985
+		EE_Error::add_success(
2986
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2987
+		);
2988
+		$this->_template_args['success'] = true;
2989
+		$this->_return_json(true, ['action' => 'create_new']);
2990
+	}
2991
+
2992
+
2993
+	/**
2994
+	 * @throws EE_Error
2995
+	 * @deprecated 4.10.25.p
2996
+	 */
2997
+	public function save_timezonestring_setting()
2998
+	{
2999
+		$this->saveTimezoneString();
3000
+	}
3001 3001
 }
Please login to merge, or discard this patch.
Spacing   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -573,20 +573,20 @@  discard block
 block discarded – undo
573 573
     {
574 574
         wp_enqueue_style(
575 575
             'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
576
+            EVENTS_ASSETS_URL.'events-admin-page.css',
577 577
             [],
578 578
             EVENT_ESPRESSO_VERSION
579 579
         );
580 580
         wp_enqueue_style(
581 581
             'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
582
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
583 583
             [],
584 584
             EVENT_ESPRESSO_VERSION
585 585
         );
586 586
         // scripts
587 587
         wp_enqueue_script(
588 588
             'event_editor_js',
589
-            EVENTS_ASSETS_URL . 'event_editor.js',
589
+            EVENTS_ASSETS_URL.'event_editor.js',
590 590
             [
591 591
                 EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
592 592
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
@@ -616,15 +616,15 @@  discard block
 block discarded – undo
616 616
         wp_enqueue_style('espresso-ui-theme');
617 617
         wp_enqueue_style(
618 618
             'event-editor-css',
619
-            EVENTS_ASSETS_URL . 'event-editor.css',
619
+            EVENTS_ASSETS_URL.'event-editor.css',
620 620
             ['ee-admin-css'],
621 621
             EVENT_ESPRESSO_VERSION
622 622
         );
623 623
         // scripts
624
-        if (! $this->admin_config->useAdvancedEditor()) {
624
+        if ( ! $this->admin_config->useAdvancedEditor()) {
625 625
             wp_enqueue_script(
626 626
                 'event-datetime-metabox',
627
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
628 628
                 ['event_editor_js', 'ee-datepicker'],
629 629
                 EVENT_ESPRESSO_VERSION
630 630
             );
@@ -702,15 +702,15 @@  discard block
 block discarded – undo
702 702
     public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
703 703
     {
704 704
         // don't need to do this when processing
705
-        if (! empty($req_type)) {
705
+        if ( ! empty($req_type)) {
706 706
             return;
707 707
         }
708 708
         // no event?
709
-        if (! $event instanceof EE_Event) {
709
+        if ( ! $event instanceof EE_Event) {
710 710
             $event = $this->_cpt_model_obj;
711 711
         }
712 712
         // STILL no event?
713
-        if (! $event instanceof EE_Event) {
713
+        if ( ! $event instanceof EE_Event) {
714 714
             return;
715 715
         }
716 716
         // don't need to keep calling this
@@ -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
@@ -804,7 +804,7 @@  discard block
 block discarded – undo
804 804
     {
805 805
         $has_timezone_string = get_option('timezone_string');
806 806
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
807
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
808 808
             EE_Error::add_attention(
809 809
                 sprintf(
810 810
                     esc_html__(
@@ -873,7 +873,7 @@  discard block
 block discarded – undo
873 873
      */
874 874
     protected function _event_legend_items(): array
875 875
     {
876
-        $items    = [
876
+        $items = [
877 877
             'view_details'   => [
878 878
                 'class' => 'dashicons dashicons-visibility',
879 879
                 'desc'  => esc_html__('View Event', 'event_espresso'),
@@ -890,31 +890,31 @@  discard block
 block discarded – undo
890 890
         $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
891 891
         $statuses = [
892 892
             'sold_out_status'  => [
893
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::sold_out,
894 894
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
895 895
             ],
896 896
             'active_status'    => [
897
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::active,
898 898
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
899 899
             ],
900 900
             'upcoming_status'  => [
901
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::upcoming,
902 902
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
903 903
             ],
904 904
             'postponed_status' => [
905
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::postponed,
906 906
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
907 907
             ],
908 908
             'cancelled_status' => [
909
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::cancelled,
910 910
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
911 911
             ],
912 912
             'expired_status'   => [
913
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::expired,
914 914
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
915 915
             ],
916 916
             'inactive_status'  => [
917
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::inactive,
918 918
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
919 919
             ],
920 920
         ];
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
      */
934 934
     private function _event_model(): EEM_Event
935 935
     {
936
-        if (! $this->_event_model instanceof EEM_Event) {
936
+        if ( ! $this->_event_model instanceof EEM_Event) {
937 937
             $this->_event_model = EE_Registry::instance()->load_model('Event');
938 938
         }
939 939
         return $this->_event_model;
@@ -988,12 +988,12 @@  discard block
 block discarded – undo
988 988
             '',
989 989
             'ee-admin-button-row ee-admin-button-row--align-start'
990 990
         );
991
-        $links_html       .= EEH_HTML::divx();
991
+        $links_html .= EEH_HTML::divx();
992 992
 
993 993
         $after_list_table['view_event_list_button'] = $links_html;
994 994
 
995 995
         $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
996
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
997 997
                 'create_new',
998 998
                 'add',
999 999
                 [],
@@ -1057,13 +1057,13 @@  discard block
 block discarded – undo
1057 1057
             'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1058 1058
         ];
1059 1059
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1060
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1060
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1061
+            $event_values['EVT_display_ticket_selector'] = $this->request->getRequestParam(
1062 1062
                 'display_ticket_selector',
1063 1063
                 false,
1064 1064
                 'bool'
1065 1065
             );
1066
-            $event_values['EVT_additional_limit']            = min(
1066
+            $event_values['EVT_additional_limit'] = min(
1067 1067
                 apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1068 1068
                 $this->request->getRequestParam(
1069 1069
                     'additional_limit',
@@ -1105,14 +1105,14 @@  discard block
 block discarded – undo
1105 1105
             ]
1106 1106
         );
1107 1107
 
1108
-        if (! $event instanceof EE_Event) {
1108
+        if ( ! $event instanceof EE_Event) {
1109 1109
             return;
1110 1110
         }
1111 1111
 
1112 1112
         // the following are default callbacks for event attachment updates
1113 1113
         // that can be overridden by caffeinated functionality and/or addons.
1114 1114
         $event_update_callbacks = [];
1115
-        if (! $this->admin_config->useAdvancedEditor()) {
1115
+        if ( ! $this->admin_config->useAdvancedEditor()) {
1116 1116
             $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1117 1117
             $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1118 1118
         }
@@ -1183,7 +1183,7 @@  discard block
 block discarded – undo
1183 1183
      */
1184 1184
     protected function _default_venue_update(EE_Event $event, array $data): bool
1185 1185
     {
1186
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1187 1187
         $venue_model = EE_Registry::instance()->load_model('Venue');
1188 1188
         $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1189 1189
         // very important.  If we don't have a venue name...
@@ -1214,7 +1214,7 @@  discard block
 block discarded – undo
1214 1214
             'status'              => 'publish',
1215 1215
         ];
1216 1216
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1217
-        if (! empty($venue_id)) {
1217
+        if ( ! empty($venue_id)) {
1218 1218
             $update_where  = [$venue_model->primary_key_name() => $venue_id];
1219 1219
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1220 1220
             // we've gotta make sure that the venue is always attached to a revision..
@@ -1264,9 +1264,9 @@  discard block
 block discarded – undo
1264 1264
             ];
1265 1265
             // if we have an id then let's get existing object first and then set the new values.
1266 1266
             //  Otherwise we instantiate a new object for save.
1267
-            if (! empty($datetime_data['DTT_ID'])) {
1267
+            if ( ! empty($datetime_data['DTT_ID'])) {
1268 1268
                 $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1269
-                if (! $datetime instanceof EE_Datetime) {
1269
+                if ( ! $datetime instanceof EE_Datetime) {
1270 1270
                     throw new RuntimeException(
1271 1271
                         sprintf(
1272 1272
                             esc_html__(
@@ -1285,7 +1285,7 @@  discard block
 block discarded – undo
1285 1285
             } else {
1286 1286
                 $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1287 1287
             }
1288
-            if (! $datetime instanceof EE_Datetime) {
1288
+            if ( ! $datetime instanceof EE_Datetime) {
1289 1289
                 throw new RuntimeException(
1290 1290
                     sprintf(
1291 1291
                         esc_html__(
@@ -1311,7 +1311,7 @@  discard block
 block discarded – undo
1311 1311
 
1312 1312
         // set up some default start and end dates in case those are not present in the incoming data
1313 1313
         $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1314
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
+        $default_start_date = $default_start_date->format($date_formats[0].' '.$date_formats[1]);
1315 1315
         // use the start date of the first datetime for the end date
1316 1316
         $first_datetime   = $event->first_datetime();
1317 1317
         $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
@@ -1319,7 +1319,7 @@  discard block
 block discarded – undo
1319 1319
         // now process the incoming data
1320 1320
         foreach ($data['edit_tickets'] as $row => $ticket_data) {
1321 1321
             $update_prices = false;
1322
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
+            $ticket_price  = $data['edit_prices'][$row][1]['PRC_amount'] ?? 0;
1323 1323
             // trim inputs to ensure any excess whitespace is removed.
1324 1324
             $ticket_data   = array_map('trim', $ticket_data);
1325 1325
             $ticket_values = [
@@ -1359,9 +1359,9 @@  discard block
 block discarded – undo
1359 1359
             // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1360 1360
             // keep in mind that if the ticket has been sold (and we have changed pricing information),
1361 1361
             // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1362
-            if (! empty($ticket_data['TKT_ID'])) {
1362
+            if ( ! empty($ticket_data['TKT_ID'])) {
1363 1363
                 $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1364
-                if (! $existing_ticket instanceof EE_Ticket) {
1364
+                if ( ! $existing_ticket instanceof EE_Ticket) {
1365 1365
                     throw new RuntimeException(
1366 1366
                         sprintf(
1367 1367
                             esc_html__(
@@ -1410,7 +1410,7 @@  discard block
 block discarded – undo
1410 1410
                     $existing_ticket->save();
1411 1411
                     // make sure this ticket is still recorded in our $saved_tickets
1412 1412
                     // so we don't run it through the regular trash routine.
1413
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
+                    $saved_tickets[$existing_ticket->ID()] = $existing_ticket;
1414 1414
                     // create new ticket that's a copy of the existing except,
1415 1415
                     // (a new id of course and not archived) AND has the new TKT_price associated with it.
1416 1416
                     $new_ticket = clone $existing_ticket;
@@ -1427,7 +1427,7 @@  discard block
 block discarded – undo
1427 1427
                 $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1428 1428
                 $update_prices              = true;
1429 1429
             }
1430
-            if (! $ticket instanceof EE_Ticket) {
1430
+            if ( ! $ticket instanceof EE_Ticket) {
1431 1431
                 throw new RuntimeException(
1432 1432
                     sprintf(
1433 1433
                         esc_html__(
@@ -1451,10 +1451,10 @@  discard block
 block discarded – undo
1451 1451
             }
1452 1452
             // initially let's add the ticket to the datetime
1453 1453
             $datetime->_add_relation_to($ticket, 'Ticket');
1454
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1454
+            $saved_tickets[$ticket->ID()] = $ticket;
1455 1455
             // add prices to ticket
1456
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1457
-                ? $data['edit_prices'][ $row ]
1456
+            $prices_data = isset($data['edit_prices'][$row]) && is_array($data['edit_prices'][$row])
1457
+                ? $data['edit_prices'][$row]
1458 1458
                 : [];
1459 1459
             $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1460 1460
         }
@@ -1468,7 +1468,7 @@  discard block
 block discarded – undo
1468 1468
             $id = absint($id);
1469 1469
             // get the ticket for this id
1470 1470
             $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1471
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1471
+            if ( ! $ticket_to_remove instanceof EE_Ticket) {
1472 1472
                 continue;
1473 1473
             }
1474 1474
             // need to get all the related datetimes on this ticket and remove from every single one of them
@@ -1525,7 +1525,7 @@  discard block
 block discarded – undo
1525 1525
                     $price->set($field, $new_price);
1526 1526
                 }
1527 1527
             }
1528
-            if (! $price instanceof EE_Price) {
1528
+            if ( ! $price instanceof EE_Price) {
1529 1529
                 throw new RuntimeException(
1530 1530
                     sprintf(
1531 1531
                         esc_html__(
@@ -1566,13 +1566,13 @@  discard block
 block discarded – undo
1566 1566
     {
1567 1567
         // load formatter helper
1568 1568
         // args for getting related registrations
1569
-        $approved_query_args        = [
1569
+        $approved_query_args = [
1570 1570
             [
1571 1571
                 'REG_deleted' => 0,
1572 1572
                 'STS_ID'      => RegStatus::APPROVED,
1573 1573
             ],
1574 1574
         ];
1575
-        $not_approved_query_args    = [
1575
+        $not_approved_query_args = [
1576 1576
             [
1577 1577
                 'REG_deleted' => 0,
1578 1578
                 'STS_ID'      => RegStatus::AWAITING_REVIEW,
@@ -1638,7 +1638,7 @@  discard block
 block discarded – undo
1638 1638
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1639 1639
         // load template
1640 1640
         EEH_Template::display_template(
1641
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1642 1642
             $publish_box_extra_args
1643 1643
         );
1644 1644
     }
@@ -1669,7 +1669,7 @@  discard block
 block discarded – undo
1669 1669
         $this->verify_cpt_object();
1670 1670
         $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1671 1671
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1672
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
+        if ( ! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1673 1673
             $this->addMetaBox(
1674 1674
                 'espresso_event_editor_event_options',
1675 1675
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1678,7 +1678,7 @@  discard block
 block discarded – undo
1678 1678
                 'side'
1679 1679
             );
1680 1680
         }
1681
-        if (! $use_advanced_editor) {
1681
+        if ( ! $use_advanced_editor) {
1682 1682
             $this->addMetaBox(
1683 1683
                 'espresso_event_editor_tickets',
1684 1684
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1690,7 +1690,7 @@  discard block
 block discarded – undo
1690 1690
         } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1691 1691
             add_action(
1692 1692
                 'add_meta_boxes_espresso_events',
1693
-                function () {
1693
+                function() {
1694 1694
                     global $current_screen;
1695 1695
                     remove_meta_box('authordiv', $current_screen, 'normal');
1696 1696
                 },
@@ -1719,7 +1719,7 @@  discard block
 block discarded – undo
1719 1719
             'trash_icon'        => 'dashicons dashicons-lock',
1720 1720
             'disabled'          => '',
1721 1721
         ];
1722
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
+        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1723 1723
         /**
1724 1724
          * 1. Start with retrieving Datetimes
1725 1725
          * 2. Fore each datetime get related tickets
@@ -1745,24 +1745,24 @@  discard block
 block discarded – undo
1745 1745
                     'default_where_conditions' => 'none',
1746 1746
                 ]
1747 1747
             );
1748
-            if (! empty($related_tickets)) {
1748
+            if ( ! empty($related_tickets)) {
1749 1749
                 $template_args['total_ticket_rows'] = count($related_tickets);
1750 1750
                 $row                                = 0;
1751 1751
                 foreach ($related_tickets as $ticket) {
1752
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
+                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1753 1753
                     $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1754 1754
                     $row++;
1755 1755
                 }
1756 1756
             } else {
1757 1757
                 $template_args['total_ticket_rows'] = 1;
1758 1758
                 /** @type EE_Ticket $ticket */
1759
-                $ticket                       = $ticket_model->create_default_object();
1759
+                $ticket = $ticket_model->create_default_object();
1760 1760
                 $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1761 1761
             }
1762 1762
         } else {
1763 1763
             $template_args['time'] = $times[0];
1764 1764
             /** @type EE_Ticket[] $tickets */
1765
-            $tickets                      = $ticket_model->get_all_default_tickets();
1765
+            $tickets = $ticket_model->get_all_default_tickets();
1766 1766
             $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1767 1767
             // NOTE: we're just sending the first default row
1768 1768
             // (decaf can't manage default tickets so this should be sufficient);
@@ -1777,9 +1777,9 @@  discard block
 block discarded – undo
1777 1777
             $ticket_model->create_default_object(),
1778 1778
             true
1779 1779
         );
1780
-        $template                                  = apply_filters(
1780
+        $template = apply_filters(
1781 1781
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1782
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1782
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1783 1783
         );
1784 1784
         EEH_Template::display_template($template, $template_args);
1785 1785
     }
@@ -1799,7 +1799,7 @@  discard block
 block discarded – undo
1799 1799
     private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1800 1800
     {
1801 1801
         $template_args = [
1802
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1802
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1803 1803
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1804 1804
                 ? ' tkt-archived'
1805 1805
                 : '',
@@ -1812,11 +1812,11 @@  discard block
 block discarded – undo
1812 1812
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1813 1813
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1814 1814
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1815
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1816
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1815
+            'trash_icon'          => ($skeleton || ( ! $ticket->get('TKT_deleted')))
1816
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1817 1817
                 ? 'dashicons dashicons-post-trash clickable'
1818 1818
                 : 'dashicons dashicons-lock entity-locked',
1819
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1819
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1820 1820
                 : ' disabled=disabled',
1821 1821
         ];
1822 1822
 
@@ -1841,7 +1841,7 @@  discard block
 block discarded – undo
1841 1841
         }
1842 1842
         if (empty($template_args['TKT_end_date'])) {
1843 1843
             // get the earliest datetime (if present);
1844
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1844
+            $earliest_datetime = $this->_cpt_model_obj->ID() > 0
1845 1845
                 ? $this->_cpt_model_obj->get_first_related(
1846 1846
                     'Datetime',
1847 1847
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
@@ -1854,7 +1854,7 @@  discard block
 block discarded – undo
1854 1854
         $template_args = array_merge($template_args, $price_args);
1855 1855
         $template      = apply_filters(
1856 1856
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1857
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1857
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1858 1858
             $ticket
1859 1859
         );
1860 1860
         return EEH_Template::display_template($template, $template_args, true);
@@ -1867,7 +1867,7 @@  discard block
 block discarded – undo
1867 1867
      */
1868 1868
     public function registration_options_meta_box()
1869 1869
     {
1870
-        $yes_no_values             = [
1870
+        $yes_no_values = [
1871 1871
             ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1872 1872
             ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1873 1873
         ];
@@ -1892,12 +1892,12 @@  discard block
 block discarded – undo
1892 1892
             'ee-input-width--reg',
1893 1893
             false
1894 1894
         );
1895
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1895
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
1896 1896
             'display_desc',
1897 1897
             $yes_no_values,
1898 1898
             $this->_cpt_model_obj->display_description()
1899 1899
         );
1900
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1900
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1901 1901
             'display_ticket_selector',
1902 1902
             $yes_no_values,
1903 1903
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -1913,7 +1913,7 @@  discard block
 block discarded – undo
1913 1913
             $default_reg_status_values
1914 1914
         );
1915 1915
         EEH_Template::display_template(
1916
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1916
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1917 1917
             $template_args
1918 1918
         );
1919 1919
     }
@@ -1936,7 +1936,7 @@  discard block
 block discarded – undo
1936 1936
     {
1937 1937
         $EEM_Event   = $this->_event_model();
1938 1938
         $offset      = ($current_page - 1) * $per_page;
1939
-        $limit       = $count ? null : $offset . ',' . $per_page;
1939
+        $limit       = $count ? null : $offset.','.$per_page;
1940 1940
         $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1941 1941
         $order       = $this->request->getRequestParam('order', 'DESC');
1942 1942
         $month_range = $this->request->getRequestParam('month_range');
@@ -1986,11 +1986,11 @@  discard block
 block discarded – undo
1986 1986
                                                         ->format(implode(' ', $start_formats));
1987 1987
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1988 1988
         }
1989
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1989
+        if ( ! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1990 1990
             $where['EVT_wp_user'] = get_current_user_id();
1991 1991
         } else {
1992
-            if (! isset($where['status'])) {
1993
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1992
+            if ( ! isset($where['status'])) {
1993
+                if ( ! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1994 1994
                     $where['OR'] = [
1995 1995
                         'status*restrict_private' => ['!=', 'private'],
1996 1996
                         'AND'                     => [
@@ -2012,7 +2012,7 @@  discard block
 block discarded – undo
2012 2012
         // search query handling
2013 2013
         $search_term = $this->request->getRequestParam('s');
2014 2014
         if ($search_term) {
2015
-            $search_term = '%' . $search_term . '%';
2015
+            $search_term = '%'.$search_term.'%';
2016 2016
             $where['OR'] = [
2017 2017
                 'EVT_name'       => ['LIKE', $search_term],
2018 2018
                 'EVT_desc'       => ['LIKE', $search_term],
@@ -2077,14 +2077,14 @@  discard block
 block discarded – undo
2077 2077
             "$year_r-$month_r-01 00:00:00",
2078 2078
             new DateTimeZone($timezone_string)
2079 2079
         );
2080
-        $start    = $DateTime->getTimestamp();
2080
+        $start = $DateTime->getTimestamp();
2081 2081
         // set the datetime to be the end of the month
2082 2082
         $DateTime->setDate(
2083 2083
             $year_r,
2084 2084
             $month_r,
2085 2085
             $DateTime->format('t')
2086 2086
         )->setTime(23, 59, 59);
2087
-        $end                             = $DateTime->getTimestamp();
2087
+        $end = $DateTime->getTimestamp();
2088 2088
         return ['BETWEEN', [$start, $end]];
2089 2089
     }
2090 2090
 
@@ -2150,7 +2150,7 @@  discard block
 block discarded – undo
2150 2150
             // clean status
2151 2151
             $event_status = sanitize_key($event_status);
2152 2152
             // grab status
2153
-            if (! empty($event_status)) {
2153
+            if ( ! empty($event_status)) {
2154 2154
                 $success = $this->_change_event_status($this->EVT_ID, $event_status);
2155 2155
             } else {
2156 2156
                 $success = false;
@@ -2190,7 +2190,7 @@  discard block
 block discarded – undo
2190 2190
         // clean status
2191 2191
         $event_status = sanitize_key($event_status);
2192 2192
         // grab status
2193
-        if (! empty($event_status)) {
2193
+        if ( ! empty($event_status)) {
2194 2194
             $success = true;
2195 2195
             // determine the event id and set to array.
2196 2196
             $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
@@ -2236,7 +2236,7 @@  discard block
 block discarded – undo
2236 2236
     private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2237 2237
     {
2238 2238
         // grab event id
2239
-        if (! $EVT_ID) {
2239
+        if ( ! $EVT_ID) {
2240 2240
             $msg = esc_html__(
2241 2241
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2242 2242
                 'event_espresso'
@@ -2273,7 +2273,7 @@  discard block
 block discarded – undo
2273 2273
         // use class to change status
2274 2274
         $this->_cpt_model_obj->set_status($event_status);
2275 2275
         $success = $this->_cpt_model_obj->save();
2276
-        if (! $success) {
2276
+        if ( ! $success) {
2277 2277
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2278 2278
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2279 2279
             return false;
@@ -2340,7 +2340,7 @@  discard block
 block discarded – undo
2340 2340
      */
2341 2341
     protected function getModelObjNodeGroupPersister(): NodeGroupDao
2342 2342
     {
2343
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2343
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2344 2344
             $this->model_obj_node_group_persister =
2345 2345
                 $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2346 2346
         }
@@ -2665,7 +2665,7 @@  discard block
 block discarded – undo
2665 2665
                                                 . esc_html__(
2666 2666
                                                     '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.',
2667 2667
                                                     'event_espresso'
2668
-                                                ) . '</strong>';
2668
+                                                ).'</strong>';
2669 2669
         $this->display_admin_caf_preview_page('template_settings_tab');
2670 2670
     }
2671 2671
 
@@ -2686,11 +2686,11 @@  discard block
 block discarded – undo
2686 2686
         $this->_set_empty_category_object();
2687 2687
         // only set if we've got an id
2688 2688
         $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2689
-        if (! $category_ID) {
2689
+        if ( ! $category_ID) {
2690 2690
             return;
2691 2691
         }
2692 2692
         $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2693
-        if (! empty($term)) {
2693
+        if ( ! empty($term)) {
2694 2694
             $this->_category->category_name       = $term->name;
2695 2695
             $this->_category->category_identifier = $term->slug;
2696 2696
             $this->_category->category_desc       = $term->description;
@@ -2791,7 +2791,7 @@  discard block
 block discarded – undo
2791 2791
             $category_select_values,
2792 2792
             $this->_category->parent
2793 2793
         );
2794
-        $template_args   = [
2794
+        $template_args = [
2795 2795
             'category'                 => $this->_category,
2796 2796
             'category_select'          => $category_select,
2797 2797
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -2799,7 +2799,7 @@  discard block
 block discarded – undo
2799 2799
             'disable'                  => '',
2800 2800
             'disabled_message'         => false,
2801 2801
         ];
2802
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2802
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2803 2803
         return EEH_Template::display_template($template, $template_args, true);
2804 2804
     }
2805 2805
 
@@ -2895,7 +2895,7 @@  discard block
 block discarded – undo
2895 2895
             return 0;
2896 2896
         }
2897 2897
         $category_ID = $insert_ids['term_id'] ?? 0;
2898
-        if (! $category_ID) {
2898
+        if ( ! $category_ID) {
2899 2899
             EE_Error::add_error(
2900 2900
                 esc_html__(
2901 2901
                     'An error occurred and the category has not been saved to the database.',
@@ -2936,7 +2936,7 @@  discard block
 block discarded – undo
2936 2936
         $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2937 2937
         $search_term = $this->request->getRequestParam('s');
2938 2938
         if ($search_term) {
2939
-            $search_term = '%' . $search_term . '%';
2939
+            $search_term = '%'.$search_term.'%';
2940 2940
             $where['OR'] = [
2941 2941
                 'Term.name'   => ['LIKE', $search_term],
2942 2942
                 'description' => ['LIKE', $search_term],
@@ -2945,7 +2945,7 @@  discard block
 block discarded – undo
2945 2945
         $query_params = [
2946 2946
             $where,
2947 2947
             'order_by'   => [$orderby => $order],
2948
-            'limit'      => $limit . ',' . $per_page,
2948
+            'limit'      => $limit.','.$per_page,
2949 2949
             'force_join' => ['Term'],
2950 2950
         ];
2951 2951
         return $count
Please login to merge, or discard this patch.
core/EE_Cron_Tasks.core.php 2 patches
Indentation   +584 added lines, -584 removed lines patch added patch discarded remove patch
@@ -16,591 +16,591 @@
 block discarded – undo
16 16
  */
17 17
 class EE_Cron_Tasks extends EE_Base
18 18
 {
19
-    /**
20
-     * WordPress doesn't allow duplicate crons within 10 minutes of the original,
21
-     * so we'll set our retry time for just over 10 minutes to avoid that
22
-     */
23
-    const reschedule_timeout = 605;
24
-
25
-
26
-    private static ?EE_Cron_Tasks $_instance = null;
27
-
28
-
29
-    public static function instance(): ?EE_Cron_Tasks
30
-    {
31
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
32
-            self::$_instance = new self();
33
-        }
34
-        return self::$_instance;
35
-    }
36
-
37
-
38
-    /**
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidInterfaceException
41
-     * @throws InvalidArgumentException
42
-     * @throws EE_Error
43
-     * @throws ReflectionException
44
-     */
45
-    private function __construct()
46
-    {
47
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
48
-        // verify that WP Cron is enabled
49
-        if (
50
-            defined('DISABLE_WP_CRON')
51
-            && DISABLE_WP_CRON
52
-            && is_admin()
53
-            && ! get_option('ee_disabled_wp_cron_check')
54
-        ) {
55
-            /**
56
-             * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
57
-             * config is loaded.
58
-             * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
59
-             * wanting to not have this functionality can just register its own action at a priority after this one to
60
-             * reverse any changes.
61
-             */
62
-            add_action(
63
-                'AHEE__EE_System__load_core_configuration__complete',
64
-                function () {
65
-                    EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
66
-                    EE_Registry::instance()->NET_CFG->update_config(true, false);
67
-                    add_option('ee_disabled_wp_cron_check', 1, '', false);
68
-                }
69
-            );
70
-        }
71
-        // UPDATE TRANSACTION WITH PAYMENT
72
-        add_action(
73
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
74
-            array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
75
-            10,
76
-            2
77
-        );
78
-        // ABANDONED / EXPIRED TRANSACTION CHECK
79
-        add_action(
80
-            'AHEE__EE_Cron_Tasks__expired_transaction_check',
81
-            array('EE_Cron_Tasks', 'expired_transaction_check')
82
-        );
83
-        // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
84
-        add_action(
85
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
86
-            array('EE_Cron_Tasks', 'clean_out_junk_transactions')
87
-        );
88
-        // logging
89
-        add_action(
90
-            'AHEE__EE_System__load_core_configuration__complete',
91
-            array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
92
-        );
93
-        EE_Registry::instance()->load_lib('Messages_Scheduler');
94
-        // clean out old gateway logs
95
-        add_action(
96
-            'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
97
-            array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
98
-        );
99
-    }
100
-
101
-    public static function log_scheduled_ee_crons(): void
102
-    {
103
-        $ee_crons = array(
104
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
105
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
106
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
107
-        );
108
-        $crons = (array) get_option('cron');
109
-        foreach ($crons as $cron) {
110
-            /** @var array[] $cron */
111
-            foreach ($ee_crons as $ee_cron) {
112
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
113
-                    do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
114
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
115
-                        if (! empty($ee_cron_details['args'])) {
116
-                            do_action(
117
-                                'AHEE_log',
118
-                                __CLASS__,
119
-                                __FUNCTION__,
120
-                                print_r($ee_cron_details['args'], true),
121
-                                "$ee_cron args"
122
-                            );
123
-                        }
124
-                    }
125
-                }
126
-            }
127
-        }
128
-    }
129
-
130
-
131
-    /**
132
-     * reschedule_cron_for_transactions_if_maintenance_mode
133
-     * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
134
-     *
135
-     * @param string $cron_task
136
-     * @param array  $TXN_IDs
137
-     * @return bool
138
-     * @throws DomainException
139
-     */
140
-    public static function reschedule_cron_for_transactions_if_maintenance_mode(string $cron_task, array $TXN_IDs): bool
141
-    {
142
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
143
-            throw new DomainException(
144
-                sprintf(
145
-                    esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
146
-                    $cron_task
147
-                )
148
-            );
149
-        }
150
-        // reschedule the cron if we can't hit the db right now
151
-        if (DbStatus::isOffline()) {
152
-            foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
153
-                // ensure $additional_vars is an array
154
-                $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
155
-                // reset cron job for the TXN
156
-                call_user_func_array(
157
-                    array('EE_Cron_Tasks', $cron_task),
158
-                    array_merge(
159
-                        array(
160
-                            time() + (10 * MINUTE_IN_SECONDS),
161
-                            $TXN_ID,
162
-                        ),
163
-                        $additional_vars
164
-                    )
165
-                );
166
-            }
167
-            return true;
168
-        }
169
-        return false;
170
-    }
171
-
172
-
173
-
174
-
175
-    /****************  UPDATE TRANSACTION WITH PAYMENT ****************/
176
-
177
-
178
-    /**
179
-     * array of TXN IDs and the payment
180
-     *
181
-     * @var array
182
-     */
183
-    protected static array $_update_transactions_with_payment = array();
184
-
185
-
186
-    /**
187
-     * schedule_update_transaction_with_payment
188
-     * sets a wp_schedule_single_event() for updating any TXNs that may
189
-     * require updating due to recently received payments
190
-     *
191
-     * @param int $timestamp
192
-     * @param int $TXN_ID
193
-     * @param int $PAY_ID
194
-     */
195
-    public static function schedule_update_transaction_with_payment(
196
-        int $timestamp,
197
-        int $TXN_ID,
198
-        int $PAY_ID
199
-    ): void {
200
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
201
-        // validate $TXN_ID and $timestamp
202
-        $TXN_ID = absint($TXN_ID);
203
-        $timestamp = absint($timestamp);
204
-        if ($TXN_ID && $timestamp) {
205
-            wp_schedule_single_event(
206
-                $timestamp,
207
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
208
-                array($TXN_ID, $PAY_ID)
209
-            );
210
-        }
211
-    }
212
-
213
-
214
-    /**
215
-     * setup_update_for_transaction_with_payment
216
-     * this is the callback for the action hook:
217
-     * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
218
-     * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
219
-     * The passed TXN_ID and associated payment gets added to an array, and then
220
-     * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
221
-     * 'shutdown' which will actually handle the processing of any
222
-     * transactions requiring updating, because doing so now would be too early
223
-     * and the required resources may not be available
224
-     *
225
-     * @param int $TXN_ID
226
-     * @param int $PAY_ID
227
-     */
228
-    public static function setup_update_for_transaction_with_payment(int $TXN_ID = 0, int $PAY_ID = 0): void
229
-    {
230
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
231
-        if (absint($TXN_ID)) {
232
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
233
-            add_action(
234
-                'shutdown',
235
-                array('EE_Cron_Tasks', 'update_transaction_with_payment'),
236
-                5
237
-            );
238
-        }
239
-    }
240
-
241
-
242
-    /**
243
-     * update_transaction_with_payment
244
-     * loops through the self::$_abandoned_transactions array
245
-     * and attempts to finalize any TXNs that have not been completed
246
-     * but have had their sessions expired, most likely due to a user not
247
-     * returning from an off-site payment gateway
248
-     *
249
-     * @throws EE_Error
250
-     * @throws DomainException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     * @throws InvalidArgumentException
254
-     * @throws ReflectionException
255
-     * @throws RuntimeException
256
-     */
257
-    public static function update_transaction_with_payment(): void
258
-    {
259
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
260
-        if (
19
+	/**
20
+	 * WordPress doesn't allow duplicate crons within 10 minutes of the original,
21
+	 * so we'll set our retry time for just over 10 minutes to avoid that
22
+	 */
23
+	const reschedule_timeout = 605;
24
+
25
+
26
+	private static ?EE_Cron_Tasks $_instance = null;
27
+
28
+
29
+	public static function instance(): ?EE_Cron_Tasks
30
+	{
31
+		if (! self::$_instance instanceof EE_Cron_Tasks) {
32
+			self::$_instance = new self();
33
+		}
34
+		return self::$_instance;
35
+	}
36
+
37
+
38
+	/**
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidInterfaceException
41
+	 * @throws InvalidArgumentException
42
+	 * @throws EE_Error
43
+	 * @throws ReflectionException
44
+	 */
45
+	private function __construct()
46
+	{
47
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
48
+		// verify that WP Cron is enabled
49
+		if (
50
+			defined('DISABLE_WP_CRON')
51
+			&& DISABLE_WP_CRON
52
+			&& is_admin()
53
+			&& ! get_option('ee_disabled_wp_cron_check')
54
+		) {
55
+			/**
56
+			 * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
57
+			 * config is loaded.
58
+			 * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
59
+			 * wanting to not have this functionality can just register its own action at a priority after this one to
60
+			 * reverse any changes.
61
+			 */
62
+			add_action(
63
+				'AHEE__EE_System__load_core_configuration__complete',
64
+				function () {
65
+					EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
66
+					EE_Registry::instance()->NET_CFG->update_config(true, false);
67
+					add_option('ee_disabled_wp_cron_check', 1, '', false);
68
+				}
69
+			);
70
+		}
71
+		// UPDATE TRANSACTION WITH PAYMENT
72
+		add_action(
73
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
74
+			array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
75
+			10,
76
+			2
77
+		);
78
+		// ABANDONED / EXPIRED TRANSACTION CHECK
79
+		add_action(
80
+			'AHEE__EE_Cron_Tasks__expired_transaction_check',
81
+			array('EE_Cron_Tasks', 'expired_transaction_check')
82
+		);
83
+		// CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
84
+		add_action(
85
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
86
+			array('EE_Cron_Tasks', 'clean_out_junk_transactions')
87
+		);
88
+		// logging
89
+		add_action(
90
+			'AHEE__EE_System__load_core_configuration__complete',
91
+			array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
92
+		);
93
+		EE_Registry::instance()->load_lib('Messages_Scheduler');
94
+		// clean out old gateway logs
95
+		add_action(
96
+			'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
97
+			array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
98
+		);
99
+	}
100
+
101
+	public static function log_scheduled_ee_crons(): void
102
+	{
103
+		$ee_crons = array(
104
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
105
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
106
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
107
+		);
108
+		$crons = (array) get_option('cron');
109
+		foreach ($crons as $cron) {
110
+			/** @var array[] $cron */
111
+			foreach ($ee_crons as $ee_cron) {
112
+				if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
113
+					do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
114
+					foreach ($cron[ $ee_cron ] as $ee_cron_details) {
115
+						if (! empty($ee_cron_details['args'])) {
116
+							do_action(
117
+								'AHEE_log',
118
+								__CLASS__,
119
+								__FUNCTION__,
120
+								print_r($ee_cron_details['args'], true),
121
+								"$ee_cron args"
122
+							);
123
+						}
124
+					}
125
+				}
126
+			}
127
+		}
128
+	}
129
+
130
+
131
+	/**
132
+	 * reschedule_cron_for_transactions_if_maintenance_mode
133
+	 * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
134
+	 *
135
+	 * @param string $cron_task
136
+	 * @param array  $TXN_IDs
137
+	 * @return bool
138
+	 * @throws DomainException
139
+	 */
140
+	public static function reschedule_cron_for_transactions_if_maintenance_mode(string $cron_task, array $TXN_IDs): bool
141
+	{
142
+		if (! method_exists('EE_Cron_Tasks', $cron_task)) {
143
+			throw new DomainException(
144
+				sprintf(
145
+					esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
146
+					$cron_task
147
+				)
148
+			);
149
+		}
150
+		// reschedule the cron if we can't hit the db right now
151
+		if (DbStatus::isOffline()) {
152
+			foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
153
+				// ensure $additional_vars is an array
154
+				$additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
155
+				// reset cron job for the TXN
156
+				call_user_func_array(
157
+					array('EE_Cron_Tasks', $cron_task),
158
+					array_merge(
159
+						array(
160
+							time() + (10 * MINUTE_IN_SECONDS),
161
+							$TXN_ID,
162
+						),
163
+						$additional_vars
164
+					)
165
+				);
166
+			}
167
+			return true;
168
+		}
169
+		return false;
170
+	}
171
+
172
+
173
+
174
+
175
+	/****************  UPDATE TRANSACTION WITH PAYMENT ****************/
176
+
177
+
178
+	/**
179
+	 * array of TXN IDs and the payment
180
+	 *
181
+	 * @var array
182
+	 */
183
+	protected static array $_update_transactions_with_payment = array();
184
+
185
+
186
+	/**
187
+	 * schedule_update_transaction_with_payment
188
+	 * sets a wp_schedule_single_event() for updating any TXNs that may
189
+	 * require updating due to recently received payments
190
+	 *
191
+	 * @param int $timestamp
192
+	 * @param int $TXN_ID
193
+	 * @param int $PAY_ID
194
+	 */
195
+	public static function schedule_update_transaction_with_payment(
196
+		int $timestamp,
197
+		int $TXN_ID,
198
+		int $PAY_ID
199
+	): void {
200
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
201
+		// validate $TXN_ID and $timestamp
202
+		$TXN_ID = absint($TXN_ID);
203
+		$timestamp = absint($timestamp);
204
+		if ($TXN_ID && $timestamp) {
205
+			wp_schedule_single_event(
206
+				$timestamp,
207
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
208
+				array($TXN_ID, $PAY_ID)
209
+			);
210
+		}
211
+	}
212
+
213
+
214
+	/**
215
+	 * setup_update_for_transaction_with_payment
216
+	 * this is the callback for the action hook:
217
+	 * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
218
+	 * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
219
+	 * The passed TXN_ID and associated payment gets added to an array, and then
220
+	 * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
221
+	 * 'shutdown' which will actually handle the processing of any
222
+	 * transactions requiring updating, because doing so now would be too early
223
+	 * and the required resources may not be available
224
+	 *
225
+	 * @param int $TXN_ID
226
+	 * @param int $PAY_ID
227
+	 */
228
+	public static function setup_update_for_transaction_with_payment(int $TXN_ID = 0, int $PAY_ID = 0): void
229
+	{
230
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
231
+		if (absint($TXN_ID)) {
232
+			self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
233
+			add_action(
234
+				'shutdown',
235
+				array('EE_Cron_Tasks', 'update_transaction_with_payment'),
236
+				5
237
+			);
238
+		}
239
+	}
240
+
241
+
242
+	/**
243
+	 * update_transaction_with_payment
244
+	 * loops through the self::$_abandoned_transactions array
245
+	 * and attempts to finalize any TXNs that have not been completed
246
+	 * but have had their sessions expired, most likely due to a user not
247
+	 * returning from an off-site payment gateway
248
+	 *
249
+	 * @throws EE_Error
250
+	 * @throws DomainException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 * @throws InvalidArgumentException
254
+	 * @throws ReflectionException
255
+	 * @throws RuntimeException
256
+	 */
257
+	public static function update_transaction_with_payment(): void
258
+	{
259
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
260
+		if (
261 261
 // are there any TXNs that need cleaning up ?
262
-            empty(self::$_update_transactions_with_payment)
263
-            // reschedule the cron if we can't hit the db right now
264
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
265
-                'schedule_update_transaction_with_payment',
266
-                self::$_update_transactions_with_payment
267
-            )
268
-        ) {
269
-            return;
270
-        }
271
-        /** @var EE_Transaction_Processor $transaction_processor */
272
-        $transaction_processor = LoaderFactory::getShared(EE_Transaction_Processor::class);
273
-        if ($transaction_processor instanceof EE_Transaction_Processor) {
274
-            // set revisit flag for payment processor
275
-            $transaction_processor->set_revisit();
276
-        }
277
-        // load EEM_Transaction
278
-        EE_Registry::instance()->load_model('Transaction');
279
-        foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
280
-            // reschedule the cron if we can't hit the db right now
281
-            if (DbStatus::isOffline()) {
282
-                // reset cron job for updating the TXN
283
-                EE_Cron_Tasks::schedule_update_transaction_with_payment(
284
-                    time() + EE_Cron_Tasks::reschedule_timeout,
285
-                    $TXN_ID,
286
-                    $PAY_ID
287
-                );
288
-                continue;
289
-            }
290
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
291
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
292
-            // verify transaction && try to update the TXN with any payments
293
-            if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
294
-                /** @var PaymentProcessor $payment_processor */
295
-                $payment_processor = LoaderFactory::getShared(PaymentProcessor::class);
296
-                $payment_processor->updateTransactionBasedOnPayment($transaction, $payment, true, true);
297
-            }
298
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
299
-        }
300
-    }
301
-
302
-
303
-
304
-    /************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
305
-
306
-
307
-    /*****************  EXPIRED TRANSACTION CHECK *****************/
308
-
309
-
310
-    /**
311
-     * array of TXN IDs
312
-     *
313
-     * @var array
314
-     */
315
-    protected static array $_expired_transactions = array();
316
-
317
-
318
-    /**
319
-     * schedule_expired_transaction_check
320
-     * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
321
-     *
322
-     * @param int $timestamp
323
-     * @param int $TXN_ID
324
-     */
325
-    public static function schedule_expired_transaction_check(
326
-        int $timestamp,
327
-        int $TXN_ID
328
-    ): void {
329
-        // validate $TXN_ID and $timestamp
330
-        $TXN_ID = absint($TXN_ID);
331
-        $timestamp = absint($timestamp);
332
-        if ($TXN_ID && $timestamp) {
333
-            wp_schedule_single_event(
334
-                $timestamp,
335
-                'AHEE__EE_Cron_Tasks__expired_transaction_check',
336
-                array($TXN_ID)
337
-            );
338
-        }
339
-    }
340
-
341
-
342
-    /**
343
-     * expired_transaction_check
344
-     * this is the callback for the action hook:
345
-     * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
346
-     * which is utilized by wp_schedule_single_event()
347
-     * in \EED_Single_Page_Checkout::_initialize_transaction().
348
-     * The passed TXN_ID gets added to an array, and then the
349
-     * process_expired_transactions() function is hooked into
350
-     * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
351
-     * processing of any failed transactions, because doing so now would be
352
-     * too early and the required resources may not be available
353
-     *
354
-     * @param int $TXN_ID
355
-     */
356
-    public static function expired_transaction_check(int $TXN_ID = 0): void
357
-    {
358
-        if (absint($TXN_ID)) {
359
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
360
-            add_action(
361
-                'shutdown',
362
-                array('EE_Cron_Tasks', 'process_expired_transactions'),
363
-                5
364
-            );
365
-        }
366
-    }
367
-
368
-
369
-    /**
370
-     * process_expired_transactions
371
-     * loops through the self::$_expired_transactions array and processes any failed TXNs
372
-     *
373
-     * @throws EE_Error
374
-     * @throws InvalidDataTypeException
375
-     * @throws InvalidInterfaceException
376
-     * @throws InvalidArgumentException
377
-     * @throws ReflectionException
378
-     * @throws DomainException
379
-     * @throws RuntimeException
380
-     */
381
-    public static function process_expired_transactions(): void
382
-    {
383
-        if (
262
+			empty(self::$_update_transactions_with_payment)
263
+			// reschedule the cron if we can't hit the db right now
264
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
265
+				'schedule_update_transaction_with_payment',
266
+				self::$_update_transactions_with_payment
267
+			)
268
+		) {
269
+			return;
270
+		}
271
+		/** @var EE_Transaction_Processor $transaction_processor */
272
+		$transaction_processor = LoaderFactory::getShared(EE_Transaction_Processor::class);
273
+		if ($transaction_processor instanceof EE_Transaction_Processor) {
274
+			// set revisit flag for payment processor
275
+			$transaction_processor->set_revisit();
276
+		}
277
+		// load EEM_Transaction
278
+		EE_Registry::instance()->load_model('Transaction');
279
+		foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
280
+			// reschedule the cron if we can't hit the db right now
281
+			if (DbStatus::isOffline()) {
282
+				// reset cron job for updating the TXN
283
+				EE_Cron_Tasks::schedule_update_transaction_with_payment(
284
+					time() + EE_Cron_Tasks::reschedule_timeout,
285
+					$TXN_ID,
286
+					$PAY_ID
287
+				);
288
+				continue;
289
+			}
290
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
291
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
292
+			// verify transaction && try to update the TXN with any payments
293
+			if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
294
+				/** @var PaymentProcessor $payment_processor */
295
+				$payment_processor = LoaderFactory::getShared(PaymentProcessor::class);
296
+				$payment_processor->updateTransactionBasedOnPayment($transaction, $payment, true, true);
297
+			}
298
+			unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
299
+		}
300
+	}
301
+
302
+
303
+
304
+	/************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
305
+
306
+
307
+	/*****************  EXPIRED TRANSACTION CHECK *****************/
308
+
309
+
310
+	/**
311
+	 * array of TXN IDs
312
+	 *
313
+	 * @var array
314
+	 */
315
+	protected static array $_expired_transactions = array();
316
+
317
+
318
+	/**
319
+	 * schedule_expired_transaction_check
320
+	 * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
321
+	 *
322
+	 * @param int $timestamp
323
+	 * @param int $TXN_ID
324
+	 */
325
+	public static function schedule_expired_transaction_check(
326
+		int $timestamp,
327
+		int $TXN_ID
328
+	): void {
329
+		// validate $TXN_ID and $timestamp
330
+		$TXN_ID = absint($TXN_ID);
331
+		$timestamp = absint($timestamp);
332
+		if ($TXN_ID && $timestamp) {
333
+			wp_schedule_single_event(
334
+				$timestamp,
335
+				'AHEE__EE_Cron_Tasks__expired_transaction_check',
336
+				array($TXN_ID)
337
+			);
338
+		}
339
+	}
340
+
341
+
342
+	/**
343
+	 * expired_transaction_check
344
+	 * this is the callback for the action hook:
345
+	 * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
346
+	 * which is utilized by wp_schedule_single_event()
347
+	 * in \EED_Single_Page_Checkout::_initialize_transaction().
348
+	 * The passed TXN_ID gets added to an array, and then the
349
+	 * process_expired_transactions() function is hooked into
350
+	 * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
351
+	 * processing of any failed transactions, because doing so now would be
352
+	 * too early and the required resources may not be available
353
+	 *
354
+	 * @param int $TXN_ID
355
+	 */
356
+	public static function expired_transaction_check(int $TXN_ID = 0): void
357
+	{
358
+		if (absint($TXN_ID)) {
359
+			self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
360
+			add_action(
361
+				'shutdown',
362
+				array('EE_Cron_Tasks', 'process_expired_transactions'),
363
+				5
364
+			);
365
+		}
366
+	}
367
+
368
+
369
+	/**
370
+	 * process_expired_transactions
371
+	 * loops through the self::$_expired_transactions array and processes any failed TXNs
372
+	 *
373
+	 * @throws EE_Error
374
+	 * @throws InvalidDataTypeException
375
+	 * @throws InvalidInterfaceException
376
+	 * @throws InvalidArgumentException
377
+	 * @throws ReflectionException
378
+	 * @throws DomainException
379
+	 * @throws RuntimeException
380
+	 */
381
+	public static function process_expired_transactions(): void
382
+	{
383
+		if (
384 384
 // are there any TXNs that need cleaning up ?
385
-            empty(self::$_expired_transactions)
386
-            // reschedule the cron if we can't hit the db right now
387
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
388
-                'schedule_expired_transaction_check',
389
-                self::$_expired_transactions
390
-            )
391
-        ) {
392
-            return;
393
-        }
394
-        /** @type EE_Transaction_Processor $transaction_processor */
395
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
396
-        // set revisit flag for txn processor
397
-        $transaction_processor->set_revisit();
398
-        // load EEM_Transaction
399
-        EE_Registry::instance()->load_model('Transaction');
400
-        foreach (self::$_expired_transactions as $TXN_ID) {
401
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
402
-            // verify transaction and whether it is failed or not
403
-            if ($transaction instanceof EE_Transaction) {
404
-                switch ($transaction->status_ID()) {
405
-                    // Completed TXNs
406
-                    case EEM_Transaction::complete_status_code:
407
-                        // Don't update the transaction/registrations if the Primary Registration is Not Approved.
408
-                        $primary_registration = $transaction->primary_registration();
409
-                        if (
410
-                            $primary_registration instanceof EE_Registration
411
-                            && $primary_registration->status_ID() !== RegStatus::AWAITING_REVIEW
412
-                        ) {
413
-                            /** @type EE_Transaction_Processor $transaction_processor */
414
-                            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
415
-                            $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
416
-                                $transaction,
417
-                                $transaction->last_payment()
418
-                            );
419
-                            do_action(
420
-                                'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
421
-                                $transaction
422
-                            );
423
-                        }
424
-                        break;
425
-                    // Overpaid TXNs
426
-                    case EEM_Transaction::overpaid_status_code:
427
-                        do_action(
428
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
429
-                            $transaction
430
-                        );
431
-                        break;
432
-                    // Incomplete TXNs
433
-                    case EEM_Transaction::incomplete_status_code:
434
-                        do_action(
435
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
436
-                            $transaction
437
-                        );
438
-                        // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
439
-                        break;
440
-                    // Abandoned TXNs
441
-                    case EEM_Transaction::abandoned_status_code:
442
-                        // run hook before updating transaction, primarily so
443
-                        // EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
444
-                        do_action(
445
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
446
-                            $transaction
447
-                        );
448
-                        // don't finalize the TXN if it has already been completed
449
-                        if ($transaction->all_reg_steps_completed() !== true) {
450
-                            /** @var PaymentProcessor $payment_processor */
451
-                            $payment_processor = LoaderFactory::getShared(PaymentProcessor::class);
452
-                            // let's simulate an IPN here which will trigger any notifications that need to go out
453
-                            $payment_processor->updateTransactionBasedOnPayment(
454
-                                $transaction,
455
-                                $transaction->last_payment(),
456
-                                true,
457
-                                true
458
-                            );
459
-                        }
460
-                        break;
461
-                    // Failed TXNs
462
-                    case EEM_Transaction::failed_status_code:
463
-                        do_action(
464
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
465
-                            $transaction
466
-                        );
467
-                        // todo :
468
-                        // perform garbage collection here and remove clean_out_junk_transactions()
469
-                        // $registrations = $transaction->registrations();
470
-                        // if (! empty($registrations)) {
471
-                        //     foreach ($registrations as $registration) {
472
-                        //         if ($registration instanceof EE_Registration) {
473
-                        //             $delete_registration = true;
474
-                        //             if ($registration->attendee() instanceof EE_Attendee) {
475
-                        //                 $delete_registration = false;
476
-                        //             }
477
-                        //             if ($delete_registration) {
478
-                        //                 $registration->delete_permanently();
479
-                        //                 $registration->delete_related_permanently();
480
-                        //             }
481
-                        //         }
482
-                        //     }
483
-                        // }
484
-                        break;
485
-                }
486
-            }
487
-            unset(self::$_expired_transactions[ $TXN_ID ]);
488
-        }
489
-    }
490
-
491
-
492
-
493
-    /*************  END OF EXPIRED TRANSACTION CHECK  *************/
494
-
495
-
496
-    /************* START CLEAN UP BOT TRANSACTIONS **********************/
497
-
498
-
499
-    /**
500
-     * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
501
-     * which is setup during activation to run on an hourly cron
502
-     *
503
-     * @throws EE_Error
504
-     * @throws InvalidArgumentException
505
-     * @throws InvalidDataTypeException
506
-     * @throws InvalidInterfaceException
507
-     * @throws DomainException
508
-     * @throws ReflectionException
509
-     */
510
-    public static function clean_out_junk_transactions(): void
511
-    {
512
-        if (DbStatus::isOnline()) {
513
-            EED_Ticket_Sales_Monitor::reset_reservation_counts();
514
-            EEM_Transaction::instance()->delete_junk_transactions();
515
-            EEM_Registration::instance()->delete_registrations_with_no_transaction();
516
-            EEM_Line_Item::instance()->delete_line_items_with_no_transaction();
517
-        }
518
-    }
519
-
520
-
521
-    /**
522
-     * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
523
-     *
524
-     * @throws EE_Error
525
-     * @throws InvalidDataTypeException
526
-     * @throws InvalidInterfaceException
527
-     * @throws InvalidArgumentException
528
-     * @throws ReflectionException
529
-     * @throws Exception
530
-     */
531
-    public static function clean_out_old_gateway_logs(): void
532
-    {
533
-        if (DbStatus::isOnline()) {
534
-            $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
535
-            $time_diff_for_comparison = apply_filters(
536
-                'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
537
-                '-' . $reg_config->gateway_log_lifespan
538
-            );
539
-            EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
540
-        }
541
-    }
542
-
543
-
544
-    /*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
545
-
546
-
547
-    /**
548
-     * @var array
549
-     */
550
-    protected static array $_abandoned_transactions = array();
551
-
552
-
553
-    /**
554
-     * @param int $timestamp
555
-     * @param int $TXN_ID
556
-     *@deprecated
557
-     */
558
-    public static function schedule_finalize_abandoned_transactions_check(int $timestamp, int $TXN_ID): void
559
-    {
560
-        EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
561
-    }
562
-
563
-
564
-    /**
565
-     * @param int $TXN_ID
566
-     *@deprecated
567
-     */
568
-    public static function check_for_abandoned_transactions(int $TXN_ID = 0): void
569
-    {
570
-        EE_Cron_Tasks::expired_transaction_check($TXN_ID);
571
-    }
572
-
573
-
574
-    /**
575
-     * @deprecated
576
-     * @throws EE_Error
577
-     * @throws DomainException
578
-     * @throws InvalidDataTypeException
579
-     * @throws InvalidInterfaceException
580
-     * @throws InvalidArgumentException
581
-     * @throws ReflectionException
582
-     * @throws RuntimeException
583
-     */
584
-    public static function finalize_abandoned_transactions(): void
585
-    {
586
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
587
-        if (
385
+			empty(self::$_expired_transactions)
386
+			// reschedule the cron if we can't hit the db right now
387
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
388
+				'schedule_expired_transaction_check',
389
+				self::$_expired_transactions
390
+			)
391
+		) {
392
+			return;
393
+		}
394
+		/** @type EE_Transaction_Processor $transaction_processor */
395
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
396
+		// set revisit flag for txn processor
397
+		$transaction_processor->set_revisit();
398
+		// load EEM_Transaction
399
+		EE_Registry::instance()->load_model('Transaction');
400
+		foreach (self::$_expired_transactions as $TXN_ID) {
401
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
402
+			// verify transaction and whether it is failed or not
403
+			if ($transaction instanceof EE_Transaction) {
404
+				switch ($transaction->status_ID()) {
405
+					// Completed TXNs
406
+					case EEM_Transaction::complete_status_code:
407
+						// Don't update the transaction/registrations if the Primary Registration is Not Approved.
408
+						$primary_registration = $transaction->primary_registration();
409
+						if (
410
+							$primary_registration instanceof EE_Registration
411
+							&& $primary_registration->status_ID() !== RegStatus::AWAITING_REVIEW
412
+						) {
413
+							/** @type EE_Transaction_Processor $transaction_processor */
414
+							$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
415
+							$transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
416
+								$transaction,
417
+								$transaction->last_payment()
418
+							);
419
+							do_action(
420
+								'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
421
+								$transaction
422
+							);
423
+						}
424
+						break;
425
+					// Overpaid TXNs
426
+					case EEM_Transaction::overpaid_status_code:
427
+						do_action(
428
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
429
+							$transaction
430
+						);
431
+						break;
432
+					// Incomplete TXNs
433
+					case EEM_Transaction::incomplete_status_code:
434
+						do_action(
435
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
436
+							$transaction
437
+						);
438
+						// todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
439
+						break;
440
+					// Abandoned TXNs
441
+					case EEM_Transaction::abandoned_status_code:
442
+						// run hook before updating transaction, primarily so
443
+						// EED_Ticket_Sales_Monitor::process_abandoned_transactions() can release reserved tickets
444
+						do_action(
445
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
446
+							$transaction
447
+						);
448
+						// don't finalize the TXN if it has already been completed
449
+						if ($transaction->all_reg_steps_completed() !== true) {
450
+							/** @var PaymentProcessor $payment_processor */
451
+							$payment_processor = LoaderFactory::getShared(PaymentProcessor::class);
452
+							// let's simulate an IPN here which will trigger any notifications that need to go out
453
+							$payment_processor->updateTransactionBasedOnPayment(
454
+								$transaction,
455
+								$transaction->last_payment(),
456
+								true,
457
+								true
458
+							);
459
+						}
460
+						break;
461
+					// Failed TXNs
462
+					case EEM_Transaction::failed_status_code:
463
+						do_action(
464
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
465
+							$transaction
466
+						);
467
+						// todo :
468
+						// perform garbage collection here and remove clean_out_junk_transactions()
469
+						// $registrations = $transaction->registrations();
470
+						// if (! empty($registrations)) {
471
+						//     foreach ($registrations as $registration) {
472
+						//         if ($registration instanceof EE_Registration) {
473
+						//             $delete_registration = true;
474
+						//             if ($registration->attendee() instanceof EE_Attendee) {
475
+						//                 $delete_registration = false;
476
+						//             }
477
+						//             if ($delete_registration) {
478
+						//                 $registration->delete_permanently();
479
+						//                 $registration->delete_related_permanently();
480
+						//             }
481
+						//         }
482
+						//     }
483
+						// }
484
+						break;
485
+				}
486
+			}
487
+			unset(self::$_expired_transactions[ $TXN_ID ]);
488
+		}
489
+	}
490
+
491
+
492
+
493
+	/*************  END OF EXPIRED TRANSACTION CHECK  *************/
494
+
495
+
496
+	/************* START CLEAN UP BOT TRANSACTIONS **********************/
497
+
498
+
499
+	/**
500
+	 * callback for 'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'
501
+	 * which is setup during activation to run on an hourly cron
502
+	 *
503
+	 * @throws EE_Error
504
+	 * @throws InvalidArgumentException
505
+	 * @throws InvalidDataTypeException
506
+	 * @throws InvalidInterfaceException
507
+	 * @throws DomainException
508
+	 * @throws ReflectionException
509
+	 */
510
+	public static function clean_out_junk_transactions(): void
511
+	{
512
+		if (DbStatus::isOnline()) {
513
+			EED_Ticket_Sales_Monitor::reset_reservation_counts();
514
+			EEM_Transaction::instance()->delete_junk_transactions();
515
+			EEM_Registration::instance()->delete_registrations_with_no_transaction();
516
+			EEM_Line_Item::instance()->delete_line_items_with_no_transaction();
517
+		}
518
+	}
519
+
520
+
521
+	/**
522
+	 * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
523
+	 *
524
+	 * @throws EE_Error
525
+	 * @throws InvalidDataTypeException
526
+	 * @throws InvalidInterfaceException
527
+	 * @throws InvalidArgumentException
528
+	 * @throws ReflectionException
529
+	 * @throws Exception
530
+	 */
531
+	public static function clean_out_old_gateway_logs(): void
532
+	{
533
+		if (DbStatus::isOnline()) {
534
+			$reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
535
+			$time_diff_for_comparison = apply_filters(
536
+				'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
537
+				'-' . $reg_config->gateway_log_lifespan
538
+			);
539
+			EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
540
+		}
541
+	}
542
+
543
+
544
+	/*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
545
+
546
+
547
+	/**
548
+	 * @var array
549
+	 */
550
+	protected static array $_abandoned_transactions = array();
551
+
552
+
553
+	/**
554
+	 * @param int $timestamp
555
+	 * @param int $TXN_ID
556
+	 *@deprecated
557
+	 */
558
+	public static function schedule_finalize_abandoned_transactions_check(int $timestamp, int $TXN_ID): void
559
+	{
560
+		EE_Cron_Tasks::schedule_expired_transaction_check($timestamp, $TXN_ID);
561
+	}
562
+
563
+
564
+	/**
565
+	 * @param int $TXN_ID
566
+	 *@deprecated
567
+	 */
568
+	public static function check_for_abandoned_transactions(int $TXN_ID = 0): void
569
+	{
570
+		EE_Cron_Tasks::expired_transaction_check($TXN_ID);
571
+	}
572
+
573
+
574
+	/**
575
+	 * @deprecated
576
+	 * @throws EE_Error
577
+	 * @throws DomainException
578
+	 * @throws InvalidDataTypeException
579
+	 * @throws InvalidInterfaceException
580
+	 * @throws InvalidArgumentException
581
+	 * @throws ReflectionException
582
+	 * @throws RuntimeException
583
+	 */
584
+	public static function finalize_abandoned_transactions(): void
585
+	{
586
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
587
+		if (
588 588
 // are there any TXNs that need cleaning up ?
589
-            empty(self::$_abandoned_transactions)
590
-            // reschedule the cron if we can't hit the db right now
591
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
592
-                'schedule_expired_transaction_check',
593
-                self::$_abandoned_transactions
594
-            )
595
-        ) {
596
-            return;
597
-        }
598
-        // combine our arrays of transaction IDs
599
-        self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
600
-        // and deal with abandoned transactions here now...
601
-        EE_Cron_Tasks::process_expired_transactions();
602
-    }
603
-
604
-
605
-    /*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
589
+			empty(self::$_abandoned_transactions)
590
+			// reschedule the cron if we can't hit the db right now
591
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
592
+				'schedule_expired_transaction_check',
593
+				self::$_abandoned_transactions
594
+			)
595
+		) {
596
+			return;
597
+		}
598
+		// combine our arrays of transaction IDs
599
+		self::$_expired_transactions = self::$_abandoned_transactions + self::$_expired_transactions;
600
+		// and deal with abandoned transactions here now...
601
+		EE_Cron_Tasks::process_expired_transactions();
602
+	}
603
+
604
+
605
+	/*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
606 606
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -28,7 +28,7 @@  discard block
 block discarded – undo
28 28
 
29 29
     public static function instance(): ?EE_Cron_Tasks
30 30
     {
31
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
31
+        if ( ! self::$_instance instanceof EE_Cron_Tasks) {
32 32
             self::$_instance = new self();
33 33
         }
34 34
         return self::$_instance;
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
              */
62 62
             add_action(
63 63
                 'AHEE__EE_System__load_core_configuration__complete',
64
-                function () {
64
+                function() {
65 65
                     EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
66 66
                     EE_Registry::instance()->NET_CFG->update_config(true, false);
67 67
                     add_option('ee_disabled_wp_cron_check', 1, '', false);
@@ -109,10 +109,10 @@  discard block
 block discarded – undo
109 109
         foreach ($crons as $cron) {
110 110
             /** @var array[] $cron */
111 111
             foreach ($ee_crons as $ee_cron) {
112
-                if (isset($cron[ $ee_cron ]) && is_array($cron[ $ee_cron ])) {
112
+                if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
113 113
                     do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
114
-                    foreach ($cron[ $ee_cron ] as $ee_cron_details) {
115
-                        if (! empty($ee_cron_details['args'])) {
114
+                    foreach ($cron[$ee_cron] as $ee_cron_details) {
115
+                        if ( ! empty($ee_cron_details['args'])) {
116 116
                             do_action(
117 117
                                 'AHEE_log',
118 118
                                 __CLASS__,
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
      */
140 140
     public static function reschedule_cron_for_transactions_if_maintenance_mode(string $cron_task, array $TXN_IDs): bool
141 141
     {
142
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
142
+        if ( ! method_exists('EE_Cron_Tasks', $cron_task)) {
143 143
             throw new DomainException(
144 144
                 sprintf(
145 145
                     esc_html__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
     {
230 230
         do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
231 231
         if (absint($TXN_ID)) {
232
-            self::$_update_transactions_with_payment[ $TXN_ID ] = $PAY_ID;
232
+            self::$_update_transactions_with_payment[$TXN_ID] = $PAY_ID;
233 233
             add_action(
234 234
                 'shutdown',
235 235
                 array('EE_Cron_Tasks', 'update_transaction_with_payment'),
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
                 $payment_processor = LoaderFactory::getShared(PaymentProcessor::class);
296 296
                 $payment_processor->updateTransactionBasedOnPayment($transaction, $payment, true, true);
297 297
             }
298
-            unset(self::$_update_transactions_with_payment[ $TXN_ID ]);
298
+            unset(self::$_update_transactions_with_payment[$TXN_ID]);
299 299
         }
300 300
     }
301 301
 
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
     public static function expired_transaction_check(int $TXN_ID = 0): void
357 357
     {
358 358
         if (absint($TXN_ID)) {
359
-            self::$_expired_transactions[ $TXN_ID ] = $TXN_ID;
359
+            self::$_expired_transactions[$TXN_ID] = $TXN_ID;
360 360
             add_action(
361 361
                 'shutdown',
362 362
                 array('EE_Cron_Tasks', 'process_expired_transactions'),
@@ -484,7 +484,7 @@  discard block
 block discarded – undo
484 484
                         break;
485 485
                 }
486 486
             }
487
-            unset(self::$_expired_transactions[ $TXN_ID ]);
487
+            unset(self::$_expired_transactions[$TXN_ID]);
488 488
         }
489 489
     }
490 490
 
@@ -534,7 +534,7 @@  discard block
 block discarded – undo
534 534
             $reg_config = LoaderFactory::getLoader()->load('EE_Registration_Config');
535 535
             $time_diff_for_comparison = apply_filters(
536 536
                 'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
537
-                '-' . $reg_config->gateway_log_lifespan
537
+                '-'.$reg_config->gateway_log_lifespan
538 538
             );
539 539
             EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
540 540
         }
Please login to merge, or discard this patch.