Completed
Branch feature/session-life-span (e72296)
by
unknown
24:55 queued 17:10
created
core/domain/values/session/SessionLifespan.php 1 patch
Indentation   +85 added lines, -85 removed lines patch added patch discarded remove patch
@@ -19,101 +19,101 @@
 block discarded – undo
19 19
  */
20 20
 class SessionLifespan
21 21
 {
22
-    /**
23
-     * how long an EE session lasts in seconds
24
-     * default session lifespan of 1 hour (for not so instant IPNs)
25
-     *
26
-     * @var int $lifespan
27
-     */
28
-    private $lifespan;
22
+	/**
23
+	 * how long an EE session lasts in seconds
24
+	 * default session lifespan of 1 hour (for not so instant IPNs)
25
+	 *
26
+	 * @var int $lifespan
27
+	 */
28
+	private $lifespan;
29 29
 
30 30
 
31
-    /**
32
-     * SessionLifespan constructor.
33
-     *
34
-     * @param int $lifespan
35
-     * @throws DomainException
36
-     */
37
-    public function __construct($lifespan = 0)
38
-    {
39
-        $lifespan = absint($lifespan);
40
-        if ($lifespan <= 0) {
41
-            $lifespanOption = new SessionLifespanOption();
42
-            $lifespan = $lifespanOption->getSessionLifespan();
43
-        }
44
-        $this->setLifespan($lifespan);
45
-    }
31
+	/**
32
+	 * SessionLifespan constructor.
33
+	 *
34
+	 * @param int $lifespan
35
+	 * @throws DomainException
36
+	 */
37
+	public function __construct($lifespan = 0)
38
+	{
39
+		$lifespan = absint($lifespan);
40
+		if ($lifespan <= 0) {
41
+			$lifespanOption = new SessionLifespanOption();
42
+			$lifespan = $lifespanOption->getSessionLifespan();
43
+		}
44
+		$this->setLifespan($lifespan);
45
+	}
46 46
 
47 47
 
48
-    /**
49
-     * @param int $lifespan
50
-     * @throws DomainException
51
-     */
52
-    protected function setLifespan($lifespan)
53
-    {
54
-        if ($lifespan < 60) {
55
-            throw new DomainException(
56
-                esc_html__(
57
-                    'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
58
-                    'event_espresso'
59
-                )
60
-            );
61
-        }
62
-        $this->lifespan = apply_filters(
63
-            'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
64
-            // apply legacy filter for now but add doing it wrong notice in future
65
-            apply_filters(
66
-                'FHEE__EE_Session__construct___lifespan',
67
-                $lifespan
68
-            )
69
-        ) + 1;
70
-    }
48
+	/**
49
+	 * @param int $lifespan
50
+	 * @throws DomainException
51
+	 */
52
+	protected function setLifespan($lifespan)
53
+	{
54
+		if ($lifespan < 60) {
55
+			throw new DomainException(
56
+				esc_html__(
57
+					'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
58
+					'event_espresso'
59
+				)
60
+			);
61
+		}
62
+		$this->lifespan = apply_filters(
63
+			'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
64
+			// apply legacy filter for now but add doing it wrong notice in future
65
+			apply_filters(
66
+				'FHEE__EE_Session__construct___lifespan',
67
+				$lifespan
68
+			)
69
+		) + 1;
70
+	}
71 71
 
72 72
 
73
-    /**
74
-     * @return int
75
-     */
76
-    public function inSeconds()
77
-    {
78
-        return $this->lifespan;
79
-    }
73
+	/**
74
+	 * @return int
75
+	 */
76
+	public function inSeconds()
77
+	{
78
+		return $this->lifespan;
79
+	}
80 80
 
81 81
 
82
-    /**
83
-     * @param string $separator
84
-     * @return string
85
-     */
86
-    public function inHoursMinutesSeconds($separator = ':')
87
-    {
88
-        return sprintf(
89
-            '%02d%s%02d%s%02d',
90
-            floor($this->lifespan / 3600),
91
-            $separator,
92
-            ($this->lifespan / 60) % 60,
93
-            $separator,
94
-            $this->lifespan % 60
95
-        );
96
-    }
82
+	/**
83
+	 * @param string $separator
84
+	 * @return string
85
+	 */
86
+	public function inHoursMinutesSeconds($separator = ':')
87
+	{
88
+		return sprintf(
89
+			'%02d%s%02d%s%02d',
90
+			floor($this->lifespan / 3600),
91
+			$separator,
92
+			($this->lifespan / 60) % 60,
93
+			$separator,
94
+			$this->lifespan % 60
95
+		);
96
+	}
97 97
 
98 98
 
99
-    /**
100
-     * Returns a timestamp for when the session would expire based on this lifespan
101
-     *
102
-     * @param bool $utc If true, displays expiration in UTC
103
-     *                  If false, displays expiration in local time
104
-     * @return int
105
-     */
106
-    public function expiration($utc = true)
107
-    {
108
-        return (int) current_time('timestamp', $utc) - $this->lifespan;
109
-    }
99
+	/**
100
+	 * Returns a timestamp for when the session would expire based on this lifespan
101
+	 *
102
+	 * @param bool $utc If true, displays expiration in UTC
103
+	 *                  If false, displays expiration in local time
104
+	 * @return int
105
+	 */
106
+	public function expiration($utc = true)
107
+	{
108
+		return (int) current_time('timestamp', $utc) - $this->lifespan;
109
+	}
110 110
 
111 111
 
112
-    /**
113
-     * @return string
114
-     */
115
-    public function __toString()
116
-    {
117
-        return (string) $this->inSeconds();
118
-    }
112
+	/**
113
+	 * @return string
114
+	 */
115
+	public function __toString()
116
+	{
117
+		return (string) $this->inSeconds();
118
+	}
119 119
 }
Please login to merge, or discard this patch.
core/domain/values/session/SessionLifespanOption.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -14,41 +14,41 @@
 block discarded – undo
14 14
  */
15 15
 class SessionLifespanOption extends WordPressOption
16 16
 {
17
-    const DEFAULT_LIFESPAN  = HOUR_IN_SECONDS;
18
-
19
-    const OPTION_NAME       = 'ee-session-lifespan';
20
-
21
-
22
-    /**
23
-     * SessionLifespanOption constructor.
24
-     */
25
-    public function __construct()
26
-    {
27
-        parent::__construct(
28
-            SessionLifespanOption::OPTION_NAME,
29
-            SessionLifespanOption::DEFAULT_LIFESPAN,
30
-            false
31
-        );
32
-    }
33
-
34
-
35
-    /**
36
-     * @return false|mixed|void
37
-     */
38
-    public function getSessionLifespan()
39
-    {
40
-        return $this->loadOption();
41
-    }
42
-
43
-    /**
44
-     * @param int $value
45
-     * @return false|mixed|void
46
-     */
47
-    public function setSessionLifespan(int $value)
48
-    {
49
-        if ($value <= 0) {
50
-            $value = SessionLifespanOption::DEFAULT_LIFESPAN;
51
-        }
52
-        return $this->updateOption($value);
53
-    }
17
+	const DEFAULT_LIFESPAN  = HOUR_IN_SECONDS;
18
+
19
+	const OPTION_NAME       = 'ee-session-lifespan';
20
+
21
+
22
+	/**
23
+	 * SessionLifespanOption constructor.
24
+	 */
25
+	public function __construct()
26
+	{
27
+		parent::__construct(
28
+			SessionLifespanOption::OPTION_NAME,
29
+			SessionLifespanOption::DEFAULT_LIFESPAN,
30
+			false
31
+		);
32
+	}
33
+
34
+
35
+	/**
36
+	 * @return false|mixed|void
37
+	 */
38
+	public function getSessionLifespan()
39
+	{
40
+		return $this->loadOption();
41
+	}
42
+
43
+	/**
44
+	 * @param int $value
45
+	 * @return false|mixed|void
46
+	 */
47
+	public function setSessionLifespan(int $value)
48
+	{
49
+		if ($value <= 0) {
50
+			$value = SessionLifespanOption::DEFAULT_LIFESPAN;
51
+		}
52
+		return $this->updateOption($value);
53
+	}
54 54
 }
Please login to merge, or discard this patch.
admin/extend/registration_form/forms/SessionLifespanFormHandler.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -12,59 +12,59 @@
 block discarded – undo
12 12
 
13 13
 class SessionLifespanFormHandler
14 14
 {
15
-    /**
16
-     * @var SessionLifespanOption
17
-     */
18
-    private $sessionLifespanOption;
15
+	/**
16
+	 * @var SessionLifespanOption
17
+	 */
18
+	private $sessionLifespanOption;
19 19
 
20 20
 
21
-    /**
22
-     * SessionLifespanForm constructor.
23
-     *
24
-     * @throws EE_Error
25
-     */
26
-    public function __construct()
27
-    {
28
-        $this->sessionLifespanOption = new SessionLifespanOption();
29
-    }
21
+	/**
22
+	 * SessionLifespanForm constructor.
23
+	 *
24
+	 * @throws EE_Error
25
+	 */
26
+	public function __construct()
27
+	{
28
+		$this->sessionLifespanOption = new SessionLifespanOption();
29
+	}
30 30
 
31 31
 
32
-    public function process(SessionLifespanForm $form)
33
-    {
34
-        try {
35
-            // if not displaying a form, then check for form submission
36
-            if ($form->was_submitted()) {
37
-                // capture form data
38
-                $form->receive_form_submission();
39
-                // validate form data
40
-                if ($form->is_valid()) {
41
-                    // grab validated data from form
42
-                    $valid_data = $form->valid_data();
43
-                    if (isset($valid_data['session_lifespan'])) {
44
-                        $session_lifespan = (int) $valid_data['session_lifespan'];
45
-                        $this->sessionLifespanOption->setSessionLifespan($session_lifespan);
46
-                    } else {
47
-                        EE_Error::add_error(
48
-                            esc_html__(
49
-                                'Invalid or missing Email Validation settings. Please refresh the form and try again.',
50
-                                'event_espresso'
51
-                            ),
52
-                            __FILE__,
53
-                            __FUNCTION__,
54
-                            __LINE__
55
-                        );
56
-                    }
57
-                } elseif ($form->submission_error_message() !== '') {
58
-                    EE_Error::add_error(
59
-                        $form->submission_error_message(),
60
-                        __FILE__,
61
-                        __FUNCTION__,
62
-                        __LINE__
63
-                    );
64
-                }
65
-            }
66
-        } catch (EE_Error $e) {
67
-            $e->get_error();
68
-        }
69
-    }
32
+	public function process(SessionLifespanForm $form)
33
+	{
34
+		try {
35
+			// if not displaying a form, then check for form submission
36
+			if ($form->was_submitted()) {
37
+				// capture form data
38
+				$form->receive_form_submission();
39
+				// validate form data
40
+				if ($form->is_valid()) {
41
+					// grab validated data from form
42
+					$valid_data = $form->valid_data();
43
+					if (isset($valid_data['session_lifespan'])) {
44
+						$session_lifespan = (int) $valid_data['session_lifespan'];
45
+						$this->sessionLifespanOption->setSessionLifespan($session_lifespan);
46
+					} else {
47
+						EE_Error::add_error(
48
+							esc_html__(
49
+								'Invalid or missing Email Validation settings. Please refresh the form and try again.',
50
+								'event_espresso'
51
+							),
52
+							__FILE__,
53
+							__FUNCTION__,
54
+							__LINE__
55
+						);
56
+					}
57
+				} elseif ($form->submission_error_message() !== '') {
58
+					EE_Error::add_error(
59
+						$form->submission_error_message(),
60
+						__FILE__,
61
+						__FUNCTION__,
62
+						__LINE__
63
+					);
64
+				}
65
+			}
66
+		} catch (EE_Error $e) {
67
+			$e->get_error();
68
+		}
69
+	}
70 70
 }
Please login to merge, or discard this patch.
admin/extend/registration_form/Extend_Registration_Form_Admin_Page.core.php 1 patch
Indentation   +1456 added lines, -1456 removed lines patch added patch discarded remove patch
@@ -16,1460 +16,1460 @@
 block discarded – undo
16 16
  */
17 17
 class Extend_Registration_Form_Admin_Page extends Registration_Form_Admin_Page
18 18
 {
19
-    /**
20
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
21
-     */
22
-    public function __construct($routing = true)
23
-    {
24
-        define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form/');
25
-        define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets/');
26
-        define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
27
-        define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates/');
28
-        define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
29
-        parent::__construct($routing);
30
-    }
31
-
32
-
33
-    /**
34
-     * @return void
35
-     */
36
-    protected function _extend_page_config()
37
-    {
38
-        $this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
39
-        $qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
40
-            ? $this->_req_data['QST_ID'] : 0;
41
-        $qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
42
-            ? $this->_req_data['QSG_ID'] : 0;
43
-
44
-        $new_page_routes = array(
45
-            'question_groups'    => array(
46
-                'func'       => '_question_groups_overview_list_table',
47
-                'capability' => 'ee_read_question_groups',
48
-            ),
49
-            'add_question'       => array(
50
-                'func'       => '_edit_question',
51
-                'capability' => 'ee_edit_questions',
52
-            ),
53
-            'insert_question'    => array(
54
-                'func'       => '_insert_or_update_question',
55
-                'args'       => array('new_question' => true),
56
-                'capability' => 'ee_edit_questions',
57
-                'noheader'   => true,
58
-            ),
59
-            'duplicate_question' => array(
60
-                'func'       => '_duplicate_question',
61
-                'capability' => 'ee_edit_questions',
62
-                'noheader'   => true,
63
-            ),
64
-            'trash_question'     => array(
65
-                'func'       => '_trash_question',
66
-                'capability' => 'ee_delete_question',
67
-                'obj_id'     => $qst_id,
68
-                'noheader'   => true,
69
-            ),
70
-
71
-            'restore_question' => array(
72
-                'func'       => '_trash_or_restore_questions',
73
-                'capability' => 'ee_delete_question',
74
-                'obj_id'     => $qst_id,
75
-                'args'       => array('trash' => false),
76
-                'noheader'   => true,
77
-            ),
78
-
79
-            'delete_question' => array(
80
-                'func'       => '_delete_question',
81
-                'capability' => 'ee_delete_question',
82
-                'obj_id'     => $qst_id,
83
-                'noheader'   => true,
84
-            ),
85
-
86
-            'trash_questions' => array(
87
-                'func'       => '_trash_or_restore_questions',
88
-                'capability' => 'ee_delete_questions',
89
-                'args'       => array('trash' => true),
90
-                'noheader'   => true,
91
-            ),
92
-
93
-            'restore_questions' => array(
94
-                'func'       => '_trash_or_restore_questions',
95
-                'capability' => 'ee_delete_questions',
96
-                'args'       => array('trash' => false),
97
-                'noheader'   => true,
98
-            ),
99
-
100
-            'delete_questions' => array(
101
-                'func'       => '_delete_questions',
102
-                'args'       => array(),
103
-                'capability' => 'ee_delete_questions',
104
-                'noheader'   => true,
105
-            ),
106
-
107
-            'add_question_group' => array(
108
-                'func'       => '_edit_question_group',
109
-                'capability' => 'ee_edit_question_groups',
110
-            ),
111
-
112
-            'edit_question_group' => array(
113
-                'func'       => '_edit_question_group',
114
-                'capability' => 'ee_edit_question_group',
115
-                'obj_id'     => $qsg_id,
116
-                'args'       => array('edit'),
117
-            ),
118
-
119
-            'delete_question_groups' => array(
120
-                'func'       => '_delete_question_groups',
121
-                'capability' => 'ee_delete_question_groups',
122
-                'noheader'   => true,
123
-            ),
124
-
125
-            'delete_question_group' => array(
126
-                'func'       => '_delete_question_groups',
127
-                'capability' => 'ee_delete_question_group',
128
-                'obj_id'     => $qsg_id,
129
-                'noheader'   => true,
130
-            ),
131
-
132
-            'trash_question_group' => array(
133
-                'func'       => '_trash_or_restore_question_groups',
134
-                'args'       => array('trash' => true),
135
-                'capability' => 'ee_delete_question_group',
136
-                'obj_id'     => $qsg_id,
137
-                'noheader'   => true,
138
-            ),
139
-
140
-            'restore_question_group' => array(
141
-                'func'       => '_trash_or_restore_question_groups',
142
-                'args'       => array('trash' => false),
143
-                'capability' => 'ee_delete_question_group',
144
-                'obj_id'     => $qsg_id,
145
-                'noheader'   => true,
146
-            ),
147
-
148
-            'insert_question_group' => array(
149
-                'func'       => '_insert_or_update_question_group',
150
-                'args'       => array('new_question_group' => true),
151
-                'capability' => 'ee_edit_question_groups',
152
-                'noheader'   => true,
153
-            ),
154
-
155
-            'update_question_group' => array(
156
-                'func'       => '_insert_or_update_question_group',
157
-                'args'       => array('new_question_group' => false),
158
-                'capability' => 'ee_edit_question_group',
159
-                'obj_id'     => $qsg_id,
160
-                'noheader'   => true,
161
-            ),
162
-
163
-            'trash_question_groups' => array(
164
-                'func'       => '_trash_or_restore_question_groups',
165
-                'args'       => array('trash' => true),
166
-                'capability' => 'ee_delete_question_groups',
167
-                'noheader'   => array('trash' => false),
168
-            ),
169
-
170
-            'restore_question_groups' => array(
171
-                'func'       => '_trash_or_restore_question_groups',
172
-                'args'       => array('trash' => false),
173
-                'capability' => 'ee_delete_question_groups',
174
-                'noheader'   => true,
175
-            ),
176
-
177
-
178
-            'espresso_update_question_group_order' => array(
179
-                'func'       => 'update_question_group_order',
180
-                'capability' => 'ee_edit_question_groups',
181
-                'noheader'   => true,
182
-            ),
183
-
184
-            'view_reg_form_settings' => array(
185
-                'func'       => '_reg_form_settings',
186
-                'capability' => 'manage_options',
187
-            ),
188
-
189
-            'update_reg_form_settings' => array(
190
-                'func'       => '_update_reg_form_settings',
191
-                'capability' => 'manage_options',
192
-                'noheader'   => true,
193
-            ),
194
-        );
195
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
196
-
197
-        $new_page_config = array(
198
-
199
-            'question_groups' => array(
200
-                'nav'           => array(
201
-                    'label' => esc_html__('Question Groups', 'event_espresso'),
202
-                    'icon' => 'dashicons-forms',
203
-                    'order' => 20,
204
-                ),
205
-                'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
206
-                'help_tabs'     => array(
207
-                    'registration_form_question_groups_help_tab'                           => array(
208
-                        'title'    => esc_html__('Question Groups', 'event_espresso'),
209
-                        'filename' => 'registration_form_question_groups',
210
-                    ),
211
-                    'registration_form_question_groups_table_column_headings_help_tab'     => array(
212
-                        'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
213
-                        'filename' => 'registration_form_question_groups_table_column_headings',
214
-                    ),
215
-                    'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
216
-                        'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
217
-                        'filename' => 'registration_form_question_groups_views_bulk_actions_search',
218
-                    ),
219
-                ),
220
-                'metaboxes'     => $this->_default_espresso_metaboxes,
221
-                'require_nonce' => false,
222
-            ),
223
-
224
-            'add_question' => array(
225
-                'nav'           => array(
226
-                    'label'      => esc_html__('Add Question', 'event_espresso'),
227
-                    'icon' => 'dashicons-plus-alt',
228
-                    'order'      => 15,
229
-                    'persistent' => false,
230
-                ),
231
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
232
-                'help_tabs'     => array(
233
-                    'registration_form_add_question_help_tab' => array(
234
-                        'title'    => esc_html__('Add Question', 'event_espresso'),
235
-                        'filename' => 'registration_form_add_question',
236
-                    ),
237
-                ),
238
-                'require_nonce' => false,
239
-            ),
240
-
241
-            'add_question_group' => array(
242
-                'nav'           => array(
243
-                    'label'      => esc_html__('Add Question Group', 'event_espresso'),
244
-                    'icon' => 'dashicons-plus-alt',
245
-                    'order'      => 25,
246
-                    'persistent' => false,
247
-                ),
248
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
249
-                'help_tabs'     => array(
250
-                    'registration_form_add_question_group_help_tab' => array(
251
-                        'title'    => esc_html__('Add Question Group', 'event_espresso'),
252
-                        'filename' => 'registration_form_add_question_group',
253
-                    ),
254
-                ),
255
-                'require_nonce' => false,
256
-            ),
257
-
258
-            'edit_question_group' => array(
259
-                'nav'           => array(
260
-                    'label'      => esc_html__('Edit Question Group', 'event_espresso'),
261
-                    'icon' => 'dashicons-edit-large',
262
-                    'order'      => 25,
263
-                    'persistent' => false,
264
-                    'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
265
-                        array('question_group_id' => $this->_req_data['question_group_id']),
266
-                        $this->_current_page_view_url
267
-                    ) : $this->_admin_base_url,
268
-                ),
269
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
270
-                'help_tabs'     => array(
271
-                    'registration_form_edit_question_group_help_tab' => array(
272
-                        'title'    => esc_html__('Edit Question Group', 'event_espresso'),
273
-                        'filename' => 'registration_form_edit_question_group',
274
-                    ),
275
-                ),
276
-                'require_nonce' => false,
277
-            ),
278
-
279
-            'view_reg_form_settings' => array(
280
-                'nav'           => array(
281
-                    'label' => esc_html__('Reg Form Settings', 'event_espresso'),
282
-                    'icon' => 'dashicons-admin-generic',
283
-                    'order' => 40,
284
-                ),
285
-                'labels'        => array(
286
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
287
-                ),
288
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
289
-                'help_tabs'     => array(
290
-                    'registration_form_reg_form_settings_help_tab' => array(
291
-                        'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
292
-                        'filename' => 'registration_form_reg_form_settings',
293
-                    ),
294
-                ),
295
-                'require_nonce' => false,
296
-            ),
297
-
298
-        );
299
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
300
-
301
-        // change the list table we're going to use so it's the NEW list table!
302
-        $this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
303
-
304
-
305
-        // additional labels
306
-        $new_labels = array(
307
-            'add_question'          => esc_html__('Add New Question', 'event_espresso'),
308
-            'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
309
-            'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
310
-            'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
311
-            'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
312
-        );
313
-        $this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
314
-    }
315
-
316
-
317
-    /**
318
-     * @return void
319
-     */
320
-    protected function _ajax_hooks()
321
-    {
322
-        add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
323
-    }
324
-
325
-
326
-    /**
327
-     * @return void
328
-     */
329
-    public function load_scripts_styles_question_groups()
330
-    {
331
-        wp_enqueue_script('espresso_ajax_table_sorting');
332
-    }
333
-
334
-
335
-    /**
336
-     * @return void
337
-     */
338
-    public function load_scripts_styles_add_question_group()
339
-    {
340
-        $this->load_scripts_styles_forms();
341
-        $this->load_sortable_question_script();
342
-    }
343
-
344
-
345
-    /**
346
-     * @return void
347
-     */
348
-    public function load_scripts_styles_edit_question_group()
349
-    {
350
-        $this->load_scripts_styles_forms();
351
-        $this->load_sortable_question_script();
352
-    }
353
-
354
-
355
-    /**
356
-     * registers and enqueues script for questions
357
-     *
358
-     * @return void
359
-     */
360
-    public function load_sortable_question_script()
361
-    {
362
-        wp_register_script(
363
-            'ee-question-sortable',
364
-            REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
365
-            array('jquery-ui-sortable'),
366
-            EVENT_ESPRESSO_VERSION,
367
-            true
368
-        );
369
-        wp_enqueue_script('ee-question-sortable');
370
-    }
371
-
372
-
373
-    /**
374
-     * @return void
375
-     */
376
-    protected function _set_list_table_views_default()
377
-    {
378
-        $this->_views = array(
379
-            'all' => array(
380
-                'slug'        => 'all',
381
-                'label'       => esc_html__('View All Questions', 'event_espresso'),
382
-                'count'       => 0,
383
-                'bulk_action' => array(
384
-                    'trash_questions' => esc_html__('Trash', 'event_espresso'),
385
-                ),
386
-            ),
387
-        );
388
-
389
-        if (
390
-            EE_Registry::instance()->CAP->current_user_can(
391
-                'ee_delete_questions',
392
-                'espresso_registration_form_trash_questions'
393
-            )
394
-        ) {
395
-            $this->_views['trash'] = array(
396
-                'slug'        => 'trash',
397
-                'label'       => esc_html__('Trash', 'event_espresso'),
398
-                'count'       => 0,
399
-                'bulk_action' => array(
400
-                    'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
401
-                    'restore_questions' => esc_html__('Restore', 'event_espresso'),
402
-                ),
403
-            );
404
-        }
405
-    }
406
-
407
-
408
-    /**
409
-     * @return void
410
-     */
411
-    protected function _set_list_table_views_question_groups()
412
-    {
413
-        $this->_views = array(
414
-            'all' => array(
415
-                'slug'        => 'all',
416
-                'label'       => esc_html__('All', 'event_espresso'),
417
-                'count'       => 0,
418
-                'bulk_action' => array(
419
-                    'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
420
-                ),
421
-            ),
422
-        );
423
-
424
-        if (
425
-            EE_Registry::instance()->CAP->current_user_can(
426
-                'ee_delete_question_groups',
427
-                'espresso_registration_form_trash_question_groups'
428
-            )
429
-        ) {
430
-            $this->_views['trash'] = array(
431
-                'slug'        => 'trash',
432
-                'label'       => esc_html__('Trash', 'event_espresso'),
433
-                'count'       => 0,
434
-                'bulk_action' => array(
435
-                    'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
436
-                    'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
437
-                ),
438
-            );
439
-        }
440
-    }
441
-
442
-
443
-    /**
444
-     * @return void
445
-     * @throws EE_Error
446
-     * @throws InvalidArgumentException
447
-     * @throws InvalidDataTypeException
448
-     * @throws InvalidInterfaceException
449
-     */
450
-    protected function _questions_overview_list_table()
451
-    {
452
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
453
-            'add_question',
454
-            'add_question',
455
-            array(),
456
-            'add-new-h2'
457
-        );
458
-        parent::_questions_overview_list_table();
459
-    }
460
-
461
-
462
-    /**
463
-     * @return void
464
-     * @throws DomainException
465
-     * @throws EE_Error
466
-     * @throws InvalidArgumentException
467
-     * @throws InvalidDataTypeException
468
-     * @throws InvalidInterfaceException
469
-     */
470
-    protected function _question_groups_overview_list_table()
471
-    {
472
-        $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
473
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
474
-            'add_question_group',
475
-            'add_question_group',
476
-            array(),
477
-            'add-new-h2'
478
-        );
479
-        $this->display_admin_list_table_page_with_sidebar();
480
-    }
481
-
482
-
483
-    /**
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     */
490
-    protected function _delete_question()
491
-    {
492
-        $success = $this->_delete_items($this->_question_model);
493
-        $this->_redirect_after_action(
494
-            $success,
495
-            $this->_question_model->item_name($success),
496
-            'deleted',
497
-            array('action' => 'default', 'status' => 'all')
498
-        );
499
-    }
500
-
501
-
502
-    /**
503
-     * @return void
504
-     * @throws EE_Error
505
-     * @throws InvalidArgumentException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidInterfaceException
508
-     */
509
-    protected function _delete_questions()
510
-    {
511
-        $success = $this->_delete_items($this->_question_model);
512
-        $this->_redirect_after_action(
513
-            $success,
514
-            $this->_question_model->item_name($success),
515
-            'deleted permanently',
516
-            array('action' => 'default', 'status' => 'trash')
517
-        );
518
-    }
519
-
520
-
521
-    /**
522
-     * Performs the deletion of a single or multiple questions or question groups.
523
-     *
524
-     * @param EEM_Soft_Delete_Base $model
525
-     * @return int number of items deleted permanently
526
-     * @throws EE_Error
527
-     * @throws InvalidArgumentException
528
-     * @throws InvalidDataTypeException
529
-     * @throws InvalidInterfaceException
530
-     */
531
-    private function _delete_items(EEM_Soft_Delete_Base $model)
532
-    {
533
-        $success = 0;
534
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
535
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
536
-            // if array has more than one element than success message should be plural
537
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
538
-            // cycle thru bulk action checkboxes
539
-            while (list($ID, $value) = each($this->_req_data['checkbox'])) {
540
-                if (! $this->_delete_item($ID, $model)) {
541
-                    $success = 0;
542
-                }
543
-            }
544
-        } elseif (! empty($this->_req_data['QSG_ID'])) {
545
-            $success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
546
-        } elseif (! empty($this->_req_data['QST_ID'])) {
547
-            $success = $this->_delete_item($this->_req_data['QST_ID'], $model);
548
-        } else {
549
-            EE_Error::add_error(
550
-                sprintf(
551
-                    esc_html__(
552
-                        "No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.",
553
-                        "event_espresso"
554
-                    )
555
-                ),
556
-                __FILE__,
557
-                __FUNCTION__,
558
-                __LINE__
559
-            );
560
-        }
561
-        return $success;
562
-    }
563
-
564
-
565
-    /**
566
-     * Deletes the specified question (and its associated question options) or question group
567
-     *
568
-     * @param int                  $id
569
-     * @param EEM_Soft_Delete_Base $model
570
-     * @return boolean
571
-     * @throws EE_Error
572
-     * @throws InvalidArgumentException
573
-     * @throws InvalidDataTypeException
574
-     * @throws InvalidInterfaceException
575
-     */
576
-    protected function _delete_item($id, $model)
577
-    {
578
-        if ($model instanceof EEM_Question) {
579
-            EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
580
-        }
581
-        return $model->delete_permanently_by_ID(absint($id));
582
-    }
583
-
584
-
585
-    /******************************    QUESTION GROUPS    ******************************/
586
-
587
-
588
-    /**
589
-     * @param string $type
590
-     * @return void
591
-     * @throws DomainException
592
-     * @throws EE_Error
593
-     * @throws InvalidArgumentException
594
-     * @throws InvalidDataTypeException
595
-     * @throws InvalidInterfaceException
596
-     */
597
-    protected function _edit_question_group($type = 'add')
598
-    {
599
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
600
-        $ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID'])
601
-            ? absint($this->_req_data['QSG_ID'])
602
-            : false;
603
-
604
-        switch ($this->_req_action) {
605
-            case 'add_question_group':
606
-                $this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
607
-                break;
608
-            case 'edit_question_group':
609
-                $this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
610
-                break;
611
-            default:
612
-                $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
613
-        }
614
-        // add ID to title if editing
615
-        $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
616
-        if ($ID) {
617
-            /** @var EE_Question_Group $questionGroup */
618
-            $questionGroup = $this->_question_group_model->get_one_by_ID($ID);
619
-            $additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
620
-            $this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
621
-        } else {
622
-            /** @var EE_Question_Group $questionGroup */
623
-            $questionGroup = EEM_Question_Group::instance()->create_default_object();
624
-            $questionGroup->set_order_to_latest();
625
-            $this->_set_add_edit_form_tags('insert_question_group');
626
-        }
627
-        $this->_template_args['values'] = $this->_yes_no_values;
628
-        $this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
629
-        $this->_template_args['QSG_ID'] = $ID ? $ID : true;
630
-        $this->_template_args['question_group'] = $questionGroup;
631
-
632
-        $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
633
-        $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
634
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
635
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
636
-            $this->_template_args,
637
-            true
638
-        );
639
-
640
-        // the details template wrapper
641
-        $this->display_admin_page_with_sidebar();
642
-    }
643
-
644
-
645
-    /**
646
-     * @return void
647
-     * @throws EE_Error
648
-     * @throws InvalidArgumentException
649
-     * @throws InvalidDataTypeException
650
-     * @throws InvalidInterfaceException
651
-     */
652
-    protected function _delete_question_groups()
653
-    {
654
-        $success = $this->_delete_items($this->_question_group_model);
655
-        $this->_redirect_after_action(
656
-            $success,
657
-            $this->_question_group_model->item_name($success),
658
-            'deleted permanently',
659
-            array('action' => 'question_groups', 'status' => 'trash')
660
-        );
661
-    }
662
-
663
-
664
-    /**
665
-     * @param bool $new_question_group
666
-     * @throws EE_Error
667
-     * @throws InvalidArgumentException
668
-     * @throws InvalidDataTypeException
669
-     * @throws InvalidInterfaceException
670
-     */
671
-    protected function _insert_or_update_question_group($new_question_group = true)
672
-    {
673
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
674
-        $set_column_values = $this->_set_column_values_for($this->_question_group_model);
675
-
676
-        // make sure identifier is unique
677
-        $identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : '';
678
-        $where_values = ['QSG_identifier' => $set_column_values['QSG_identifier']];
679
-        if (! $new_question_group && isset($set_column_values['QSG_ID'])) {
680
-            $where_values['QSG_ID'] = ['!=', $set_column_values['QSG_ID']];
681
-        }
682
-        $identifier_exists = ! empty($identifier_value)
683
-            ? $this->_question_group_model->count([$where_values]) > 0
684
-            : false;
685
-        if ($identifier_exists) {
686
-            $set_column_values['QSG_identifier'] .= uniqid('id', true);
687
-        }
688
-
689
-        if ($new_question_group) {
690
-            $QSG_ID = $this->_question_group_model->insert($set_column_values);
691
-            $success = $QSG_ID ? 1 : 0;
692
-            if ($success === 0) {
693
-                EE_Error::add_error(
694
-                    esc_html__('Something went wrong saving the question group.', 'event_espresso'),
695
-                    __FILE__,
696
-                    __FUNCTION__,
697
-                    __LINE__
698
-                );
699
-                $this->_redirect_after_action(
700
-                    false,
701
-                    '',
702
-                    '',
703
-                    array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
704
-                    true
705
-                );
706
-            }
707
-        } else {
708
-            $QSG_ID = absint($this->_req_data['QSG_ID']);
709
-            unset($set_column_values['QSG_ID']);
710
-            $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
711
-        }
712
-
713
-        $phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
714
-            EEM_Attendee::system_question_phone
715
-        );
716
-        // update the existing related questions
717
-        // BUT FIRST...  delete the phone question from the Question_Group_Question
718
-        // if it is being added to this question group (therefore removed from the existing group)
719
-        if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
720
-            // delete where QST ID = system phone question ID and Question Group ID is NOT this group
721
-            EEM_Question_Group_Question::instance()->delete(
722
-                array(
723
-                    array(
724
-                        'QST_ID' => $phone_question_id,
725
-                        'QSG_ID' => array('!=', $QSG_ID),
726
-                    ),
727
-                )
728
-            );
729
-        }
730
-        /** @type EE_Question_Group $question_group */
731
-        $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
732
-        $questions = $question_group->questions();
733
-        // make sure system phone question is added to list of questions for this group
734
-        if (! isset($questions[ $phone_question_id ])) {
735
-            $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
736
-        }
737
-
738
-        foreach ($questions as $question_ID => $question) {
739
-            // first we always check for order.
740
-            if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
741
-                // update question order
742
-                $question_group->update_question_order(
743
-                    $question_ID,
744
-                    $this->_req_data['question_orders'][ $question_ID ]
745
-                );
746
-            }
747
-
748
-            // then we always check if adding or removing.
749
-            if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
750
-                $question_group->add_question($question_ID);
751
-            } else {
752
-                // not found, remove it (but only if not a system question for the personal group
753
-                // with the exception of lname system question - we allow removal of it)
754
-                if (
755
-                    in_array(
756
-                        $question->system_ID(),
757
-                        EEM_Question::instance()->required_system_questions_in_system_question_group(
758
-                            $question_group->system_group()
759
-                        )
760
-                    )
761
-                ) {
762
-                    continue;
763
-                } else {
764
-                    $question_group->remove_question($question_ID);
765
-                }
766
-            }
767
-        }
768
-        // save new related questions
769
-        if (isset($this->_req_data['questions'])) {
770
-            foreach ($this->_req_data['questions'] as $QST_ID) {
771
-                $question_group->add_question($QST_ID);
772
-                if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
773
-                    $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
774
-                }
775
-            }
776
-        }
777
-
778
-        if ($success !== false) {
779
-            $msg = $new_question_group
780
-                ? sprintf(
781
-                    esc_html__('The %s has been created', 'event_espresso'),
782
-                    $this->_question_group_model->item_name()
783
-                )
784
-                : sprintf(
785
-                    esc_html__(
786
-                        'The %s has been updated',
787
-                        'event_espresso'
788
-                    ),
789
-                    $this->_question_group_model->item_name()
790
-                );
791
-            EE_Error::add_success($msg);
792
-        }
793
-        $this->_redirect_after_action(
794
-            false,
795
-            '',
796
-            '',
797
-            array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
798
-            true
799
-        );
800
-    }
801
-
802
-
803
-    /**
804
-     * duplicates a question and all its question options and redirects to the new question.
805
-     *
806
-     * @return void
807
-     * @throws EE_Error
808
-     * @throws InvalidArgumentException
809
-     * @throws ReflectionException
810
-     * @throws InvalidDataTypeException
811
-     * @throws InvalidInterfaceException
812
-     */
813
-    public function _duplicate_question()
814
-    {
815
-        $question_ID = (int) $this->_req_data['QST_ID'];
816
-        $question = EEM_Question::instance()->get_one_by_ID($question_ID);
817
-        if ($question instanceof EE_Question) {
818
-            $new_question = $question->duplicate();
819
-            if ($new_question instanceof EE_Question) {
820
-                $this->_redirect_after_action(
821
-                    true,
822
-                    esc_html__('Question', 'event_espresso'),
823
-                    esc_html__('Duplicated', 'event_espresso'),
824
-                    array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
825
-                    true
826
-                );
827
-            } else {
828
-                global $wpdb;
829
-                EE_Error::add_error(
830
-                    sprintf(
831
-                        esc_html__(
832
-                            'Could not duplicate question with ID %1$d because: %2$s',
833
-                            'event_espresso'
834
-                        ),
835
-                        $question_ID,
836
-                        $wpdb->last_error
837
-                    ),
838
-                    __FILE__,
839
-                    __FUNCTION__,
840
-                    __LINE__
841
-                );
842
-                $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
843
-            }
844
-        } else {
845
-            EE_Error::add_error(
846
-                sprintf(
847
-                    esc_html__(
848
-                        'Could not duplicate question with ID %d because it didn\'t exist!',
849
-                        'event_espresso'
850
-                    ),
851
-                    $question_ID
852
-                ),
853
-                __FILE__,
854
-                __FUNCTION__,
855
-                __LINE__
856
-            );
857
-            $this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
858
-        }
859
-    }
860
-
861
-
862
-    /**
863
-     * @param bool $trash
864
-     * @throws EE_Error
865
-     */
866
-    protected function _trash_or_restore_question_groups($trash = true)
867
-    {
868
-        $this->_trash_or_restore_items($this->_question_group_model, $trash);
869
-    }
870
-
871
-
872
-    /**
873
-     *_trash_question
874
-     *
875
-     * @return void
876
-     * @throws EE_Error
877
-     */
878
-    protected function _trash_question()
879
-    {
880
-        $success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
881
-        $query_args = array('action' => 'default', 'status' => 'all');
882
-        $this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
883
-    }
884
-
885
-
886
-    /**
887
-     * @param bool $trash
888
-     * @throws EE_Error
889
-     */
890
-    protected function _trash_or_restore_questions($trash = true)
891
-    {
892
-        $this->_trash_or_restore_items($this->_question_model, $trash);
893
-    }
894
-
895
-
896
-    /**
897
-     * Internally used to delete or restore items, using the request data. Meant to be
898
-     * flexible between question or question groups
899
-     *
900
-     * @param EEM_Soft_Delete_Base $model
901
-     * @param boolean              $trash whether to trash or restore
902
-     * @throws EE_Error
903
-     */
904
-    private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
905
-    {
906
-
907
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
908
-
909
-        $success = 1;
910
-        // Checkboxes
911
-        // echo "trash $trash";
912
-        // var_dump($this->_req_data['checkbox']);die;
913
-        if (isset($this->_req_data['checkbox'])) {
914
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
915
-                // if array has more than one element than success message should be plural
916
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
917
-                // cycle thru bulk action checkboxes
918
-                while (list($ID, $value) = each($this->_req_data['checkbox'])) {
919
-                    if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
920
-                        $success = 0;
921
-                    }
922
-                }
923
-            } else {
924
-                // grab single id and delete
925
-                $ID = absint($this->_req_data['checkbox']);
926
-                if (! $model->delete_or_restore_by_ID($trash, $ID)) {
927
-                    $success = 0;
928
-                }
929
-            }
930
-        } else {
931
-            // delete via trash link
932
-            // grab single id and delete
933
-            $ID = absint($this->_req_data[ $model->primary_key_name() ]);
934
-            if (! $model->delete_or_restore_by_ID($trash, $ID)) {
935
-                $success = 0;
936
-            }
937
-        }
938
-
939
-
940
-        $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
941
-        // echo "action :$action";
942
-        // $action = 'questions' ? 'default' : $action;
943
-        if ($trash) {
944
-            $action_desc = 'trashed';
945
-            $status = 'trash';
946
-        } else {
947
-            $action_desc = 'restored';
948
-            $status = 'all';
949
-        }
950
-        $this->_redirect_after_action(
951
-            $success,
952
-            $model->item_name($success),
953
-            $action_desc,
954
-            array('action' => $action, 'status' => $status)
955
-        );
956
-    }
957
-
958
-
959
-    /**
960
-     * @param            $per_page
961
-     * @param int        $current_page
962
-     * @param bool|false $count
963
-     * @return EE_Soft_Delete_Base_Class[]|int
964
-     * @throws EE_Error
965
-     * @throws InvalidArgumentException
966
-     * @throws InvalidDataTypeException
967
-     * @throws InvalidInterfaceException
968
-     */
969
-    public function get_trashed_questions($per_page, $current_page = 1, $count = false)
970
-    {
971
-        $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
972
-
973
-        if ($count) {
974
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
975
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
976
-            $results = $this->_question_model->count_deleted($where);
977
-        } else {
978
-            // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
979
-            $results = $this->_question_model->get_all_deleted($query_params);
980
-        }
981
-        return $results;
982
-    }
983
-
984
-
985
-    /**
986
-     * @param            $per_page
987
-     * @param int        $current_page
988
-     * @param bool|false $count
989
-     * @return EE_Soft_Delete_Base_Class[]|int
990
-     * @throws EE_Error
991
-     * @throws InvalidArgumentException
992
-     * @throws InvalidDataTypeException
993
-     * @throws InvalidInterfaceException
994
-     */
995
-    public function get_question_groups($per_page, $current_page = 1, $count = false)
996
-    {
997
-        $questionGroupModel = EEM_Question_Group::instance();
998
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
999
-        if ($count) {
1000
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
1001
-            $results = $questionGroupModel->count($where);
1002
-        } else {
1003
-            $results = $questionGroupModel->get_all($query_params);
1004
-        }
1005
-        return $results;
1006
-    }
1007
-
1008
-
1009
-    /**
1010
-     * @param      $per_page
1011
-     * @param int  $current_page
1012
-     * @param bool $count
1013
-     * @return EE_Soft_Delete_Base_Class[]|int
1014
-     * @throws EE_Error
1015
-     * @throws InvalidArgumentException
1016
-     * @throws InvalidDataTypeException
1017
-     * @throws InvalidInterfaceException
1018
-     */
1019
-    public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
1020
-    {
1021
-        $questionGroupModel = EEM_Question_Group::instance();
1022
-        $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
1023
-        if ($count) {
1024
-            $where = isset($query_params[0]) ? array($query_params[0]) : array();
1025
-            $query_params['limit'] = null;
1026
-            $results = $questionGroupModel->count_deleted($where);
1027
-        } else {
1028
-            $results = $questionGroupModel->get_all_deleted($query_params);
1029
-        }
1030
-        return $results;
1031
-    }
1032
-
1033
-
1034
-    /**
1035
-     * method for performing updates to question order
1036
-     *
1037
-     * @return void results array
1038
-     * @throws EE_Error
1039
-     * @throws InvalidArgumentException
1040
-     * @throws InvalidDataTypeException
1041
-     * @throws InvalidInterfaceException
1042
-     */
1043
-    public function update_question_group_order()
1044
-    {
1045
-
1046
-        $success = esc_html__('Question group order was updated successfully.', 'event_espresso');
1047
-
1048
-        // grab our row IDs
1049
-        $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
1050
-            ? explode(',', rtrim($this->_req_data['row_ids'], ','))
1051
-            : array();
1052
-
1053
-        $perpage = ! empty($this->_req_data['perpage'])
1054
-            ? (int) $this->_req_data['perpage']
1055
-            : null;
1056
-        $curpage = ! empty($this->_req_data['curpage'])
1057
-            ? (int) $this->_req_data['curpage']
1058
-            : null;
1059
-
1060
-        if (! empty($row_ids)) {
1061
-            // figure out where we start the row_id count at for the current page.
1062
-            $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
1063
-
1064
-            $row_count = count($row_ids);
1065
-            for ($i = 0; $i < $row_count; $i++) {
1066
-                // Update the questions when re-ordering
1067
-                $updated = EEM_Question_Group::instance()->update(
1068
-                    array('QSG_order' => $qsgcount),
1069
-                    array(array('QSG_ID' => $row_ids[ $i ]))
1070
-                );
1071
-                if ($updated === false) {
1072
-                    $success = false;
1073
-                }
1074
-                $qsgcount++;
1075
-            }
1076
-        } else {
1077
-            $success = false;
1078
-        }
1079
-
1080
-        $errors = ! $success
1081
-            ? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
1082
-            : false;
1083
-
1084
-        echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
1085
-        die();
1086
-    }
1087
-
1088
-
1089
-
1090
-    /***************************************       REGISTRATION SETTINGS       ***************************************/
1091
-
1092
-
1093
-    /**
1094
-     * @throws DomainException
1095
-     * @throws EE_Error
1096
-     * @throws InvalidArgumentException
1097
-     * @throws InvalidDataTypeException
1098
-     * @throws InvalidInterfaceException
1099
-     */
1100
-    protected function _reg_form_settings()
1101
-    {
1102
-        $this->_template_args['values'] = $this->_yes_no_values;
1103
-        add_action(
1104
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1105
-            array($this, 'email_validation_settings_form'),
1106
-            2
1107
-        );
1108
-        add_action(
1109
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1110
-            array($this, 'copy_attendee_info_settings_form'),
1111
-            4
1112
-        );
1113
-        add_action(
1114
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1115
-            array($this, 'setSessionLifespan'),
1116
-            4.9
1117
-        );
1118
-        $this->_template_args = (array) apply_filters(
1119
-            'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
1120
-            $this->_template_args
1121
-        );
1122
-        $this->_set_add_edit_form_tags('update_reg_form_settings');
1123
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
1124
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1125
-            REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
1126
-            $this->_template_args,
1127
-            true
1128
-        );
1129
-        $this->display_admin_page_with_sidebar();
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     * @return void
1135
-     * @throws EE_Error
1136
-     * @throws InvalidArgumentException
1137
-     * @throws ReflectionException
1138
-     * @throws InvalidDataTypeException
1139
-     * @throws InvalidInterfaceException
1140
-     */
1141
-    protected function _update_reg_form_settings()
1142
-    {
1143
-        EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
1144
-            EE_Registry::instance()->CFG->registration
1145
-        );
1146
-        EE_Registry::instance()->CFG->registration = $this->update_copy_attendee_info_settings_form(
1147
-            EE_Registry::instance()->CFG->registration
1148
-        );
1149
-        $this->updateSessionLifespan();
1150
-        EE_Registry::instance()->CFG->registration = apply_filters(
1151
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
1152
-            EE_Registry::instance()->CFG->registration
1153
-        );
1154
-        $success = $this->_update_espresso_configuration(
1155
-            esc_html__('Registration Form Options', 'event_espresso'),
1156
-            EE_Registry::instance()->CFG,
1157
-            __FILE__,
1158
-            __FUNCTION__,
1159
-            __LINE__
1160
-        );
1161
-        $this->_redirect_after_action(
1162
-            $success,
1163
-            esc_html__('Registration Form Options', 'event_espresso'),
1164
-            'updated',
1165
-            array('action' => 'view_reg_form_settings')
1166
-        );
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * @return void
1172
-     * @throws EE_Error
1173
-     * @throws InvalidArgumentException
1174
-     * @throws InvalidDataTypeException
1175
-     * @throws InvalidInterfaceException
1176
-     */
1177
-    public function copy_attendee_info_settings_form()
1178
-    {
1179
-        echo wp_kses($this->_copy_attendee_info_settings_form()->get_html(), AllowedTags::getWithFormTags());
1180
-    }
1181
-
1182
-    /**
1183
-     * _copy_attendee_info_settings_form
1184
-     *
1185
-     * @access protected
1186
-     * @return EE_Form_Section_Proper
1187
-     * @throws \EE_Error
1188
-     */
1189
-    protected function _copy_attendee_info_settings_form()
1190
-    {
1191
-        return new EE_Form_Section_Proper(
1192
-            array(
1193
-                'name'            => 'copy_attendee_info_settings',
1194
-                'html_id'         => 'copy_attendee_info_settings',
1195
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1196
-                'subsections'     => apply_filters(
1197
-                    'FHEE__Extend_Registration_Form_Admin_Page___copy_attendee_info_settings_form__form_subsections',
1198
-                    array(
1199
-                        'copy_attendee_info_hdr'   => new EE_Form_Section_HTML(
1200
-                            EEH_HTML::h2(esc_html__('Copy Attendee Info Settings', 'event_espresso'))
1201
-                        ),
1202
-                        'copy_attendee_info' => new EE_Yes_No_Input(
1203
-                            array(
1204
-                                'html_label_text' => esc_html__(
1205
-                                    'Allow copy #1 attendee info to extra attendees?',
1206
-                                    'event_espresso'
1207
-                                ),
1208
-                                'html_help_text'  => esc_html__(
1209
-                                    'Set to yes if you want to enable the copy of #1 attendee info to extra attendees at Registration Form.',
1210
-                                    'event_espresso'
1211
-                                ),
1212
-                                'default'         => EE_Registry::instance()->CFG->registration->copyAttendeeInfo(),
1213
-                                'required'        => false,
1214
-                                'display_html_label_text' => false,
1215
-                            )
1216
-                        ),
1217
-                    )
1218
-                ),
1219
-            )
1220
-        );
1221
-    }
1222
-
1223
-    /**
1224
-     * @param EE_Registration_Config $EE_Registration_Config
1225
-     * @return EE_Registration_Config
1226
-     * @throws EE_Error
1227
-     * @throws InvalidArgumentException
1228
-     * @throws ReflectionException
1229
-     * @throws InvalidDataTypeException
1230
-     * @throws InvalidInterfaceException
1231
-     */
1232
-    public function update_copy_attendee_info_settings_form(EE_Registration_Config $EE_Registration_Config)
1233
-    {
1234
-        $prev_copy_attendee_info = $EE_Registration_Config->copyAttendeeInfo();
1235
-        try {
1236
-            $copy_attendee_info_settings_form = $this->_copy_attendee_info_settings_form();
1237
-            // if not displaying a form, then check for form submission
1238
-            if ($copy_attendee_info_settings_form->was_submitted()) {
1239
-                // capture form data
1240
-                $copy_attendee_info_settings_form->receive_form_submission();
1241
-                // validate form data
1242
-                if ($copy_attendee_info_settings_form->is_valid()) {
1243
-                    // grab validated data from form
1244
-                    $valid_data = $copy_attendee_info_settings_form->valid_data();
1245
-                    if (isset($valid_data['copy_attendee_info'])) {
1246
-                        $EE_Registration_Config->setCopyAttendeeInfo($valid_data['copy_attendee_info']);
1247
-                    } else {
1248
-                        EE_Error::add_error(
1249
-                            esc_html__(
1250
-                                'Invalid or missing Copy Attendee Info settings. Please refresh the form and try again.',
1251
-                                'event_espresso'
1252
-                            ),
1253
-                            __FILE__,
1254
-                            __FUNCTION__,
1255
-                            __LINE__
1256
-                        );
1257
-                    }
1258
-                } elseif ($copy_attendee_info_settings_form->submission_error_message() !== '') {
1259
-                    EE_Error::add_error(
1260
-                        $copy_attendee_info_settings_form->submission_error_message(),
1261
-                        __FILE__,
1262
-                        __FUNCTION__,
1263
-                        __LINE__
1264
-                    );
1265
-                }
1266
-            }
1267
-        } catch (EE_Error $e) {
1268
-            $e->get_error();
1269
-        }
1270
-        return $EE_Registration_Config;
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * @return void
1276
-     * @throws EE_Error
1277
-     * @throws InvalidArgumentException
1278
-     * @throws InvalidDataTypeException
1279
-     * @throws InvalidInterfaceException
1280
-     */
1281
-    public function email_validation_settings_form()
1282
-    {
1283
-        echo wp_kses($this->_email_validation_settings_form()->get_html(), AllowedTags::getWithFormTags());
1284
-    }
1285
-
1286
-
1287
-    /**
1288
-     * _email_validation_settings_form
1289
-     *
1290
-     * @access protected
1291
-     * @return EE_Form_Section_Proper
1292
-     * @throws \EE_Error
1293
-     */
1294
-    protected function _email_validation_settings_form()
1295
-    {
1296
-        return new EE_Form_Section_Proper(
1297
-            array(
1298
-                'name'            => 'email_validation_settings',
1299
-                'html_id'         => 'email_validation_settings',
1300
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1301
-                'subsections'     => apply_filters(
1302
-                    'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1303
-                    array(
1304
-                        'email_validation_hdr'   => new EE_Form_Section_HTML(
1305
-                            EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1306
-                        ),
1307
-                        'email_validation_level' => new EE_Select_Input(
1308
-                            array(
1309
-                                'basic'      => esc_html__('Basic', 'event_espresso'),
1310
-                                'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1311
-                                'i18n'       => esc_html__('International', 'event_espresso'),
1312
-                                'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1313
-                            ),
1314
-                            array(
1315
-                                'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1316
-                                                     . EEH_Template::get_help_tab_link('email_validation_info'),
1317
-                                'html_help_text'  => esc_html__(
1318
-                                    'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.',
1319
-                                    'event_espresso'
1320
-                                ),
1321
-                                'default'         => isset(
1322
-                                    EE_Registry::instance()->CFG->registration->email_validation_level
1323
-                                )
1324
-                                    ? EE_Registry::instance()->CFG->registration->email_validation_level
1325
-                                    : 'wp_default',
1326
-                                'required'        => false,
1327
-                            )
1328
-                        ),
1329
-                    )
1330
-                ),
1331
-            )
1332
-        );
1333
-    }
1334
-
1335
-
1336
-    /**
1337
-     * @param EE_Registration_Config $EE_Registration_Config
1338
-     * @return EE_Registration_Config
1339
-     * @throws EE_Error
1340
-     * @throws InvalidArgumentException
1341
-     * @throws ReflectionException
1342
-     * @throws InvalidDataTypeException
1343
-     * @throws InvalidInterfaceException
1344
-     */
1345
-    public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1346
-    {
1347
-        $prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1348
-        try {
1349
-            $email_validation_settings_form = $this->_email_validation_settings_form();
1350
-            // if not displaying a form, then check for form submission
1351
-            if ($email_validation_settings_form->was_submitted()) {
1352
-                // capture form data
1353
-                $email_validation_settings_form->receive_form_submission();
1354
-                // validate form data
1355
-                if ($email_validation_settings_form->is_valid()) {
1356
-                    // grab validated data from form
1357
-                    $valid_data = $email_validation_settings_form->valid_data();
1358
-                    if (isset($valid_data['email_validation_level'])) {
1359
-                        $email_validation_level = $valid_data['email_validation_level'];
1360
-                        // now if they want to use international email addresses
1361
-                        if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1362
-                            // in case we need to reset their email validation level,
1363
-                            // make sure that the previous value wasn't already set to one of the i18n options.
1364
-                            if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1365
-                                // if so, then reset it back to "basic" since that is the only other option that,
1366
-                                // despite offering poor validation, supports i18n email addresses
1367
-                                $prev_email_validation_level = 'basic';
1368
-                            }
1369
-                            // confirm our i18n email validation will work on the server
1370
-                            if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1371
-                                // or reset email validation level to previous value
1372
-                                $email_validation_level = $prev_email_validation_level;
1373
-                            }
1374
-                        }
1375
-                        $EE_Registration_Config->email_validation_level = $email_validation_level;
1376
-                    } else {
1377
-                        EE_Error::add_error(
1378
-                            esc_html__(
1379
-                                'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1380
-                                'event_espresso'
1381
-                            ),
1382
-                            __FILE__,
1383
-                            __FUNCTION__,
1384
-                            __LINE__
1385
-                        );
1386
-                    }
1387
-                } elseif ($email_validation_settings_form->submission_error_message() !== '') {
1388
-                    EE_Error::add_error(
1389
-                        $email_validation_settings_form->submission_error_message(),
1390
-                        __FILE__,
1391
-                        __FUNCTION__,
1392
-                        __LINE__
1393
-                    );
1394
-                }
1395
-            }
1396
-        } catch (EE_Error $e) {
1397
-            $e->get_error();
1398
-        }
1399
-        return $EE_Registration_Config;
1400
-    }
1401
-
1402
-
1403
-    /**
1404
-     * confirms that the server's PHP version has the PCRE module enabled,
1405
-     * and that the PCRE version works with our i18n email validation
1406
-     *
1407
-     * @param EE_Registration_Config $EE_Registration_Config
1408
-     * @param string                 $email_validation_level
1409
-     * @return bool
1410
-     */
1411
-    private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1412
-    {
1413
-        // first check that PCRE is enabled
1414
-        if (! defined('PREG_BAD_UTF8_ERROR')) {
1415
-            EE_Error::add_error(
1416
-                sprintf(
1417
-                    esc_html__(
1418
-                        'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.',
1419
-                        'event_espresso'
1420
-                    ),
1421
-                    '<br />'
1422
-                ),
1423
-                __FILE__,
1424
-                __FUNCTION__,
1425
-                __LINE__
1426
-            );
1427
-            return false;
1428
-        } else {
1429
-            // PCRE support is enabled, but let's still
1430
-            // perform a test to see if the server will support it.
1431
-            // but first, save the updated validation level to the config,
1432
-            // so that the validation strategy picks it up.
1433
-            // this will get bumped back down if it doesn't work
1434
-            $EE_Registration_Config->email_validation_level = $email_validation_level;
1435
-            try {
1436
-                $email_validator = new EE_Email_Validation_Strategy();
1437
-                $i18n_email_address = apply_filters(
1438
-                    'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1439
-                    'jägerjü[email protected]'
1440
-                );
1441
-                $email_validator->validate($i18n_email_address);
1442
-            } catch (Exception $e) {
1443
-                EE_Error::add_error(
1444
-                    sprintf(
1445
-                        esc_html__(
1446
-                            'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s',
1447
-                            'event_espresso'
1448
-                        ),
1449
-                        '<br />',
1450
-                        '<a href="http://php.net/manual/en/pcre.installation.php" target="_blank" rel="noopener noreferrer">http://php.net/manual/en/pcre.installation.php</a>'
1451
-                    ),
1452
-                    __FILE__,
1453
-                    __FUNCTION__,
1454
-                    __LINE__
1455
-                );
1456
-                return false;
1457
-            }
1458
-        }
1459
-        return true;
1460
-    }
1461
-
1462
-
1463
-    public function setSessionLifespan()
1464
-    {
1465
-        $session_lifespan_form = new SessionLifespanForm();
1466
-        echo wp_kses($session_lifespan_form->get_html(), AllowedTags::getWithFormTags());
1467
-    }
1468
-
1469
-
1470
-    public function updateSessionLifespan()
1471
-    {
1472
-        $handler = new SessionLifespanFormHandler();
1473
-        $handler->process(new SessionLifespanForm());
1474
-    }
19
+	/**
20
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
21
+	 */
22
+	public function __construct($routing = true)
23
+	{
24
+		define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form/');
25
+		define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets/');
26
+		define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/');
27
+		define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates/');
28
+		define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/');
29
+		parent::__construct($routing);
30
+	}
31
+
32
+
33
+	/**
34
+	 * @return void
35
+	 */
36
+	protected function _extend_page_config()
37
+	{
38
+		$this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN;
39
+		$qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID'])
40
+			? $this->_req_data['QST_ID'] : 0;
41
+		$qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID'])
42
+			? $this->_req_data['QSG_ID'] : 0;
43
+
44
+		$new_page_routes = array(
45
+			'question_groups'    => array(
46
+				'func'       => '_question_groups_overview_list_table',
47
+				'capability' => 'ee_read_question_groups',
48
+			),
49
+			'add_question'       => array(
50
+				'func'       => '_edit_question',
51
+				'capability' => 'ee_edit_questions',
52
+			),
53
+			'insert_question'    => array(
54
+				'func'       => '_insert_or_update_question',
55
+				'args'       => array('new_question' => true),
56
+				'capability' => 'ee_edit_questions',
57
+				'noheader'   => true,
58
+			),
59
+			'duplicate_question' => array(
60
+				'func'       => '_duplicate_question',
61
+				'capability' => 'ee_edit_questions',
62
+				'noheader'   => true,
63
+			),
64
+			'trash_question'     => array(
65
+				'func'       => '_trash_question',
66
+				'capability' => 'ee_delete_question',
67
+				'obj_id'     => $qst_id,
68
+				'noheader'   => true,
69
+			),
70
+
71
+			'restore_question' => array(
72
+				'func'       => '_trash_or_restore_questions',
73
+				'capability' => 'ee_delete_question',
74
+				'obj_id'     => $qst_id,
75
+				'args'       => array('trash' => false),
76
+				'noheader'   => true,
77
+			),
78
+
79
+			'delete_question' => array(
80
+				'func'       => '_delete_question',
81
+				'capability' => 'ee_delete_question',
82
+				'obj_id'     => $qst_id,
83
+				'noheader'   => true,
84
+			),
85
+
86
+			'trash_questions' => array(
87
+				'func'       => '_trash_or_restore_questions',
88
+				'capability' => 'ee_delete_questions',
89
+				'args'       => array('trash' => true),
90
+				'noheader'   => true,
91
+			),
92
+
93
+			'restore_questions' => array(
94
+				'func'       => '_trash_or_restore_questions',
95
+				'capability' => 'ee_delete_questions',
96
+				'args'       => array('trash' => false),
97
+				'noheader'   => true,
98
+			),
99
+
100
+			'delete_questions' => array(
101
+				'func'       => '_delete_questions',
102
+				'args'       => array(),
103
+				'capability' => 'ee_delete_questions',
104
+				'noheader'   => true,
105
+			),
106
+
107
+			'add_question_group' => array(
108
+				'func'       => '_edit_question_group',
109
+				'capability' => 'ee_edit_question_groups',
110
+			),
111
+
112
+			'edit_question_group' => array(
113
+				'func'       => '_edit_question_group',
114
+				'capability' => 'ee_edit_question_group',
115
+				'obj_id'     => $qsg_id,
116
+				'args'       => array('edit'),
117
+			),
118
+
119
+			'delete_question_groups' => array(
120
+				'func'       => '_delete_question_groups',
121
+				'capability' => 'ee_delete_question_groups',
122
+				'noheader'   => true,
123
+			),
124
+
125
+			'delete_question_group' => array(
126
+				'func'       => '_delete_question_groups',
127
+				'capability' => 'ee_delete_question_group',
128
+				'obj_id'     => $qsg_id,
129
+				'noheader'   => true,
130
+			),
131
+
132
+			'trash_question_group' => array(
133
+				'func'       => '_trash_or_restore_question_groups',
134
+				'args'       => array('trash' => true),
135
+				'capability' => 'ee_delete_question_group',
136
+				'obj_id'     => $qsg_id,
137
+				'noheader'   => true,
138
+			),
139
+
140
+			'restore_question_group' => array(
141
+				'func'       => '_trash_or_restore_question_groups',
142
+				'args'       => array('trash' => false),
143
+				'capability' => 'ee_delete_question_group',
144
+				'obj_id'     => $qsg_id,
145
+				'noheader'   => true,
146
+			),
147
+
148
+			'insert_question_group' => array(
149
+				'func'       => '_insert_or_update_question_group',
150
+				'args'       => array('new_question_group' => true),
151
+				'capability' => 'ee_edit_question_groups',
152
+				'noheader'   => true,
153
+			),
154
+
155
+			'update_question_group' => array(
156
+				'func'       => '_insert_or_update_question_group',
157
+				'args'       => array('new_question_group' => false),
158
+				'capability' => 'ee_edit_question_group',
159
+				'obj_id'     => $qsg_id,
160
+				'noheader'   => true,
161
+			),
162
+
163
+			'trash_question_groups' => array(
164
+				'func'       => '_trash_or_restore_question_groups',
165
+				'args'       => array('trash' => true),
166
+				'capability' => 'ee_delete_question_groups',
167
+				'noheader'   => array('trash' => false),
168
+			),
169
+
170
+			'restore_question_groups' => array(
171
+				'func'       => '_trash_or_restore_question_groups',
172
+				'args'       => array('trash' => false),
173
+				'capability' => 'ee_delete_question_groups',
174
+				'noheader'   => true,
175
+			),
176
+
177
+
178
+			'espresso_update_question_group_order' => array(
179
+				'func'       => 'update_question_group_order',
180
+				'capability' => 'ee_edit_question_groups',
181
+				'noheader'   => true,
182
+			),
183
+
184
+			'view_reg_form_settings' => array(
185
+				'func'       => '_reg_form_settings',
186
+				'capability' => 'manage_options',
187
+			),
188
+
189
+			'update_reg_form_settings' => array(
190
+				'func'       => '_update_reg_form_settings',
191
+				'capability' => 'manage_options',
192
+				'noheader'   => true,
193
+			),
194
+		);
195
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
196
+
197
+		$new_page_config = array(
198
+
199
+			'question_groups' => array(
200
+				'nav'           => array(
201
+					'label' => esc_html__('Question Groups', 'event_espresso'),
202
+					'icon' => 'dashicons-forms',
203
+					'order' => 20,
204
+				),
205
+				'list_table'    => 'Registration_Form_Question_Groups_Admin_List_Table',
206
+				'help_tabs'     => array(
207
+					'registration_form_question_groups_help_tab'                           => array(
208
+						'title'    => esc_html__('Question Groups', 'event_espresso'),
209
+						'filename' => 'registration_form_question_groups',
210
+					),
211
+					'registration_form_question_groups_table_column_headings_help_tab'     => array(
212
+						'title'    => esc_html__('Question Groups Table Column Headings', 'event_espresso'),
213
+						'filename' => 'registration_form_question_groups_table_column_headings',
214
+					),
215
+					'registration_form_question_groups_views_bulk_actions_search_help_tab' => array(
216
+						'title'    => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'),
217
+						'filename' => 'registration_form_question_groups_views_bulk_actions_search',
218
+					),
219
+				),
220
+				'metaboxes'     => $this->_default_espresso_metaboxes,
221
+				'require_nonce' => false,
222
+			),
223
+
224
+			'add_question' => array(
225
+				'nav'           => array(
226
+					'label'      => esc_html__('Add Question', 'event_espresso'),
227
+					'icon' => 'dashicons-plus-alt',
228
+					'order'      => 15,
229
+					'persistent' => false,
230
+				),
231
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
232
+				'help_tabs'     => array(
233
+					'registration_form_add_question_help_tab' => array(
234
+						'title'    => esc_html__('Add Question', 'event_espresso'),
235
+						'filename' => 'registration_form_add_question',
236
+					),
237
+				),
238
+				'require_nonce' => false,
239
+			),
240
+
241
+			'add_question_group' => array(
242
+				'nav'           => array(
243
+					'label'      => esc_html__('Add Question Group', 'event_espresso'),
244
+					'icon' => 'dashicons-plus-alt',
245
+					'order'      => 25,
246
+					'persistent' => false,
247
+				),
248
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
249
+				'help_tabs'     => array(
250
+					'registration_form_add_question_group_help_tab' => array(
251
+						'title'    => esc_html__('Add Question Group', 'event_espresso'),
252
+						'filename' => 'registration_form_add_question_group',
253
+					),
254
+				),
255
+				'require_nonce' => false,
256
+			),
257
+
258
+			'edit_question_group' => array(
259
+				'nav'           => array(
260
+					'label'      => esc_html__('Edit Question Group', 'event_espresso'),
261
+					'icon' => 'dashicons-edit-large',
262
+					'order'      => 25,
263
+					'persistent' => false,
264
+					'url'        => isset($this->_req_data['question_group_id']) ? add_query_arg(
265
+						array('question_group_id' => $this->_req_data['question_group_id']),
266
+						$this->_current_page_view_url
267
+					) : $this->_admin_base_url,
268
+				),
269
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
270
+				'help_tabs'     => array(
271
+					'registration_form_edit_question_group_help_tab' => array(
272
+						'title'    => esc_html__('Edit Question Group', 'event_espresso'),
273
+						'filename' => 'registration_form_edit_question_group',
274
+					),
275
+				),
276
+				'require_nonce' => false,
277
+			),
278
+
279
+			'view_reg_form_settings' => array(
280
+				'nav'           => array(
281
+					'label' => esc_html__('Reg Form Settings', 'event_espresso'),
282
+					'icon' => 'dashicons-admin-generic',
283
+					'order' => 40,
284
+				),
285
+				'labels'        => array(
286
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
287
+				),
288
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
289
+				'help_tabs'     => array(
290
+					'registration_form_reg_form_settings_help_tab' => array(
291
+						'title'    => esc_html__('Registration Form Settings', 'event_espresso'),
292
+						'filename' => 'registration_form_reg_form_settings',
293
+					),
294
+				),
295
+				'require_nonce' => false,
296
+			),
297
+
298
+		);
299
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
300
+
301
+		// change the list table we're going to use so it's the NEW list table!
302
+		$this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table';
303
+
304
+
305
+		// additional labels
306
+		$new_labels = array(
307
+			'add_question'          => esc_html__('Add New Question', 'event_espresso'),
308
+			'delete_question'       => esc_html__('Delete Question', 'event_espresso'),
309
+			'add_question_group'    => esc_html__('Add New Question Group', 'event_espresso'),
310
+			'edit_question_group'   => esc_html__('Edit Question Group', 'event_espresso'),
311
+			'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'),
312
+		);
313
+		$this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels);
314
+	}
315
+
316
+
317
+	/**
318
+	 * @return void
319
+	 */
320
+	protected function _ajax_hooks()
321
+	{
322
+		add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order'));
323
+	}
324
+
325
+
326
+	/**
327
+	 * @return void
328
+	 */
329
+	public function load_scripts_styles_question_groups()
330
+	{
331
+		wp_enqueue_script('espresso_ajax_table_sorting');
332
+	}
333
+
334
+
335
+	/**
336
+	 * @return void
337
+	 */
338
+	public function load_scripts_styles_add_question_group()
339
+	{
340
+		$this->load_scripts_styles_forms();
341
+		$this->load_sortable_question_script();
342
+	}
343
+
344
+
345
+	/**
346
+	 * @return void
347
+	 */
348
+	public function load_scripts_styles_edit_question_group()
349
+	{
350
+		$this->load_scripts_styles_forms();
351
+		$this->load_sortable_question_script();
352
+	}
353
+
354
+
355
+	/**
356
+	 * registers and enqueues script for questions
357
+	 *
358
+	 * @return void
359
+	 */
360
+	public function load_sortable_question_script()
361
+	{
362
+		wp_register_script(
363
+			'ee-question-sortable',
364
+			REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js',
365
+			array('jquery-ui-sortable'),
366
+			EVENT_ESPRESSO_VERSION,
367
+			true
368
+		);
369
+		wp_enqueue_script('ee-question-sortable');
370
+	}
371
+
372
+
373
+	/**
374
+	 * @return void
375
+	 */
376
+	protected function _set_list_table_views_default()
377
+	{
378
+		$this->_views = array(
379
+			'all' => array(
380
+				'slug'        => 'all',
381
+				'label'       => esc_html__('View All Questions', 'event_espresso'),
382
+				'count'       => 0,
383
+				'bulk_action' => array(
384
+					'trash_questions' => esc_html__('Trash', 'event_espresso'),
385
+				),
386
+			),
387
+		);
388
+
389
+		if (
390
+			EE_Registry::instance()->CAP->current_user_can(
391
+				'ee_delete_questions',
392
+				'espresso_registration_form_trash_questions'
393
+			)
394
+		) {
395
+			$this->_views['trash'] = array(
396
+				'slug'        => 'trash',
397
+				'label'       => esc_html__('Trash', 'event_espresso'),
398
+				'count'       => 0,
399
+				'bulk_action' => array(
400
+					'delete_questions'  => esc_html__('Delete Permanently', 'event_espresso'),
401
+					'restore_questions' => esc_html__('Restore', 'event_espresso'),
402
+				),
403
+			);
404
+		}
405
+	}
406
+
407
+
408
+	/**
409
+	 * @return void
410
+	 */
411
+	protected function _set_list_table_views_question_groups()
412
+	{
413
+		$this->_views = array(
414
+			'all' => array(
415
+				'slug'        => 'all',
416
+				'label'       => esc_html__('All', 'event_espresso'),
417
+				'count'       => 0,
418
+				'bulk_action' => array(
419
+					'trash_question_groups' => esc_html__('Trash', 'event_espresso'),
420
+				),
421
+			),
422
+		);
423
+
424
+		if (
425
+			EE_Registry::instance()->CAP->current_user_can(
426
+				'ee_delete_question_groups',
427
+				'espresso_registration_form_trash_question_groups'
428
+			)
429
+		) {
430
+			$this->_views['trash'] = array(
431
+				'slug'        => 'trash',
432
+				'label'       => esc_html__('Trash', 'event_espresso'),
433
+				'count'       => 0,
434
+				'bulk_action' => array(
435
+					'delete_question_groups'  => esc_html__('Delete Permanently', 'event_espresso'),
436
+					'restore_question_groups' => esc_html__('Restore', 'event_espresso'),
437
+				),
438
+			);
439
+		}
440
+	}
441
+
442
+
443
+	/**
444
+	 * @return void
445
+	 * @throws EE_Error
446
+	 * @throws InvalidArgumentException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws InvalidInterfaceException
449
+	 */
450
+	protected function _questions_overview_list_table()
451
+	{
452
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
453
+			'add_question',
454
+			'add_question',
455
+			array(),
456
+			'add-new-h2'
457
+		);
458
+		parent::_questions_overview_list_table();
459
+	}
460
+
461
+
462
+	/**
463
+	 * @return void
464
+	 * @throws DomainException
465
+	 * @throws EE_Error
466
+	 * @throws InvalidArgumentException
467
+	 * @throws InvalidDataTypeException
468
+	 * @throws InvalidInterfaceException
469
+	 */
470
+	protected function _question_groups_overview_list_table()
471
+	{
472
+		$this->_search_btn_label = esc_html__('Question Groups', 'event_espresso');
473
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
474
+			'add_question_group',
475
+			'add_question_group',
476
+			array(),
477
+			'add-new-h2'
478
+		);
479
+		$this->display_admin_list_table_page_with_sidebar();
480
+	}
481
+
482
+
483
+	/**
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 */
490
+	protected function _delete_question()
491
+	{
492
+		$success = $this->_delete_items($this->_question_model);
493
+		$this->_redirect_after_action(
494
+			$success,
495
+			$this->_question_model->item_name($success),
496
+			'deleted',
497
+			array('action' => 'default', 'status' => 'all')
498
+		);
499
+	}
500
+
501
+
502
+	/**
503
+	 * @return void
504
+	 * @throws EE_Error
505
+	 * @throws InvalidArgumentException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidInterfaceException
508
+	 */
509
+	protected function _delete_questions()
510
+	{
511
+		$success = $this->_delete_items($this->_question_model);
512
+		$this->_redirect_after_action(
513
+			$success,
514
+			$this->_question_model->item_name($success),
515
+			'deleted permanently',
516
+			array('action' => 'default', 'status' => 'trash')
517
+		);
518
+	}
519
+
520
+
521
+	/**
522
+	 * Performs the deletion of a single or multiple questions or question groups.
523
+	 *
524
+	 * @param EEM_Soft_Delete_Base $model
525
+	 * @return int number of items deleted permanently
526
+	 * @throws EE_Error
527
+	 * @throws InvalidArgumentException
528
+	 * @throws InvalidDataTypeException
529
+	 * @throws InvalidInterfaceException
530
+	 */
531
+	private function _delete_items(EEM_Soft_Delete_Base $model)
532
+	{
533
+		$success = 0;
534
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
535
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
536
+			// if array has more than one element than success message should be plural
537
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
538
+			// cycle thru bulk action checkboxes
539
+			while (list($ID, $value) = each($this->_req_data['checkbox'])) {
540
+				if (! $this->_delete_item($ID, $model)) {
541
+					$success = 0;
542
+				}
543
+			}
544
+		} elseif (! empty($this->_req_data['QSG_ID'])) {
545
+			$success = $this->_delete_item($this->_req_data['QSG_ID'], $model);
546
+		} elseif (! empty($this->_req_data['QST_ID'])) {
547
+			$success = $this->_delete_item($this->_req_data['QST_ID'], $model);
548
+		} else {
549
+			EE_Error::add_error(
550
+				sprintf(
551
+					esc_html__(
552
+						"No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.",
553
+						"event_espresso"
554
+					)
555
+				),
556
+				__FILE__,
557
+				__FUNCTION__,
558
+				__LINE__
559
+			);
560
+		}
561
+		return $success;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Deletes the specified question (and its associated question options) or question group
567
+	 *
568
+	 * @param int                  $id
569
+	 * @param EEM_Soft_Delete_Base $model
570
+	 * @return boolean
571
+	 * @throws EE_Error
572
+	 * @throws InvalidArgumentException
573
+	 * @throws InvalidDataTypeException
574
+	 * @throws InvalidInterfaceException
575
+	 */
576
+	protected function _delete_item($id, $model)
577
+	{
578
+		if ($model instanceof EEM_Question) {
579
+			EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id))));
580
+		}
581
+		return $model->delete_permanently_by_ID(absint($id));
582
+	}
583
+
584
+
585
+	/******************************    QUESTION GROUPS    ******************************/
586
+
587
+
588
+	/**
589
+	 * @param string $type
590
+	 * @return void
591
+	 * @throws DomainException
592
+	 * @throws EE_Error
593
+	 * @throws InvalidArgumentException
594
+	 * @throws InvalidDataTypeException
595
+	 * @throws InvalidInterfaceException
596
+	 */
597
+	protected function _edit_question_group($type = 'add')
598
+	{
599
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
600
+		$ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID'])
601
+			? absint($this->_req_data['QSG_ID'])
602
+			: false;
603
+
604
+		switch ($this->_req_action) {
605
+			case 'add_question_group':
606
+				$this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso');
607
+				break;
608
+			case 'edit_question_group':
609
+				$this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso');
610
+				break;
611
+			default:
612
+				$this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action));
613
+		}
614
+		// add ID to title if editing
615
+		$this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title;
616
+		if ($ID) {
617
+			/** @var EE_Question_Group $questionGroup */
618
+			$questionGroup = $this->_question_group_model->get_one_by_ID($ID);
619
+			$additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID));
620
+			$this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields);
621
+		} else {
622
+			/** @var EE_Question_Group $questionGroup */
623
+			$questionGroup = EEM_Question_Group::instance()->create_default_object();
624
+			$questionGroup->set_order_to_latest();
625
+			$this->_set_add_edit_form_tags('insert_question_group');
626
+		}
627
+		$this->_template_args['values'] = $this->_yes_no_values;
628
+		$this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group();
629
+		$this->_template_args['QSG_ID'] = $ID ? $ID : true;
630
+		$this->_template_args['question_group'] = $questionGroup;
631
+
632
+		$redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url);
633
+		$this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL);
634
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
635
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php',
636
+			$this->_template_args,
637
+			true
638
+		);
639
+
640
+		// the details template wrapper
641
+		$this->display_admin_page_with_sidebar();
642
+	}
643
+
644
+
645
+	/**
646
+	 * @return void
647
+	 * @throws EE_Error
648
+	 * @throws InvalidArgumentException
649
+	 * @throws InvalidDataTypeException
650
+	 * @throws InvalidInterfaceException
651
+	 */
652
+	protected function _delete_question_groups()
653
+	{
654
+		$success = $this->_delete_items($this->_question_group_model);
655
+		$this->_redirect_after_action(
656
+			$success,
657
+			$this->_question_group_model->item_name($success),
658
+			'deleted permanently',
659
+			array('action' => 'question_groups', 'status' => 'trash')
660
+		);
661
+	}
662
+
663
+
664
+	/**
665
+	 * @param bool $new_question_group
666
+	 * @throws EE_Error
667
+	 * @throws InvalidArgumentException
668
+	 * @throws InvalidDataTypeException
669
+	 * @throws InvalidInterfaceException
670
+	 */
671
+	protected function _insert_or_update_question_group($new_question_group = true)
672
+	{
673
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
674
+		$set_column_values = $this->_set_column_values_for($this->_question_group_model);
675
+
676
+		// make sure identifier is unique
677
+		$identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : '';
678
+		$where_values = ['QSG_identifier' => $set_column_values['QSG_identifier']];
679
+		if (! $new_question_group && isset($set_column_values['QSG_ID'])) {
680
+			$where_values['QSG_ID'] = ['!=', $set_column_values['QSG_ID']];
681
+		}
682
+		$identifier_exists = ! empty($identifier_value)
683
+			? $this->_question_group_model->count([$where_values]) > 0
684
+			: false;
685
+		if ($identifier_exists) {
686
+			$set_column_values['QSG_identifier'] .= uniqid('id', true);
687
+		}
688
+
689
+		if ($new_question_group) {
690
+			$QSG_ID = $this->_question_group_model->insert($set_column_values);
691
+			$success = $QSG_ID ? 1 : 0;
692
+			if ($success === 0) {
693
+				EE_Error::add_error(
694
+					esc_html__('Something went wrong saving the question group.', 'event_espresso'),
695
+					__FILE__,
696
+					__FUNCTION__,
697
+					__LINE__
698
+				);
699
+				$this->_redirect_after_action(
700
+					false,
701
+					'',
702
+					'',
703
+					array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
704
+					true
705
+				);
706
+			}
707
+		} else {
708
+			$QSG_ID = absint($this->_req_data['QSG_ID']);
709
+			unset($set_column_values['QSG_ID']);
710
+			$success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID)));
711
+		}
712
+
713
+		$phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string(
714
+			EEM_Attendee::system_question_phone
715
+		);
716
+		// update the existing related questions
717
+		// BUT FIRST...  delete the phone question from the Question_Group_Question
718
+		// if it is being added to this question group (therefore removed from the existing group)
719
+		if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) {
720
+			// delete where QST ID = system phone question ID and Question Group ID is NOT this group
721
+			EEM_Question_Group_Question::instance()->delete(
722
+				array(
723
+					array(
724
+						'QST_ID' => $phone_question_id,
725
+						'QSG_ID' => array('!=', $QSG_ID),
726
+					),
727
+				)
728
+			);
729
+		}
730
+		/** @type EE_Question_Group $question_group */
731
+		$question_group = $this->_question_group_model->get_one_by_ID($QSG_ID);
732
+		$questions = $question_group->questions();
733
+		// make sure system phone question is added to list of questions for this group
734
+		if (! isset($questions[ $phone_question_id ])) {
735
+			$questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id);
736
+		}
737
+
738
+		foreach ($questions as $question_ID => $question) {
739
+			// first we always check for order.
740
+			if (! empty($this->_req_data['question_orders'][ $question_ID ])) {
741
+				// update question order
742
+				$question_group->update_question_order(
743
+					$question_ID,
744
+					$this->_req_data['question_orders'][ $question_ID ]
745
+				);
746
+			}
747
+
748
+			// then we always check if adding or removing.
749
+			if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) {
750
+				$question_group->add_question($question_ID);
751
+			} else {
752
+				// not found, remove it (but only if not a system question for the personal group
753
+				// with the exception of lname system question - we allow removal of it)
754
+				if (
755
+					in_array(
756
+						$question->system_ID(),
757
+						EEM_Question::instance()->required_system_questions_in_system_question_group(
758
+							$question_group->system_group()
759
+						)
760
+					)
761
+				) {
762
+					continue;
763
+				} else {
764
+					$question_group->remove_question($question_ID);
765
+				}
766
+			}
767
+		}
768
+		// save new related questions
769
+		if (isset($this->_req_data['questions'])) {
770
+			foreach ($this->_req_data['questions'] as $QST_ID) {
771
+				$question_group->add_question($QST_ID);
772
+				if (isset($this->_req_data['question_orders'][ $QST_ID ])) {
773
+					$question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]);
774
+				}
775
+			}
776
+		}
777
+
778
+		if ($success !== false) {
779
+			$msg = $new_question_group
780
+				? sprintf(
781
+					esc_html__('The %s has been created', 'event_espresso'),
782
+					$this->_question_group_model->item_name()
783
+				)
784
+				: sprintf(
785
+					esc_html__(
786
+						'The %s has been updated',
787
+						'event_espresso'
788
+					),
789
+					$this->_question_group_model->item_name()
790
+				);
791
+			EE_Error::add_success($msg);
792
+		}
793
+		$this->_redirect_after_action(
794
+			false,
795
+			'',
796
+			'',
797
+			array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID),
798
+			true
799
+		);
800
+	}
801
+
802
+
803
+	/**
804
+	 * duplicates a question and all its question options and redirects to the new question.
805
+	 *
806
+	 * @return void
807
+	 * @throws EE_Error
808
+	 * @throws InvalidArgumentException
809
+	 * @throws ReflectionException
810
+	 * @throws InvalidDataTypeException
811
+	 * @throws InvalidInterfaceException
812
+	 */
813
+	public function _duplicate_question()
814
+	{
815
+		$question_ID = (int) $this->_req_data['QST_ID'];
816
+		$question = EEM_Question::instance()->get_one_by_ID($question_ID);
817
+		if ($question instanceof EE_Question) {
818
+			$new_question = $question->duplicate();
819
+			if ($new_question instanceof EE_Question) {
820
+				$this->_redirect_after_action(
821
+					true,
822
+					esc_html__('Question', 'event_espresso'),
823
+					esc_html__('Duplicated', 'event_espresso'),
824
+					array('action' => 'edit_question', 'QST_ID' => $new_question->ID()),
825
+					true
826
+				);
827
+			} else {
828
+				global $wpdb;
829
+				EE_Error::add_error(
830
+					sprintf(
831
+						esc_html__(
832
+							'Could not duplicate question with ID %1$d because: %2$s',
833
+							'event_espresso'
834
+						),
835
+						$question_ID,
836
+						$wpdb->last_error
837
+					),
838
+					__FILE__,
839
+					__FUNCTION__,
840
+					__LINE__
841
+				);
842
+				$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
843
+			}
844
+		} else {
845
+			EE_Error::add_error(
846
+				sprintf(
847
+					esc_html__(
848
+						'Could not duplicate question with ID %d because it didn\'t exist!',
849
+						'event_espresso'
850
+					),
851
+					$question_ID
852
+				),
853
+				__FILE__,
854
+				__FUNCTION__,
855
+				__LINE__
856
+			);
857
+			$this->_redirect_after_action(false, '', '', array('action' => 'default'), false);
858
+		}
859
+	}
860
+
861
+
862
+	/**
863
+	 * @param bool $trash
864
+	 * @throws EE_Error
865
+	 */
866
+	protected function _trash_or_restore_question_groups($trash = true)
867
+	{
868
+		$this->_trash_or_restore_items($this->_question_group_model, $trash);
869
+	}
870
+
871
+
872
+	/**
873
+	 *_trash_question
874
+	 *
875
+	 * @return void
876
+	 * @throws EE_Error
877
+	 */
878
+	protected function _trash_question()
879
+	{
880
+		$success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']);
881
+		$query_args = array('action' => 'default', 'status' => 'all');
882
+		$this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args);
883
+	}
884
+
885
+
886
+	/**
887
+	 * @param bool $trash
888
+	 * @throws EE_Error
889
+	 */
890
+	protected function _trash_or_restore_questions($trash = true)
891
+	{
892
+		$this->_trash_or_restore_items($this->_question_model, $trash);
893
+	}
894
+
895
+
896
+	/**
897
+	 * Internally used to delete or restore items, using the request data. Meant to be
898
+	 * flexible between question or question groups
899
+	 *
900
+	 * @param EEM_Soft_Delete_Base $model
901
+	 * @param boolean              $trash whether to trash or restore
902
+	 * @throws EE_Error
903
+	 */
904
+	private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true)
905
+	{
906
+
907
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
908
+
909
+		$success = 1;
910
+		// Checkboxes
911
+		// echo "trash $trash";
912
+		// var_dump($this->_req_data['checkbox']);die;
913
+		if (isset($this->_req_data['checkbox'])) {
914
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
915
+				// if array has more than one element than success message should be plural
916
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
917
+				// cycle thru bulk action checkboxes
918
+				while (list($ID, $value) = each($this->_req_data['checkbox'])) {
919
+					if (! $model->delete_or_restore_by_ID($trash, absint($ID))) {
920
+						$success = 0;
921
+					}
922
+				}
923
+			} else {
924
+				// grab single id and delete
925
+				$ID = absint($this->_req_data['checkbox']);
926
+				if (! $model->delete_or_restore_by_ID($trash, $ID)) {
927
+					$success = 0;
928
+				}
929
+			}
930
+		} else {
931
+			// delete via trash link
932
+			// grab single id and delete
933
+			$ID = absint($this->_req_data[ $model->primary_key_name() ]);
934
+			if (! $model->delete_or_restore_by_ID($trash, $ID)) {
935
+				$success = 0;
936
+			}
937
+		}
938
+
939
+
940
+		$action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) );
941
+		// echo "action :$action";
942
+		// $action = 'questions' ? 'default' : $action;
943
+		if ($trash) {
944
+			$action_desc = 'trashed';
945
+			$status = 'trash';
946
+		} else {
947
+			$action_desc = 'restored';
948
+			$status = 'all';
949
+		}
950
+		$this->_redirect_after_action(
951
+			$success,
952
+			$model->item_name($success),
953
+			$action_desc,
954
+			array('action' => $action, 'status' => $status)
955
+		);
956
+	}
957
+
958
+
959
+	/**
960
+	 * @param            $per_page
961
+	 * @param int        $current_page
962
+	 * @param bool|false $count
963
+	 * @return EE_Soft_Delete_Base_Class[]|int
964
+	 * @throws EE_Error
965
+	 * @throws InvalidArgumentException
966
+	 * @throws InvalidDataTypeException
967
+	 * @throws InvalidInterfaceException
968
+	 */
969
+	public function get_trashed_questions($per_page, $current_page = 1, $count = false)
970
+	{
971
+		$query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page);
972
+
973
+		if ($count) {
974
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
975
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
976
+			$results = $this->_question_model->count_deleted($where);
977
+		} else {
978
+			// note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items
979
+			$results = $this->_question_model->get_all_deleted($query_params);
980
+		}
981
+		return $results;
982
+	}
983
+
984
+
985
+	/**
986
+	 * @param            $per_page
987
+	 * @param int        $current_page
988
+	 * @param bool|false $count
989
+	 * @return EE_Soft_Delete_Base_Class[]|int
990
+	 * @throws EE_Error
991
+	 * @throws InvalidArgumentException
992
+	 * @throws InvalidDataTypeException
993
+	 * @throws InvalidInterfaceException
994
+	 */
995
+	public function get_question_groups($per_page, $current_page = 1, $count = false)
996
+	{
997
+		$questionGroupModel = EEM_Question_Group::instance();
998
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
999
+		if ($count) {
1000
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
1001
+			$results = $questionGroupModel->count($where);
1002
+		} else {
1003
+			$results = $questionGroupModel->get_all($query_params);
1004
+		}
1005
+		return $results;
1006
+	}
1007
+
1008
+
1009
+	/**
1010
+	 * @param      $per_page
1011
+	 * @param int  $current_page
1012
+	 * @param bool $count
1013
+	 * @return EE_Soft_Delete_Base_Class[]|int
1014
+	 * @throws EE_Error
1015
+	 * @throws InvalidArgumentException
1016
+	 * @throws InvalidDataTypeException
1017
+	 * @throws InvalidInterfaceException
1018
+	 */
1019
+	public function get_trashed_question_groups($per_page, $current_page = 1, $count = false)
1020
+	{
1021
+		$questionGroupModel = EEM_Question_Group::instance();
1022
+		$query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page);
1023
+		if ($count) {
1024
+			$where = isset($query_params[0]) ? array($query_params[0]) : array();
1025
+			$query_params['limit'] = null;
1026
+			$results = $questionGroupModel->count_deleted($where);
1027
+		} else {
1028
+			$results = $questionGroupModel->get_all_deleted($query_params);
1029
+		}
1030
+		return $results;
1031
+	}
1032
+
1033
+
1034
+	/**
1035
+	 * method for performing updates to question order
1036
+	 *
1037
+	 * @return void results array
1038
+	 * @throws EE_Error
1039
+	 * @throws InvalidArgumentException
1040
+	 * @throws InvalidDataTypeException
1041
+	 * @throws InvalidInterfaceException
1042
+	 */
1043
+	public function update_question_group_order()
1044
+	{
1045
+
1046
+		$success = esc_html__('Question group order was updated successfully.', 'event_espresso');
1047
+
1048
+		// grab our row IDs
1049
+		$row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids'])
1050
+			? explode(',', rtrim($this->_req_data['row_ids'], ','))
1051
+			: array();
1052
+
1053
+		$perpage = ! empty($this->_req_data['perpage'])
1054
+			? (int) $this->_req_data['perpage']
1055
+			: null;
1056
+		$curpage = ! empty($this->_req_data['curpage'])
1057
+			? (int) $this->_req_data['curpage']
1058
+			: null;
1059
+
1060
+		if (! empty($row_ids)) {
1061
+			// figure out where we start the row_id count at for the current page.
1062
+			$qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage;
1063
+
1064
+			$row_count = count($row_ids);
1065
+			for ($i = 0; $i < $row_count; $i++) {
1066
+				// Update the questions when re-ordering
1067
+				$updated = EEM_Question_Group::instance()->update(
1068
+					array('QSG_order' => $qsgcount),
1069
+					array(array('QSG_ID' => $row_ids[ $i ]))
1070
+				);
1071
+				if ($updated === false) {
1072
+					$success = false;
1073
+				}
1074
+				$qsgcount++;
1075
+			}
1076
+		} else {
1077
+			$success = false;
1078
+		}
1079
+
1080
+		$errors = ! $success
1081
+			? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso')
1082
+			: false;
1083
+
1084
+		echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors));
1085
+		die();
1086
+	}
1087
+
1088
+
1089
+
1090
+	/***************************************       REGISTRATION SETTINGS       ***************************************/
1091
+
1092
+
1093
+	/**
1094
+	 * @throws DomainException
1095
+	 * @throws EE_Error
1096
+	 * @throws InvalidArgumentException
1097
+	 * @throws InvalidDataTypeException
1098
+	 * @throws InvalidInterfaceException
1099
+	 */
1100
+	protected function _reg_form_settings()
1101
+	{
1102
+		$this->_template_args['values'] = $this->_yes_no_values;
1103
+		add_action(
1104
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1105
+			array($this, 'email_validation_settings_form'),
1106
+			2
1107
+		);
1108
+		add_action(
1109
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1110
+			array($this, 'copy_attendee_info_settings_form'),
1111
+			4
1112
+		);
1113
+		add_action(
1114
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
1115
+			array($this, 'setSessionLifespan'),
1116
+			4.9
1117
+		);
1118
+		$this->_template_args = (array) apply_filters(
1119
+			'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args',
1120
+			$this->_template_args
1121
+		);
1122
+		$this->_set_add_edit_form_tags('update_reg_form_settings');
1123
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
1124
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1125
+			REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php',
1126
+			$this->_template_args,
1127
+			true
1128
+		);
1129
+		$this->display_admin_page_with_sidebar();
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 * @return void
1135
+	 * @throws EE_Error
1136
+	 * @throws InvalidArgumentException
1137
+	 * @throws ReflectionException
1138
+	 * @throws InvalidDataTypeException
1139
+	 * @throws InvalidInterfaceException
1140
+	 */
1141
+	protected function _update_reg_form_settings()
1142
+	{
1143
+		EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form(
1144
+			EE_Registry::instance()->CFG->registration
1145
+		);
1146
+		EE_Registry::instance()->CFG->registration = $this->update_copy_attendee_info_settings_form(
1147
+			EE_Registry::instance()->CFG->registration
1148
+		);
1149
+		$this->updateSessionLifespan();
1150
+		EE_Registry::instance()->CFG->registration = apply_filters(
1151
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
1152
+			EE_Registry::instance()->CFG->registration
1153
+		);
1154
+		$success = $this->_update_espresso_configuration(
1155
+			esc_html__('Registration Form Options', 'event_espresso'),
1156
+			EE_Registry::instance()->CFG,
1157
+			__FILE__,
1158
+			__FUNCTION__,
1159
+			__LINE__
1160
+		);
1161
+		$this->_redirect_after_action(
1162
+			$success,
1163
+			esc_html__('Registration Form Options', 'event_espresso'),
1164
+			'updated',
1165
+			array('action' => 'view_reg_form_settings')
1166
+		);
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * @return void
1172
+	 * @throws EE_Error
1173
+	 * @throws InvalidArgumentException
1174
+	 * @throws InvalidDataTypeException
1175
+	 * @throws InvalidInterfaceException
1176
+	 */
1177
+	public function copy_attendee_info_settings_form()
1178
+	{
1179
+		echo wp_kses($this->_copy_attendee_info_settings_form()->get_html(), AllowedTags::getWithFormTags());
1180
+	}
1181
+
1182
+	/**
1183
+	 * _copy_attendee_info_settings_form
1184
+	 *
1185
+	 * @access protected
1186
+	 * @return EE_Form_Section_Proper
1187
+	 * @throws \EE_Error
1188
+	 */
1189
+	protected function _copy_attendee_info_settings_form()
1190
+	{
1191
+		return new EE_Form_Section_Proper(
1192
+			array(
1193
+				'name'            => 'copy_attendee_info_settings',
1194
+				'html_id'         => 'copy_attendee_info_settings',
1195
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1196
+				'subsections'     => apply_filters(
1197
+					'FHEE__Extend_Registration_Form_Admin_Page___copy_attendee_info_settings_form__form_subsections',
1198
+					array(
1199
+						'copy_attendee_info_hdr'   => new EE_Form_Section_HTML(
1200
+							EEH_HTML::h2(esc_html__('Copy Attendee Info Settings', 'event_espresso'))
1201
+						),
1202
+						'copy_attendee_info' => new EE_Yes_No_Input(
1203
+							array(
1204
+								'html_label_text' => esc_html__(
1205
+									'Allow copy #1 attendee info to extra attendees?',
1206
+									'event_espresso'
1207
+								),
1208
+								'html_help_text'  => esc_html__(
1209
+									'Set to yes if you want to enable the copy of #1 attendee info to extra attendees at Registration Form.',
1210
+									'event_espresso'
1211
+								),
1212
+								'default'         => EE_Registry::instance()->CFG->registration->copyAttendeeInfo(),
1213
+								'required'        => false,
1214
+								'display_html_label_text' => false,
1215
+							)
1216
+						),
1217
+					)
1218
+				),
1219
+			)
1220
+		);
1221
+	}
1222
+
1223
+	/**
1224
+	 * @param EE_Registration_Config $EE_Registration_Config
1225
+	 * @return EE_Registration_Config
1226
+	 * @throws EE_Error
1227
+	 * @throws InvalidArgumentException
1228
+	 * @throws ReflectionException
1229
+	 * @throws InvalidDataTypeException
1230
+	 * @throws InvalidInterfaceException
1231
+	 */
1232
+	public function update_copy_attendee_info_settings_form(EE_Registration_Config $EE_Registration_Config)
1233
+	{
1234
+		$prev_copy_attendee_info = $EE_Registration_Config->copyAttendeeInfo();
1235
+		try {
1236
+			$copy_attendee_info_settings_form = $this->_copy_attendee_info_settings_form();
1237
+			// if not displaying a form, then check for form submission
1238
+			if ($copy_attendee_info_settings_form->was_submitted()) {
1239
+				// capture form data
1240
+				$copy_attendee_info_settings_form->receive_form_submission();
1241
+				// validate form data
1242
+				if ($copy_attendee_info_settings_form->is_valid()) {
1243
+					// grab validated data from form
1244
+					$valid_data = $copy_attendee_info_settings_form->valid_data();
1245
+					if (isset($valid_data['copy_attendee_info'])) {
1246
+						$EE_Registration_Config->setCopyAttendeeInfo($valid_data['copy_attendee_info']);
1247
+					} else {
1248
+						EE_Error::add_error(
1249
+							esc_html__(
1250
+								'Invalid or missing Copy Attendee Info settings. Please refresh the form and try again.',
1251
+								'event_espresso'
1252
+							),
1253
+							__FILE__,
1254
+							__FUNCTION__,
1255
+							__LINE__
1256
+						);
1257
+					}
1258
+				} elseif ($copy_attendee_info_settings_form->submission_error_message() !== '') {
1259
+					EE_Error::add_error(
1260
+						$copy_attendee_info_settings_form->submission_error_message(),
1261
+						__FILE__,
1262
+						__FUNCTION__,
1263
+						__LINE__
1264
+					);
1265
+				}
1266
+			}
1267
+		} catch (EE_Error $e) {
1268
+			$e->get_error();
1269
+		}
1270
+		return $EE_Registration_Config;
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * @return void
1276
+	 * @throws EE_Error
1277
+	 * @throws InvalidArgumentException
1278
+	 * @throws InvalidDataTypeException
1279
+	 * @throws InvalidInterfaceException
1280
+	 */
1281
+	public function email_validation_settings_form()
1282
+	{
1283
+		echo wp_kses($this->_email_validation_settings_form()->get_html(), AllowedTags::getWithFormTags());
1284
+	}
1285
+
1286
+
1287
+	/**
1288
+	 * _email_validation_settings_form
1289
+	 *
1290
+	 * @access protected
1291
+	 * @return EE_Form_Section_Proper
1292
+	 * @throws \EE_Error
1293
+	 */
1294
+	protected function _email_validation_settings_form()
1295
+	{
1296
+		return new EE_Form_Section_Proper(
1297
+			array(
1298
+				'name'            => 'email_validation_settings',
1299
+				'html_id'         => 'email_validation_settings',
1300
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1301
+				'subsections'     => apply_filters(
1302
+					'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections',
1303
+					array(
1304
+						'email_validation_hdr'   => new EE_Form_Section_HTML(
1305
+							EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso'))
1306
+						),
1307
+						'email_validation_level' => new EE_Select_Input(
1308
+							array(
1309
+								'basic'      => esc_html__('Basic', 'event_espresso'),
1310
+								'wp_default' => esc_html__('WordPress Default', 'event_espresso'),
1311
+								'i18n'       => esc_html__('International', 'event_espresso'),
1312
+								'i18n_dns'   => esc_html__('International + DNS Check', 'event_espresso'),
1313
+							),
1314
+							array(
1315
+								'html_label_text' => esc_html__('Email Validation Level', 'event_espresso')
1316
+													 . EEH_Template::get_help_tab_link('email_validation_info'),
1317
+								'html_help_text'  => esc_html__(
1318
+									'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.',
1319
+									'event_espresso'
1320
+								),
1321
+								'default'         => isset(
1322
+									EE_Registry::instance()->CFG->registration->email_validation_level
1323
+								)
1324
+									? EE_Registry::instance()->CFG->registration->email_validation_level
1325
+									: 'wp_default',
1326
+								'required'        => false,
1327
+							)
1328
+						),
1329
+					)
1330
+				),
1331
+			)
1332
+		);
1333
+	}
1334
+
1335
+
1336
+	/**
1337
+	 * @param EE_Registration_Config $EE_Registration_Config
1338
+	 * @return EE_Registration_Config
1339
+	 * @throws EE_Error
1340
+	 * @throws InvalidArgumentException
1341
+	 * @throws ReflectionException
1342
+	 * @throws InvalidDataTypeException
1343
+	 * @throws InvalidInterfaceException
1344
+	 */
1345
+	public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config)
1346
+	{
1347
+		$prev_email_validation_level = $EE_Registration_Config->email_validation_level;
1348
+		try {
1349
+			$email_validation_settings_form = $this->_email_validation_settings_form();
1350
+			// if not displaying a form, then check for form submission
1351
+			if ($email_validation_settings_form->was_submitted()) {
1352
+				// capture form data
1353
+				$email_validation_settings_form->receive_form_submission();
1354
+				// validate form data
1355
+				if ($email_validation_settings_form->is_valid()) {
1356
+					// grab validated data from form
1357
+					$valid_data = $email_validation_settings_form->valid_data();
1358
+					if (isset($valid_data['email_validation_level'])) {
1359
+						$email_validation_level = $valid_data['email_validation_level'];
1360
+						// now if they want to use international email addresses
1361
+						if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') {
1362
+							// in case we need to reset their email validation level,
1363
+							// make sure that the previous value wasn't already set to one of the i18n options.
1364
+							if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') {
1365
+								// if so, then reset it back to "basic" since that is the only other option that,
1366
+								// despite offering poor validation, supports i18n email addresses
1367
+								$prev_email_validation_level = 'basic';
1368
+							}
1369
+							// confirm our i18n email validation will work on the server
1370
+							if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) {
1371
+								// or reset email validation level to previous value
1372
+								$email_validation_level = $prev_email_validation_level;
1373
+							}
1374
+						}
1375
+						$EE_Registration_Config->email_validation_level = $email_validation_level;
1376
+					} else {
1377
+						EE_Error::add_error(
1378
+							esc_html__(
1379
+								'Invalid or missing Email Validation settings. Please refresh the form and try again.',
1380
+								'event_espresso'
1381
+							),
1382
+							__FILE__,
1383
+							__FUNCTION__,
1384
+							__LINE__
1385
+						);
1386
+					}
1387
+				} elseif ($email_validation_settings_form->submission_error_message() !== '') {
1388
+					EE_Error::add_error(
1389
+						$email_validation_settings_form->submission_error_message(),
1390
+						__FILE__,
1391
+						__FUNCTION__,
1392
+						__LINE__
1393
+					);
1394
+				}
1395
+			}
1396
+		} catch (EE_Error $e) {
1397
+			$e->get_error();
1398
+		}
1399
+		return $EE_Registration_Config;
1400
+	}
1401
+
1402
+
1403
+	/**
1404
+	 * confirms that the server's PHP version has the PCRE module enabled,
1405
+	 * and that the PCRE version works with our i18n email validation
1406
+	 *
1407
+	 * @param EE_Registration_Config $EE_Registration_Config
1408
+	 * @param string                 $email_validation_level
1409
+	 * @return bool
1410
+	 */
1411
+	private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level)
1412
+	{
1413
+		// first check that PCRE is enabled
1414
+		if (! defined('PREG_BAD_UTF8_ERROR')) {
1415
+			EE_Error::add_error(
1416
+				sprintf(
1417
+					esc_html__(
1418
+						'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.',
1419
+						'event_espresso'
1420
+					),
1421
+					'<br />'
1422
+				),
1423
+				__FILE__,
1424
+				__FUNCTION__,
1425
+				__LINE__
1426
+			);
1427
+			return false;
1428
+		} else {
1429
+			// PCRE support is enabled, but let's still
1430
+			// perform a test to see if the server will support it.
1431
+			// but first, save the updated validation level to the config,
1432
+			// so that the validation strategy picks it up.
1433
+			// this will get bumped back down if it doesn't work
1434
+			$EE_Registration_Config->email_validation_level = $email_validation_level;
1435
+			try {
1436
+				$email_validator = new EE_Email_Validation_Strategy();
1437
+				$i18n_email_address = apply_filters(
1438
+					'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address',
1439
+					'jägerjü[email protected]'
1440
+				);
1441
+				$email_validator->validate($i18n_email_address);
1442
+			} catch (Exception $e) {
1443
+				EE_Error::add_error(
1444
+					sprintf(
1445
+						esc_html__(
1446
+							'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s',
1447
+							'event_espresso'
1448
+						),
1449
+						'<br />',
1450
+						'<a href="http://php.net/manual/en/pcre.installation.php" target="_blank" rel="noopener noreferrer">http://php.net/manual/en/pcre.installation.php</a>'
1451
+					),
1452
+					__FILE__,
1453
+					__FUNCTION__,
1454
+					__LINE__
1455
+				);
1456
+				return false;
1457
+			}
1458
+		}
1459
+		return true;
1460
+	}
1461
+
1462
+
1463
+	public function setSessionLifespan()
1464
+	{
1465
+		$session_lifespan_form = new SessionLifespanForm();
1466
+		echo wp_kses($session_lifespan_form->get_html(), AllowedTags::getWithFormTags());
1467
+	}
1468
+
1469
+
1470
+	public function updateSessionLifespan()
1471
+	{
1472
+		$handler = new SessionLifespanFormHandler();
1473
+		$handler->process(new SessionLifespanForm());
1474
+	}
1475 1475
 }
Please login to merge, or discard this patch.
caffeinated/admin/extend/registration_form/forms/SessionLifespanForm.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -12,51 +12,51 @@
 block discarded – undo
12 12
 
13 13
 class SessionLifespanForm extends EE_Form_Section_Proper
14 14
 {
15
-    /**
16
-     * @var SessionLifespanOption
17
-     */
18
-    private $sessionLifespanOption;
15
+	/**
16
+	 * @var SessionLifespanOption
17
+	 */
18
+	private $sessionLifespanOption;
19 19
 
20 20
 
21
-    /**
22
-     * SessionLifespanForm constructor.
23
-     *
24
-     * @throws EE_Error
25
-     */
26
-    public function __construct()
27
-    {
28
-        $this->sessionLifespanOption = new SessionLifespanOption();
21
+	/**
22
+	 * SessionLifespanForm constructor.
23
+	 *
24
+	 * @throws EE_Error
25
+	 */
26
+	public function __construct()
27
+	{
28
+		$this->sessionLifespanOption = new SessionLifespanOption();
29 29
 
30
-        parent::__construct([
31
-            'name'            => 'session_lifespan',
32
-            'html_id'         => 'session_lifespan',
33
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
34
-            'subsections'     => apply_filters(
35
-                'FHEE__EventEspresso_caffeinated_admin_extend_registration_form_forms_SessionLifespanForm__construct__form_subsections',
36
-                [
37
-                    'session_lifespan_hdr'   => new EE_Form_Section_HTML(
38
-                        EEH_HTML::h2(esc_html__('Session Settings', 'event_espresso'))
39
-                    ),
40
-                    'session_lifespan' => new EE_Select_Input(
41
-                        [
42
-                            300     => esc_html__('Five Minutes', 'event_espresso'),
43
-                            900     => esc_html__('Fifteen Minutes', 'event_espresso'),
44
-                            1800    => esc_html__('Thirty Minutes', 'event_espresso'),
45
-                            3600    => esc_html__('One Hour', 'event_espresso'),
46
-                            7200    => esc_html__('Two Hours', 'event_espresso'),
47
-                        ],
48
-                        [
49
-                            'html_label_text' => esc_html__('Session Lifespan', 'event_espresso'),
50
-                            'html_help_text'  => esc_html__(
51
-                                'Controls how long a user has to complete the registration form. Defaults to 1 hour.',
52
-                                'event_espresso'
53
-                            ),
54
-                            'default'         => $this->sessionLifespanOption->getSessionLifespan(),
55
-                            'required'        => false,
56
-                        ]
57
-                    ),
58
-                ]
59
-            ),
60
-        ]);
61
-    }
30
+		parent::__construct([
31
+			'name'            => 'session_lifespan',
32
+			'html_id'         => 'session_lifespan',
33
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
34
+			'subsections'     => apply_filters(
35
+				'FHEE__EventEspresso_caffeinated_admin_extend_registration_form_forms_SessionLifespanForm__construct__form_subsections',
36
+				[
37
+					'session_lifespan_hdr'   => new EE_Form_Section_HTML(
38
+						EEH_HTML::h2(esc_html__('Session Settings', 'event_espresso'))
39
+					),
40
+					'session_lifespan' => new EE_Select_Input(
41
+						[
42
+							300     => esc_html__('Five Minutes', 'event_espresso'),
43
+							900     => esc_html__('Fifteen Minutes', 'event_espresso'),
44
+							1800    => esc_html__('Thirty Minutes', 'event_espresso'),
45
+							3600    => esc_html__('One Hour', 'event_espresso'),
46
+							7200    => esc_html__('Two Hours', 'event_espresso'),
47
+						],
48
+						[
49
+							'html_label_text' => esc_html__('Session Lifespan', 'event_espresso'),
50
+							'html_help_text'  => esc_html__(
51
+								'Controls how long a user has to complete the registration form. Defaults to 1 hour.',
52
+								'event_espresso'
53
+							),
54
+							'default'         => $this->sessionLifespanOption->getSessionLifespan(),
55
+							'required'        => false,
56
+						]
57
+					),
58
+				]
59
+			),
60
+		]);
61
+	}
62 62
 }
Please login to merge, or discard this patch.